tstellar / rpms / gcc

Forked from rpms/gcc 4 years ago
Clone
Blob Blame History Raw
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.

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

--- gcc/cp/decl2.c	(revision 129783)
+++ gcc/cp/decl2.c	(revision 129784)
@@ -3499,9 +3499,9 @@ build_offset_ref_call_from_tree (tree fn
 	 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);
--- gcc/testsuite/g++.dg/template/ptrmem18.C	(revision 0)
+++ gcc/testsuite/g++.dg/template/ptrmem18.C	(revision 129784)
@@ -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 ();
+}