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>
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)
converted_arg = build_base_path (PLUS_EXPR,
arg,
cand->conversion_path,
1);
1, complain);
/* Check that the base class is accessible. */
if (!accessible_base_p (TREE_TYPE (argtype),
BINFO_TYPE (cand->conversion_path), true))
......@@ -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)),
TREE_TYPE (parmtype), ba_unique, NULL);
converted_arg = build_base_path (PLUS_EXPR, converted_arg,
base_binfo, 1);
base_binfo, 1, complain);
argarray[j++] = converted_arg;
parm = TREE_CHAIN (parm);
......@@ -6706,7 +6706,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
if (TREE_DEPRECATED (fn))
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]))
argarray[0] = save_expr (argarray[0]);
t = build_pointer_type (TREE_TYPE (fn));
......@@ -6916,7 +6917,7 @@ build_special_member_call (tree instance, tree name, VEC(tree,gc) **args,
/* However, for assignment operators, we must convert
dynamically if the base is virtual. */
instance = build_base_path (PLUS_EXPR, instance,
binfo, /*nonnull=*/1);
binfo, /*nonnull=*/1, complain);
}
}
......
......@@ -235,7 +235,8 @@ tree
build_base_path (enum tree_code code,
tree expr,
tree binfo,
int nonnull)
int nonnull,
tsubst_flags_t complain)
{
tree v_binfo = NULL_TREE;
tree d_binfo = NULL_TREE;
......@@ -276,14 +277,16 @@ build_base_path (enum tree_code code,
if (code == MINUS_EXPR && 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));
if (complain & tf_error)
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;
}
if (!want_pointer)
/* 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
expr = mark_rvalue_use (expr);
......@@ -341,7 +344,7 @@ build_base_path (enum tree_code code,
interesting to the optimizers anyway. */
&& !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);
if (want_pointer)
expr = build_address (expr);
......@@ -366,19 +369,18 @@ build_base_path (enum tree_code code,
t = TREE_TYPE (TYPE_VFIELD (current_class_type));
t = build_pointer_type (t);
v_offset = convert (t, current_vtt_parm);
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);
}
else
v_offset = build_vfield_ref (cp_build_indirect_ref (expr, RO_NULL,
tf_warning_or_error),
complain),
TREE_TYPE (TREE_TYPE (expr)));
v_offset = fold_build_pointer_plus (v_offset, BINFO_VPTR_FIELD (v_binfo));
v_offset = build1 (NOP_EXPR,
build_pointer_type (ptrdiff_type_node),
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;
offset = convert_to_integer (ptrdiff_type_node,
......@@ -418,7 +420,7 @@ build_base_path (enum tree_code code,
null_test = NULL;
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:
if (null_test)
......@@ -523,7 +525,7 @@ convert_to_base (tree object, tree type, bool check_access, bool nonnull,
if (!binfo || binfo == 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
......
......@@ -4790,7 +4790,7 @@ extern void validate_conversion_obstack (void);
/* in class.c */
extern tree build_vfield_ref (tree, 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,
tsubst_flags_t);
extern tree convert_to_base_statically (tree, tree);
......
/* Language-level data type conversion for GNU C++.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
2011 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
......@@ -157,7 +157,8 @@ cp_convert_to_pointer (tree type, tree expr)
if (binfo || same_p)
{
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. */
return build_nop (type, expr);
}
......@@ -275,7 +276,8 @@ convert_to_pointer_force (tree type, tree expr)
return error_mark_node;
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)
return error_mark_node;
/* Add any qualifier conversions. */
......@@ -341,7 +343,8 @@ build_up_reference (tree type, tree arg, int flags, tree decl)
return error_mark_node;
if (binfo == NULL_TREE)
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
rval
......
......@@ -100,7 +100,8 @@ dfs_initialize_vtbl_ptrs (tree binfo, void *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);
}
......@@ -963,7 +964,7 @@ emit_mem_initializers (tree mem_inits)
tree base_addr;
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,
cp_build_indirect_ref (base_addr, RO_NULL,
tf_warning_or_error),
......
......@@ -516,7 +516,8 @@ do_build_copy_constructor (tree fndecl)
for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0;
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)
init = move (init);
member_init_list
......@@ -531,7 +532,8 @@ do_build_copy_constructor (tree fndecl)
if (BINFO_VIRTUAL_P (base_binfo))
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)
init = move (init);
member_init_list
......@@ -624,7 +626,8 @@ do_build_copy_assign (tree fndecl)
/* We must convert PARM directly to the base class
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)
converted_parm = move (converted_parm);
/* Call the base class assignment operator. */
......
/* RunTime Type Identification
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.
Mostly written by Jason Merrill (jason@cygnus.com).
......@@ -616,7 +616,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
if (binfo)
{
expr = build_base_path (PLUS_EXPR, convert_from_reference (expr),
binfo, 0);
binfo, 0, complain);
if (TREE_CODE (exprtype) == POINTER_TYPE)
expr = rvalue (expr);
return expr;
......
......@@ -2221,7 +2221,7 @@ build_class_member_access_expr (tree object, tree member,
/* Convert to the base. */
object = build_base_path (PLUS_EXPR, object, binfo,
/*nonnull=*/1);
/*nonnull=*/1, complain);
/* If we found the base successfully then we should be able
to convert to it successfully. */
gcc_assert (object != error_mark_node);
......@@ -3073,7 +3073,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function)
basetype = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)),
basetype, ba_check, NULL);
instance_ptr = build_base_path (PLUS_EXPR, instance_ptr, basetype,
1);
1, tf_warning_or_error);
if (instance_ptr == error_mark_node)
return error_mark_node;
}
......@@ -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"
is not a virtual base of "D". */
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
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,
base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
c_cast_p ? ba_unique : ba_check,
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);
}
......
......@@ -1398,7 +1398,8 @@ build_scoped_ref (tree datum, tree basetype, tree* binfo_p)
}
*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.
......@@ -1565,7 +1566,8 @@ build_m_component_ref (tree datum, tree component)
/* Convert object to the correct base. */
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
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>
* 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