re PR c++/33616 ("lvalue required as unary '&' operand" with template pmf)
authorJakub Jelinek <jakub@redhat.com>
Tue, 30 Oct 2007 22:37:53 +0000 (23:37 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 30 Oct 2007 22:37:53 +0000 (23:37 +0100)
PR c++/33616
* decl2.c (build_offset_ref_call_from_tree): Call
build_non_dependent_expr on object prior to building ADDR_EXPR from it
if FN is DOTSTAR_EXPR.

* g++.dg/template/ptrmem18.C: New test.

From-SVN: r129784

gcc/cp/ChangeLog
gcc/cp/decl2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/ptrmem18.C [new file with mode: 0644]

index d5b73e797cb85efa2384c7a33241c65a2b91fb2c..5e2447f94c32d01b9dc0b96ff396db0637a20f3d 100644 (file)
@@ -1,3 +1,10 @@
+2007-10-30  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/33616
+       * decl2.c (build_offset_ref_call_from_tree): Call
+       build_non_dependent_expr on object prior to building ADDR_EXPR from it
+       if FN is DOTSTAR_EXPR.
+
 2007-10-30  Douglas Gregor  <doug.gregor@gmail.com>
 
        PR c++/31993
index 0a978344fa13ddee00f85c9da7e9a2aa90878326..db0d9f38ee0b54e2c81375b50a48451344d47a88 100644 (file)
@@ -3499,9 +3499,9 @@ build_offset_ref_call_from_tree (tree fn, tree args)
         parameter.  That must be done before the FN is transformed
         because we depend on the form of FN.  */
       args = build_non_dependent_args (args);
+      object = build_non_dependent_expr (object);
       if (TREE_CODE (fn) == DOTSTAR_EXPR)
        object = build_unary_op (ADDR_EXPR, object, 0);
-      object = build_non_dependent_expr (object);
       args = tree_cons (NULL_TREE, object, args);
       /* Now that the arguments are done, transform FN.  */
       fn = build_non_dependent_expr (fn);
index 5a266cee36f3acd3529e8282ad08751de1a6600f..4fcafd01bbd2bab7d4fca8e3c88d1d294ac8f903 100644 (file)
@@ -1,3 +1,8 @@
+2007-10-30  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/33616
+       * g++.dg/template/ptrmem18.C: New test.
+
 2007-10-30  Francois-Xavier Coudert  <fxcoudert@gcc.gnu.org>
 
        PR fortran/33596
diff --git a/gcc/testsuite/g++.dg/template/ptrmem18.C b/gcc/testsuite/g++.dg/template/ptrmem18.C
new file mode 100644 (file)
index 0000000..c3124cd
--- /dev/null
@@ -0,0 +1,49 @@
+// PR c++/33616
+// { dg-do run }
+// { dg-options "-O2" }
+
+extern "C" void abort ();
+
+struct S {
+  int c;
+  S () : c (0) {}
+  virtual void f1 () { c += 1; }
+  virtual void f2 () { c += 16; }
+};
+
+struct T {
+  S s;
+};
+
+typedef void (S::*Q) ();
+
+template <Q P>
+void test1 (T *t)
+{
+  (t->s.*P)();
+}
+
+template <Q P>
+void test2 (T *t)
+{
+  S &s = t->s;
+  (s.*P)();
+}
+
+int
+main ()
+{
+  T t;
+  test1 <&S::f1> (&t);
+  if (t.s.c != 1)
+    abort ();
+  test1 <&S::f2> (&t);
+  if (t.s.c != 17)
+    abort ();
+  test2 <&S::f1> (&t);
+  if (t.s.c != 18)
+    abort ();
+  test2 <&S::f2> (&t);
+  if (t.s.c != 34)
+    abort ();
+}