summaryrefslogtreecommitdiff
path: root/gcc/cp/semantics.c
diff options
context:
space:
mode:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>2003-08-01 09:34:09 +0000
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>2003-08-01 09:34:09 +0000
commit942ab15bc1a3ec6a744bca6ee544ad0cd3459949 (patch)
treebbb501c90255aea4dd7368daf077d8f0d4280c1c /gcc/cp/semantics.c
parent1cc57cf8fb921c68995c837ff99aaed68dbfb31e (diff)
downloadgcc-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.c129
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;
}