tree template_type = TREE_TYPE (TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (type))));
tree p_array_type = TREE_TYPE (TYPE_FIELDS (type));
tree etype = TREE_TYPE (expr);
- tree template_tree;
+ tree template_addr;
vec<constructor_elt, va_gc> *v;
vec_alloc (v, 2);
tree field = TYPE_FIELDS (TREE_TYPE (etype));
expr = gnat_protect_expr (expr);
- if (TREE_CODE (expr) == ADDR_EXPR)
- expr = TREE_OPERAND (expr, 0);
- else
+
+ /* If we have a TYPE_UNCONSTRAINED_ARRAY attached to the RECORD_TYPE,
+ the thin pointer value has been shifted so we shift it back to get
+ the template address. */
+ if (TYPE_UNCONSTRAINED_ARRAY (TREE_TYPE (etype)))
{
- /* If we have a TYPE_UNCONSTRAINED_ARRAY attached to the RECORD_TYPE,
- the thin pointer value has been shifted so we first need to shift
- it back to get the template address. */
- if (TYPE_UNCONSTRAINED_ARRAY (TREE_TYPE (etype)))
- expr
- = build_binary_op (POINTER_PLUS_EXPR, etype, expr,
- fold_build1 (NEGATE_EXPR, sizetype,
- byte_position
- (DECL_CHAIN (field))));
- expr = build1 (INDIRECT_REF, TREE_TYPE (etype), expr);
+ template_addr
+ = build_binary_op (POINTER_PLUS_EXPR, etype, expr,
+ fold_build1 (NEGATE_EXPR, sizetype,
+ byte_position
+ (DECL_CHAIN (field))));
+ template_addr
+ = fold_convert (TREE_TYPE (DECL_CHAIN (TYPE_FIELDS (type))),
+ template_addr);
}
- template_tree = build_component_ref (expr, NULL_TREE, field, false);
- expr = build_unary_op (ADDR_EXPR, NULL_TREE,
- build_component_ref (expr, NULL_TREE,
- DECL_CHAIN (field), false));
+ /* Otherwise we explicitly take the address of the fields. */
+ else
+ {
+ expr = build_unary_op (INDIRECT_REF, NULL_TREE, expr);
+ template_addr
+ = build_unary_op (ADDR_EXPR, NULL_TREE,
+ build_component_ref (expr, NULL_TREE, field,
+ false));
+ expr = build_unary_op (ADDR_EXPR, NULL_TREE,
+ build_component_ref (expr, NULL_TREE,
+ DECL_CHAIN (field),
+ false));
+ }
}
/* Otherwise, build the constructor for the template. */
else
- template_tree = build_template (template_type, TREE_TYPE (etype), expr);
+ template_addr
+ = build_unary_op (ADDR_EXPR, NULL_TREE,
+ build_template (template_type, TREE_TYPE (etype),
+ expr));
/* The final result is a constructor for the fat pointer.
Note that the call to "build_template" above is still fine because it
will only refer to the provided TEMPLATE_TYPE in this case. */
- CONSTRUCTOR_APPEND_ELT (v, TYPE_FIELDS (type),
- convert (p_array_type, expr));
- CONSTRUCTOR_APPEND_ELT (v, DECL_CHAIN (TYPE_FIELDS (type)),
- build_unary_op (ADDR_EXPR, NULL_TREE,
- template_tree));
+ CONSTRUCTOR_APPEND_ELT (v, TYPE_FIELDS (type), convert (p_array_type, expr));
+ CONSTRUCTOR_APPEND_ELT (v, DECL_CHAIN (TYPE_FIELDS (type)), template_addr);
return gnat_build_constructor (type, v);
}
\f
* *
* C Implementation File *
* *
- * Copyright (C) 1992-2013, Free Software Foundation, Inc. *
+ * Copyright (C) 1992-2014, Free Software Foundation, Inc. *
* *
* GNAT is free software; you can redistribute it and/or modify it under *
* terms of the GNU General Public License as published by the Free Soft- *
gnat_build_constructor (tree type, vec<constructor_elt, va_gc> *v)
{
bool allconstant = (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST);
+ bool read_only = true;
bool side_effects = false;
tree result, obj, val;
unsigned int n_elmts;
|| !initializer_constant_valid_p (val, TREE_TYPE (val)))
allconstant = false;
+ if (!TREE_READONLY (val))
+ read_only = false;
+
if (TREE_SIDE_EFFECTS (val))
side_effects = true;
}
CONSTRUCTOR_NO_CLEARING (result) = 1;
TREE_CONSTANT (result) = TREE_STATIC (result) = allconstant;
TREE_SIDE_EFFECTS (result) = side_effects;
- TREE_READONLY (result) = TYPE_READONLY (type) || allconstant;
+ TREE_READONLY (result) = TYPE_READONLY (type) || read_only || allconstant;
return result;
}
\f
if (!TREE_READONLY (t))
return NULL_TREE;
- if (TREE_CODE (t) == PARM_DECL)
+ if (TREE_CODE (t) == CONSTRUCTOR || TREE_CODE (t) == PARM_DECL)
return fold_convert (type, expr);
if (TREE_CODE (t) == VAR_DECL