diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 23bde4ae480..ab776ac2892 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2002-02-08 Jakub Jelinek + + * c-common.c (c_expand_expr): Revert 2002-02-06 patch. + * c-parse.in (compstmt): Clear last_expr_type. + 2002-02-07 Richard Henderson * loop.c (strength_reduce): Sink final_value when not diff --git a/gcc/c-common.c b/gcc/c-common.c index 4b7946b4194..6b986d81c03 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -3466,32 +3466,22 @@ c_expand_expr (exp, target, tmode, modifier) /* If we want the result of this expression, find the last EXPR_STMT in the COMPOUND_STMT and mark it as addressable. */ - if (target != const0_rtx) + if (target != const0_rtx + && TREE_CODE (STMT_EXPR_STMT (exp)) == COMPOUND_STMT + && TREE_CODE (COMPOUND_BODY (STMT_EXPR_STMT (exp))) == SCOPE_STMT) { - tree expr = STMT_EXPR_STMT (exp); - tree last; + tree expr = COMPOUND_BODY (STMT_EXPR_STMT (exp)); + tree last = TREE_CHAIN (expr); - while (TREE_CODE (expr) == COMPOUND_STMT - && TREE_CODE (COMPOUND_BODY (expr)) == SCOPE_STMT) + while (TREE_CHAIN (last)) { - expr = COMPOUND_BODY (expr); - last = TREE_CHAIN (expr); - - while (TREE_CHAIN (last)) - { - expr = last; - last = TREE_CHAIN (last); - } - - if (TREE_CODE (last) != SCOPE_STMT) - abort (); - - if (TREE_CODE (expr) == EXPR_STMT) - { - TREE_ADDRESSABLE (expr) = 1; - break; - } + expr = last; + last = TREE_CHAIN (last); } + + if (TREE_CODE (last) == SCOPE_STMT + && TREE_CODE (expr) == EXPR_STMT) + TREE_ADDRESSABLE (expr) = 1; } expand_stmt (STMT_EXPR_STMT (exp)); diff --git a/gcc/c-parse.in b/gcc/c-parse.in index 524d407e801..176041bf0c8 100644 --- a/gcc/c-parse.in +++ b/gcc/c-parse.in @@ -2172,6 +2172,7 @@ compstmt_primary_start: compstmt: compstmt_start compstmt_nostart { RECHAIN_STMTS ($1, COMPOUND_BODY ($1)); + last_expr_type = NULL_TREE; $$ = $1; } ; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ad7dd540dce..25bf9d92070 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2002-02-08 Jakub Jelinek + + * parse.y (primary, primary_no_id): Use compstmt_or_stmtexpr + instead of compstmt. + (compstmt_or_stmtexpr): Renamed from compstmt. + (compstmt): In addition to compstmt_or_stmtexpr clear last_expr_type. + 2002-02-07 Nathan Sidwell Rename instantiate_type_flags to tsubst_flags_t & expand use. diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index 7941a89ac01..7faeabaf87c 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -1592,7 +1592,7 @@ primary: pedwarn ("ISO C++ forbids braced-groups within expressions"); $$ = begin_stmt_expr (); } - compstmt ')' + compstmt_or_stmtexpr ')' { $$ = finish_stmt_expr ($2); } /* Koenig lookup support We could store lastiddecl in $1 to avoid another lookup, @@ -1717,7 +1717,7 @@ primary_no_id: YYERROR; } $$ = expand_start_stmt_expr (); } - compstmt ')' + compstmt_or_stmtexpr ')' { if (pedantic) pedwarn ("ISO C++ forbids braced-groups within expressions"); $$ = expand_end_stmt_expr ($2); } @@ -3324,7 +3324,7 @@ label_decl: } ; -compstmt: +compstmt_or_stmtexpr: save_lineno '{' { $$ = begin_compound_stmt (0); } compstmtend @@ -3332,6 +3332,11 @@ compstmt: finish_compound_stmt (0, $3); } ; +compstmt: + compstmt_or_stmtexpr + { last_expr_type = NULL_TREE; } + ; + simple_if: IF { $$ = begin_if_stmt (); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c373f211e34..dbb5cefab28 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2002-02-08 Jakub Jelinek + + * gcc.c-torture/execute/20020206-1.c: Test whether nesting 2 + expression statements work instead. + * gcc.dg/noncompile/20020207-1.c: New test. + 2002-02-07 Richard Henderson * gcc.dg/debug/dwarf2-1.c (foo): Return a value. diff --git a/gcc/testsuite/gcc.c-torture/execute/20020206-1.c b/gcc/testsuite/gcc.c-torture/execute/20020206-1.c index 93147c9ada1..8450800a176 100644 --- a/gcc/testsuite/gcc.c-torture/execute/20020206-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/20020206-1.c @@ -1,6 +1,3 @@ -/* This testcase ICEd because c_expand_expr did not mark statement expression - return value as one which shouldn't be ignored. */ - struct A { unsigned int a, b, c; }; @@ -23,7 +20,7 @@ int main () { struct A d; - d = ({ { bar (); } }); + d = ({ ({ bar (); }); }); baz (&d); exit (0); } diff --git a/gcc/testsuite/gcc.dg/noncompile/20020207-1.c b/gcc/testsuite/gcc.dg/noncompile/20020207-1.c new file mode 100644 index 00000000000..945eb1b1b97 --- /dev/null +++ b/gcc/testsuite/gcc.dg/noncompile/20020207-1.c @@ -0,0 +1,32 @@ +/* This testcase ICEd because statement expression type was set, but was not + as used. */ + +struct A { + unsigned int a, b, c; +}; + +extern void abort (void); +extern void exit (int); + +struct A bar (void) +{ + return (struct A) { 176, 52, 31 }; +} + +void baz (struct A *a) +{ + if (a->a != 176 || a->b != 52 || a->c != 31) + abort (); +} + +int main () +{ + struct A d; + + d = ({ { bar (); } }); /* { dg-error "void value" } */ + d = ({ if (1) { bar (); } }); /* { dg-error "void value" } */ + d = ({ while (0) { bar (); } }); /* { dg-error "void value" } */ + d = ({ do { bar (); } while (0); }); /* { dg-error "void value" } */ + baz (&d); + exit (0); +}