This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gomp4.5] Fix checking ICE with atomic in a template


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  <jakub@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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]