From: Jakub Jelinek Date: Wed, 9 Sep 2015 07:23:11 +0000 (+0200) Subject: re PR c/67495 (#pragma omp atomic ICEs) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f4b189d53bbc5def47c17cdc04c1c7fd291f29b1;p=gcc.git re PR c/67495 (#pragma omp atomic ICEs) PR c/67495 * c-parser.c (c_parser_omp_atomic): Use c_parser_cast_expression instead of c_parser_unary_expression. If the result is !lvalue_p, wrap the result of c_fully_fold into NON_LVALUE_EXPR. * gcc.dg/gomp/pr67495.c: New test. From-SVN: r227576 --- diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index a61df71ae8e..dadec059618 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,10 @@ +2015-09-09 Jakub Jelinek + + PR c/67495 + * c-parser.c (c_parser_omp_atomic): Use c_parser_cast_expression + instead of c_parser_unary_expression. If the result is !lvalue_p, + wrap the result of c_fully_fold into NON_LVALUE_EXPR. + 2015-09-04 Marek Polacek PR sanitizer/67279 diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 11a2b0f9731..86ccbe7730c 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -12422,6 +12422,7 @@ c_parser_omp_atomic (location_t loc, c_parser *parser) bool structured_block = false; bool swapped = false; bool seq_cst = false; + bool non_lvalue_p; if (c_parser_next_token_is (parser, CPP_NAME)) { @@ -12475,20 +12476,33 @@ c_parser_omp_atomic (location_t loc, c_parser *parser) { case OMP_ATOMIC_READ: case NOP_EXPR: /* atomic write */ - v = c_parser_unary_expression (parser).value; + v = c_parser_cast_expression (parser, NULL).value; + non_lvalue_p = !lvalue_p (v); v = c_fully_fold (v, false, NULL); if (v == error_mark_node) goto saw_error; + if (non_lvalue_p) + v = non_lvalue (v); loc = c_parser_peek_token (parser)->location; if (!c_parser_require (parser, CPP_EQ, "expected %<=%>")) goto saw_error; if (code == NOP_EXPR) - lhs = c_parser_expression (parser).value; + { + lhs = c_parser_expression (parser).value; + lhs = c_fully_fold (lhs, false, NULL); + if (lhs == error_mark_node) + goto saw_error; + } else - lhs = c_parser_unary_expression (parser).value; - lhs = c_fully_fold (lhs, false, NULL); - if (lhs == error_mark_node) - goto saw_error; + { + lhs = c_parser_cast_expression (parser, NULL).value; + non_lvalue_p = !lvalue_p (lhs); + lhs = c_fully_fold (lhs, false, NULL); + if (lhs == error_mark_node) + goto saw_error; + if (non_lvalue_p) + lhs = non_lvalue (lhs); + } if (code == NOP_EXPR) { /* atomic write is represented by OMP_ATOMIC with NOP_EXPR @@ -12507,10 +12521,13 @@ c_parser_omp_atomic (location_t loc, c_parser *parser) } else { - v = c_parser_unary_expression (parser).value; + v = c_parser_cast_expression (parser, NULL).value; + non_lvalue_p = !lvalue_p (v); v = c_fully_fold (v, false, NULL); if (v == error_mark_node) goto saw_error; + if (non_lvalue_p) + v = non_lvalue (v); if (!c_parser_require (parser, CPP_EQ, "expected %<=%>")) goto saw_error; } @@ -12523,7 +12540,7 @@ c_parser_omp_atomic (location_t loc, c_parser *parser) old or new x should be captured. */ restart: eloc = c_parser_peek_token (parser)->location; - expr = c_parser_unary_expression (parser); + expr = c_parser_cast_expression (parser, NULL); lhs = expr.value; expr = default_function_array_conversion (eloc, expr); unfolded_lhs = expr.value; @@ -12616,6 +12633,8 @@ restart: } /* FALLTHRU */ default: + if (!lvalue_p (unfolded_lhs)) + lhs = non_lvalue (lhs); switch (c_parser_peek_token (parser)->type) { case CPP_MULT_EQ: @@ -12730,20 +12749,25 @@ stmt_done: { if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) goto saw_error; - v = c_parser_unary_expression (parser).value; + v = c_parser_cast_expression (parser, NULL).value; + non_lvalue_p = !lvalue_p (v); v = c_fully_fold (v, false, NULL); if (v == error_mark_node) goto saw_error; + if (non_lvalue_p) + v = non_lvalue (v); if (!c_parser_require (parser, CPP_EQ, "expected %<=%>")) goto saw_error; eloc = c_parser_peek_token (parser)->location; - expr = c_parser_unary_expression (parser); + expr = c_parser_cast_expression (parser, NULL); lhs1 = expr.value; expr = default_function_array_read_conversion (eloc, expr); unfolded_lhs1 = expr.value; lhs1 = c_fully_fold (lhs1, false, NULL); if (lhs1 == error_mark_node) goto saw_error; + if (!lvalue_p (unfolded_lhs1)) + lhs1 = non_lvalue (lhs1); } if (structured_block) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 15c503f43f3..4afb642ac93 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-09-09 Jakub Jelinek + + PR c/67495 + * gcc.dg/gomp/pr67495.c: New test. + 2015-09-09 Aditya Kumar Sebastian Pop diff --git a/gcc/testsuite/gcc.dg/gomp/pr67495.c b/gcc/testsuite/gcc.dg/gomp/pr67495.c new file mode 100644 index 00000000000..1011a266972 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/pr67495.c @@ -0,0 +1,38 @@ +/* PR c/67495 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp" } */ + +int a, b, c; + +void +foo (void) +{ +#pragma omp atomic capture + a = (float)a + b; /* { dg-error "invalid operator" } */ +#pragma omp atomic read + (float) a = b; /* { dg-error "lvalue required" } */ +#pragma omp atomic write + (float) a = b; /* { dg-error "lvalue required" } */ +#pragma omp atomic read + a = (float) b; /* { dg-error "lvalue required" } */ +#pragma omp atomic capture + (float) a = b += c; /* { dg-error "lvalue required" } */ +#pragma omp atomic capture + { a += b; (float) c = a; } /* { dg-error "lvalue required" } */ +#pragma omp atomic capture + { a += b; c = (float) a; } /* { dg-error "uses two different expressions for memory" } */ +#pragma omp atomic capture + a = (int)a + b; /* { dg-error "invalid operator" } */ +#pragma omp atomic read + (int) a = b; /* { dg-error "lvalue required" } */ +#pragma omp atomic write + (int) a = b; /* { dg-error "lvalue required" } */ +#pragma omp atomic read + a = (int) b; /* { dg-error "lvalue required" } */ +#pragma omp atomic capture + (int) a = b += c; /* { dg-error "lvalue required" } */ +#pragma omp atomic capture + { a += b; (int) c = a; } /* { dg-error "lvalue required" } */ +#pragma omp atomic capture + { a += b; c = (int) a; } /* { dg-error "lvalue required" } */ +}