aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-04-27 15:04:09 -0400
committerJason Merrill <jason@gcc.gnu.org>2010-04-27 15:04:09 -0400
commit798ec80703636f8572e33e10dbeb86f497490fbf (patch)
tree48971fe479cf9c97700e306634a2abedadc66ebd /gcc
parent6ad86a5b264dcf68f9eee93da90af06d15d91e4a (diff)
downloadgcc-798ec80703636f8572e33e10dbeb86f497490fbf.zip
gcc-798ec80703636f8572e33e10dbeb86f497490fbf.tar.gz
gcc-798ec80703636f8572e33e10dbeb86f497490fbf.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/call.c8
-rw-r--r--gcc/cp/class.c11
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae17.C28
6 files changed, 59 insertions, 8 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a996461..d4b82a9 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,15 @@
+2010-04-27 Jason Merrill <jason@redhat.com>
+
+ 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 <fabien.chene@gmail.com>
Jason Merrill <jason@redhat.com>
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 90f84e0..a97f7dc 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 26da21b..07dfb1c 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 a7ed134..dd89171 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 21d9e0d..ce7206a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2010-04-27 Jason Merrill <jason@redhat.com>
+
+ PR c++/41468
+ * g++.dg/template/sfinae17.C: New.
+
2010-04-27 Fabien ChĂȘne <fabien.chene@gmail.com>
* 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 0000000..eb043cb
--- /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 <class T> T create();
+
+typedef char one[1];
+typedef char two[2];
+
+template <class T>
+ one &f(char (*)[sizeof static_cast<T>(create<D *>())]);
+template <class T>
+ two &f(...);
+
+int main()
+{
+ static_assert(sizeof f<int>(0) == sizeof(two), "");
+ static_assert(sizeof f<B *>(0) == sizeof(two), "");
+}