type has a name/declaration of it's own, but special attention
is required if the type is anonymous.
- We handle the NORMAL and FIELD contexts here by attaching an
- artificial TYPE_DECL to such pointed-to type. This forces the
- sizes evaluation at a safe point and ensures it is not deferred
- until e.g. within a deeper conditional context.
-
- We expect nothing to be needed here for PARM or TYPENAME.
- Pushing a TYPE_DECL at this point for TYPENAME would actually
- be incorrect, as we might be in the middle of an expression
- with side effects on the pointed-to type size "arguments" prior
- to the pointer declaration point and the fake TYPE_DECL in the
- enclosing context would force the size evaluation prior to the
- side effects. */
-
+ We attach an artificial TYPE_DECL to such pointed-to type
+ and arrange for it to be included in a DECL_EXPR. This
+ forces the sizes evaluation at a safe point and ensures it
+ is not deferred until e.g. within a deeper conditional context.
+
+ PARM contexts have no enclosing statement list that
+ can hold the DECL_EXPR, so we need to use a BIND_EXPR
+ instead, and add it to the list of expressions that
+ need to be evaluated.
+
+ TYPENAME contexts do have an enclosing statement list,
+ but it would be incorrect to use it, as the size should
+ only be evaluated if the containing expression is
+ evaluated. We might also be in the middle of an
+ expression with side effects on the pointed-to type size
+ "arguments" prior to the pointer declaration point and
+ the fake TYPE_DECL in the enclosing context would force
+ the size evaluation prior to the side effects. We therefore
+ use BIND_EXPRs in TYPENAME contexts too. */
if (!TYPE_NAME (type)
- && (decl_context == NORMAL || decl_context == FIELD)
&& variably_modified_type_p (type, NULL_TREE))
{
+ tree bind = NULL_TREE;
+ if (decl_context == TYPENAME || decl_context == PARM)
+ {
+ bind = build3 (BIND_EXPR, void_type_node, NULL_TREE,
+ NULL_TREE, NULL_TREE);
+ TREE_SIDE_EFFECTS (bind) = 1;
+ BIND_EXPR_BODY (bind) = push_stmt_list ();
+ push_scope ();
+ }
tree decl = build_decl (loc, TYPE_DECL, NULL_TREE, type);
DECL_ARTIFICIAL (decl) = 1;
pushdecl (decl);
finish_decl (decl, loc, NULL_TREE, NULL_TREE, NULL_TREE);
TYPE_NAME (type) = decl;
+ if (bind)
+ {
+ pop_scope ();
+ BIND_EXPR_BODY (bind)
+ = pop_stmt_list (BIND_EXPR_BODY (bind));
+ if (*expr)
+ *expr = build2 (COMPOUND_EXPR, void_type_node, *expr,
+ bind);
+ else
+ *expr = bind;
+ }
}
type = c_build_pointer_type (type);