mirror of git://gcc.gnu.org/git/gcc.git
Implement explicit conversions ops as specified in N2437.
* decl.c (grokdeclarator): Handle explicit conversion ops. (check_initializer): Pass flags to store_init_value. * decl2.c (maybe_emit_vtables): Likewise. * init.c (expand_aggr_init_1): Likewise. * call.c (convert_class_to_reference): Take flags parm, check DECL_NONCONVERTING_P. (build_user_type_conversion_1): Check DECL_NONCONVERTING_P. (add_builtin_candidates): Simplify getting type of conversion. (build_object_call): Likewise. Check DECL_NONCONVERTING_P. (implicit_conversion): Pass through LOOKUP_ONLYCONVERTING. (reference_binding): Take flags parm. Direct-initialize copy parm. (add_function_candidate): Direct-initialize the copy parm. (add_conv_candidate): Use LOOKUP_IMPLICIT, not LOOKUP_NORMAL. (build_builtin_candidate): Add LOOKUP_ONLYCONVERTING. (conditional_conversion): Likewise. (convert_like_real): Only complain about DECL_NONCONVERTING_P constructors. (perform_implicit_conversion_flags): Add flags parm to perform_implicit_conversion. Improve diagnostics. * cp-tree.h (LOOKUP_IMPLICIT): New macro. (LOOKUP_COPY_PARM): New bit macro. * cvt.c (build_expr_type_conversion): Check DECL_NONCONVERTING_P. * typeck.c (convert_for_assignment): Take flags parm, pass it to perform_implicit_conversion_flags. (cp_build_modify_expr): Pass flags to convert_for_assignment. (convert_for_initialization): Likewise. * typeck2.c (store_init_value): Take flags parm, pass to digest_init_flags. (digest_init_flags): Add flags parm to digest_init. (digest_init_r): Take flags parm, pass to convert_for_initialization. (process_init_constructor_array): Pass it. (process_init_constructor_record): Likewise. (process_init_constructor_union): Likewise. From-SVN: r147677
This commit is contained in:
parent
82725547db
commit
e57d93c6bc
|
@ -1,3 +1,40 @@
|
|||
2009-05-18 Jason Merrill <jason@redhat.com>
|
||||
|
||||
Implement explicit conversions ops as specified in N2437.
|
||||
* decl.c (grokdeclarator): Handle explicit conversion ops.
|
||||
(check_initializer): Pass flags to store_init_value.
|
||||
* decl2.c (maybe_emit_vtables): Likewise.
|
||||
* init.c (expand_aggr_init_1): Likewise.
|
||||
* call.c (convert_class_to_reference): Take flags parm,
|
||||
check DECL_NONCONVERTING_P.
|
||||
(build_user_type_conversion_1): Check DECL_NONCONVERTING_P.
|
||||
(add_builtin_candidates): Simplify getting type of conversion.
|
||||
(build_object_call): Likewise. Check DECL_NONCONVERTING_P.
|
||||
(implicit_conversion): Pass through LOOKUP_ONLYCONVERTING.
|
||||
(reference_binding): Take flags parm. Direct-initialize copy parm.
|
||||
(add_function_candidate): Direct-initialize the copy parm.
|
||||
(add_conv_candidate): Use LOOKUP_IMPLICIT, not LOOKUP_NORMAL.
|
||||
(build_builtin_candidate): Add LOOKUP_ONLYCONVERTING.
|
||||
(conditional_conversion): Likewise.
|
||||
(convert_like_real): Only complain about DECL_NONCONVERTING_P
|
||||
constructors.
|
||||
(perform_implicit_conversion_flags): Add flags parm to
|
||||
perform_implicit_conversion. Improve diagnostics.
|
||||
* cp-tree.h (LOOKUP_IMPLICIT): New macro.
|
||||
(LOOKUP_COPY_PARM): New bit macro.
|
||||
* cvt.c (build_expr_type_conversion): Check DECL_NONCONVERTING_P.
|
||||
* typeck.c (convert_for_assignment): Take flags parm, pass it to
|
||||
perform_implicit_conversion_flags.
|
||||
(cp_build_modify_expr): Pass flags to convert_for_assignment.
|
||||
(convert_for_initialization): Likewise.
|
||||
* typeck2.c (store_init_value): Take flags parm, pass to
|
||||
digest_init_flags.
|
||||
(digest_init_flags): Add flags parm to digest_init.
|
||||
(digest_init_r): Take flags parm, pass to convert_for_initialization.
|
||||
(process_init_constructor_array): Pass it.
|
||||
(process_init_constructor_record): Likewise.
|
||||
(process_init_constructor_union): Likewise.
|
||||
|
||||
2009-05-16 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/40139
|
||||
|
|
|
@ -190,7 +190,7 @@ static tree source_type (conversion *);
|
|||
static void add_warning (struct z_candidate *, struct z_candidate *);
|
||||
static bool reference_related_p (tree, tree);
|
||||
static bool reference_compatible_p (tree, tree);
|
||||
static conversion *convert_class_to_reference (tree, tree, tree);
|
||||
static conversion *convert_class_to_reference (tree, tree, tree, int);
|
||||
static conversion *direct_reference_binding (tree, conversion *);
|
||||
static bool promoted_arithmetic_type_p (tree);
|
||||
static conversion *conditional_conversion (tree, tree);
|
||||
|
@ -993,7 +993,7 @@ reference_compatible_p (tree t1, tree t2)
|
|||
converted to T as in [over.match.ref]. */
|
||||
|
||||
static conversion *
|
||||
convert_class_to_reference (tree reference_type, tree s, tree expr)
|
||||
convert_class_to_reference (tree reference_type, tree s, tree expr, int flags)
|
||||
{
|
||||
tree conversions;
|
||||
tree arglist;
|
||||
|
@ -1034,7 +1034,7 @@ convert_class_to_reference (tree reference_type, tree s, tree expr)
|
|||
|
||||
t = TREE_TYPE (reference_type);
|
||||
|
||||
while (conversions)
|
||||
for (; conversions; conversions = TREE_CHAIN (conversions))
|
||||
{
|
||||
tree fns = TREE_VALUE (conversions);
|
||||
|
||||
|
@ -1043,6 +1043,10 @@ convert_class_to_reference (tree reference_type, tree s, tree expr)
|
|||
tree f = OVL_CURRENT (fns);
|
||||
tree t2 = TREE_TYPE (TREE_TYPE (f));
|
||||
|
||||
if (DECL_NONCONVERTING_P (f)
|
||||
&& (flags & LOOKUP_ONLYCONVERTING))
|
||||
continue;
|
||||
|
||||
cand = NULL;
|
||||
|
||||
/* If this is a template function, try to get an exact
|
||||
|
@ -1101,7 +1105,6 @@ convert_class_to_reference (tree reference_type, tree s, tree expr)
|
|||
cand->second_conv->bad_p |= cand->convs[0]->bad_p;
|
||||
}
|
||||
}
|
||||
conversions = TREE_CHAIN (conversions);
|
||||
}
|
||||
|
||||
candidates = splice_viable (candidates, pedantic, &any_viable_p);
|
||||
|
@ -1303,7 +1306,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
|
|||
|
||||
the reference is bound to the lvalue result of the conversion
|
||||
in the second case. */
|
||||
conv = convert_class_to_reference (rto, from, expr);
|
||||
conv = convert_class_to_reference (rto, from, expr, flags);
|
||||
if (conv)
|
||||
return conv;
|
||||
}
|
||||
|
@ -1347,6 +1350,12 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
|
|||
conversion operator). */
|
||||
flags |= LOOKUP_NO_TEMP_BIND;
|
||||
|
||||
/* Temporaries are copy-initialized, except for this hack to allow
|
||||
explicit conversion ops to the copy ctor. See also
|
||||
add_function_candidate. */
|
||||
if (!(flags & LOOKUP_COPY_PARM))
|
||||
flags |= LOOKUP_ONLYCONVERTING;
|
||||
|
||||
conv = implicit_conversion (to, from, expr, c_cast_p,
|
||||
flags);
|
||||
if (!conv)
|
||||
|
@ -1394,8 +1403,7 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p,
|
|||
&& (flags & LOOKUP_NO_CONVERSION) == 0)
|
||||
{
|
||||
struct z_candidate *cand;
|
||||
int convflags = ((flags & LOOKUP_NO_TEMP_BIND)
|
||||
|LOOKUP_ONLYCONVERTING);
|
||||
int convflags = (flags & (LOOKUP_NO_TEMP_BIND|LOOKUP_ONLYCONVERTING));
|
||||
|
||||
if (CLASS_TYPE_P (to)
|
||||
&& !CLASSTYPE_NON_AGGREGATE (complete_type (to))
|
||||
|
@ -1547,9 +1555,17 @@ add_function_candidate (struct z_candidate **candidates,
|
|||
parmtype = build_pointer_type (parmtype);
|
||||
}
|
||||
|
||||
if ((flags & LOOKUP_NO_COPY_CTOR_CONVERSION)
|
||||
&& ctype && i == 0 && DECL_COPY_CONSTRUCTOR_P (fn))
|
||||
lflags |= LOOKUP_NO_CONVERSION;
|
||||
if (ctype && i == 0 && DECL_COPY_CONSTRUCTOR_P (fn))
|
||||
{
|
||||
/* Hack: Direct-initialize copy parm (i.e. suppress
|
||||
LOOKUP_ONLYCONVERTING) to make explicit conversion ops
|
||||
work. See also reference_binding. */
|
||||
lflags |= LOOKUP_COPY_PARM;
|
||||
if (flags & LOOKUP_NO_COPY_CTOR_CONVERSION)
|
||||
lflags |= LOOKUP_NO_CONVERSION;
|
||||
}
|
||||
else
|
||||
lflags |= LOOKUP_ONLYCONVERTING;
|
||||
|
||||
t = implicit_conversion (parmtype, argtype, arg,
|
||||
/*c_cast_p=*/false, lflags);
|
||||
|
@ -1612,7 +1628,7 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
|
|||
parmnode = parmlist;
|
||||
argnode = arglist;
|
||||
viable = 1;
|
||||
flags = LOOKUP_NORMAL;
|
||||
flags = LOOKUP_IMPLICIT;
|
||||
|
||||
/* Don't bother looking up the same type twice. */
|
||||
if (*candidates && (*candidates)->fn == totype)
|
||||
|
@ -1679,6 +1695,7 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname,
|
|||
|
||||
num_convs = args[2] ? 3 : (args[1] ? 2 : 1);
|
||||
convs = alloc_conversions (num_convs);
|
||||
flags |= LOOKUP_ONLYCONVERTING;
|
||||
|
||||
for (i = 0; i < 2; ++i)
|
||||
{
|
||||
|
@ -2268,7 +2285,7 @@ add_builtin_candidates (struct z_candidate **candidates, enum tree_code code,
|
|||
|
||||
for (; convs; convs = TREE_CHAIN (convs))
|
||||
{
|
||||
type = TREE_TYPE (TREE_TYPE (OVL_CURRENT (TREE_VALUE (convs))));
|
||||
type = TREE_TYPE (convs);
|
||||
|
||||
if (i == 0 && ref1
|
||||
&& (TREE_CODE (type) != REFERENCE_TYPE
|
||||
|
@ -2785,6 +2802,10 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
|
|||
{
|
||||
tree fn = OVL_CURRENT (fns);
|
||||
|
||||
if (DECL_NONCONVERTING_P (fn)
|
||||
&& (flags & LOOKUP_ONLYCONVERTING))
|
||||
continue;
|
||||
|
||||
/* [over.match.funcs] For conversion functions, the function
|
||||
is considered to be a member of the class of the implicit
|
||||
object argument for the purpose of defining the type of
|
||||
|
@ -3214,7 +3235,7 @@ build_object_call (tree obj, tree args, tsubst_flags_t complain)
|
|||
for (; convs; convs = TREE_CHAIN (convs))
|
||||
{
|
||||
tree fns = TREE_VALUE (convs);
|
||||
tree totype = TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns)));
|
||||
tree totype = TREE_TYPE (convs);
|
||||
|
||||
if ((TREE_CODE (totype) == POINTER_TYPE
|
||||
&& TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
|
||||
|
@ -3226,6 +3247,10 @@ build_object_call (tree obj, tree args, tsubst_flags_t complain)
|
|||
for (; fns; fns = OVL_NEXT (fns))
|
||||
{
|
||||
tree fn = OVL_CURRENT (fns);
|
||||
|
||||
if (DECL_NONCONVERTING_P (fn))
|
||||
continue;
|
||||
|
||||
if (TREE_CODE (fn) == TEMPLATE_DECL)
|
||||
add_template_conv_candidate
|
||||
(&candidates, fn, obj, args, totype,
|
||||
|
@ -3348,7 +3373,7 @@ conditional_conversion (tree e1, tree e2)
|
|||
t1,
|
||||
e1,
|
||||
/*c_cast_p=*/false,
|
||||
LOOKUP_NO_TEMP_BIND);
|
||||
LOOKUP_NO_TEMP_BIND|LOOKUP_ONLYCONVERTING);
|
||||
if (conv)
|
||||
return conv;
|
||||
}
|
||||
|
@ -3386,7 +3411,7 @@ conditional_conversion (tree e1, tree e2)
|
|||
converted to the type that expression E2 would have if E2 were
|
||||
converted to an rvalue (or the type it has, if E2 is an rvalue). */
|
||||
return implicit_conversion (t2, t1, e1, /*c_cast_p=*/false,
|
||||
LOOKUP_NORMAL);
|
||||
LOOKUP_IMPLICIT);
|
||||
}
|
||||
|
||||
/* Implement [expr.cond]. ARG1, ARG2, and ARG3 are the three
|
||||
|
@ -4584,7 +4609,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
|
|||
|
||||
/* When converting from an init list we consider explicit
|
||||
constructors, but actually trying to call one is an error. */
|
||||
if (DECL_NONCONVERTING_P (convfn))
|
||||
if (DECL_NONCONVERTING_P (convfn) && DECL_CONSTRUCTOR_P (convfn))
|
||||
{
|
||||
if (complain & tf_error)
|
||||
error ("converting to %qT from initializer list would use "
|
||||
|
@ -7025,7 +7050,7 @@ can_convert_arg_bad (tree to, tree from, tree arg)
|
|||
doing a bad conversion, convert_like will complain. */
|
||||
|
||||
tree
|
||||
perform_implicit_conversion (tree type, tree expr, tsubst_flags_t complain)
|
||||
perform_implicit_conversion_flags (tree type, tree expr, tsubst_flags_t complain, int flags)
|
||||
{
|
||||
conversion *conv;
|
||||
void *p;
|
||||
|
@ -7038,11 +7063,21 @@ perform_implicit_conversion (tree type, tree expr, tsubst_flags_t complain)
|
|||
|
||||
conv = implicit_conversion (type, TREE_TYPE (expr), expr,
|
||||
/*c_cast_p=*/false,
|
||||
LOOKUP_NORMAL);
|
||||
flags);
|
||||
|
||||
if (!conv)
|
||||
{
|
||||
if (complain & tf_error)
|
||||
error ("could not convert %qE to %qT", expr, type);
|
||||
{
|
||||
/* If expr has unknown type, then it is an overloaded function.
|
||||
Call instantiate_type to get good error messages. */
|
||||
if (TREE_TYPE (expr) == unknown_type_node)
|
||||
instantiate_type (type, expr, complain);
|
||||
else if (invalid_nonstatic_memfn_p (expr, complain))
|
||||
/* We gave an error. */;
|
||||
else
|
||||
error ("could not convert %qE to %qT", expr, type);
|
||||
}
|
||||
expr = error_mark_node;
|
||||
}
|
||||
else if (processing_template_decl)
|
||||
|
@ -7062,6 +7097,12 @@ perform_implicit_conversion (tree type, tree expr, tsubst_flags_t complain)
|
|||
return expr;
|
||||
}
|
||||
|
||||
tree
|
||||
perform_implicit_conversion (tree type, tree expr, tsubst_flags_t complain)
|
||||
{
|
||||
return perform_implicit_conversion_flags (type, expr, complain, LOOKUP_IMPLICIT);
|
||||
}
|
||||
|
||||
/* Convert EXPR to TYPE (as a direct-initialization) if that is
|
||||
permitted. If the conversion is valid, the converted expression is
|
||||
returned. Otherwise, NULL_TREE is returned, except in the case
|
||||
|
|
|
@ -1963,8 +1963,8 @@ struct GTY(()) lang_decl {
|
|||
is mutable. */
|
||||
#define DECL_MUTABLE_P(NODE) (DECL_LANG_FLAG_0 (NODE))
|
||||
|
||||
/* Nonzero for _DECL means that this constructor is a non-converting
|
||||
constructor. */
|
||||
/* Nonzero for _DECL means that this constructor or conversion function is
|
||||
non-converting. */
|
||||
#define DECL_NONCONVERTING_P(NODE) \
|
||||
(DECL_LANG_SPECIFIC (NODE)->decl_flags.nonconverting)
|
||||
|
||||
|
@ -3758,8 +3758,10 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
|
|||
/* Even if the function found by lookup is a virtual function, it
|
||||
should be called directly. */
|
||||
#define LOOKUP_NONVIRTUAL (1 << 2)
|
||||
/* Non-converting (i.e., "explicit") constructors are not tried. */
|
||||
/* Non-converting (i.e., "explicit") constructors are not tried. This flag
|
||||
indicates that we are not performing direct-initialization. */
|
||||
#define LOOKUP_ONLYCONVERTING (1 << 3)
|
||||
#define LOOKUP_IMPLICIT (LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING)
|
||||
/* If a temporary is created, it should be created so that it lives
|
||||
as long as the current variable bindings; otherwise it only lives
|
||||
until the end of the complete-expression. It also forces
|
||||
|
@ -3793,6 +3795,8 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
|
|||
/* Avoid user-defined conversions for the first parameter of a copy
|
||||
constructor. */
|
||||
#define LOOKUP_NO_COPY_CTOR_CONVERSION (LOOKUP_NO_NARROWING << 1)
|
||||
/* This is the first parameter of a copy constructor. */
|
||||
#define LOOKUP_COPY_PARM (LOOKUP_NO_COPY_CTOR_CONVERSION << 1)
|
||||
|
||||
#define LOOKUP_NAMESPACES_ONLY(F) \
|
||||
(((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES))
|
||||
|
@ -4200,6 +4204,7 @@ extern tree initialize_reference (tree, tree, tree, tree *);
|
|||
extern tree make_temporary_var_for_ref_to_temp (tree, tree);
|
||||
extern tree strip_top_quals (tree);
|
||||
extern tree perform_implicit_conversion (tree, tree, tsubst_flags_t);
|
||||
extern tree perform_implicit_conversion_flags (tree, tree, tsubst_flags_t, int);
|
||||
extern tree perform_direct_initialization_if_possible (tree, tree, bool,
|
||||
tsubst_flags_t);
|
||||
extern tree in_charge_arg_for_name (tree);
|
||||
|
@ -5001,9 +5006,10 @@ extern void readonly_error (tree, const char *);
|
|||
extern void complete_type_check_abstract (tree);
|
||||
extern int abstract_virtuals_error (tree, tree);
|
||||
|
||||
extern tree store_init_value (tree, tree);
|
||||
extern tree store_init_value (tree, tree, int);
|
||||
extern void check_narrowing (tree, tree);
|
||||
extern tree digest_init (tree, tree);
|
||||
extern tree digest_init_flags (tree, tree, int);
|
||||
extern tree build_scoped_ref (tree, tree, tree *);
|
||||
extern tree build_x_arrow (tree);
|
||||
extern tree build_m_component_ref (tree, tree);
|
||||
|
|
|
@ -1181,6 +1181,9 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
|
|||
if (winner && winner == cand)
|
||||
continue;
|
||||
|
||||
if (DECL_NONCONVERTING_P (cand))
|
||||
continue;
|
||||
|
||||
candidate = non_reference (TREE_TYPE (TREE_TYPE (cand)));
|
||||
|
||||
switch (TREE_CODE (candidate))
|
||||
|
|
|
@ -5176,7 +5176,7 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
|
|||
return build_aggr_init_full_exprs (decl, init, flags);
|
||||
else if (TREE_CODE (init) != TREE_VEC)
|
||||
{
|
||||
init_code = store_init_value (decl, init);
|
||||
init_code = store_init_value (decl, init, flags);
|
||||
if (pedantic && TREE_CODE (type) == ARRAY_TYPE
|
||||
&& DECL_INITIAL (decl)
|
||||
&& TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
|
||||
|
@ -8413,6 +8413,14 @@ grokdeclarator (const cp_declarator *declarator,
|
|||
"class definition",
|
||||
name);
|
||||
}
|
||||
else if (ctype && sfk == sfk_conversion)
|
||||
{
|
||||
if (explicitp == 1)
|
||||
{
|
||||
maybe_warn_cpp0x ("explicit conversion operators");
|
||||
explicitp = 2;
|
||||
}
|
||||
}
|
||||
|
||||
arg_types = grokparms (declarator->u.function.parameters,
|
||||
&parms);
|
||||
|
|
|
@ -1764,7 +1764,7 @@ maybe_emit_vtables (tree ctype)
|
|||
|
||||
if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
|
||||
{
|
||||
tree expr = store_init_value (vtbl, DECL_INITIAL (vtbl));
|
||||
tree expr = store_init_value (vtbl, DECL_INITIAL (vtbl), LOOKUP_NORMAL);
|
||||
|
||||
/* It had better be all done at compile-time. */
|
||||
gcc_assert (!expr);
|
||||
|
|
|
@ -1387,7 +1387,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags,
|
|||
/* If store_init_value returns NULL_TREE, the INIT has been
|
||||
recorded as the DECL_INITIAL for EXP. That means there's
|
||||
nothing more we have to do. */
|
||||
init = store_init_value (exp, init);
|
||||
init = store_init_value (exp, init, flags);
|
||||
if (init)
|
||||
finish_expr_stmt (init);
|
||||
return;
|
||||
|
|
|
@ -48,7 +48,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
static tree pfn_from_ptrmemfunc (tree);
|
||||
static tree delta_from_ptrmemfunc (tree);
|
||||
static tree convert_for_assignment (tree, tree, const char *, tree, int,
|
||||
tsubst_flags_t);
|
||||
tsubst_flags_t, int);
|
||||
static tree cp_pointer_int_sum (enum tree_code, tree, tree);
|
||||
static tree rationalize_conditional_expr (enum tree_code, tree,
|
||||
tsubst_flags_t);
|
||||
|
@ -6157,12 +6157,14 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
|
|||
}
|
||||
|
||||
if (modifycode == INIT_EXPR)
|
||||
/* Calls with INIT_EXPR are all direct-initialization, so don't set
|
||||
LOOKUP_ONLYCONVERTING. */
|
||||
newrhs = convert_for_initialization (lhs, olhstype, newrhs, LOOKUP_NORMAL,
|
||||
"initialization", NULL_TREE, 0,
|
||||
complain);
|
||||
else
|
||||
newrhs = convert_for_assignment (olhstype, newrhs, "assignment",
|
||||
NULL_TREE, 0, complain);
|
||||
NULL_TREE, 0, complain, LOOKUP_IMPLICIT);
|
||||
|
||||
if (!same_type_p (lhstype, olhstype))
|
||||
newrhs = cp_convert_and_check (lhstype, newrhs);
|
||||
|
@ -6568,7 +6570,7 @@ delta_from_ptrmemfunc (tree t)
|
|||
static tree
|
||||
convert_for_assignment (tree type, tree rhs,
|
||||
const char *errtype, tree fndecl, int parmnum,
|
||||
tsubst_flags_t complain)
|
||||
tsubst_flags_t complain, int flags)
|
||||
{
|
||||
tree rhstype;
|
||||
enum tree_code coder;
|
||||
|
@ -6689,7 +6691,8 @@ convert_for_assignment (tree type, tree rhs,
|
|||
TREE_NO_WARNING (rhs) = 1;
|
||||
}
|
||||
|
||||
return perform_implicit_conversion (strip_top_quals (type), rhs, complain);
|
||||
return perform_implicit_conversion_flags (strip_top_quals (type), rhs,
|
||||
complain, flags);
|
||||
}
|
||||
|
||||
/* Convert RHS to be of type TYPE.
|
||||
|
@ -6780,7 +6783,7 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags,
|
|||
return ocp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
|
||||
|
||||
return convert_for_assignment (type, rhs, errtype, fndecl, parmnum,
|
||||
complain);
|
||||
complain, flags);
|
||||
}
|
||||
|
||||
/* If RETVAL is the address of, or a reference to, a local variable or
|
||||
|
|
|
@ -586,7 +586,7 @@ split_nonconstant_init (tree dest, tree init)
|
|||
for static variable. In that case, caller must emit the code. */
|
||||
|
||||
tree
|
||||
store_init_value (tree decl, tree init)
|
||||
store_init_value (tree decl, tree init, int flags)
|
||||
{
|
||||
tree value, type;
|
||||
|
||||
|
@ -628,7 +628,7 @@ store_init_value (tree decl, tree init)
|
|||
/* End of special C++ code. */
|
||||
|
||||
/* Digest the specified initializer into an expression. */
|
||||
value = digest_init (type, init);
|
||||
value = digest_init_flags (type, init, flags);
|
||||
/* If the initializer is not a constant, fill in DECL_INITIAL with
|
||||
the bits that are constant, and then return an expression that
|
||||
will perform the dynamic initialization. */
|
||||
|
@ -717,7 +717,7 @@ check_narrowing (tree type, tree init)
|
|||
NESTED is true iff we are being called for an element of a CONSTRUCTOR. */
|
||||
|
||||
static tree
|
||||
digest_init_r (tree type, tree init, bool nested)
|
||||
digest_init_r (tree type, tree init, bool nested, int flags)
|
||||
{
|
||||
enum tree_code code = TREE_CODE (type);
|
||||
|
||||
|
@ -796,9 +796,9 @@ digest_init_r (tree type, tree init, bool nested)
|
|||
|
||||
if (cxx_dialect != cxx98 && nested)
|
||||
check_narrowing (type, init);
|
||||
init = convert_for_initialization (0, type, init, LOOKUP_NORMAL,
|
||||
init = convert_for_initialization (0, type, init, flags,
|
||||
"initialization", NULL_TREE, 0,
|
||||
tf_warning_or_error);
|
||||
tf_warning_or_error);
|
||||
exp = &init;
|
||||
|
||||
/* Skip any conversions since we'll be outputting the underlying
|
||||
|
@ -842,7 +842,7 @@ digest_init_r (tree type, tree init, bool nested)
|
|||
}
|
||||
|
||||
return convert_for_initialization (NULL_TREE, type, init,
|
||||
LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING,
|
||||
flags,
|
||||
"initialization", NULL_TREE, 0,
|
||||
tf_warning_or_error);
|
||||
}
|
||||
|
@ -851,7 +851,13 @@ digest_init_r (tree type, tree init, bool nested)
|
|||
tree
|
||||
digest_init (tree type, tree init)
|
||||
{
|
||||
return digest_init_r (type, init, false);
|
||||
return digest_init_r (type, init, false, LOOKUP_IMPLICIT);
|
||||
}
|
||||
|
||||
tree
|
||||
digest_init_flags (tree type, tree init, int flags)
|
||||
{
|
||||
return digest_init_r (type, init, false, flags);
|
||||
}
|
||||
|
||||
/* Set of flags used within process_init_constructor to describe the
|
||||
|
@ -924,7 +930,7 @@ process_init_constructor_array (tree type, tree init)
|
|||
else
|
||||
ce->index = size_int (i);
|
||||
gcc_assert (ce->value);
|
||||
ce->value = digest_init_r (TREE_TYPE (type), ce->value, true);
|
||||
ce->value = digest_init_r (TREE_TYPE (type), ce->value, true, LOOKUP_IMPLICIT);
|
||||
|
||||
if (ce->value != error_mark_node)
|
||||
gcc_assert (same_type_ignoring_top_level_qualifiers_p
|
||||
|
@ -1031,7 +1037,7 @@ process_init_constructor_record (tree type, tree init)
|
|||
}
|
||||
|
||||
gcc_assert (ce->value);
|
||||
next = digest_init_r (type, ce->value, true);
|
||||
next = digest_init_r (type, ce->value, true, LOOKUP_IMPLICIT);
|
||||
++idx;
|
||||
}
|
||||
else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
|
||||
|
@ -1046,7 +1052,7 @@ process_init_constructor_record (tree type, tree init)
|
|||
else
|
||||
next = build_constructor (init_list_type_node, NULL);
|
||||
|
||||
next = digest_init_r (TREE_TYPE (field), next, true);
|
||||
next = digest_init_r (TREE_TYPE (field), next, true, LOOKUP_IMPLICIT);
|
||||
|
||||
/* Warn when some struct elements are implicitly initialized. */
|
||||
warning (OPT_Wmissing_field_initializers,
|
||||
|
@ -1156,7 +1162,7 @@ process_init_constructor_union (tree type, tree init)
|
|||
}
|
||||
|
||||
if (ce->value && ce->value != error_mark_node)
|
||||
ce->value = digest_init_r (TREE_TYPE (ce->index), ce->value, true);
|
||||
ce->value = digest_init_r (TREE_TYPE (ce->index), ce->value, true, LOOKUP_IMPLICIT);
|
||||
|
||||
return picflag_from_initializer (ce->value);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2009-05-18 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* g++.dg/cpp0x/explicit1.C: New.
|
||||
* g++.dg/cpp0x/explicit2.C: New.
|
||||
|
||||
2009-05-18 Dodji Seketeli <dodji@redhat.com>
|
||||
|
||||
PR debug/40109
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
// Test for explicit conversion ops from N2437.
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
class U; class V;
|
||||
class T
|
||||
{
|
||||
public:
|
||||
T( U const & );
|
||||
//implicit converting ctor
|
||||
explicit T( V const & );
|
||||
// explicit ctor
|
||||
};
|
||||
class U
|
||||
{
|
||||
};
|
||||
class V
|
||||
{
|
||||
};
|
||||
class W
|
||||
{
|
||||
public:
|
||||
operator T() const;
|
||||
};
|
||||
class X
|
||||
{
|
||||
public:
|
||||
explicit operator T() const; // theoretical
|
||||
};
|
||||
int main()
|
||||
{
|
||||
U u; V v; W w; X x;
|
||||
// Direct initialization:
|
||||
T t1( u );
|
||||
T t2( v );
|
||||
T t3( w );
|
||||
T t4( x );
|
||||
// Copy initialization:
|
||||
T t5 = u;
|
||||
T t6 = v; // { dg-error "" }
|
||||
T t7 = w;
|
||||
T t8 = x; // { dg-error "" }
|
||||
// Cast notation:
|
||||
T t9 = (T) u;
|
||||
T t10 = (T) v;
|
||||
T t11 = (T) w;
|
||||
T t12 = (T) x;
|
||||
// Static cast:
|
||||
T t13 = static_cast<T>( u );
|
||||
T t14 = static_cast<T>( v );
|
||||
T t15 = static_cast<T>( w );
|
||||
T t16 = static_cast<T>( x );
|
||||
// Function-style cast:
|
||||
T t17 = T( u );
|
||||
T t18 = T( v );
|
||||
T t19 = T( w );
|
||||
T t20 = T( x );
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// Test for explicit conversion ops in various conversion situations.
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
typedef void (*pfn)();
|
||||
|
||||
struct A
|
||||
{
|
||||
explicit operator int() const;
|
||||
explicit operator pfn() const;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
A a;
|
||||
int i = a; // { dg-error "" }
|
||||
const int &ir = a; // { dg-error "" }
|
||||
a(); // { dg-error "" }
|
||||
a + 1; // { dg-message "" } (error and note on same line)
|
||||
|
||||
int j (a);
|
||||
(int)a;
|
||||
static_cast<int>(a);
|
||||
}
|
||||
|
||||
struct B
|
||||
{
|
||||
int i;
|
||||
B(const A& a): i(a) { }
|
||||
};
|
Loading…
Reference in New Issue