re PR c++/67257 (Internal compiler error in retrieve_specialization)
authorJason Merrill <jason@redhat.com>
Tue, 22 Dec 2015 21:46:44 +0000 (16:46 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 22 Dec 2015 21:46:44 +0000 (16:46 -0500)
PR c++/67257
* parser.c (cp_parser_single_declaration): Reject a class template
that also declares a variable.

From-SVN: r231913

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/g++.dg/cpp0x/pr51226.C
gcc/testsuite/g++.dg/cpp1y/auto-fn28.C [new file with mode: 0644]

index dbc7b3e800799b2f8c6ebcb56a5fa03b4620ca83..c081160f31656a705dfdb0a0a48f844e75b586a1 100644 (file)
@@ -1,5 +1,9 @@
 2015-12-22  Jason Merrill  <jason@redhat.com>
 
+       PR c++/67257
+       * parser.c (cp_parser_single_declaration): Reject a class template
+       that also declares a variable.
+
        PR c++/67339
        * parser.c (cp_parser_elaborated_type_specifier): Use CLASS_TYPE_P
        rather than check for RECORD_TYPE.
index 262bfb2880571bbd2e5a0536f461993af3b9b356..842dded1fcab6c305433b1a972a239ce34c3bcec 100644 (file)
@@ -25642,7 +25642,8 @@ cp_parser_single_declaration (cp_parser* parser,
   /* Check for the declaration of a template class.  */
   if (declares_class_or_enum)
     {
-      if (cp_parser_declares_only_class_p (parser))
+      if (cp_parser_declares_only_class_p (parser)
+         || (declares_class_or_enum & 2))
        {
          // If this is a declaration, but not a definition, associate
          // any constraints with the type declaration. Constraints
@@ -25673,6 +25674,19 @@ cp_parser_single_declaration (cp_parser* parser,
 
          /* Perform access checks for template parameters.  */
          cp_parser_perform_template_parameter_access_checks (checks);
+
+         /* Give a helpful diagnostic for
+              template <class T> struct A { } a;
+            if we aren't already recovering from an error.  */
+         if (!cp_parser_declares_only_class_p (parser)
+             && !seen_error ())
+           {
+             error_at (cp_lexer_peek_token (parser->lexer)->location,
+                       "a class template declaration must not declare "
+                       "anything else");
+             cp_parser_skip_to_end_of_block_or_statement (parser);
+             goto out;
+           }
        }
     }
 
index 7e52e93e219a799da4d192826e9ae63a61a60bdf..89200ee3d27760740729890d0dd16b463a5c985f 100644 (file)
@@ -6,4 +6,7 @@ template<int> struct A           // { dg-message "provided" }
   enum E : int;
 };
 
-template<> enum A<>::E : int {}  // { dg-error "wrong number|expected" }
+template<> enum A<>::E : int {}  // { dg-error "wrong number" }
+
+// { dg-prune-output "expected" }
+// { dg-prune-output "specialization" }
diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn28.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn28.C
new file mode 100644 (file)
index 0000000..fb3659b
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/67257
+// { dg-do compile { target c++14 } }
+
+template <typename> struct plus;
+template <typename> struct A {
+  template <typename T> auto operator()(T);
+} foldl;                       // { dg-error "" }
+void foo() { foldl<plus<int>>(0); }
+
+// { dg-prune-output "not declared" }
+// { dg-prune-output "expected" }