]> granicus.if.org Git - clang/commitdiff
Diagnose the use of typedefs for template specialization types in the scope
authorJohn McCall <rjmccall@apple.com>
Tue, 15 Dec 2009 02:19:47 +0000 (02:19 +0000)
committerJohn McCall <rjmccall@apple.com>
Tue, 15 Dec 2009 02:19:47 +0000 (02:19 +0000)
specifiers for out-of-line declarations, e.g.
  typedef Temp<int> MyTemp;
  template <> MyTemp::foo;

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91395 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaTemplate.cpp
test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp

index e33fbe96d45829cc6f0ed19a26c73beefa60b89c..a890323e6c0d9f16cb2f9d9db9d40890dbe870fa 100644 (file)
@@ -971,6 +971,9 @@ def err_template_tag_noparams : Error<
 def err_template_decl_ref : Error<
   "cannot refer to class template %0 without a template argument list">;
 
+def err_typedef_in_def_scope : Error<
+  "cannot use typedef %0 in scope specifier for out-of-line declaration">;
+
 // C++ Template Argument Lists
 def err_template_arg_list_different_arity : Error<
   "%select{too few|too many}0 template arguments for "
index 9fa57c03eaf75a271f075c1b952a772ea1a94087..ac1b1ec0eed0f978967e3c40c4ae72dfec4250b3 100644 (file)
@@ -1170,8 +1170,27 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
     ExplicitSpecializationsInSpecifier;
   for (NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
        NNS; NNS = NNS->getPrefix()) {
+    const Type *T = NNS->getAsType();
+    if (!T) break;
+
+    // C++0x [temp.expl.spec]p17:
+    //   A member or a member template may be nested within many
+    //   enclosing class templates. In an explicit specialization for
+    //   such a member, the member declaration shall be preceded by a
+    //   template<> for each enclosing class template that is
+    //   explicitly specialized.
+    // We interpret this as forbidding typedefs of template
+    // specializations in the scope specifiers of out-of-line decls.
+    if (const TypedefType *TT = dyn_cast<TypedefType>(T)) {
+      const Type *UnderlyingT = TT->LookThroughTypedefs().getTypePtr();
+      if (isa<TemplateSpecializationType>(UnderlyingT))
+        // FIXME: better source location information.
+        Diag(DeclStartLoc, diag::err_typedef_in_def_scope) << QualType(T,0);
+      T = UnderlyingT;
+    }
+
     if (const TemplateSpecializationType *SpecType
-          = dyn_cast_or_null<TemplateSpecializationType>(NNS->getAsType())) {
+          = dyn_cast<TemplateSpecializationType>(T)) {
       TemplateDecl *Template = SpecType->getTemplateName().getAsTemplateDecl();
       if (!Template)
         continue; // FIXME: should this be an error? probably...
index 883cb71d5686c25e9ae8a0a74504314ce561699d..06653044c3bb60fbfa1d3f4ab1a8d5a7e5c8c312 100644 (file)
@@ -10,3 +10,15 @@ template<> template<> class A<int>::B<double>;
 template<> template<> void A<char>::B<char>::mf();
 
 template<> void A<char>::B<int>::mf(); // expected-error{{requires 'template<>'}}
+
+namespace test1 {
+  template <class> class A {
+    static int foo;
+    static int bar;
+  };
+  typedef A<int> AA;
+  
+  template <> int AA::foo = 0; // expected-error {{cannot use typedef}}
+  int AA::bar = 1; // expected-error {{cannot use typedef}} expected-error {{template specialization requires 'template<>'}}
+  int A<float>::bar = 2; // expected-error {{template specialization requires 'template<>'}}
+}