diff options
Diffstat (limited to 'gcc/cp/semantics.c')
| -rw-r--r-- | gcc/cp/semantics.c | 96 |
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; |
