r193144 - Sema: Do not allow template declarations inside local classes
Howard Hinnant
hhinnant at apple.com
Tue Oct 22 09:49:41 PDT 2013
Thanks, fix committed revision 193169.
Howard
On Oct 22, 2013, at 10:08 AM, David Majnemer <david.majnemer at gmail.com> wrote:
> Yep, looks like libcxxabi violates 14.5.2 [temp.mem]/p2. Looks like this violation was introduced back in r184097. Note that trying to compile with GCC gets us a similar error:
> invalid declaration of member template in local class
>
> CC'ing Howard Hinnant.
>
>
> On Tue, Oct 22, 2013 at 4:36 AM, İsmail Dönmez <ismail at donmez.ws> wrote:
> This breaks libc++abi:
>
> [ 52s] + clang++ -c -g -O3 -fPIC -std=c++11 -stdlib=libc++ -fstrict-aliasing -Wstrict-aliasing=2 -Wsign-conversion -Wshadow -Wconversion -Wunused-variable -Wmissing-field-initializers -Wchar-subscripts -Wmismatched-tags -Wmissing-braces -Wshorten-64-to-32 -Wsign-compare -Wstrict-aliasing=2 -Wstrict-overflow=4 -Wunused-parameter -Wnewline-eof -I../include ../src/cxa_demangle.cpp
> [ 53s] ../src/cxa_demangle.cpp:4624:9: error: templates cannot be declared inside of a local class
> [ 53s] template <size_t N>
> [ 53s] ^~~~~~~~~~~~~~~~~~~
> [ 53s] ../src/cxa_demangle.cpp:4631:8: error: no matching constructor for initialization of 'Db'
> [ 53s] Db db(a);
> [ 53s] ^ ~
> [ 53s] ../src/cxa_demangle.cpp:4609:12: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'arena<bs>' to 'Db' for 1st argument
> [ 53s] struct Db
> [ 53s] ^
> [ 53s] ../src/cxa_demangle.cpp:4609:12: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'arena<bs>' to 'const Db' for 1st argument
> [ 53s] struct Db
> [ 53s] ^
> [ 53s] ../src/cxa_demangle.cpp:4609:12: note: candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided
>
>
> On Tue, Oct 22, 2013 at 7:14 AM, David Majnemer <david.majnemer at gmail.com> wrote:
> Author: majnemer
> Date: Mon Oct 21 23:14:18 2013
> New Revision: 193144
>
> URL: http://llvm.org/viewvc/llvm-project?rev=193144&view=rev
> Log:
> Sema: Do not allow template declarations inside local classes
>
> Summary:
> Enforce the rule in C++11 [temp.mem]p2 that local classes cannot have
> member templates.
>
> This fixes PR16947.
>
> N.B. C++14 has slightly different wording to afford generic lambdas
> declared inside of functions.
>
> Fun fact: Some formulations of local classes with member templates
> would cause clang to crash during Itanium mangling, such as the
> following:
>
> void outer_mem() {
> struct Inner {
> template <typename = void>
> struct InnerTemplateClass {
> static void itc_mem() {}
> };
> };
> Inner::InnerTemplateClass<>::itc_mem();
> }
>
> Reviewers: eli.friedman, rsmith, doug.gregor, faisalv
>
> Reviewed By: doug.gregor
>
> CC: cfe-commits, ygao
>
> Differential Revision: http://llvm-reviews.chandlerc.com/D1866
>
> Added:
> cfe/trunk/test/CXX/temp/temp.decls/temp.mem/p2.cpp
> Removed:
> cfe/trunk/test/PCH/cxx-local-templates.cpp
> cfe/trunk/test/PCH/cxx1y-local-templates.cpp
> cfe/trunk/test/SemaTemplate/local-member-templates.cpp
> Modified:
> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> cfe/trunk/lib/Sema/SemaTemplate.cpp
> cfe/trunk/test/CodeGenCXX/mangle-local-class-names.cpp
> cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=193144&r1=193143&r2=193144&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Oct 21 23:14:18 2013
> @@ -2835,6 +2835,8 @@ def warn_template_export_unsupported : W
> "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<
>
> Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=193144&r1=193143&r2=193144&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Oct 21 23:14:18 2013
> @@ -5459,8 +5459,20 @@ Sema::CheckTemplateDeclScope(Scope *S, T
> while (Ctx && isa<LinkageSpecDecl>(Ctx))
> Ctx = Ctx->getParent();
>
> - if (Ctx && (Ctx->isFileContext() || Ctx->isRecord()))
> - return false;
> + if (Ctx) {
> + if (Ctx->isFileContext())
> + return false;
> + if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(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)
>
> Added: cfe/trunk/test/CXX/temp/temp.decls/temp.mem/p2.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.mem/p2.cpp?rev=193144&view=auto
> ==============================================================================
> --- cfe/trunk/test/CXX/temp/temp.decls/temp.mem/p2.cpp (added)
> +++ cfe/trunk/test/CXX/temp/temp.decls/temp.mem/p2.cpp Mon Oct 21 23:14:18 2013
> @@ -0,0 +1,12 @@
> +// RUN: %clang_cc1 -fsyntax-only -verify %s
> +
> +template <typename>
> +void quux();
> +
> +void fun() {
> + struct foo {
> + template <typename> struct bar {}; // expected-error{{templates cannot be declared inside of a local class}}
> + template <typename> void baz() {} // expected-error{{templates cannot be declared inside of a local class}}
> + template <typename> void qux(); // expected-error{{templates cannot be declared inside of a local class}}
> + };
> +}
>
> Modified: cfe/trunk/test/CodeGenCXX/mangle-local-class-names.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-local-class-names.cpp?rev=193144&r1=193143&r2=193144&view=diff
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/mangle-local-class-names.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/mangle-local-class-names.cpp Mon Oct 21 23:14:18 2013
> @@ -75,16 +75,6 @@ inline void OmittingCode(float x) {
> }
> void CallOmittingCode() { OmittingCode(1); }
>
> -// CHECK: @_ZZ25LocalTemplateFunctionTestdEN5Local3fooIdEET_S1_
> -int LocalTemplateFunctionTest(double d) {
> - struct Local {
> - template<class T> T foo(T t) {
> - return t;
> - }
> - };
> - return Local().foo(d);
> -}
> -
> // CHECK: @_ZZ15LocalAnonStructvENUt0_1gEv
> inline void LocalAnonStruct() {
> if (0) {
>
> Removed: cfe/trunk/test/PCH/cxx-local-templates.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx-local-templates.cpp?rev=193143&view=auto
> ==============================================================================
> --- cfe/trunk/test/PCH/cxx-local-templates.cpp (original)
> +++ cfe/trunk/test/PCH/cxx-local-templates.cpp (removed)
> @@ -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<class T> T foo(T t) {
> - return t;
> - }
> - };
> - return Local{}.foo(d);
> -}
> -
> -template<class U>
> -U template_test(U d) {
> - struct Local {
> - template<class T> T foo(T t) {
> - return t;
> - }
> - };
> - return Local{}.foo(d);
> -}
> -
> -int nested_local() {
> - struct Inner1 {
> - int inner1_foo(char c) {
> - struct Inner2 {
> - template<class T> 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
>
> Removed: cfe/trunk/test/PCH/cxx1y-local-templates.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx1y-local-templates.cpp?rev=193143&view=auto
> ==============================================================================
> --- cfe/trunk/test/PCH/cxx1y-local-templates.cpp (original)
> +++ cfe/trunk/test/PCH/cxx1y-local-templates.cpp (removed)
> @@ -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<class T> 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<class T> 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
>
> Modified: cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp?rev=193144&r1=193143&r2=193144&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp (original)
> +++ cfe/trunk/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp Mon Oct 21 23:14:18 2013
> @@ -44,13 +44,14 @@ namespace dr1330_example {
> A<int>().f(42);
> }
>
> + struct S {
> + template<typename T>
> + static int f() noexcept(noexcept(A<T>().f("boo!"))) { return 0; } // \
> + // expected-note {{instantiation of exception spec}}
> + typedef decltype(f<S>()) X;
> + };
> +
> int test2() {
> - struct S {
> - template<typename T>
> - static int f() noexcept(noexcept(A<T>().f("boo!"))) { return 0; } // \
> - // expected-note {{instantiation of exception spec}}
> - typedef decltype(f<S>()) X;
> - };
> S().f<S>(); // ok
> S().f<int>(); // expected-note {{instantiation of exception spec}}
> }
>
> Removed: cfe/trunk/test/SemaTemplate/local-member-templates.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/local-member-templates.cpp?rev=193143&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaTemplate/local-member-templates.cpp (original)
> +++ cfe/trunk/test/SemaTemplate/local-member-templates.cpp (removed)
> @@ -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 <class T> struct Outer {
> - template <class U> int outer_mem(T t, U u) {
> - struct Inner {
> - template <class V> int inner_mem(T t, U u, V v) {
> - struct InnerInner {
> - template <class W> 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 <class U> int outer_mem(T t, U *u);
> -};
> -
> -template int Outer<int>::outer_mem(int, char);
> -
> -template <class T> template <class U> int Outer<T>::outer_mem(T t, U *u) {
> - struct Inner {
> - template <class V>
> - int inner_mem(T t, U u, V v) { //expected-note{{candidate function}}
> - struct InnerInner {
> - template <class W> 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<int>::outer_mem(int, char *); //expected-note{{in instantiation of function}}
> -
> -} // end ns
> -
> -namespace nested_local_templates_2 {
> -
> -template <class T> struct Outer {
> - template <class U> void outer_mem(T t, U u) {
> - struct Inner {
> - template <class V> struct InnerTemplateClass {
> - template <class W>
> - void itc_mem(T t, U u, V v, W w) { //expected-note{{candidate function}}
> - struct InnerInnerInner {
> - template <class X> void iii_mem(X x) {}
> - };
> - InnerInnerInner i;
> - i.iii_mem("abc");
> - }
> - };
> - };
> - Inner i;
> - typename Inner::template InnerTemplateClass<Inner> ii;
> - ii.itc_mem(t, u, i, "jim");
> - ii.itc_mem(t, u, 0, "abd"); //expected-error{{no matching member function}}
> - }
> -};
> -
> -template void
> -Outer<int>::outer_mem(int, char); //expected-note{{in instantiation of}}
> -
> -}
> -
> -namespace more_nested_local_templates {
> -
> -int test() {
> - struct Local {
> - template<class U> void foo(U u) {
> - struct Inner {
> - template<class A>
> - 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
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
>
More information about the cfe-commits
mailing list