Hi! c_parser_binary_expression was using build2 to create a temporary holder for binary expression that c_parser_atomic and c_finish_omp_atomic can then handle. The latter performs then all the needed checking.
Unfortunately, build2 performs some checking too, e.g. PLUS_EXPR vs. POINTER_PLUS_EXPR or matching types of the arguments, nothing we can guarantee at the parsing time. So we need something like C++ build_min_nt*. This patch implements that inline. Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk, queued for backporting. 2020-11-24 Jakub Jelinek <ja...@redhat.com> PR c/97958 * c-parser.c (c_parser_binary_expression): For omp atomic binary expressions, use make_node instead of build2 to avoid checking build2 performs. * c-c++-common/gomp/pr97958.c: New test. --- gcc/c/c-parser.c.jj 2020-11-14 10:40:11.063411474 +0100 +++ gcc/c/c-parser.c 2020-11-23 18:35:40.242698775 +0100 @@ -7865,9 +7865,13 @@ c_parser_binary_expression (c_parser *pa && stack[1].expr.value != error_mark_node \ && (c_tree_equal (stack[0].expr.value, omp_atomic_lhs) \ || c_tree_equal (stack[1].expr.value, omp_atomic_lhs))) \ - stack[0].expr.value \ - = build2 (stack[1].op, TREE_TYPE (stack[0].expr.value), \ - stack[0].expr.value, stack[1].expr.value); \ + { \ + tree t = make_node (stack[1].op); \ + TREE_TYPE (t) = TREE_TYPE (stack[0].expr.value); \ + TREE_OPERAND (t, 0) = stack[0].expr.value; \ + TREE_OPERAND (t, 1) = stack[1].expr.value; \ + stack[0].expr.value = t; \ + } \ else \ stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \ stack[sp].op, \ --- gcc/testsuite/c-c++-common/gomp/pr97958.c.jj 2020-11-23 18:39:12.143349754 +0100 +++ gcc/testsuite/c-c++-common/gomp/pr97958.c 2020-11-23 18:38:49.637599241 +0100 @@ -0,0 +1,17 @@ +/* PR c/97958 */ + +int *p; + +void +foo (void) +{ + #pragma omp atomic + p = p + 1; +} + +void +bar (void) +{ + #pragma omp atomic /* { dg-error "invalid expression type for '#pragma omp atomic'" } */ + bar = bar + 1; +} Jakub