mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-02 08:40:26 +08:00
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
This commit is contained in:
parent
ee02baae96
commit
a271590a43
@ -1,3 +1,19 @@
|
||||
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);
|
||||
|
13
gcc/cp/cvt.c
13
gcc/cp/cvt.c
@ -1,7 +1,7 @@
|
||||
/* 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. */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* 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. */
|
||||
|
@ -1,3 +1,8 @@
|
||||
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
|
||||
|
24
gcc/testsuite/g++.dg/template/sfinae28.C
Normal file
24
gcc/testsuite/g++.dg/template/sfinae28.C
Normal file
@ -0,0 +1,24 @@
|
||||
// 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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user