aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog16
-rw-r--r--gcc/cp/call.c9
-rw-r--r--gcc/cp/class.c24
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/cvt.c13
-rw-r--r--gcc/cp/init.c5
-rw-r--r--gcc/cp/method.c9
-rw-r--r--gcc/cp/rtti.c4
-rw-r--r--gcc/cp/typeck.c9
-rw-r--r--gcc/cp/typeck2.c6
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae28.C24
12 files changed, 92 insertions, 34 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6754977..7600017 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index b616cff..8c99f7a 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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);
}
}
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 1887526..acfe3f2 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 573c166..f2c9211 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 8a23d51..3e618d3 100644
--- a/gcc/cp/cvt.c
+++ b/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
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 68d4e68..ac3221e 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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),
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 757e711..88bb2a9 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -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. */
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 434b772..818b8d0 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -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;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index ed52f3c..955e37a 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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);
}
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 1c0bb38..96b95c2 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -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. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4f0cebc..c5175fa 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/g++.dg/template/sfinae28.C b/gcc/testsuite/g++.dg/template/sfinae28.C
new file mode 100644
index 0000000..1bd9c2c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/sfinae28.C
@@ -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;
+}