From 0cd6b1b456d0e3d5632d8776a61843456c456da3 Mon Sep 17 00:00:00 2001 From: mpolacek Date: Thu, 23 Apr 2015 14:35:12 +0000 Subject: [PATCH] PR c/65345 * c-decl.c (set_labels_context_r): New function. (store_parm_decls): Call it via walk_tree_without_duplicates. * c-typeck.c (convert_lvalue_to_rvalue): Use create_tmp_var_raw instead of create_tmp_var. Build TARGET_EXPR instead of COMPOUND_EXPR. (build_atomic_assign): Use create_tmp_var_raw instead of create_tmp_var. Build TARGET_EXPRs instead of MODIFY_EXPR. * gcc.dg/pr65345-1.c: New test. * gcc.dg/pr65345-2.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@222370 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/c/ChangeLog | 11 ++++++++ gcc/c/c-decl.c | 31 ++++++++++++++++++++- gcc/c/c-typeck.c | 26 +++++++++++------- gcc/testsuite/ChangeLog | 6 ++++ gcc/testsuite/gcc.dg/pr65345-1.c | 35 ++++++++++++++++++++++++ gcc/testsuite/gcc.dg/pr65345-2.c | 59 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 157 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr65345-1.c create mode 100644 gcc/testsuite/gcc.dg/pr65345-2.c diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index e5c19e0acbf..c613e9d5dd8 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,14 @@ +2015-04-23 Marek Polacek + + PR c/65345 + * c-decl.c (set_labels_context_r): New function. + (store_parm_decls): Call it via walk_tree_without_duplicates. + * c-typeck.c (convert_lvalue_to_rvalue): Use create_tmp_var_raw + instead of create_tmp_var. Build TARGET_EXPR instead of + COMPOUND_EXPR. + (build_atomic_assign): Use create_tmp_var_raw instead of + create_tmp_var. Build TARGET_EXPRs instead of MODIFY_EXPR. + 2015-04-20 Ilya Verbin * c-parser.c (c_parser_oacc_enter_exit_data): Remove excess semicolon. diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index e28a294dcc3..27ecd8bf513 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -8796,6 +8796,21 @@ store_parm_decls_from (struct c_arg_info *arg_info) store_parm_decls (); } +/* Called by walk_tree to look for and update context-less labels. */ + +static tree +set_labels_context_r (tree *tp, int *walk_subtrees, void *data) +{ + if (TREE_CODE (*tp) == LABEL_EXPR + && DECL_CONTEXT (LABEL_EXPR_LABEL (*tp)) == NULL_TREE) + { + DECL_CONTEXT (LABEL_EXPR_LABEL (*tp)) = static_cast(data); + *walk_subtrees = 0; + } + + return NULL_TREE; +} + /* Store the parameter declarations into the current function declaration. This is called after parsing the parameter declarations, before digesting the body of the function. @@ -8850,7 +8865,21 @@ store_parm_decls (void) thus won't naturally see the SAVE_EXPR containing the increment. All other pending sizes would be handled by gimplify_parameters. */ if (arg_info->pending_sizes) - add_stmt (arg_info->pending_sizes); + { + /* In very special circumstances, e.g. for code like + _Atomic int i = 5; + void f (int a[i += 2]) {} + we need to execute the atomic assignment on function entry. + But in this case, it is not just a straight store, it has the + op= form, which means that build_atomic_assign has generated + gotos, labels, etc. Because at that time the function decl + for F has not been created yet, those labels do not have any + function context. But we have the fndecl now, so update the + labels accordingly. gimplify_expr would crash otherwise. */ + walk_tree_without_duplicates (&arg_info->pending_sizes, + set_labels_context_r, fndecl); + add_stmt (arg_info->pending_sizes); + } } /* Store PARM_DECLs in PARMS into scope temporarily. Used for diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index ebe4c735891..91735b54dea 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -2039,7 +2039,7 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr exp, /* Remove the qualifiers for the rest of the expressions and create the VAL temp variable to hold the RHS. */ nonatomic_type = build_qualified_type (expr_type, TYPE_UNQUALIFIED); - tmp = create_tmp_var (nonatomic_type); + tmp = create_tmp_var_raw (nonatomic_type); tmp_addr = build_unary_op (loc, ADDR_EXPR, tmp, 0); TREE_ADDRESSABLE (tmp) = 1; TREE_NO_WARNING (tmp) = 1; @@ -2055,7 +2055,8 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr exp, mark_exp_read (exp.value); /* Return tmp which contains the value loaded. */ - exp.value = build2 (COMPOUND_EXPR, nonatomic_type, func_call, tmp); + exp.value = build4 (TARGET_EXPR, nonatomic_type, tmp, func_call, + NULL_TREE, NULL_TREE); } return exp; } @@ -3686,10 +3687,11 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode, the VAL temp variable to hold the RHS. */ nonatomic_lhs_type = build_qualified_type (lhs_type, TYPE_UNQUALIFIED); nonatomic_rhs_type = build_qualified_type (rhs_type, TYPE_UNQUALIFIED); - val = create_tmp_var (nonatomic_rhs_type); + val = create_tmp_var_raw (nonatomic_rhs_type); TREE_ADDRESSABLE (val) = 1; TREE_NO_WARNING (val) = 1; - rhs = build2 (MODIFY_EXPR, nonatomic_rhs_type, val, rhs); + rhs = build4 (TARGET_EXPR, nonatomic_rhs_type, val, rhs, NULL_TREE, + NULL_TREE); SET_EXPR_LOCATION (rhs, loc); add_stmt (rhs); @@ -3715,12 +3717,12 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode, } /* Create the variables and labels required for the op= form. */ - old = create_tmp_var (nonatomic_lhs_type); + old = create_tmp_var_raw (nonatomic_lhs_type); old_addr = build_unary_op (loc, ADDR_EXPR, old, 0); TREE_ADDRESSABLE (old) = 1; TREE_NO_WARNING (old) = 1; - newval = create_tmp_var (nonatomic_lhs_type); + newval = create_tmp_var_raw (nonatomic_lhs_type); newval_addr = build_unary_op (loc, ADDR_EXPR, newval, 0); TREE_ADDRESSABLE (newval) = 1; @@ -3736,7 +3738,9 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode, params->quick_push (old_addr); params->quick_push (seq_cst); func_call = c_build_function_call_vec (loc, vNULL, fndecl, params, NULL); - add_stmt (func_call); + old = build4 (TARGET_EXPR, nonatomic_lhs_type, old, func_call, NULL_TREE, + NULL_TREE); + add_stmt (old); params->truncate (0); /* Create the expressions for floating-point environment @@ -3755,12 +3759,14 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode, /* newval = old + val; */ rhs = build_binary_op (loc, modifycode, old, val, 1); + rhs = c_fully_fold (rhs, false, NULL); rhs = convert_for_assignment (loc, UNKNOWN_LOCATION, nonatomic_lhs_type, rhs, NULL_TREE, ic_assign, false, NULL_TREE, NULL_TREE, 0); if (rhs != error_mark_node) { - rhs = build2 (MODIFY_EXPR, nonatomic_lhs_type, newval, rhs); + rhs = build4 (TARGET_EXPR, nonatomic_lhs_type, newval, rhs, NULL_TREE, + NULL_TREE); SET_EXPR_LOCATION (rhs, loc); add_stmt (rhs); } @@ -3782,7 +3788,7 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode, stmt = build3 (COND_EXPR, void_type_node, func_call, goto_stmt, NULL_TREE); SET_EXPR_LOCATION (stmt, loc); add_stmt (stmt); - + if (clear_call) add_stmt (clear_call); @@ -3790,7 +3796,7 @@ build_atomic_assign (location_t loc, tree lhs, enum tree_code modifycode, goto_stmt = build1 (GOTO_EXPR, void_type_node, loop_decl); SET_EXPR_LOCATION (goto_stmt, loc); add_stmt (goto_stmt); - + /* done: */ add_stmt (done_label); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e4a224a6066..5f55eb091a8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2015-04-23 Marek Polacek + + PR c/65345 + * gcc.dg/pr65345-1.c: New test. + * gcc.dg/pr65345-2.c: New test. + 2015-04-23 Bill Schmidt * gcc.target/powerpc/crypto-builtin-2.c: New. diff --git a/gcc/testsuite/gcc.dg/pr65345-1.c b/gcc/testsuite/gcc.dg/pr65345-1.c new file mode 100644 index 00000000000..d11947b459c --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr65345-1.c @@ -0,0 +1,35 @@ +/* PR c/65345 */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +_Atomic int i = 3; + +int a1 = sizeof (i + 1); +int a2 = sizeof (i = 0); +int a3 = sizeof (i++); +int a4 = sizeof (i--); +int a5 = sizeof (-i); + +int b1 = _Alignof (i + 1); +int b2 = _Alignof (i = 0); +int b3 = _Alignof (i++); +int b4 = _Alignof (i--); +int b5 = _Alignof (-i); + +int c1 = i; /* { dg-error "initializer element is not constant" } */ +int c2 = (i ? 1 : 2); /* { dg-error "initializer element is not constant" } */ +int c3[i]; /* { dg-error "variably modified" } */ +int c4 = 0 || i; /* { dg-error "initializer element is not constant" } */ +int c5 = (i += 10); /* { dg-error "initializer element is not constant" } */ + +_Static_assert (_Generic (i, int: 1, default: 0) == 1, "1"); +_Static_assert (_Generic (i + 1, int: 1, default: 0) == 1, "2"); +_Static_assert (_Generic (i = 0, int: 1, default: 0) == 1, "3"); +_Static_assert (_Generic (i++, int: 1, default: 0) == 1, "4"); +_Static_assert (_Generic (i--, int: 1, default: 0) == 1, "5"); + +void fn1 (int a[i + 1]); +void fn2 (int a[i = 0]); +void fn3 (int a[i++]); +void fn4 (int a[i--]); +void fn5 (int a[-i]); diff --git a/gcc/testsuite/gcc.dg/pr65345-2.c b/gcc/testsuite/gcc.dg/pr65345-2.c new file mode 100644 index 00000000000..438100dcf7d --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr65345-2.c @@ -0,0 +1,59 @@ +/* PR c/65345 */ +/* { dg-do run } */ +/* { dg-options "" } */ + +#define CHECK(X) if (!(X)) __builtin_abort () + +_Atomic int i = 5; +_Atomic int j = 2; + +void +fn1 (int a[i = 0]) +{ +} + +void +fn2 (int a[i += 2]) +{ +} + +void +fn3 (int a[++i]) +{ +} + +void +fn4 (int a[++i]) +{ +} + +void +fn5 (int a[++i][j = 10]) +{ +} + +void +fn6 (int a[i = 7][j--]) +{ +} + +int +main () +{ + int a[10]; + int aa[10][10]; + fn1 (a); + CHECK (i == 0); + fn2 (a); + CHECK (i == 2); + fn3 (a); + CHECK (i == 3); + fn4 (a); + CHECK (i == 4); + fn5 (aa); + CHECK (i == 5); + CHECK (j == 10); + fn6 (aa); + CHECK (i == 7); + CHECK (j == 9); +} -- 2.11.4.GIT