From 0b45aeddd8b0a144ac78998ff0f65490dc2ad1fc Mon Sep 17 00:00:00 2001
From: Mark Mitchell <mark@codesourcery.com>
Date: Fri, 13 Oct 2006 08:38:43 +0000
Subject: [PATCH] re PR c++/28506 (ICE with initializers for functions)

	PR c++/28506
	* parser.c (function_declarator_p): New function.
	(cp_parser_init_declarator): Use it.
	(cp_parser_member_declaration): Likewise.
	PR c++/28506
	* g++.dg/parse/pure1.C: New test.

From-SVN: r117687
---
 gcc/cp/ChangeLog                   |  7 +++++++
 gcc/cp/parser.c                    | 24 ++++++++++++++++++++----
 gcc/testsuite/ChangeLog            |  5 +++++
 gcc/testsuite/g++.dg/parse/pure1.C | 11 +++++++++++
 4 files changed, 43 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/parse/pure1.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 18958d46baba..b1df987227d2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2006-10-13  Mark Mitchell  <mark@codesourcery.com>
+
+	PR c++/28506
+	* parser.c (function_declarator_p): New function.
+	(cp_parser_init_declarator): Use it.
+	(cp_parser_member_declaration): Likewise.
+
 2006-10-12  Mark Mitchell  <mark@codesourcery.com>
 
 	PR c++/29318
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 41fe858b5efb..cb357cfd5956 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -965,6 +965,24 @@ make_parameter_declarator (cp_decl_specifier_seq *decl_specifiers,
   return parameter;
 }
 
+/* Returns true iff DECLARATOR  is a declaration for a function.  */
+
+static bool
+function_declarator_p (const cp_declarator *declarator)
+{
+  while (declarator)
+    {
+      if (declarator->kind == cdk_function
+	  && declarator->declarator->kind == cdk_id)
+	return true;
+      if (declarator->kind == cdk_id
+	  || declarator->kind == cdk_error)
+	return false;
+      declarator = declarator->declarator;
+    }
+  return false;
+}
+ 
 /* The parser.  */
 
 /* Overview
@@ -11157,8 +11175,7 @@ cp_parser_init_declarator (cp_parser* parser,
   is_non_constant_init = true;
   if (is_initialized)
     {
-      if (declarator->kind == cdk_function
-	  && declarator->declarator->kind == cdk_id
+      if (function_declarator_p (declarator)
 	  && initialization_kind == CPP_EQ)
 	initializer = cp_parser_pure_specifier (parser);
       else
@@ -13825,8 +13842,7 @@ cp_parser_member_declaration (cp_parser* parser)
 		     for a pure-specifier; otherwise, we look for a
 		     constant-initializer.  When we call `grokfield', it will
 		     perform more stringent semantics checks.  */
-		  if (declarator->kind == cdk_function
-		      && declarator->declarator->kind == cdk_id)
+		  if (function_declarator_p (declarator))
 		    initializer = cp_parser_pure_specifier (parser);
 		  else
 		    /* Parse the initializer.  */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 67419090c20e..3a48c5d4c4d6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2006-10-13  Mark Mitchell  <mark@codesourcery.com>
+
+	PR c++/28506
+	* g++.dg/parse/pure1.C: New test.
+
 2006-10-13  Francois-Xavier Coudert  <coudert@clipper.ens.fr>
 
 	PR fortran/21435
diff --git a/gcc/testsuite/g++.dg/parse/pure1.C b/gcc/testsuite/g++.dg/parse/pure1.C
new file mode 100644
index 000000000000..2b6f28b7df51
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/pure1.C
@@ -0,0 +1,11 @@
+// PR c++/28506
+
+struct A
+{
+  virtual void* foo() = 1; // { dg-error "pure" }
+};
+
+struct B
+{
+  void operator()()() = 1; // { dg-error "pure|function|initializer" }
+};
-- 
GitLab