A couple of small bugs involving pointers to member functions in templates. In 61500, we were failing to handle MEMBER_REF in lvalue_kind. In 61488, we were failing to handle unlowered PMF syntax used as a template argument.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit ef46b757ccae754f3edc937acfa39bcc19e57111
Author: Jason Merrill <ja...@redhat.com>
Date:   Fri Jun 13 15:01:15 2014 -0400

    	PR c++/61488
    	* pt.c (check_valid_ptrmem_cst_expr): Fix for template context.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 8858908..df57293 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5350,6 +5350,10 @@ check_valid_ptrmem_cst_expr (tree type, tree expr,
     return true;
   if (cxx_dialect >= cxx11 && null_member_pointer_value_p (expr))
     return true;
+  if (processing_template_decl
+      && TREE_CODE (expr) == ADDR_EXPR
+      && TREE_CODE (TREE_OPERAND (expr, 0)) == OFFSET_REF)
+    return true;
   if (complain & tf_error)
     {
       error ("%qE is not a valid template argument for type %qT",
diff --git a/gcc/testsuite/g++.dg/template/ptrmem28.C b/gcc/testsuite/g++.dg/template/ptrmem28.C
new file mode 100644
index 0000000..0379960
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/ptrmem28.C
@@ -0,0 +1,10 @@
+// PR c++/61488
+
+struct A {
+  typedef int (A::*cont_func)();
+  template <A::cont_func> void wait(int);
+  int notify();
+
+  void fix() { wait<&A::notify>(0); } // OK
+  template <int> void repair() { wait<&A::notify>(0); }
+};
commit 7a2deb52336c87960d6c75439978302d0facdda8
Author: jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Mon Jun 16 11:45:37 2014 +0000

    	PR c++/61500
    	* tree.c (lvalue_kind): Handle MEMBER_REF and DOTSTAR_EXPR.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@211703 138bc75d-0d04-0410-961f-82ee72b054a4

diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 587ae80..3616605 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -102,6 +102,16 @@ lvalue_kind (const_tree ref)
     case IMAGPART_EXPR:
       return lvalue_kind (TREE_OPERAND (ref, 0));
 
+    case MEMBER_REF:
+    case DOTSTAR_EXPR:
+      if (TREE_CODE (ref) == MEMBER_REF)
+	op1_lvalue_kind = clk_ordinary;
+      else
+	op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 0));
+      if (TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (ref, 1))))
+	op1_lvalue_kind = clk_none;
+      return op1_lvalue_kind;
+
     case COMPONENT_REF:
       op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 0));
       /* Look at the member designator.  */
diff --git a/gcc/testsuite/g++.dg/template/ptrmem27.C b/gcc/testsuite/g++.dg/template/ptrmem27.C
new file mode 100644
index 0000000..8c63f9c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/ptrmem27.C
@@ -0,0 +1,22 @@
+// PR c++/61500
+
+struct X {
+  int i;
+  int j;
+
+  int foo(int X::* ptr);
+
+  template <int X::* ptr>
+  int bar();
+};
+
+int X::foo(int X::* ptr) {
+  int* p = &(this->*ptr);  // OK.
+  return *p;
+}
+
+template <int X::* ptr>
+int X::bar() {
+  int* p = &(this->*ptr);  // gcc 4.9.0: OK in C++98 mode, fails in C++11 mode.
+  return *p;
+}

Reply via email to