Commit a271590a by Paolo Carlini Committed by Paolo Carlini

re PR c++/44267 (SFINAE does not handle down static_cast over virtual inheritance)

/cp
2011-09-24  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/44267
	* class.c (build_base_path): Add a tsubst_flags_t parameter.
	(convert_to_base): Adjust call.
	* typeck.c (build_class_member_access_expr,
	get_member_function_from_ptrfunc, build_static_cast_1): Likewise.
	* init.c (dfs_initialize_vtbl_ptrs, emit_mem_initializers): Likewise.
	* method.c (do_build_copy_constructor, do_build_copy_assign): Likewise.
	* rtti.c (build_dynamic_cast_1): Likewise.
	* typeck2.c (build_scoped_ref, build_m_component_ref): Likewise.
	* call.c (build_over_call, build_special_member_call): Likewise.
	* cvt.c (cp_convert_to_pointer, convert_to_pointer_force,
	build_up_reference): Likewise.
	* cp-tree.h (build_base_path): Adjust declaration.

/testsuite
2011-09-24  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/44267
	* g++.dg/template/sfinae28.C: New.

From-SVN: r179141
parent ee02baae
2011-09-24 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/44267
* class.c (build_base_path): Add a tsubst_flags_t parameter.
(convert_to_base): Adjust call.
* typeck.c (build_class_member_access_expr,
get_member_function_from_ptrfunc, build_static_cast_1): Likewise.
* init.c (dfs_initialize_vtbl_ptrs, emit_mem_initializers): Likewise.
* method.c (do_build_copy_constructor, do_build_copy_assign): Likewise.
* rtti.c (build_dynamic_cast_1): Likewise.
* typeck2.c (build_scoped_ref, build_m_component_ref): Likewise.
* call.c (build_over_call, build_special_member_call): Likewise.
* cvt.c (cp_convert_to_pointer, convert_to_pointer_force,
build_up_reference): Likewise.
* cp-tree.h (build_base_path): Adjust declaration.
2011-09-23 Jason Merrill <jason@redhat.com> 2011-09-23 Jason Merrill <jason@redhat.com>
Core 253 - allow const objects with no initializer or Core 253 - allow const objects with no initializer or
......
...@@ -6449,7 +6449,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) ...@@ -6449,7 +6449,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
converted_arg = build_base_path (PLUS_EXPR, converted_arg = build_base_path (PLUS_EXPR,
arg, arg,
cand->conversion_path, cand->conversion_path,
1); 1, complain);
/* Check that the base class is accessible. */ /* Check that the base class is accessible. */
if (!accessible_base_p (TREE_TYPE (argtype), if (!accessible_base_p (TREE_TYPE (argtype),
BINFO_TYPE (cand->conversion_path), true)) BINFO_TYPE (cand->conversion_path), true))
...@@ -6462,7 +6462,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) ...@@ -6462,7 +6462,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
base_binfo = lookup_base (TREE_TYPE (TREE_TYPE (converted_arg)), base_binfo = lookup_base (TREE_TYPE (TREE_TYPE (converted_arg)),
TREE_TYPE (parmtype), ba_unique, NULL); TREE_TYPE (parmtype), ba_unique, NULL);
converted_arg = build_base_path (PLUS_EXPR, converted_arg, converted_arg = build_base_path (PLUS_EXPR, converted_arg,
base_binfo, 1); base_binfo, 1, complain);
argarray[j++] = converted_arg; argarray[j++] = converted_arg;
parm = TREE_CHAIN (parm); parm = TREE_CHAIN (parm);
...@@ -6706,7 +6706,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) ...@@ -6706,7 +6706,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
if (TREE_DEPRECATED (fn)) if (TREE_DEPRECATED (fn))
warn_deprecated_use (fn, NULL_TREE); warn_deprecated_use (fn, NULL_TREE);
argarray[0] = build_base_path (PLUS_EXPR, argarray[0], binfo, 1); argarray[0] = build_base_path (PLUS_EXPR, argarray[0], binfo, 1,
complain);
if (TREE_SIDE_EFFECTS (argarray[0])) if (TREE_SIDE_EFFECTS (argarray[0]))
argarray[0] = save_expr (argarray[0]); argarray[0] = save_expr (argarray[0]);
t = build_pointer_type (TREE_TYPE (fn)); t = build_pointer_type (TREE_TYPE (fn));
...@@ -6916,7 +6917,7 @@ build_special_member_call (tree instance, tree name, VEC(tree,gc) **args, ...@@ -6916,7 +6917,7 @@ build_special_member_call (tree instance, tree name, VEC(tree,gc) **args,
/* However, for assignment operators, we must convert /* However, for assignment operators, we must convert
dynamically if the base is virtual. */ dynamically if the base is virtual. */
instance = build_base_path (PLUS_EXPR, instance, instance = build_base_path (PLUS_EXPR, instance,
binfo, /*nonnull=*/1); binfo, /*nonnull=*/1, complain);
} }
} }
......
...@@ -235,7 +235,8 @@ tree ...@@ -235,7 +235,8 @@ tree
build_base_path (enum tree_code code, build_base_path (enum tree_code code,
tree expr, tree expr,
tree binfo, tree binfo,
int nonnull) int nonnull,
tsubst_flags_t complain)
{ {
tree v_binfo = NULL_TREE; tree v_binfo = NULL_TREE;
tree d_binfo = NULL_TREE; tree d_binfo = NULL_TREE;
...@@ -276,14 +277,16 @@ build_base_path (enum tree_code code, ...@@ -276,14 +277,16 @@ build_base_path (enum tree_code code,
if (code == MINUS_EXPR && v_binfo) if (code == MINUS_EXPR && v_binfo)
{ {
error ("cannot convert from base %qT to derived type %qT via virtual base %qT", if (complain & tf_error)
BINFO_TYPE (binfo), BINFO_TYPE (d_binfo), BINFO_TYPE (v_binfo)); error ("cannot convert from base %qT to derived type %qT via "
"virtual base %qT", BINFO_TYPE (binfo), BINFO_TYPE (d_binfo),
BINFO_TYPE (v_binfo));
return error_mark_node; return error_mark_node;
} }
if (!want_pointer) if (!want_pointer)
/* This must happen before the call to save_expr. */ /* This must happen before the call to save_expr. */
expr = cp_build_addr_expr (expr, tf_warning_or_error); expr = cp_build_addr_expr (expr, complain);
else else
expr = mark_rvalue_use (expr); expr = mark_rvalue_use (expr);
...@@ -341,7 +344,7 @@ build_base_path (enum tree_code code, ...@@ -341,7 +344,7 @@ build_base_path (enum tree_code code,
interesting to the optimizers anyway. */ interesting to the optimizers anyway. */
&& !has_empty) && !has_empty)
{ {
expr = cp_build_indirect_ref (expr, RO_NULL, tf_warning_or_error); expr = cp_build_indirect_ref (expr, RO_NULL, complain);
expr = build_simple_base_path (expr, binfo); expr = build_simple_base_path (expr, binfo);
if (want_pointer) if (want_pointer)
expr = build_address (expr); expr = build_address (expr);
...@@ -366,19 +369,18 @@ build_base_path (enum tree_code code, ...@@ -366,19 +369,18 @@ build_base_path (enum tree_code code,
t = TREE_TYPE (TYPE_VFIELD (current_class_type)); t = TREE_TYPE (TYPE_VFIELD (current_class_type));
t = build_pointer_type (t); t = build_pointer_type (t);
v_offset = convert (t, current_vtt_parm); v_offset = convert (t, current_vtt_parm);
v_offset = cp_build_indirect_ref (v_offset, RO_NULL, v_offset = cp_build_indirect_ref (v_offset, RO_NULL, complain);
tf_warning_or_error);
} }
else else
v_offset = build_vfield_ref (cp_build_indirect_ref (expr, RO_NULL, v_offset = build_vfield_ref (cp_build_indirect_ref (expr, RO_NULL,
tf_warning_or_error), complain),
TREE_TYPE (TREE_TYPE (expr))); TREE_TYPE (TREE_TYPE (expr)));
v_offset = fold_build_pointer_plus (v_offset, BINFO_VPTR_FIELD (v_binfo)); v_offset = fold_build_pointer_plus (v_offset, BINFO_VPTR_FIELD (v_binfo));
v_offset = build1 (NOP_EXPR, v_offset = build1 (NOP_EXPR,
build_pointer_type (ptrdiff_type_node), build_pointer_type (ptrdiff_type_node),
v_offset); v_offset);
v_offset = cp_build_indirect_ref (v_offset, RO_NULL, tf_warning_or_error); v_offset = cp_build_indirect_ref (v_offset, RO_NULL, complain);
TREE_CONSTANT (v_offset) = 1; TREE_CONSTANT (v_offset) = 1;
offset = convert_to_integer (ptrdiff_type_node, offset = convert_to_integer (ptrdiff_type_node,
...@@ -418,7 +420,7 @@ build_base_path (enum tree_code code, ...@@ -418,7 +420,7 @@ build_base_path (enum tree_code code,
null_test = NULL; null_test = NULL;
if (!want_pointer) if (!want_pointer)
expr = cp_build_indirect_ref (expr, RO_NULL, tf_warning_or_error); expr = cp_build_indirect_ref (expr, RO_NULL, complain);
out: out:
if (null_test) if (null_test)
...@@ -523,7 +525,7 @@ convert_to_base (tree object, tree type, bool check_access, bool nonnull, ...@@ -523,7 +525,7 @@ convert_to_base (tree object, tree type, bool check_access, bool nonnull,
if (!binfo || binfo == error_mark_node) if (!binfo || binfo == error_mark_node)
return error_mark_node; return error_mark_node;
return build_base_path (PLUS_EXPR, object, binfo, nonnull); return build_base_path (PLUS_EXPR, object, binfo, nonnull, complain);
} }
/* EXPR is an expression with unqualified class type. BASE is a base /* EXPR is an expression with unqualified class type. BASE is a base
......
...@@ -4790,7 +4790,7 @@ extern void validate_conversion_obstack (void); ...@@ -4790,7 +4790,7 @@ extern void validate_conversion_obstack (void);
/* in class.c */ /* in class.c */
extern tree build_vfield_ref (tree, tree); extern tree build_vfield_ref (tree, tree);
extern tree build_base_path (enum tree_code, tree, extern tree build_base_path (enum tree_code, tree,
tree, int); tree, int, tsubst_flags_t);
extern tree convert_to_base (tree, tree, bool, bool, extern tree convert_to_base (tree, tree, bool, bool,
tsubst_flags_t); tsubst_flags_t);
extern tree convert_to_base_statically (tree, tree); extern tree convert_to_base_statically (tree, tree);
......
/* Language-level data type conversion for GNU C++. /* Language-level data type conversion for GNU C++.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
Free Software Foundation, Inc. 2011 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com) Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC. This file is part of GCC.
...@@ -157,7 +157,8 @@ cp_convert_to_pointer (tree type, tree expr) ...@@ -157,7 +157,8 @@ cp_convert_to_pointer (tree type, tree expr)
if (binfo || same_p) if (binfo || same_p)
{ {
if (binfo) if (binfo)
expr = build_base_path (code, expr, binfo, 0); expr = build_base_path (code, expr, binfo, 0,
tf_warning_or_error);
/* Add any qualifier conversions. */ /* Add any qualifier conversions. */
return build_nop (type, expr); return build_nop (type, expr);
} }
...@@ -275,7 +276,8 @@ convert_to_pointer_force (tree type, tree expr) ...@@ -275,7 +276,8 @@ convert_to_pointer_force (tree type, tree expr)
return error_mark_node; return error_mark_node;
if (binfo) if (binfo)
{ {
expr = build_base_path (code, expr, binfo, 0); expr = build_base_path (code, expr, binfo, 0,
tf_warning_or_error);
if (expr == error_mark_node) if (expr == error_mark_node)
return error_mark_node; return error_mark_node;
/* Add any qualifier conversions. */ /* Add any qualifier conversions. */
...@@ -341,7 +343,8 @@ build_up_reference (tree type, tree arg, int flags, tree decl) ...@@ -341,7 +343,8 @@ build_up_reference (tree type, tree arg, int flags, tree decl)
return error_mark_node; return error_mark_node;
if (binfo == NULL_TREE) if (binfo == NULL_TREE)
return error_not_base_type (target_type, argtype); return error_not_base_type (target_type, argtype);
rval = build_base_path (PLUS_EXPR, rval, binfo, 1); rval = build_base_path (PLUS_EXPR, rval, binfo, 1,
tf_warning_or_error);
} }
else else
rval rval
......
...@@ -100,7 +100,8 @@ dfs_initialize_vtbl_ptrs (tree binfo, void *data) ...@@ -100,7 +100,8 @@ dfs_initialize_vtbl_ptrs (tree binfo, void *data)
{ {
tree base_ptr = TREE_VALUE ((tree) data); tree base_ptr = TREE_VALUE ((tree) data);
base_ptr = build_base_path (PLUS_EXPR, base_ptr, binfo, /*nonnull=*/1); base_ptr = build_base_path (PLUS_EXPR, base_ptr, binfo, /*nonnull=*/1,
tf_warning_or_error);
expand_virtual_init (binfo, base_ptr); expand_virtual_init (binfo, base_ptr);
} }
...@@ -963,7 +964,7 @@ emit_mem_initializers (tree mem_inits) ...@@ -963,7 +964,7 @@ emit_mem_initializers (tree mem_inits)
tree base_addr; tree base_addr;
base_addr = build_base_path (PLUS_EXPR, current_class_ptr, base_addr = build_base_path (PLUS_EXPR, current_class_ptr,
subobject, 1); subobject, 1, tf_warning_or_error);
expand_aggr_init_1 (subobject, NULL_TREE, expand_aggr_init_1 (subobject, NULL_TREE,
cp_build_indirect_ref (base_addr, RO_NULL, cp_build_indirect_ref (base_addr, RO_NULL,
tf_warning_or_error), tf_warning_or_error),
......
...@@ -516,7 +516,8 @@ do_build_copy_constructor (tree fndecl) ...@@ -516,7 +516,8 @@ do_build_copy_constructor (tree fndecl)
for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0; for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0;
VEC_iterate (tree, vbases, i, binfo); i++) VEC_iterate (tree, vbases, i, binfo); i++)
{ {
init = build_base_path (PLUS_EXPR, parm, binfo, 1); init = build_base_path (PLUS_EXPR, parm, binfo, 1,
tf_warning_or_error);
if (move_p) if (move_p)
init = move (init); init = move (init);
member_init_list member_init_list
...@@ -531,7 +532,8 @@ do_build_copy_constructor (tree fndecl) ...@@ -531,7 +532,8 @@ do_build_copy_constructor (tree fndecl)
if (BINFO_VIRTUAL_P (base_binfo)) if (BINFO_VIRTUAL_P (base_binfo))
continue; continue;
init = build_base_path (PLUS_EXPR, parm, base_binfo, 1); init = build_base_path (PLUS_EXPR, parm, base_binfo, 1,
tf_warning_or_error);
if (move_p) if (move_p)
init = move (init); init = move (init);
member_init_list member_init_list
...@@ -624,7 +626,8 @@ do_build_copy_assign (tree fndecl) ...@@ -624,7 +626,8 @@ do_build_copy_assign (tree fndecl)
/* We must convert PARM directly to the base class /* We must convert PARM directly to the base class
explicitly since the base class may be ambiguous. */ explicitly since the base class may be ambiguous. */
converted_parm = build_base_path (PLUS_EXPR, parm, base_binfo, 1); converted_parm = build_base_path (PLUS_EXPR, parm, base_binfo, 1,
tf_warning_or_error);
if (move_p) if (move_p)
converted_parm = move (converted_parm); converted_parm = move (converted_parm);
/* Call the base class assignment operator. */ /* Call the base class assignment operator. */
......
/* RunTime Type Identification /* RunTime Type Identification
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009, 2010 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc. Free Software Foundation, Inc.
Mostly written by Jason Merrill (jason@cygnus.com). Mostly written by Jason Merrill (jason@cygnus.com).
...@@ -616,7 +616,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain) ...@@ -616,7 +616,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
if (binfo) if (binfo)
{ {
expr = build_base_path (PLUS_EXPR, convert_from_reference (expr), expr = build_base_path (PLUS_EXPR, convert_from_reference (expr),
binfo, 0); binfo, 0, complain);
if (TREE_CODE (exprtype) == POINTER_TYPE) if (TREE_CODE (exprtype) == POINTER_TYPE)
expr = rvalue (expr); expr = rvalue (expr);
return expr; return expr;
......
...@@ -2221,7 +2221,7 @@ build_class_member_access_expr (tree object, tree member, ...@@ -2221,7 +2221,7 @@ build_class_member_access_expr (tree object, tree member,
/* Convert to the base. */ /* Convert to the base. */
object = build_base_path (PLUS_EXPR, object, binfo, object = build_base_path (PLUS_EXPR, object, binfo,
/*nonnull=*/1); /*nonnull=*/1, complain);
/* If we found the base successfully then we should be able /* If we found the base successfully then we should be able
to convert to it successfully. */ to convert to it successfully. */
gcc_assert (object != error_mark_node); gcc_assert (object != error_mark_node);
...@@ -3073,7 +3073,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function) ...@@ -3073,7 +3073,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
basetype = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)), basetype = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)),
basetype, ba_check, NULL); basetype, ba_check, NULL);
instance_ptr = build_base_path (PLUS_EXPR, instance_ptr, basetype, instance_ptr = build_base_path (PLUS_EXPR, instance_ptr, basetype,
1); 1, tf_warning_or_error);
if (instance_ptr == error_mark_node) if (instance_ptr == error_mark_node)
return error_mark_node; return error_mark_node;
} }
...@@ -5772,7 +5772,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, ...@@ -5772,7 +5772,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
/* Convert from "B*" to "D*". This function will check that "B" /* Convert from "B*" to "D*". This function will check that "B"
is not a virtual base of "D". */ is not a virtual base of "D". */
expr = build_base_path (MINUS_EXPR, build_address (expr), expr = build_base_path (MINUS_EXPR, build_address (expr),
base, /*nonnull=*/false); base, /*nonnull=*/false, complain);
/* Convert the pointer to a reference -- but then remember that /* Convert the pointer to a reference -- but then remember that
there are no expressions with reference type in C++. there are no expressions with reference type in C++.
...@@ -5874,7 +5874,8 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, ...@@ -5874,7 +5874,8 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype), base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
c_cast_p ? ba_unique : ba_check, c_cast_p ? ba_unique : ba_check,
NULL); NULL);
expr = build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false); expr = build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false,
complain);
return cp_fold_convert(type, expr); return cp_fold_convert(type, expr);
} }
......
...@@ -1398,7 +1398,8 @@ build_scoped_ref (tree datum, tree basetype, tree* binfo_p) ...@@ -1398,7 +1398,8 @@ build_scoped_ref (tree datum, tree basetype, tree* binfo_p)
} }
*binfo_p = binfo; *binfo_p = binfo;
return build_base_path (PLUS_EXPR, datum, binfo, 1); return build_base_path (PLUS_EXPR, datum, binfo, 1,
tf_warning_or_error);
} }
/* Build a reference to an object specified by the C++ `->' operator. /* Build a reference to an object specified by the C++ `->' operator.
...@@ -1565,7 +1566,8 @@ build_m_component_ref (tree datum, tree component) ...@@ -1565,7 +1566,8 @@ build_m_component_ref (tree datum, tree component)
/* Convert object to the correct base. */ /* Convert object to the correct base. */
if (binfo) if (binfo)
datum = build_base_path (PLUS_EXPR, datum, binfo, 1); datum = build_base_path (PLUS_EXPR, datum, binfo, 1,
tf_warning_or_error);
/* Build an expression for "object + offset" where offset is the /* Build an expression for "object + offset" where offset is the
value stored in the pointer-to-data-member. */ value stored in the pointer-to-data-member. */
......
2011-09-24 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/44267
* g++.dg/template/sfinae28.C: New.
2011-09-23 Ian Lance Taylor <iant@google.com> 2011-09-23 Ian Lance Taylor <iant@google.com>
* go.test/go-test.exp (errchk): Handle more cases of getting * go.test/go-test.exp (errchk): Handle more cases of getting
......
// Origin: PR c++/44267
struct B {};
struct D : B {};
struct VD : virtual B {};
template <class T> T create();
typedef char one[1];
typedef char two[2];
template <class D, class B>
one& f(char (*)[sizeof(static_cast<D>(create<B>()))]);
template <class D, class B>
two& f(...);
int main()
{
f<D*, int>(0);
f<D*, B*>(0);
f<VD*, B*>(0);
return 0;
}
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