File revert-pr25950.diff of Package gcc43
Index: gcc/cp/call.c
===================================================================
*** gcc/cp/call.c.orig 2007-11-27 14:27:45.000000000 +0100
--- gcc/cp/call.c 2007-11-28 11:57:06.000000000 +0100
*************** struct conversion {
*** 89,94 ****
--- 89,98 ----
temporary should be created to hold the result of the
conversion. */
BOOL_BITFIELD need_temporary_p : 1;
+ /* If KIND is ck_identity or ck_base_conv, true to indicate that the
+ copy constructor must be accessible, even though it is not being
+ used. */
+ BOOL_BITFIELD check_copy_constructor_p : 1;
/* If KIND is ck_ptr or ck_pmem, true to indicate that a conversion
from a pointer-to-derived to pointer-to-base is being performed. */
BOOL_BITFIELD base_p : 1;
*************** static conversion *merge_conversion_sequ
*** 197,202 ****
--- 201,207 ----
static bool magic_varargs_p (tree);
typedef void (*diagnostic_fn_t) (const char *, ...) ATTRIBUTE_GCC_CXXDIAG(1,2);
static tree build_temp (tree, tree, int, diagnostic_fn_t *);
+ static void check_constructor_callable (tree, tree);
/* Returns nonzero iff the destructor name specified in NAME matches BASETYPE.
NAME can take many forms... */
*************** standard_conversion (tree to, tree from,
*** 861,873 ****
else if (fcode == VECTOR_TYPE && tcode == VECTOR_TYPE
&& vector_types_convertible_p (from, to, false))
return build_conv (ck_std, to, conv);
! /* A derived-to-base conversion sequence is a user-defined conversion
! because it involves a constructor call, even though it has the rank of
! a standard conversion, so we don't consider it if we aren't allowing
! user-defined conversions. But if we're binding directly to a
! reference, it's only a pointer conversion. */
! else if ((!(flags & LOOKUP_NO_CONVERSION)
! || (flags & LOOKUP_NO_TEMP_BIND))
&& IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
&& is_properly_derived_from (from, to))
{
--- 866,872 ----
else if (fcode == VECTOR_TYPE && tcode == VECTOR_TYPE
&& vector_types_convertible_p (from, to, false))
return build_conv (ck_std, to, conv);
! else if (!(flags & LOOKUP_CONSTRUCTOR_CALLABLE)
&& IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
&& is_properly_derived_from (from, to))
{
*************** standard_conversion (tree to, tree from,
*** 877,884 ****
/* The derived-to-base conversion indicates the initialization
of a parameter with base type from an object of a derived
type. A temporary object is created to hold the result of
! the conversion unless we're binding directly to a reference. */
! conv->need_temporary_p = !(flags & LOOKUP_NO_TEMP_BIND);
}
else
return NULL;
--- 876,883 ----
/* The derived-to-base conversion indicates the initialization
of a parameter with base type from an object of a derived
type. A temporary object is created to hold the result of
! the conversion. */
! conv->need_temporary_p = true;
}
else
return NULL;
*************** reference_binding (tree rto, tree rfrom,
*** 1154,1165 ****
compatible_p = reference_compatible_p (to, from);
/* Directly bind reference when target expression's type is compatible with
! the reference and expression is an lvalue. In DR391, the wording in
! [8.5.3/5 dcl.init.ref] is changed to also require direct bindings for
! const and rvalue references to rvalues of compatible class type. */
if (compatible_p
&& (lvalue_p
! || ((CP_TYPE_CONST_NON_VOLATILE_P(to) || TYPE_REF_IS_RVALUE (rto))
&& CLASS_TYPE_P (from))))
{
/* [dcl.init.ref]
--- 1153,1166 ----
compatible_p = reference_compatible_p (to, from);
/* Directly bind reference when target expression's type is compatible with
! the reference and expression is an lvalue. In C++0x, the wording in
! [8.5.3/5 dcl.init.ref] is changed to also allow direct bindings for const
! and rvalue references to rvalues of compatible class type, as part of
! DR391. */
if (compatible_p
&& (lvalue_p
! || ((cxx_dialect != cxx98)
! && (CP_TYPE_CONST_NON_VOLATILE_P(to) || TYPE_REF_IS_RVALUE (rto))
&& CLASS_TYPE_P (from))))
{
/* [dcl.init.ref]
*************** reference_binding (tree rto, tree rfrom,
*** 1170,1183 ****
is reference-compatible with "cv2 T2,"
the reference is bound directly to the initializer expression
! lvalue.
!
! [...]
! If the initializer expression is an rvalue, with T2 a class type,
! and "cv1 T1" is reference-compatible with "cv2 T2", the reference
! is bound to the object represented by the rvalue or to a sub-object
! within that object. */
!
conv = build_identity_conv (from, expr);
conv = direct_reference_binding (rto, conv);
--- 1171,1177 ----
is reference-compatible with "cv2 T2,"
the reference is bound directly to the initializer expression
! lvalue. */
conv = build_identity_conv (from, expr);
conv = direct_reference_binding (rto, conv);
*************** reference_binding (tree rto, tree rfrom,
*** 1257,1262 ****
--- 1251,1282 ----
/* [dcl.init.ref]
+ If the initializer expression is an rvalue, with T2 a class type,
+ and "cv1 T1" is reference-compatible with "cv2 T2", the reference
+ is bound in one of the following ways:
+
+ -- The reference is bound to the object represented by the rvalue
+ or to a sub-object within that object.
+
+ -- ...
+
+ We use the first alternative. The implicit conversion sequence
+ is supposed to be same as we would obtain by generating a
+ temporary. Fortunately, if the types are reference compatible,
+ then this is either an identity conversion or the derived-to-base
+ conversion, just as for direct binding. */
+ if (CLASS_TYPE_P (from) && compatible_p)
+ {
+ conv = build_identity_conv (from, expr);
+ conv = direct_reference_binding (rto, conv);
+ conv->rvaluedness_matches_p = TYPE_REF_IS_RVALUE (rto);
+ if (!(flags & LOOKUP_CONSTRUCTOR_CALLABLE))
+ conv->u.next->check_copy_constructor_p = true;
+ return conv;
+ }
+
+ /* [dcl.init.ref]
+
Otherwise, a temporary of type "cv1 T1" is created and
initialized from the initializer expression using the rules for a
non-reference copy initialization. If T1 is reference-related to
*************** reference_binding (tree rto, tree rfrom,
*** 1265,1275 ****
if (related_p && !at_least_as_qualified_p (to, from))
return NULL;
- /* We're generating a temporary now, but don't bind any more in the
- conversion (specifically, don't slice the temporary returned by a
- conversion operator). */
- flags |= LOOKUP_NO_TEMP_BIND;
-
conv = implicit_conversion (to, from, expr, c_cast_p,
flags);
if (!conv)
--- 1285,1290 ----
*************** implicit_conversion (tree to, tree from,
*** 1314,1323 ****
&& (flags & LOOKUP_NO_CONVERSION) == 0)
{
struct z_candidate *cand;
- int convflags = ((flags & LOOKUP_NO_TEMP_BIND)
- |LOOKUP_ONLYCONVERTING);
! cand = build_user_type_conversion_1 (to, expr, convflags);
if (cand)
conv = cand->second_conv;
--- 1329,1337 ----
&& (flags & LOOKUP_NO_CONVERSION) == 0)
{
struct z_candidate *cand;
! cand = build_user_type_conversion_1
! (to, expr, LOOKUP_ONLYCONVERTING);
if (cand)
conv = cand->second_conv;
*************** build_user_type_conversion_1 (tree totyp
*** 2576,2582 ****
conversion *conv = NULL;
tree args = NULL_TREE;
bool any_viable_p;
- int convflags;
/* We represent conversion within a hierarchy using RVALUE_CONV and
BASE_CONV, as specified by [over.best.ics]; these become plain
--- 2590,2595 ----
*************** build_user_type_conversion_1 (tree totyp
*** 2607,2617 ****
candidates = 0;
flags |= LOOKUP_NO_CONVERSION;
- /* It's OK to bind a temporary for converting constructor arguments, but
- not in converting the return value of a conversion operator. */
- convflags = ((flags & LOOKUP_NO_TEMP_BIND) | LOOKUP_NO_CONVERSION);
- flags &= ~LOOKUP_NO_TEMP_BIND;
-
if (ctors)
{
tree t;
--- 2620,2625 ----
*************** build_user_type_conversion_1 (tree totyp
*** 2656,2661 ****
--- 2664,2670 ----
{
tree fns;
tree conversion_path = TREE_PURPOSE (conv_fns);
+ int convflags = LOOKUP_NO_CONVERSION;
/* If we are called to convert to a reference type, we are trying to
find an lvalue binding, so don't even consider temporaries. If
*************** enforce_access (tree basetype_path, tree
*** 4264,4269 ****
--- 4273,4293 ----
return true;
}
+ /* Check that a callable constructor to initialize a temporary of
+ TYPE from an EXPR exists. */
+
+ static void
+ check_constructor_callable (tree type, tree expr)
+ {
+ build_special_member_call (NULL_TREE,
+ complete_ctor_identifier,
+ build_tree_list (NULL_TREE, expr),
+ type,
+ LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING
+ | LOOKUP_NO_CONVERSION
+ | LOOKUP_CONSTRUCTOR_CALLABLE);
+ }
+
/* Initialize a temporary of type TYPE with EXPR. The FLAGS are a
bitwise or of LOOKUP_* values. If any errors are warnings are
generated, set *DIAGNOSTIC_FN to "error" or "warning",
*************** convert_like_real (conversion *convs, tr
*** 4422,4427 ****
--- 4446,4453 ----
if (inner >= 0)
{
expr = decl_constant_value (expr);
+ if (convs->check_copy_constructor_p)
+ check_constructor_callable (totype, expr);
if (expr == null_node && INTEGRAL_TYPE_P (totype))
/* If __null has been converted to an integer type, we do not
want to warn about uses of EXPR as an integer, rather than
*************** convert_like_real (conversion *convs, tr
*** 4457,4462 ****
--- 4483,4490 ----
{
/* We are going to bind a reference directly to a base-class
subobject of EXPR. */
+ if (convs->check_copy_constructor_p)
+ check_constructor_callable (TREE_TYPE (expr), expr);
/* Build an expression for `*((base*) &expr)'. */
expr = build_unary_op (ADDR_EXPR, expr, 0);
expr = convert_to_base (expr, build_pointer_type (totype),
*************** initialize_reference (tree type, tree ex
*** 6800,6805 ****
--- 6828,6835 ----
remember that the conversion was required. */
if (conv->kind == ck_base)
{
+ if (conv->check_copy_constructor_p)
+ check_constructor_callable (TREE_TYPE (expr), expr);
base_conv_type = conv->type;
conv = conv->u.next;
}
Index: gcc/cp/cp-tree.h
===================================================================
*** gcc/cp/cp-tree.h.orig 2007-11-19 11:36:02.000000000 +0100
--- gcc/cp/cp-tree.h 2007-11-28 11:53:41.000000000 +0100
*************** enum overload_flags { NO_SPECIAL = 0, DT
*** 3698,3707 ****
#define LOOKUP_PREFER_NAMESPACES (1 << 9)
/* Accept types or namespaces. */
#define LOOKUP_PREFER_BOTH (LOOKUP_PREFER_TYPES | LOOKUP_PREFER_NAMESPACES)
/* Return friend declarations and un-declared builtin functions.
(Normally, these entities are registered in the symbol table, but
not found by lookup.) */
! #define LOOKUP_HIDDEN (LOOKUP_PREFER_NAMESPACES << 1)
/* Prefer that the lvalue be treated as an rvalue. */
#define LOOKUP_PREFER_RVALUE (LOOKUP_HIDDEN << 1)
--- 3698,3710 ----
#define LOOKUP_PREFER_NAMESPACES (1 << 9)
/* Accept types or namespaces. */
#define LOOKUP_PREFER_BOTH (LOOKUP_PREFER_TYPES | LOOKUP_PREFER_NAMESPACES)
+ /* We are checking that a constructor can be called -- but we do not
+ actually plan to call it. */
+ #define LOOKUP_CONSTRUCTOR_CALLABLE (1 << 10)
/* Return friend declarations and un-declared builtin functions.
(Normally, these entities are registered in the symbol table, but
not found by lookup.) */
! #define LOOKUP_HIDDEN (LOOKUP_CONSTRUCTOR_CALLABLE << 1)
/* Prefer that the lvalue be treated as an rvalue. */
#define LOOKUP_PREFER_RVALUE (LOOKUP_HIDDEN << 1)