Patchwork C++ PATCH for c++/54359 ('this' in trailing-return-type with out-of-class method defn)

login
register
mail settings
Submitter Jason Merrill
Date March 18, 2013, 3:45 a.m.
Message ID <51468DE6.9040804@redhat.com>
Download mbox | patch
Permalink /patch/228359/
State New
Headers show

Comments

Jason Merrill - March 18, 2013, 3:45 a.m.
This patch caused c++/56639: when within a function we were trying to 
parse something that could be either a declaration or an expression, we 
went to set current_class_ptr and failed the assertion that it wasn't 
already set.  We could save and restore the value, but instead with this 
patch I take advantage of the fact that there can never be a declaration 
with a qualified-id at function scope.

Tested x86_64-pc-linux-gnu, applied to trunk.

Patch

commit 1d92c03f05ea76a2c10b491f4b31852c8a6b04d5
Author: Jason Merrill <jason@redhat.com>
Date:   Sun Mar 17 21:48:31 2013 -0400

    	PR c++/54359
    	PR c++/56639
    	* parser.c (cp_parser_direct_declarator): Bail if we see a
    	qualified-id not at namespace scope.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 0222e90..23fe3f3 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -16707,9 +16707,18 @@  cp_parser_direct_declarator (cp_parser* parser,
 	handle_declarator:;
 	  scope = get_scope_of_declarator (declarator);
 	  if (scope)
-	    /* Any names that appear after the declarator-id for a
-	       member are looked up in the containing scope.  */
-	    pushed_scope = push_scope (scope);
+	    {
+	      /* Any names that appear after the declarator-id for a
+		 member are looked up in the containing scope.  */
+	      if (at_function_scope_p ())
+		{
+		  /* But declarations with qualified-ids can't appear in a
+		     function.  */
+		  cp_parser_error (parser, "qualified-id in declaration");
+		  break;
+		}
+	      pushed_scope = push_scope (scope);
+	    }
 	  parser->in_declarator_p = true;
 	  if ((ctor_dtor_or_conv_p && *ctor_dtor_or_conv_p)
 	      || (declarator && declarator->kind == cdk_id))
diff --git a/gcc/testsuite/g++.dg/parse/typename7.C b/gcc/testsuite/g++.dg/parse/typename7.C
index 2d823f8..6ec7696 100644
--- a/gcc/testsuite/g++.dg/parse/typename7.C
+++ b/gcc/testsuite/g++.dg/parse/typename7.C
@@ -22,7 +22,7 @@  struct B
     A().bar<typename T>(t); } // { dg-error "expected|parse error|no matching" }
   // { dg-message "candidate" "candidate note" { target *-*-* } 22 }
   void bad(T t) {
-    B<typename T>::bar(t); } // { dg-error "invalid|not a template" }
+    B<typename T>::bar(t); } // { dg-error "invalid|qualified-id|not a template" }
 };
 
 void baz()
diff --git a/gcc/testsuite/g++.dg/template/arrow2.C b/gcc/testsuite/g++.dg/template/arrow2.C
new file mode 100644
index 0000000..8ec9e01
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/arrow2.C
@@ -0,0 +1,12 @@ 
+// PR c++/56639
+
+struct A {
+  int i;
+  static A* f();
+};
+
+struct B {
+  void g() {
+    int (A::f()->i);
+  }
+};