From: jason Date: Tue, 27 Apr 2010 19:04:09 +0000 (+0000) Subject: PR c++/41468 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=640a46a5c7038d1d97009cd1d4106ed24281985b;p=thirdparty%2Fgcc.git PR c++/41468 * class.c (convert_to_base): Add complain parameter. Pass ba_quiet to lookup_base if we don't want errors. (build_vfield_ref): Pass complain to convert_to_base. * call.c (convert_like_real): Likewise. (initialize_reference): Likewise. (perform_direct_initialization_if_possible): Pass complain to convert_like_real. * cp-tree.h: Adjust. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@158798 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a996461cca0c..d4b82a9a20ac 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2010-04-27 Jason Merrill + + PR c++/41468 + * class.c (convert_to_base): Add complain parameter. Pass + ba_quiet to lookup_base if we don't want errors. + (build_vfield_ref): Pass complain to convert_to_base. + * call.c (convert_like_real): Likewise. + (initialize_reference): Likewise. + (perform_direct_initialization_if_possible): Pass complain to + convert_like_real. + * cp-tree.h: Adjust. + 2010-04-27 Fabien Chêne Jason Merrill diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 90f84e020ae9..a97f7dcea108 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5019,7 +5019,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, /* Build an expression for `*((base*) &expr)'. */ expr = cp_build_unary_op (ADDR_EXPR, expr, 0, complain); expr = convert_to_base (expr, build_pointer_type (totype), - !c_cast_p, /*nonnull=*/true); + !c_cast_p, /*nonnull=*/true, complain); expr = cp_build_indirect_ref (expr, RO_IMPLICIT_CONVERSION, complain); return expr; } @@ -5142,7 +5142,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, case ck_ptr: if (convs->base_p) expr = convert_to_base (expr, totype, !c_cast_p, - /*nonnull=*/false); + /*nonnull=*/false, complain); return build_nop (totype, expr); case ck_pmem: @@ -7584,7 +7584,7 @@ perform_direct_initialization_if_possible (tree type, expr = convert_like_real (conv, expr, NULL_TREE, 0, 0, /*issue_conversion_warnings=*/false, c_cast_p, - tf_warning_or_error); + complain); /* Free all the conversions we allocated. */ obstack_free (&conversion_obstack, p); @@ -7810,7 +7810,7 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup, expr = convert_to_base (expr, build_pointer_type (base_conv_type), /*check_access=*/true, - /*nonnull=*/true); + /*nonnull=*/true, complain); expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), init, expr); } else diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 26da21b8c825..07dfb1ce561e 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -506,10 +506,12 @@ build_simple_base_path (tree expr, tree binfo) assumed to be non-NULL. */ tree -convert_to_base (tree object, tree type, bool check_access, bool nonnull) +convert_to_base (tree object, tree type, bool check_access, bool nonnull, + tsubst_flags_t complain) { tree binfo; tree object_type; + base_access access; if (TYPE_PTR_P (TREE_TYPE (object))) { @@ -519,8 +521,11 @@ convert_to_base (tree object, tree type, bool check_access, bool nonnull) else object_type = TREE_TYPE (object); + access = check_access ? ba_check : ba_unique; + if (!(complain & tf_error)) + access |= ba_quiet; binfo = lookup_base (object_type, type, - check_access ? ba_check : ba_unique, + access, NULL); if (!binfo || binfo == error_mark_node) return error_mark_node; @@ -575,7 +580,7 @@ build_vfield_ref (tree datum, tree type) /* First, convert to the requested type. */ if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (datum), type)) datum = convert_to_base (datum, type, /*check_access=*/false, - /*nonnull=*/true); + /*nonnull=*/true, tf_warning_or_error); /* Second, the requested type may not be the owner of its own vptr. If not, convert to the base class that owns it. We cannot use diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index a7ed134a52d4..dd891715fc33 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4569,7 +4569,8 @@ extern void validate_conversion_obstack (void); extern tree build_vfield_ref (tree, tree); extern tree build_base_path (enum tree_code, tree, tree, int); -extern tree convert_to_base (tree, tree, bool, bool); +extern tree convert_to_base (tree, tree, bool, bool, + tsubst_flags_t); extern tree convert_to_base_statically (tree, tree); extern tree build_vtbl_ref (tree, tree); extern tree build_vfn_ref (tree, tree); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 21d9e0d17565..ce7206a007c9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-04-27 Jason Merrill + + PR c++/41468 + * g++.dg/template/sfinae17.C: New. + 2010-04-27 Fabien Chêne * g++.dg/init/pr42844.C: New. diff --git a/gcc/testsuite/g++.dg/template/sfinae17.C b/gcc/testsuite/g++.dg/template/sfinae17.C new file mode 100644 index 000000000000..eb043cbddfbe --- /dev/null +++ b/gcc/testsuite/g++.dg/template/sfinae17.C @@ -0,0 +1,28 @@ +// The conversion from D* to B* is ambiguous, but that should not produce +// an error, it should remove the first f overload by SFINAE. + +#define static_assert(TEST,STR) \ + do { int ar[(TEST)?1:-1]; } while (0); + +struct B {}; + +struct B1 : B {}; +struct B2 : B {}; + +struct D : B1, B2 {}; + +template T create(); + +typedef char one[1]; +typedef char two[2]; + +template + one &f(char (*)[sizeof static_cast(create())]); +template + two &f(...); + +int main() +{ + static_assert(sizeof f(0) == sizeof(two), ""); + static_assert(sizeof f(0) == sizeof(two), ""); +}