summaryrefslogtreecommitdiffstats
path: root/gnu/usr.bin/cc/cc1plus/cvt.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/cc/cc1plus/cvt.c')
-rw-r--r--gnu/usr.bin/cc/cc1plus/cvt.c151
1 files changed, 70 insertions, 81 deletions
diff --git a/gnu/usr.bin/cc/cc1plus/cvt.c b/gnu/usr.bin/cc/cc1plus/cvt.c
index 7777350..a156f20 100644
--- a/gnu/usr.bin/cc/cc1plus/cvt.c
+++ b/gnu/usr.bin/cc/cc1plus/cvt.c
@@ -663,10 +663,12 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
if (form == REFERENCE_TYPE)
{
- rval = copy_node (expr);
- TREE_TYPE (rval) = build_pointer_type (TREE_TYPE (TREE_TYPE (expr)));
- rval = cp_convert (build_pointer_type (TREE_TYPE (reftype)), rval,
+ tree type = TREE_TYPE (expr);
+ tree tmp = copy_node (expr);
+ TREE_TYPE (tmp) = build_pointer_type (TREE_TYPE (TREE_TYPE (expr)));
+ rval = cp_convert (build_pointer_type (TREE_TYPE (reftype)), tmp,
convtype, flags);
+ TREE_TYPE (tmp) = type;
TREE_TYPE (rval) = reftype;
return rval;
}
@@ -1283,12 +1285,9 @@ cp_convert (type, expr, convtype, flags)
if (IS_AGGR_TYPE_CODE (code))
{
tree dtype = TREE_TYPE (e);
+ tree ctor = NULL_TREE;
+ tree conversion = NULL_TREE;
- if (TREE_CODE (dtype) == REFERENCE_TYPE)
- {
- e = convert_from_reference (e);
- dtype = TREE_TYPE (e);
- }
dtype = TYPE_MAIN_VARIANT (dtype);
/* Conversion of object pointers or signature pointers/references
@@ -1321,87 +1320,77 @@ cp_convert (type, expr, convtype, flags)
There may be some ambiguity between using a constructor
vs. using a type conversion operator when both apply. */
- else if (IS_AGGR_TYPE (dtype))
- {
- tree binfo;
-
- tree conversion;
-
- if (! DERIVED_FROM_P (type, dtype) && TYPE_HAS_CONVERSION (dtype))
- conversion = build_type_conversion (CONVERT_EXPR, type, e, 1);
- else
- conversion = NULL_TREE;
-
- if (TYPE_HAS_CONSTRUCTOR (type))
- {
- tree rval = build_method_call (NULL_TREE, constructor_name_full (type),
- build_tree_list (NULL_TREE, e),
- TYPE_BINFO (type),
- conversion ? LOOKUP_NO_CONVERSION : 0);
+ if (IS_AGGR_TYPE (dtype) && ! DERIVED_FROM_P (type, dtype)
+ && TYPE_HAS_CONVERSION (dtype))
+ conversion = build_type_conversion (CONVERT_EXPR, type, e, 1);
- if (rval != error_mark_node)
- {
- if (conversion)
- {
- error ("both constructor and type conversion operator apply");
- return error_mark_node;
- }
- /* call to constructor successful. */
- rval = build_cplus_new (type, rval, 1);
- return rval;
- }
- }
- /* Type conversion successful/applies. */
- if (conversion)
- {
- if (conversion == error_mark_node)
- error ("ambiguous pointer conversion");
- return conversion;
- }
-
- /* now try normal C++ assignment semantics. */
- binfo = TYPE_BINFO (dtype);
- if (BINFO_TYPE (binfo) == type
- || (binfo = get_binfo (type, dtype, 1)))
- {
- if (binfo == error_mark_node)
- return error_mark_node;
- }
- if (binfo != NULL_TREE)
- {
- if (lvalue_p (e))
- {
- e = build_unary_op (ADDR_EXPR, e, 0);
+ if (conversion == error_mark_node)
+ {
+ error ("ambiguous pointer conversion");
+ return conversion;
+ }
- if (! BINFO_OFFSET_ZEROP (binfo))
- e = build (PLUS_EXPR, TYPE_POINTER_TO (type),
- e, BINFO_OFFSET (binfo));
- return build1 (INDIRECT_REF, type, e);
- }
+ if (TYPE_HAS_CONSTRUCTOR (type))
+ ctor = build_method_call (NULL_TREE, constructor_name_full (type),
+ build_tree_list (NULL_TREE, e),
+ TYPE_BINFO (type),
+ LOOKUP_NORMAL | LOOKUP_SPECULATIVELY
+ | (conversion ? LOOKUP_NO_CONVERSION : 0));
- sorry ("addressable aggregates");
- return error_mark_node;
- }
- error ("conversion between incompatible aggregate types requested");
+ if (ctor == error_mark_node)
+ {
+ cp_error ("in conversion to type `%T'", type);
return error_mark_node;
}
- /* conversion from non-aggregate to aggregate type requires
- constructor. */
- else if (TYPE_HAS_CONSTRUCTOR (type))
+
+ if (conversion && ctor)
{
- tree rval;
- tree init = build_method_call (NULL_TREE, constructor_name_full (type),
- build_tree_list (NULL_TREE, e),
- TYPE_BINFO (type), LOOKUP_NORMAL);
- if (init == error_mark_node)
+ error ("both constructor and type conversion operator apply");
+ return error_mark_node;
+ }
+ else if (conversion)
+ return conversion;
+ else if (ctor)
+ {
+ if (current_function_decl)
+ /* We can't pass 1 to the with_cleanup_p arg here, because that
+ screws up passing classes by value. */
+ ctor = build_cplus_new (type, ctor, 0);
+ else
{
- cp_error ("in conversion to type `%T'", type);
- return error_mark_node;
+ register tree parm = TREE_OPERAND (ctor, 1);
+
+ /* Initializers for static variables and parameters
+ have to handle doing the initialization and
+ cleanup themselves. */
+ my_friendly_assert (TREE_CODE (ctor) == CALL_EXPR, 322);
+#if 0
+ /* The following assertion fails in cases where we
+ are initializing a static member variable of a
+ particular instance of a template class with a
+ call to a constructor of the given instance, as
+ in:
+
+ TMPL<int> object = TMPL<int>();
+
+ Curiously, the assertion does not fail if we do
+ the same thing for a static member of a
+ non-template class, as in:
+
+ T object = T();
+
+ I can't see why we should care here whether or not
+ the initializer expression involves a call to
+ `new', so for the time being, it seems best to
+ just avoid doing this assertion. */
+ my_friendly_assert (TREE_CALLS_NEW (TREE_VALUE (parm)),
+ 323);
+#endif
+ TREE_VALUE (parm) = NULL_TREE;
+ ctor = build_indirect_ref (ctor, NULL_PTR);
+ TREE_HAS_CONSTRUCTOR (ctor) = 1;
}
- /* We can't pass 1 to the with_cleanup_p arg here, because that
- screws up passing classes by value. */
- rval = build_cplus_new (type, init, 0);
- return rval;
+ return ctor;
}
}
OpenPOWER on IntegriCloud