Hi! This patch fixes an ICE, where c_finish_omp_atomic is called on a template for diagnostics purposes because the expressions aren't type dependent, but still calling save_expr on C++ trees is harmful (e.g. SCOPE_REF contains a type as one of the arguments, rather than expression).
2015-10-29 Jakub Jelinek <ja...@redhat.com> gcc/c-family/ * c-common.h (c_finish_omp_atomic): Add TEST argument. * c-omp.c (c_finish_omp_atomic): Likewise. Don't call save_expr or create_tmp_var* if TEST is true. gcc/cp/ * semantics.c (finish_omp_atomic): Adjust c_finish_omp_atomic caller. gcc/testsuite/ * g++.dg/gomp/atomic-17.C: New test. --- gcc/c-family/c-common.h.jj 2015-10-19 15:04:58.000000000 +0200 +++ gcc/c-family/c-common.h 2015-10-29 16:31:52.132631191 +0100 @@ -1262,7 +1262,8 @@ extern tree c_finish_omp_critical (locat extern tree c_finish_omp_ordered (location_t, tree, tree); extern void c_finish_omp_barrier (location_t); extern tree c_finish_omp_atomic (location_t, enum tree_code, enum tree_code, - tree, tree, tree, tree, tree, bool, bool); + tree, tree, tree, tree, tree, bool, bool, + bool = false); extern void c_finish_omp_flush (location_t); extern void c_finish_omp_taskwait (location_t); extern void c_finish_omp_taskyield (location_t); --- gcc/c-family/c-omp.c.jj 2015-10-27 12:27:26.000000000 +0100 +++ gcc/c-family/c-omp.c 2015-10-29 16:31:28.736966176 +0100 @@ -175,12 +175,14 @@ c_finish_omp_taskyield (location_t loc) LOC is the location of the atomic statement. The value returned is either error_mark_node (if the construct was erroneous) or an OMP_ATOMIC* node which should be added to the current statement - tree with add_stmt. */ + tree with add_stmt. If TEST is set, avoid calling save_expr + or create_tmp_var*. */ tree c_finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode, tree lhs, tree rhs, - tree v, tree lhs1, tree rhs1, bool swapped, bool seq_cst) + tree v, tree lhs1, tree rhs1, bool swapped, bool seq_cst, + bool test) { tree x, type, addr, pre = NULL_TREE; @@ -212,8 +214,10 @@ c_finish_omp_atomic (location_t loc, enu addr = build_unary_op (loc, ADDR_EXPR, lhs, 0); if (addr == error_mark_node) return error_mark_node; - addr = save_expr (addr); - if (TREE_CODE (addr) != SAVE_EXPR + if (!test) + addr = save_expr (addr); + if (!test + && TREE_CODE (addr) != SAVE_EXPR && (TREE_CODE (addr) != ADDR_EXPR || !VAR_P (TREE_OPERAND (addr, 0)))) { @@ -269,12 +273,15 @@ c_finish_omp_atomic (location_t loc, enu if (rhs1 && VAR_P (rhs1) && VAR_P (lhs) - && rhs1 != lhs) + && rhs1 != lhs + && !test) { if (code == OMP_ATOMIC) - error_at (loc, "%<#pragma omp atomic update%> uses two different variables for memory"); + error_at (loc, "%<#pragma omp atomic update%> uses two different " + "variables for memory"); else - error_at (loc, "%<#pragma omp atomic capture%> uses two different variables for memory"); + error_at (loc, "%<#pragma omp atomic capture%> uses two different " + "variables for memory"); return error_mark_node; } @@ -284,9 +291,10 @@ c_finish_omp_atomic (location_t loc, enu location, just diagnose different variables. */ if (lhs1 && VAR_P (lhs1) && VAR_P (lhs)) { - if (lhs1 != lhs) + if (lhs1 != lhs && !test) { - error_at (loc, "%<#pragma omp atomic capture%> uses two different variables for memory"); + error_at (loc, "%<#pragma omp atomic capture%> uses two " + "different variables for memory"); return error_mark_node; } } @@ -308,7 +316,8 @@ c_finish_omp_atomic (location_t loc, enu x = omit_one_operand_loc (loc, type, x, lhs1addr); else { - x = save_expr (x); + if (!test) + x = save_expr (x); x = omit_two_operands_loc (loc, type, x, x, lhs1addr); } } --- gcc/cp/semantics.c.jj 2015-10-29 14:07:44.000000000 +0100 +++ gcc/cp/semantics.c 2015-10-29 16:32:42.415911221 +0100 @@ -8159,7 +8159,8 @@ finish_omp_atomic (enum tree_code code, return; } stmt = c_finish_omp_atomic (input_location, code, opcode, lhs, rhs, - v, lhs1, rhs1, swapped, seq_cst); + v, lhs1, rhs1, swapped, seq_cst, + processing_template_decl != 0); if (stmt == error_mark_node) return; } --- gcc/testsuite/g++.dg/gomp/atomic-17.C.jj 2015-10-29 16:35:23.014611725 +0100 +++ gcc/testsuite/g++.dg/gomp/atomic-17.C 2015-10-29 16:11:36.000000000 +0100 @@ -0,0 +1,12 @@ +template <typename T> +struct A { int foo (); int c; }; + +template <typename T> +int +A<T>::foo () +{ + int j; + #pragma omp atomic read + j = A::c; + return j; +} Jakub