diff options
author | nathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-08-01 09:34:09 +0000 |
---|---|---|
committer | nathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4> | 2003-08-01 09:34:09 +0000 |
commit | 942ab15bc1a3ec6a744bca6ee544ad0cd3459949 (patch) | |
tree | bbb501c90255aea4dd7368daf077d8f0d4280c1c /gcc/cp/semantics.c | |
parent | 1cc57cf8fb921c68995c837ff99aaed68dbfb31e (diff) | |
download | gcc-942ab15bc1a3ec6a744bca6ee544ad0cd3459949.tar.gz |
PR c++/11295
* doc/extend.texi (Statement Expressions): Document C++ semantics.
cp:
PR c++/11295
* cp-tree.h (tubst_flags_t): Add tf_stmt_expr_cmpd,
tf_stmt_expr_body.
(finish_stmt_expr_expr): Declare.
* parser.c (cp_parser_primary_expression): Tell
cp_parser_compount_statement that it is a statement expression.
(cp_parser_statement, cp_parser_labeled_statement,
cp_parser_compound_statement, cp_parser_statement_seq_opt): Add
in_statement_expr_p parameter.
(cp_parser_expression_statement): Likewise. Call
finish_stmt_expr_expr for final expression of a statement
expression.
(cp_parser_for_init_statement,
cp_parser_implicitly_scoped_statement,
cp_parser_already_scoped_statement, cp_parser_function_definition,
cp_parser_try_block, cp_parser_handled): Adjust.
* pt.c (tsubst_copy) <STMT_EXPR case>: Pass tf_stmt_expr.
(tsubst_expr): Process tf_stmt_expr and tf_stmt_exprs flags.
(tsubst_expr) <EXPR_STMT case>: Check tf_stmt_exprs flag.
* semantics.c (finish_expr_stmt): Do not deal with statement
expressions.
(begin_stmt_expr): Clear last_expr_type.
(finish_stmt_expr_expr): New.
(finish_stmt_expr): Process the value expression.
testsuite:
PR c++/11295
* g++.dg/ext/stmtexpr1.C: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@70043 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/semantics.c')
-rw-r--r-- | gcc/cp/semantics.c | 129 |
1 files changed, 99 insertions, 30 deletions
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index de5b190ee02..80a3d60136d 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -416,21 +416,10 @@ tree finish_expr_stmt (tree expr) { tree r = NULL_TREE; - tree expr_type = NULL_TREE;; if (expr != NULL_TREE) { - if (!processing_template_decl - && !(stmts_are_full_exprs_p ()) - && ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE - && lvalue_p (expr)) - || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)) - expr = decay_conversion (expr); - - /* Remember the type of the expression. */ - expr_type = TREE_TYPE (expr); - - if (!processing_template_decl && stmts_are_full_exprs_p ()) + if (!processing_template_decl) expr = convert_to_void (expr, "statement"); r = add_stmt (build_stmt (EXPR_STMT, expr)); @@ -438,10 +427,6 @@ finish_expr_stmt (tree expr) finish_stmt (); - /* This was an expression-statement, so we save the type of the - expression. */ - last_expr_type = expr_type; - return r; } @@ -1415,14 +1400,73 @@ begin_stmt_expr (void) if (! cfun && !last_tree) begin_stmt_tree (&scope_chain->x_saved_tree); + last_expr_type = NULL_TREE; + keep_next_level (1); - /* If we're building a statement tree, then the upcoming compound - statement will be chained onto the tree structure, starting at - last_tree. We return last_tree so that we can later unhook the - compound statement. */ + return last_tree; } +/* Process the final expression of a statement expression. EXPR can be + NULL, if the final expression is empty. Build up a TARGET_EXPR so + that the result value can be safely returned to the enclosing + expression. */ + +tree +finish_stmt_expr_expr (tree expr) +{ + tree result = NULL_TREE; + tree type = void_type_node; + + if (expr) + { + type = TREE_TYPE (expr); + + if (!processing_template_decl && !VOID_TYPE_P (TREE_TYPE (expr))) + { + if (TREE_CODE (type) == ARRAY_TYPE + || TREE_CODE (type) == FUNCTION_TYPE) + expr = decay_conversion (expr); + + expr = convert_from_reference (expr); + expr = require_complete_type (expr); + + /* Build a TARGET_EXPR for this aggregate. finish_stmt_expr + will then pull it apart so the lifetime of the target is + within the scope of the expresson containing this statement + expression. */ + if (TREE_CODE (expr) == TARGET_EXPR) + ; + else if (!IS_AGGR_TYPE (type) || TYPE_HAS_TRIVIAL_INIT_REF (type)) + expr = build_target_expr_with_type (expr, type); + else + { + /* Copy construct. */ + expr = build_special_member_call + (NULL_TREE, complete_ctor_identifier, + build_tree_list (NULL_TREE, expr), + TYPE_BINFO (type), LOOKUP_NORMAL); + expr = build_cplus_new (type, expr); + my_friendly_assert (TREE_CODE (expr) == TARGET_EXPR, 20030729); + } + } + + if (expr != error_mark_node) + { + result = build_stmt (EXPR_STMT, expr); + add_stmt (result); + } + } + + finish_stmt (); + + /* Remember the last expression so that finish_stmt_expr can pull it + apart. */ + last_expr_type = result ? result : void_type_node; + + return result; +} + /* Finish a statement-expression. RTL_EXPR should be the value returned by the previous begin_stmt_expr; EXPR is the statement-expression. Returns an expression representing the @@ -1432,18 +1476,27 @@ tree finish_stmt_expr (tree rtl_expr) { tree result; - - /* If the last thing in the statement-expression was not an - expression-statement, then it has type `void'. In a template, we - cannot distinguish the case where the last expression-statement - had a dependent type from the case where the last statement was - not an expression-statement. Therefore, we (incorrectly) treat - the STMT_EXPR as dependent in that case. */ - if (!last_expr_type && !processing_template_decl) - last_expr_type = void_type_node; - result = build_min (STMT_EXPR, last_expr_type, last_tree); + tree result_stmt = last_expr_type; + tree type; + + if (!last_expr_type) + type = void_type_node; + else + { + if (result_stmt == void_type_node) + { + type = void_type_node; + result_stmt = NULL_TREE; + } + else + type = TREE_TYPE (EXPR_STMT_EXPR (result_stmt)); + } + + result = build_min (STMT_EXPR, type, last_tree); TREE_SIDE_EFFECTS (result) = 1; + last_expr_type = NULL_TREE; + /* Remove the compound statement from the tree structure; it is now saved in the STMT_EXPR. */ last_tree = rtl_expr; @@ -1455,6 +1508,22 @@ finish_stmt_expr (tree rtl_expr) && TREE_CHAIN (scope_chain->x_saved_tree) == NULL_TREE) finish_stmt_tree (&scope_chain->x_saved_tree); + if (processing_template_decl) + return result; + + if (!VOID_TYPE_P (type)) + { + /* Pull out the TARGET_EXPR that is the final expression. Put + the target's init_expr as the final expression and then put + the statement expression itself as the target's init + expr. Finally, return the target expression. */ + tree last_expr = EXPR_STMT_EXPR (result_stmt); + + my_friendly_assert (TREE_CODE (last_expr) == TARGET_EXPR, 20030729); + EXPR_STMT_EXPR (result_stmt) = TREE_OPERAND (last_expr, 1); + TREE_OPERAND (last_expr, 1) = result; + result = last_expr; + } return result; } |