From 798ec80703636f8572e33e10dbeb86f497490fbf Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 27 Apr 2010 15:04:09 -0400 Subject: [PATCH] re PR c++/41468 (SFINAE for expressions doesn't consider ambiguous conversion sequences) 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. From-SVN: r158798 --- gcc/cp/ChangeLog | 12 ++++++++++ gcc/cp/call.c | 8 +++---- gcc/cp/class.c | 11 +++++++--- gcc/cp/cp-tree.h | 3 ++- gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/template/sfinae17.C | 28 ++++++++++++++++++++++++ 6 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/sfinae17.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a996461cca0..d4b82a9a20a 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 90f84e020ae..a97f7dcea10 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 26da21b8c82..07dfb1ce561 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 a7ed134a52d..dd891715fc3 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 21d9e0d1756..ce7206a007c 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 00000000000..eb043cbddfb --- /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), ""); +}