Patchwork C++ PATCH for c++/47198 (ice-after-error with invalid type-name)

login
register
mail settings
Submitter Jason Merrill
Date March 10, 2011, 3:20 p.m.
Message ID <4D78EC4D.6080300@redhat.com>
Download mbox | patch
Permalink /patch/86298/
State New
Headers show

Comments

Jason Merrill - March 10, 2011, 3:20 p.m.
The call to cp_parser_skip_to_end_of_block_or_statement from 
cp_parser_parse_and_diagnose_invalid_type_name means that we're done 
looking at the current declaration; in the testcase, we were continuing 
to try to parse a declaration after skipping past the ;, so we ended up 
treating the constructor declarator as going with the template header. 
Instead, we should clean up and return.  This patch also slightly 
improves error recovery on a few other testcases.

Tested x86_64-pc-linux-gnu, applied to trunk.
commit 2659b79922e437e422612b2a4272c199446cf543
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Mar 10 01:22:45 2011 -0500

    	PR c++/47198
    	* parser.c (cp_parser_single_declaration): Just return if
    	cp_parser_parse_and_diagnose_invalid_type_name complained.

Patch

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 510fcb1..7e9b286 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -20102,8 +20102,15 @@  cp_parser_single_declaration (cp_parser* parser,
     }
 
   /* Complain about missing 'typename' or other invalid type names.  */
-  if (!decl_specifiers.any_type_specifiers_p)
-    cp_parser_parse_and_diagnose_invalid_type_name (parser);
+  if (!decl_specifiers.any_type_specifiers_p
+      && cp_parser_parse_and_diagnose_invalid_type_name (parser))
+    {
+      /* cp_parser_parse_and_diagnose_invalid_type_name calls
+	 cp_parser_skip_to_end_of_block_or_statement, so don't try to parse
+	 the rest of this declaration.  */
+      decl = error_mark_node;
+      goto out;
+    }
 
   /* If it's not a template class, try for a template function.  If
      the next token is a `;', then this declaration does not declare
@@ -20137,19 +20144,21 @@  cp_parser_single_declaration (cp_parser* parser,
       }
     }
 
-  pop_deferring_access_checks ();
-
-  /* Clear any current qualification; whatever comes next is the start
-     of something new.  */
-  parser->scope = NULL_TREE;
-  parser->qualifying_scope = NULL_TREE;
-  parser->object_scope = NULL_TREE;
   /* Look for a trailing `;' after the declaration.  */
   if (!function_definition_p
       && (decl == error_mark_node
 	  || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON)))
     cp_parser_skip_to_end_of_block_or_statement (parser);
 
+ out:
+  pop_deferring_access_checks ();
+
+  /* Clear any current qualification; whatever comes next is the start
+     of something new.  */
+  parser->scope = NULL_TREE;
+  parser->qualifying_scope = NULL_TREE;
+  parser->object_scope = NULL_TREE;
+
   return decl;
 }
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/syntax-err1.C b/gcc/testsuite/g++.dg/cpp0x/syntax-err1.C
new file mode 100644
index 0000000..ce1c9ee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/syntax-err1.C
@@ -0,0 +1,8 @@ 
+// PR c++/47198
+// { dg-options -std=c++0x }
+
+struct S
+{
+  template < int > sometype foo (); // { dg-error "sometype. does not name a type" }
+  S () = default;
+};
diff --git a/gcc/testsuite/g++.dg/parse/error36.C b/gcc/testsuite/g++.dg/parse/error36.C
index 0d7f8cf..8fcaa2f 100644
--- a/gcc/testsuite/g++.dg/parse/error36.C
+++ b/gcc/testsuite/g++.dg/parse/error36.C
@@ -30,4 +30,3 @@  void g(const A<T>::type &t);	// { dg-error "typename" }
 
 // PR c++/18451
 template <class T> A<T>::B A<T>::b; // { dg-error "typename" }
-// { dg-error "expected" "" { target *-*-* } 32 }
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ctor2.C b/gcc/testsuite/g++.old-deja/g++.pt/ctor2.C
index eb8f312..a8be91d 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/ctor2.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/ctor2.C
@@ -10,4 +10,4 @@  struct A {
 template <class T>
 A<T>::A<T>()   // { dg-error "constructor|qualified name" }
 {
-} // { dg-error "end of input" }
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename3.C b/gcc/testsuite/g++.old-deja/g++.pt/typename3.C
index 0708f1f..ad026a7 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/typename3.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/typename3.C
@@ -18,4 +18,4 @@  struct B : public A<U>
 
 template <class U>
 B<U>::A_Type B<U>::Func() { // { dg-error "typename" } implicit typename
-}			    // { dg-error "expected" }
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename4.C b/gcc/testsuite/g++.old-deja/g++.pt/typename4.C
index 7238470..47fb250 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/typename4.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/typename4.C
@@ -23,4 +23,4 @@  struct C : public B<U>
 
 template <class U>
 C<U>::A_Type C<U>::Func() { // { dg-error "typename" } implicit typename
-}			    // { dg-error "expected" }
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename6.C b/gcc/testsuite/g++.old-deja/g++.pt/typename6.C
index 0a5f018..7347812 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/typename6.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/typename6.C
@@ -17,4 +17,4 @@  struct B : public A<U>
 template <class U>
 A<U>::A_Type B<U>::Func()       // { dg-error "typename" } function
 {				
-} // { dg-error "expected" }
+}