re PR c++/56104 (Wrong "dereferencing type-punned pointer" warning)
authorJason Merrill <jason@redhat.com>
Fri, 25 Jan 2013 17:55:09 +0000 (12:55 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 25 Jan 2013 17:55:09 +0000 (12:55 -0500)
PR c++/56104
* typeck.c (get_member_function_from_ptrfunc): Optimize if the
dynamic type has no virtual functions.

From-SVN: r195470

gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/testsuite/g++.dg/warn/pmf2.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.mike/pmf1.C

index 9a25935adff127fbcd60739af544946efc80d66c..3d304917b3c574c29b0fbb225ec542f3cc07772a 100644 (file)
@@ -1,3 +1,9 @@
+2013-01-25  Jason Merrill  <jason@redhat.com>
+
+       PR c++/56104
+       * typeck.c (get_member_function_from_ptrfunc): Optimize if the
+       dynamic type has no virtual functions.
+
 2013-01-22  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/55944
index 093e7c148fab720f9d1181b4c2b193efef42bebf..bfac39494e2a6c736f3f550ac4f52cdaac0c04d0 100644 (file)
@@ -3122,7 +3122,8 @@ build_array_ref (location_t loc, tree array, tree idx)
    With the final ISO C++ rules, such an optimization is
    incorrect: A pointer to a derived member can be static_cast
    to pointer-to-base-member, as long as the dynamic object
-   later has the right member.  */
+   later has the right member.  So now we only do this optimization
+   when we know the dynamic type of the object.  */
 
 tree
 get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
@@ -3133,8 +3134,10 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
 
   if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
     {
-      tree idx, delta, e1, e2, e3, vtbl, basetype;
+      tree idx, delta, e1, e2, e3, vtbl;
+      bool nonvirtual;
       tree fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
+      tree basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
 
       tree instance_ptr = *instance_ptrptr;
       tree instance_save_expr = 0;
@@ -3157,6 +3160,12 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
            }
        }
 
+      /* True if we know that the dynamic type of the object doesn't have
+        virtual functions, so we can assume the PFN field is a pointer.  */
+      nonvirtual = (COMPLETE_TYPE_P (basetype)
+                   && !TYPE_POLYMORPHIC_P (basetype)
+                   && resolves_to_fixed_type_p (instance_ptr, 0));
+
       if (TREE_SIDE_EFFECTS (instance_ptr))
        instance_ptr = instance_save_expr = save_expr (instance_ptr);
 
@@ -3167,7 +3176,9 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
       e3 = pfn_from_ptrmemfunc (function);
       delta = delta_from_ptrmemfunc (function);
       idx = build1 (NOP_EXPR, vtable_index_type, e3);
-      switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
+      if (nonvirtual)
+       e1 = integer_zero_node;
+      else switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
        {
        case ptrmemfunc_vbit_in_pfn:
          e1 = cp_build_binary_op (input_location,
@@ -3204,7 +3215,6 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
         a member of C, and no conversion is required.  In fact,
         lookup_base will fail in that case, because incomplete
         classes do not have BINFOs.  */
-      basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
       if (!same_type_ignoring_top_level_qualifiers_p
          (basetype, TREE_TYPE (TREE_TYPE (instance_ptr))))
        {
@@ -3221,6 +3231,10 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
       /* Hand back the adjusted 'this' argument to our caller.  */
       *instance_ptrptr = instance_ptr;
 
+      if (nonvirtual)
+       /* Now just return the pointer.  */
+       return e3;
+
       /* Next extract the vtable pointer from the object.  */
       vtbl = build1 (NOP_EXPR, build_pointer_type (vtbl_ptr_type_node),
                     instance_ptr);
@@ -3228,11 +3242,6 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
       if (vtbl == error_mark_node)
        return error_mark_node;
 
-      /* If the object is not dynamic the access invokes undefined
-        behavior.  As it is not executed in this case silence the
-        spurious warnings it may provoke.  */
-      TREE_NO_WARNING (vtbl) = 1;
-
       /* Finally, extract the function pointer from the vtable.  */
       e2 = fold_build_pointer_plus_loc (input_location, vtbl, idx);
       e2 = cp_build_indirect_ref (e2, RO_NULL, complain);
diff --git a/gcc/testsuite/g++.dg/warn/pmf2.C b/gcc/testsuite/g++.dg/warn/pmf2.C
new file mode 100644 (file)
index 0000000..be13819
--- /dev/null
@@ -0,0 +1,24 @@
+// PR c++/56104
+// { dg-options "-Wall -O2" }
+
+struct Foo
+{
+  Foo();
+  Foo(const Foo&);
+    void call()
+    {}
+};
+
+template<class MEMSIG, MEMSIG MEMFUNC>
+struct Wrap
+{
+    inline static void call( Foo cc )
+    {
+      (cc.*MEMFUNC)();     // <- warning here
+    }
+};
+
+void bar()
+{
+  Wrap<void (Foo::*)(), &Foo::call>::call( Foo() );
+}
index 15460ebaaa506208cf8c5568541c97650f049f40..aa1ea3efaefb543cb4a403cc08ce6028d629af73 100644 (file)
@@ -1,5 +1,5 @@
 // { dg-do run  }
-// extern "C" printf(const char *, ...);
+// extern "C" int printf(const char *, ...);
 
 class X
 {