aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/semantics.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/semantics.c')
-rw-r--r--gcc/cp/semantics.c96
1 files changed, 37 insertions, 59 deletions
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index fb4ea0a..56dbe6f 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1612,70 +1612,46 @@ finish_stmt_expr_expr (tree expr, tree stmt_expr)
of the last statement is the value of the entire expression. */
if (expr)
{
- tree type;
- type = TREE_TYPE (expr);
- if (!dependent_type_p (type) && !VOID_TYPE_P (type))
+ tree type = TREE_TYPE (expr);
+
+ if (processing_template_decl)
+ {
+ expr = build_stmt (EXPR_STMT, expr);
+ expr = add_stmt (expr);
+ /* Mark the last statement so that we can recognize it as such at
+ template-instantiation time. */
+ EXPR_STMT_STMT_EXPR_RESULT (expr) = 1;
+ }
+ else if (VOID_TYPE_P (type))
{
- expr = decay_conversion (expr);
+ /* Just treat this like an ordinary statement. */
+ expr = finish_expr_stmt (expr);
+ }
+ else
+ {
+ /* It actually has a value we need to deal with. First, force it
+ to be an rvalue so that we won't need to build up a copy
+ constructor call later when we try to assign it to something. */
+ expr = force_rvalue (expr);
if (error_operand_p (expr))
return error_mark_node;
+
+ /* Update for array-to-pointer decay. */
type = TREE_TYPE (expr);
+
+ /* Wrap it in a CLEANUP_POINT_EXPR and add it to the list like a
+ normal statement, but don't convert to void or actually add
+ the EXPR_STMT. */
+ if (TREE_CODE (expr) != CLEANUP_POINT_EXPR)
+ expr = maybe_cleanup_point_expr (expr);
+ add_stmt (expr);
}
+
/* The type of the statement-expression is the type of the last
expression. */
TREE_TYPE (stmt_expr) = type;
- /* We must take particular care if TYPE is a class type. In
- particular if EXPR creates a temporary of class type, then it
- must be destroyed at the semicolon terminating the last
- statement -- but we must make a copy before that happens.
-
- This problem is solved by using a TARGET_EXPR to initialize a
- new temporary variable. The TARGET_EXPR itself is placed
- outside the statement-expression. However, the last
- statement in the statement-expression is transformed from
- EXPR to (approximately) T = EXPR, where T is the new
- temporary variable. Thus, the lifetime of the new temporary
- extends to the full-expression surrounding the
- statement-expression. */
- if (!processing_template_decl && !VOID_TYPE_P (type))
- {
- tree target_expr;
- if (CLASS_TYPE_P (type)
- && !TYPE_HAS_TRIVIAL_INIT_REF (type))
- {
- target_expr = build_target_expr_with_type (expr, type);
- expr = TARGET_EXPR_INITIAL (target_expr);
- }
- else
- {
- /* Normally, build_target_expr will not create a
- TARGET_EXPR for scalars. However, we need the
- temporary here, in order to solve the scoping
- problem described above. */
- target_expr = force_target_expr (type, expr);
- expr = TARGET_EXPR_INITIAL (target_expr);
- expr = build2 (INIT_EXPR,
- type,
- TARGET_EXPR_SLOT (target_expr),
- expr);
- }
- TARGET_EXPR_INITIAL (target_expr) = NULL_TREE;
- /* Save away the TARGET_EXPR in the TREE_TYPE field of the
- STATEMENT_EXPR. We will retrieve it in
- finish_stmt_expr. */
- TREE_TYPE (stmt_expr) = target_expr;
- }
}
- /* Having modified EXPR to reflect the extra initialization, we now
- treat it just like an ordinary statement. */
- expr = finish_expr_stmt (expr);
-
- /* Mark the last statement so that we can recognize it as such at
- template-instantiation time. */
- if (expr && processing_template_decl)
- EXPR_STMT_STMT_EXPR_RESULT (expr) = 1;
-
return stmt_expr;
}
@@ -1696,6 +1672,7 @@ finish_stmt_expr (tree stmt_expr, bool has_no_scope)
type = TREE_TYPE (stmt_expr);
result = pop_stmt_list (stmt_expr);
+ TREE_TYPE (result) = type;
if (processing_template_decl)
{
@@ -1703,12 +1680,13 @@ finish_stmt_expr (tree stmt_expr, bool has_no_scope)
TREE_SIDE_EFFECTS (result) = 1;
STMT_EXPR_NO_SCOPE (result) = has_no_scope;
}
- else if (!TYPE_P (type))
+ else if (CLASS_TYPE_P (type))
{
- gcc_assert (TREE_CODE (type) == TARGET_EXPR);
- TARGET_EXPR_INITIAL (type) = result;
- TREE_TYPE (result) = void_type_node;
- result = type;
+ /* Wrap the statement-expression in a TARGET_EXPR so that the
+ temporary object created by the final expression is destroyed at
+ the end of the full-expression containing the
+ statement-expression. */
+ result = force_target_expr (type, result);
}
return result;