Commit e18724aa by Jason Merrill Committed by Jason Merrill

re PR c++/56104 (Wrong "dereferencing type-punned pointer" warning)

	PR c++/56104
	* typeck.c (get_member_function_from_ptrfunc): Optimize if the
	dynamic type has no virtual functions.

From-SVN: r195470
parent b7d7d917
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> 2013-01-22 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/55944 PR c++/55944
......
...@@ -3122,7 +3122,8 @@ build_array_ref (location_t loc, tree array, tree idx) ...@@ -3122,7 +3122,8 @@ build_array_ref (location_t loc, tree array, tree idx)
With the final ISO C++ rules, such an optimization is With the final ISO C++ rules, such an optimization is
incorrect: A pointer to a derived member can be static_cast incorrect: A pointer to a derived member can be static_cast
to pointer-to-base-member, as long as the dynamic object 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 tree
get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function, get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
...@@ -3133,8 +3134,10 @@ 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))) 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 fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
tree basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
tree instance_ptr = *instance_ptrptr; tree instance_ptr = *instance_ptrptr;
tree instance_save_expr = 0; tree instance_save_expr = 0;
...@@ -3157,6 +3160,12 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function, ...@@ -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)) if (TREE_SIDE_EFFECTS (instance_ptr))
instance_ptr = instance_save_expr = save_expr (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, ...@@ -3167,7 +3176,9 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
e3 = pfn_from_ptrmemfunc (function); e3 = pfn_from_ptrmemfunc (function);
delta = delta_from_ptrmemfunc (function); delta = delta_from_ptrmemfunc (function);
idx = build1 (NOP_EXPR, vtable_index_type, e3); 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: case ptrmemfunc_vbit_in_pfn:
e1 = cp_build_binary_op (input_location, e1 = cp_build_binary_op (input_location,
...@@ -3204,7 +3215,6 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function, ...@@ -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, a member of C, and no conversion is required. In fact,
lookup_base will fail in that case, because incomplete lookup_base will fail in that case, because incomplete
classes do not have BINFOs. */ classes do not have BINFOs. */
basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
if (!same_type_ignoring_top_level_qualifiers_p if (!same_type_ignoring_top_level_qualifiers_p
(basetype, TREE_TYPE (TREE_TYPE (instance_ptr)))) (basetype, TREE_TYPE (TREE_TYPE (instance_ptr))))
{ {
...@@ -3221,6 +3231,10 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function, ...@@ -3221,6 +3231,10 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
/* Hand back the adjusted 'this' argument to our caller. */ /* Hand back the adjusted 'this' argument to our caller. */
*instance_ptrptr = instance_ptr; *instance_ptrptr = instance_ptr;
if (nonvirtual)
/* Now just return the pointer. */
return e3;
/* Next extract the vtable pointer from the object. */ /* Next extract the vtable pointer from the object. */
vtbl = build1 (NOP_EXPR, build_pointer_type (vtbl_ptr_type_node), vtbl = build1 (NOP_EXPR, build_pointer_type (vtbl_ptr_type_node),
instance_ptr); instance_ptr);
...@@ -3228,11 +3242,6 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function, ...@@ -3228,11 +3242,6 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function,
if (vtbl == error_mark_node) if (vtbl == error_mark_node)
return 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. */ /* Finally, extract the function pointer from the vtable. */
e2 = fold_build_pointer_plus_loc (input_location, vtbl, idx); e2 = fold_build_pointer_plus_loc (input_location, vtbl, idx);
e2 = cp_build_indirect_ref (e2, RO_NULL, complain); e2 = cp_build_indirect_ref (e2, RO_NULL, complain);
......
// 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() );
}
// { dg-do run } // { dg-do run }
// extern "C" printf(const char *, ...); // extern "C" int printf(const char *, ...);
class X class X
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment