diff mbox

C++ PATCH for c++/67257 (ICE with broken template)

Message ID 5679C26F.4040007@redhat.com
State New
Headers show

Commit Message

Jason Merrill Dec. 22, 2015, 9:36 p.m. UTC
A template can declare a class template or a variable template, but not 
both at once.  We were failing to diagnose this.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox

Patch

commit 316f3a84bf6f512e09b3d3aa72a1600f4cba0a75
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Dec 21 13:46:09 2015 -0500

    	PR c++/67257
    	* parser.c (cp_parser_single_declaration): Reject a class template
    	that also declares a variable.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 262bfb2..842dded 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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;
+	    }
 	}
     }
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr51226.C b/gcc/testsuite/g++.dg/cpp0x/pr51226.C
index 7e52e93..89200ee 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr51226.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr51226.C
@@ -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
index 0000000..fb3659b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/auto-fn28.C
@@ -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" }