]> granicus.if.org Git - clang/commitdiff
Diagnose attempts to explicitly instantiate a template at class scope. Previously...
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 9 Feb 2017 22:14:25 +0000 (22:14 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 9 Feb 2017 22:14:25 +0000 (22:14 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@294639 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Parse/ParseDeclCXX.cpp
test/Parser/cxx-template-decl.cpp
test/Parser/eof.cpp
test/SemaCXX/cxx1y-variable-templates_in_class.cpp
test/SemaTemplate/explicit-instantiation.cpp
test/SemaTemplate/template-id-expr.cpp

index d55890960331f5d0ec1617091229849d8d510d17..8d89f4093749d5c0043834b3e2985a4c0f637afb 100644 (file)
@@ -2459,9 +2459,10 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
   if (Tok.is(tok::kw_template)) {
     assert(!TemplateInfo.TemplateParams &&
            "Nested template improperly parsed?");
+    ObjCDeclContextSwitch ObjCDC(*this);
     SourceLocation DeclEnd;
     return DeclGroupPtrTy::make(
-        DeclGroupRef(ParseDeclarationStartingWithTemplate(
+        DeclGroupRef(ParseTemplateDeclarationOrSpecialization(
             Declarator::MemberContext, DeclEnd, AS, AccessAttrs)));
   }
 
index efa42ad30d049715d6c74a3ced860cfc3ff61a4f..9ad422e7ab7184406b0ed6ed8d8f66ad21a5c3a6 100644 (file)
@@ -238,3 +238,13 @@ struct t2 : base<int,
 // expected-error@-1 {{expected '{' after base class list}}
 
 }
+
+namespace class_scope_instantiation {
+  struct A {
+    template<typename T> void f(T);
+    template void f<int>(int); // expected-error {{expected '<' after 'template'}}
+    template void f(float); // expected-error {{expected '<' after 'template'}}
+    extern template // expected-error {{expected member name or ';'}}
+      void f(double);
+  };
+}
index 3c966c50e1db36974440b2fbf30e9dac192e8ac7..4a06587edea37828245e46ba8c17378c11eecd55 100644 (file)
@@ -1,6 +1,6 @@
 // RUN: not %clang_cc1 %s -fsyntax-only 2>&1 | FileCheck %s
 
-// CHECK: error: expected member name or ';' after declaration specifiers
+// CHECK: error: expected '<' after 'template'
 // CHECK: error: expected '}'
 // CHECK: note: to match this '{'
 // CHECK: error: expected ';' after class
index 76f1bb9905b9a6933097ebee232de4640ae21132..66f0f10f0f3d9a6f137786b1f003417c359127d9 100644 (file)
@@ -17,8 +17,7 @@ class A {
   template<typename T> CONST float right<float,T> = 5;  // expected-error {{member 'right' declared as a template}}
   template<> static CONST int right<int,int> = 7;       // expected-error {{explicit specialization of 'right' in class scope}}
   template<> static CONST float right<float,int>;       // expected-error {{explicit specialization of 'right' in class scope}}
-  template static CONST int right<int,int>;     // expected-error {{template specialization requires 'template<>'}} \
-                                                // expected-error {{explicit specialization of 'right' in class scope}}
+  template static CONST int right<int,int>;     // expected-error {{expected '<' after 'template'}}
 };
 
 namespace out_of_line {
@@ -166,8 +165,7 @@ namespace constexpred {
     template<typename T> constexpr float right<float,T> = 5;  // expected-error {{non-static data member cannot be constexpr; did you intend to make it static?}}
     template<> static constexpr int right<int,int> = 7;       // expected-error {{explicit specialization of 'right' in class scope}}
     template<> static constexpr float right<float,int>;       // expected-error {{explicit specialization of 'right' in class scope}}
-    template static constexpr int right<int,int>;     // expected-error {{template specialization requires 'template<>'}} \
-                                                  // expected-error {{explicit specialization of 'right' in class scope}}
+    template static constexpr int right<int,int>;     // expected-error {{expected '<' after 'template'}}
   };
 }
 #endif
index 040a932e972016abb942d546624cfeb9785b21ee..010716dd1426664126aade7c083f2c3409c8bbfe 100644 (file)
@@ -103,8 +103,8 @@ namespace PR7622 {
 // Test that we do not crash.
 class TC1 {
   class TC2 {
-    template // FIXME: error here.
-    void foo() { }
+    template
+    void foo() { } // expected-error{{expected '<' after 'template'}}
    };
 };
 
index e311b5832d0d2066e444493a0ac09b0ed20ef288..65c4e998accfb88ef55fd1748002798dacabc952 100644 (file)
@@ -98,7 +98,11 @@ void f5() {
 template void f5<0>(); // expected-note {{in instantiation of function template specialization 'f5<0>' requested here}}
 
 class C {};
-template <template <typename> class D>  // expected-note{{previous use is here}}
+template <template <typename> class D>
 class E {
-  template class D<C>;  // expected-error {{template template argument 'D' cannot be referenced with a class specifier}}
+  template class D<C>;  // expected-error {{expected '<' after 'template'}}
+  template<> class D<C>;  // expected-error {{cannot specialize a template template parameter}}
+  friend class D<C>; // expected-error {{type alias template 'D' cannot be referenced with a class specifier}}
 };
+template<typename T> using D = int; // expected-note {{declared here}} expected-warning {{extension}}
+E<D> ed; // expected-note {{instantiation of}}