diff mbox

C++ PATCH for c++/49691 (ICE in cp_parser_late_return_type_opt)

Message ID 4E19B5EF.2020101@redhat.com
State New
Headers show

Commit Message

Jason Merrill July 10, 2011, 2:23 p.m. UTC
My patch to implement DR 1207 caused this regression, where within a 
member function, a tentative parse that could involve a 
trailing-return-type leads to confusion.  Fixed by not relying on 
current_class_type to decide whether or not we're declaring a member 
function.

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

Patch

commit 1393efb69e650d966116c88a74efe2a1a014fa84
Author: Jason Merrill <jason@redhat.com>
Date:   Sat Jul 9 16:30:53 2011 -0400

    	PR c++/49691
    	* parser.c (cp_parser_late_return_type_opt): Check quals parameter
    	rather than current_class_type to determine whether to set 'this'.
    	(cp_parser_direct_declarator): Pass -1 to quals if member_p is false.
    	(cp_parser_init_declarator): Pass down member_p.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 6bb15ed..64be923 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -14388,7 +14388,7 @@  cp_parser_init_declarator (cp_parser* parser,
     = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
 			    &ctor_dtor_or_conv_p,
 			    /*parenthesized_p=*/NULL,
-			    /*member_p=*/false);
+			    member_p);
   /* Gather up the deferred checks.  */
   stop_deferring_access_checks ();
 
@@ -14971,8 +14971,8 @@  cp_parser_direct_declarator (cp_parser* parser,
 		  /* Parse the virt-specifier-seq.  */
 		  virt_specifiers = cp_parser_virt_specifier_seq_opt (parser);
 
-		  late_return
-		    = cp_parser_late_return_type_opt (parser, cv_quals);
+		  late_return = (cp_parser_late_return_type_opt
+				 (parser, member_p ? cv_quals : -1));
 
 		  /* Create the function-declarator.  */
 		  declarator = make_call_declarator (declarator,
@@ -15538,7 +15538,10 @@  cp_parser_virt_specifier_seq_opt (cp_parser* parser)
 
    -> trailing-type-specifier-seq abstract-declarator(opt)
 
-   Returns the type indicated by the type-id.  */
+   Returns the type indicated by the type-id.
+
+   QUALS is either a bitmask of cv_qualifiers or -1 for a non-member
+   function.  */
 
 static tree
 cp_parser_late_return_type_opt (cp_parser* parser, cp_cv_quals quals)
@@ -15555,7 +15558,7 @@  cp_parser_late_return_type_opt (cp_parser* parser, cp_cv_quals quals)
   /* Consume the ->.  */
   cp_lexer_consume_token (parser->lexer);
 
-  if (current_class_type)
+  if (quals >= 0)
     {
       /* DR 1207: 'this' is in scope in the trailing return type.  */
       tree this_parm = build_this_parm (current_class_type, quals);
diff --git a/gcc/testsuite/g++.dg/cpp0x/regress/regress6.C b/gcc/testsuite/g++.dg/cpp0x/regress/regress6.C
new file mode 100644
index 0000000..6de64c0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/regress/regress6.C
@@ -0,0 +1,11 @@ 
+// PR c++/49691
+// { dg-options -std=c++0x }
+
+struct A { int x; };
+A* f();
+struct B {
+  void g()
+  {
+    int(f()->x);
+  }
+};
diff --git a/gcc/testsuite/g++.dg/parse/crash45.C b/gcc/testsuite/g++.dg/parse/crash45.C
index 8696ab4..d2fbc8c 100644
--- a/gcc/testsuite/g++.dg/parse/crash45.C
+++ b/gcc/testsuite/g++.dg/parse/crash45.C
@@ -3,5 +3,5 @@ 
 
 struct A
 {
-  template <class> int f (B);	// { dg-error "was not declared in this scope|cannot be a member template" }
+  template <class> int f (B);	// { dg-error "was not declared in this scope|cannot be a member template|has not been declared" }
 };
diff --git a/gcc/testsuite/g++.dg/template/crash38.C b/gcc/testsuite/g++.dg/template/crash38.C
index c652cc8..f4cf299 100644
--- a/gcc/testsuite/g++.dg/template/crash38.C
+++ b/gcc/testsuite/g++.dg/template/crash38.C
@@ -4,5 +4,5 @@  class A
 {
   template<class R>
   static void f(X&); // { dg-error "" }
-  inline void A::f<void>(X&); // { dg-error "f|expected" }
+  inline void A::f<void>(X&); // { dg-error "f|expected|not been declared" }
 };
diff --git a/gcc/testsuite/g++.dg/template/crash64.C b/gcc/testsuite/g++.dg/template/crash64.C
index 750e3da..1d8fd00 100644
--- a/gcc/testsuite/g++.dg/template/crash64.C
+++ b/gcc/testsuite/g++.dg/template/crash64.C
@@ -2,5 +2,5 @@ 
 
 struct A
 {
-  template<int> void foo()(0); // { dg-error "initializer" } 
+  template<int> void foo()(0); // { dg-error "" }
 };