re PR c++/37016 (member function pointer failure with optimization)
authorJason Merrill <jason@redhat.com>
Tue, 5 Aug 2008 22:22:00 +0000 (18:22 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 5 Aug 2008 22:22:00 +0000 (18:22 -0400)
        PR c++/37016
        * tree-ssa.c (useless_type_conversion_p_1): Call langhook
        if TYPE_STRUCTURAL_EQUALITY_P is true for both types.

From-SVN: r138740

gcc/ChangeLog
gcc/testsuite/g++.dg/opt/pmf1.C [new file with mode: 0644]
gcc/tree-ssa.c

index 8bce42a..eb2467b 100644 (file)
@@ -1,3 +1,9 @@
+2008-08-04  Jason Merrill  <jason@redhat.com>
+
+       PR c++/37016
+       * tree-ssa.c (useless_type_conversion_p_1): Call langhook
+       if TYPE_STRUCTURAL_EQUALITY_P is true for both types.
+
 2008-08-05  Richard Henderson  <rth@redhat.com>
 
        * configure.ac (HAVE_GAS_CFI_DIRECTIVE): Check .cfi_personality.
diff --git a/gcc/testsuite/g++.dg/opt/pmf1.C b/gcc/testsuite/g++.dg/opt/pmf1.C
new file mode 100644 (file)
index 0000000..428e753
--- /dev/null
@@ -0,0 +1,76 @@
+// PR c++/37016
+// { dg-do run }
+// { dg-options "-O2 -Wall" }
+
+/*                                                                              
+  Basic design concept is that WorldObject implements remote method call        
+  functionality using the "curiously recurring template pattern" to enable      
+  forwarding calls from the generic base class that implements the transport    
+  layer to the derived class.                                                   
+
+  The specific failure was in forwarding calls to items in a container.         
+  This is emulated here by wrapping a single item.                              
+
+  In the main program there are two forms of the call.  In the last             
+  (uncommented) form the member function pointer is for clarity                 
+  assigned to a variable (itemfunptr) before making the call.                   
+  With 4.3.0 and 4.3.1 this code compiles incorrectly with -O1 or greater       
+  to produce this warning                                                       
+
+  reproduce.cc: In function ‘int main()’:                                       
+  reproduce.cc:26: warning: ‘itemfunptr.void (Container::*)(void
+(Item::*)(int), int)::__pfn’ is used uninitialized in this function             
+  reproduce.cc:47: note: ‘itemfunptr.void (Container::*)(void (Item::*)(int),
+int)::__pfn’ was declared here                                                  
+
+  and the resulting executable segvs.  It works correctly with -O0.             
+
+  With 4.2.3 and earlier it works correctly with optimization.                  
+
+  In the first (commented out) form of the call in the main program             
+  we directly refer to desired member function.  This compiles                  
+  and executes correctly with all tested versions.                              
+*/
+
+extern "C" int printf (const char *, ...);
+
+template <class Derived>
+struct WorldObject {
+    template <typename memfunT, typename arg1T, typename arg2T>
+    void forward(memfunT memfun, arg1T arg1, arg2T arg2) {
+        Derived* obj = static_cast<Derived*>(this);
+        (obj->*memfun)(arg1, arg2);
+    }
+};
+
+struct Item {
+    void fred(int a) {
+      printf ("a=%d\n", a);
+    }
+};
+
+struct Container : public WorldObject<Container> {
+    Item item;
+    template <typename itemfunT, typename arg1T>
+    void itemfun(itemfunT itemfun, int a) {
+        (item.*itemfun)(a);
+    }
+};
+
+int main() {
+    typedef void (Item::*itemfun)(int);
+
+    Container t;
+
+    // This call compiles and executes correctly with all versions tested       
+    //t.forward(&Container::itemfun<itemfun,int>, &Item::fred, 1);              
+
+    // This call compiles with a warning and segvs on execution if using        
+    // -O1 or greater with 4.3.*.  4.2.* is correct.                            
+    void (Container::*itemfunptr)(itemfun, int) =
+&Container::itemfun<itemfun,int>;
+    t.forward(itemfunptr, &Item::fred, 1);
+
+    return 0;
+}
+
index fbfcbf2..c308a35 100644 (file)
@@ -1165,12 +1165,18 @@ useless_type_conversion_p_1 (tree outer_type, tree inner_type)
       if (TREE_CODE (inner_type) != TREE_CODE (outer_type))
        return false;
 
-      /* ???  Add structural equivalence check.  */
+      /* ???  This seems to be necessary even for aggregates that don't
+        have TYPE_STRUCTURAL_EQUALITY_P set.  */
 
       /* ???  This should eventually just return false.  */
       return lang_hooks.types_compatible_p (inner_type, outer_type);
     }
-
+  /* Also for functions and possibly other types with
+     TYPE_STRUCTURAL_EQUALITY_P set.  */
+  else if (TYPE_STRUCTURAL_EQUALITY_P (inner_type)
+          && TYPE_STRUCTURAL_EQUALITY_P (outer_type))
+    return lang_hooks.types_compatible_p (inner_type, outer_type);
+  
   return false;
 }