[PATCH] Adding a diagnostic for member templates inside a local class

YunZhong Gao gaoyunzhong at gmail.com
Mon Mar 25 17:02:06 PDT 2013


Hi doug.gregor,

Currently, clang++ accepts the following codes without any error message.

int test(void)
{
  class A {
    template<class T> class B
    {  T t; };
  };

  return 0;
}

However, I believe that an error message is required according to the C++03 and C++11.
In particular, section 14.5 clause 2 (of both specs) says "A local class shall not have member templates."

This patch adds a diagnostic for member templates declared inside a local class.

http://llvm-reviews.chandlerc.com/D575

Files:
  test/SemaTemplate/member-template-local-class.cpp
  test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaTemplate.cpp

Index: test/SemaTemplate/member-template-local-class.cpp
===================================================================
--- test/SemaTemplate/member-template-local-class.cpp
+++ test/SemaTemplate/member-template-local-class.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -verify -fsyntax-only %s
+
+int test1(void)
+{
+  class A {
+    template<class T>  // expected-error {{member template is not allowed in a local class}} 
+    class B
+    {
+      T t;
+    };
+  };
+
+  return 0;
+}
+
+int test2(void)
+{
+  class A {
+    template<class T> // expected-error {{member template is not allowed in a local class}}
+    int B()
+    {
+      return 0;
+    }
+  };
+
+  return 0;
+}
+
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<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}}
   }
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -2655,7 +2655,9 @@
   "%select{|template parameter }0redeclaration">;
 def note_template_param_different_kind : Note<
   "template parameter has a different kind in template argument">;
-  
+def err_member_template_in_local_class : Error<
+    "member template is not allowed in a local class">;
+
 def err_template_nontype_parm_different_type : Error<
   "template non-type parameter has a different type %0 in template "
   "%select{|template parameter }1redeclaration">;
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -4908,6 +4908,15 @@
   while (Ctx && isa<LinkageSpecDecl>(Ctx))
     Ctx = Ctx->getParent();
 
+  if (Ctx && Ctx->isRecord()) {
+    const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Ctx);
+    if (RD && RD->isLocalClass()) {
+      return Diag(TemplateParams->getTemplateLoc(), 
+                  diag::err_member_template_in_local_class)
+               << TemplateParams->getSourceRange();
+    }
+  }
+
   if (Ctx && (Ctx->isFileContext() || Ctx->isRecord()))
     return false;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D575.1.patch
Type: text/x-patch
Size: 2952 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130325/30abd861/attachment.bin>


More information about the cfe-commits mailing list