diff mbox series

[committed] Fix #pragma omp cancel ... if handling (PR c++/88976)

Message ID 20190124194503.GT30353@tucnak
State New
Headers show
Series [committed] Fix #pragma omp cancel ... if handling (PR c++/88976) | expand

Commit Message

Jakub Jelinek Jan. 24, 2019, 7:45 p.m. UTC
Hi!

The following patch fixes C++ FE ICE during instantiation if if clause
argument is type or value dependent (ideally we'd keep the cancel
directive as OMP_* and finish it again during instantiation, but adding a
new tree code etc. just for this seems overkill).  Fixed by using what we
use for if clauses on other constructs when not processing_template_decl,
otherwise do what we used to do, but in a processing_template_decl friendly
way.

While at it, I've noticed we don't diagnose the case when cancel directive
has incorrectly more than one if clause and both if clauses have different
modifiers and the last one has cancel modifier (all other cases are
diagnosed already during the if clause parsing or at this spot for the
match of the if clause modifier).

Bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk.

2019-01-24  Jakub Jelinek  <jakub@redhat.com>

	PR c++/88976
	* c-typeck.c (c_finish_omp_cancel): Diagnose more than one if
	on #pragma omp cancel with different modifiers.

	* semantics.c (finish_omp_cancel): Diagnose more than one if
	on #pragma omp cancel with different modifiers.  Use
	maybe_convert_cond when not in template or build_x_binary_op
	otherwise.

	* c-c++-common/gomp/cancel-2.c: New test.
	* gcc.dg/gomp/cancel-1.c: New test.
	* g++.dg/gomp/cancel-1.C: New test.
	* g++.dg/gomp/cancel-2.C: New test.
	* g++.dg/gomp/cancel-3.C: New test.


	Jakub
diff mbox series

Patch

--- gcc/c/c-typeck.c.jj	2019-01-19 09:39:16.703866621 +0100
+++ gcc/c/c-typeck.c	2019-01-24 15:58:49.065106156 +0100
@@ -12766,6 +12766,18 @@  c_finish_omp_cancel (location_t loc, tre
 	  && OMP_CLAUSE_IF_MODIFIER (ifc) != VOID_CST)
 	error_at (OMP_CLAUSE_LOCATION (ifc),
 		  "expected %<cancel%> %<if%> clause modifier");
+      else
+	{
+	  tree ifc2 = omp_find_clause (OMP_CLAUSE_CHAIN (ifc), OMP_CLAUSE_IF);
+	  if (ifc2 != NULL_TREE)
+	    {
+	      gcc_assert (OMP_CLAUSE_IF_MODIFIER (ifc) == VOID_CST
+			  && OMP_CLAUSE_IF_MODIFIER (ifc2) != ERROR_MARK
+			  && OMP_CLAUSE_IF_MODIFIER (ifc2) != VOID_CST);
+	      error_at (OMP_CLAUSE_LOCATION (ifc2),
+			"expected %<cancel%> %<if%> clause modifier");
+	    }
+	}
 
       tree type = TREE_TYPE (OMP_CLAUSE_IF_EXPR (ifc));
       ifc = fold_build2_loc (OMP_CLAUSE_LOCATION (ifc), NE_EXPR,
--- gcc/cp/semantics.c.jj	2019-01-17 13:19:59.802488931 +0100
+++ gcc/cp/semantics.c	2019-01-24 15:59:04.395854827 +0100
@@ -9055,11 +9055,26 @@  finish_omp_cancel (tree clauses)
 	  && OMP_CLAUSE_IF_MODIFIER (ifc) != VOID_CST)
 	error_at (OMP_CLAUSE_LOCATION (ifc),
 		  "expected %<cancel%> %<if%> clause modifier");
+      else
+	{
+	  tree ifc2 = omp_find_clause (OMP_CLAUSE_CHAIN (ifc), OMP_CLAUSE_IF);
+	  if (ifc2 != NULL_TREE)
+	    {
+	      gcc_assert (OMP_CLAUSE_IF_MODIFIER (ifc) == VOID_CST
+			  && OMP_CLAUSE_IF_MODIFIER (ifc2) != ERROR_MARK
+			  && OMP_CLAUSE_IF_MODIFIER (ifc2) != VOID_CST);
+	      error_at (OMP_CLAUSE_LOCATION (ifc2),
+			"expected %<cancel%> %<if%> clause modifier");
+	    }
+	}
 
-      tree type = TREE_TYPE (OMP_CLAUSE_IF_EXPR (ifc));
-      ifc = fold_build2_loc (OMP_CLAUSE_LOCATION (ifc), NE_EXPR,
-			     boolean_type_node, OMP_CLAUSE_IF_EXPR (ifc),
-			     build_zero_cst (type));
+      if (!processing_template_decl)
+	ifc = maybe_convert_cond (OMP_CLAUSE_IF_EXPR (ifc));
+      else
+	ifc = build_x_binary_op (OMP_CLAUSE_LOCATION (ifc), NE_EXPR,
+				 OMP_CLAUSE_IF_EXPR (ifc), ERROR_MARK,
+				 integer_zero_node, ERROR_MARK,
+				 NULL, tf_warning_or_error);
     }
   else
     ifc = boolean_true_node;
--- gcc/testsuite/c-c++-common/gomp/cancel-2.c.jj	2019-01-24 16:07:08.278947844 +0100
+++ gcc/testsuite/c-c++-common/gomp/cancel-2.c	2019-01-24 16:07:27.576632880 +0100
@@ -0,0 +1,15 @@ 
+/* { dg-do compile } */
+
+void
+foo (void)
+{
+  #pragma omp parallel
+  {
+    #pragma omp cancel parallel if (1) if (1)			/* { dg-error "too many 'if' clauses without modifier" } */
+    #pragma omp cancel parallel if (cancel: 1) if (cancel: 1)	/* { dg-error "too many 'if' clauses with 'cancel' modifier" } */
+    #pragma omp cancel parallel if (cancel: 1) if (1)		/* { dg-error "if any 'if' clause has modifier, then all 'if' clauses have to use modifier" } */
+    #pragma omp cancel parallel if (cancel: 1) if (parallel: 1)	/* { dg-error "expected 'cancel' 'if' clause modifier" } */
+    #pragma omp cancel parallel if (1) if (cancel: 1)		/* { dg-error "if any 'if' clause has modifier, then all 'if' clauses have to use modifier" } */
+    #pragma omp cancel parallel if (parallel: 1) if (cancel: 1)	/* { dg-error "expected 'cancel' 'if' clause modifier" } */
+  }
+}
--- gcc/testsuite/gcc.dg/gomp/cancel-1.c.jj	2019-01-24 16:09:10.673950248 +0100
+++ gcc/testsuite/gcc.dg/gomp/cancel-1.c	2019-01-24 16:09:04.268054790 +0100
@@ -0,0 +1,12 @@ 
+/* { dg-do compile } */
+
+struct S { int s; } s;
+
+void
+foo (void)
+{
+  #pragma omp parallel
+  {
+    #pragma omp cancel parallel if (s)	/* { dg-error "used struct type value where scalar is required" } */
+  }
+}
--- gcc/testsuite/g++.dg/gomp/cancel-1.C.jj	2019-01-24 15:28:47.824360398 +0100
+++ gcc/testsuite/g++.dg/gomp/cancel-1.C	2019-01-24 15:29:55.956287233 +0100
@@ -0,0 +1,26 @@ 
+// PR c++/88976
+// { dg-do compile }
+
+template <class T> void
+foo (T x)
+{
+#pragma omp parallel
+  {
+  #pragma omp cancel parallel if (x)
+  }
+#pragma omp parallel
+  {
+  #pragma omp cancel parallel if (1 == 1)
+  }
+}
+
+void
+bar (int x, double y, long long z)
+{
+  foo (0);
+  foo (1LL);
+  foo (1.25);
+  foo (x);
+  foo (y);
+  foo (z);
+}
--- gcc/testsuite/g++.dg/gomp/cancel-2.C.jj	2019-01-24 15:30:29.935752008 +0100
+++ gcc/testsuite/g++.dg/gomp/cancel-2.C	2019-01-24 16:28:29.271017193 +0100
@@ -0,0 +1,20 @@ 
+// PR c++/88976
+// { dg-do compile }
+
+template <class T> void
+foo (T x)
+{
+#pragma omp parallel
+  {
+  #pragma omp cancel parallel if (x)	// { dg-error "no match for" }
+  }
+}
+
+struct S {};
+
+void
+bar ()
+{
+  S s;
+  foo (s);
+}
--- gcc/testsuite/g++.dg/gomp/cancel-3.C.jj	2019-01-24 16:07:35.803498617 +0100
+++ gcc/testsuite/g++.dg/gomp/cancel-3.C	2019-01-24 16:09:52.962260054 +0100
@@ -0,0 +1,12 @@ 
+// { dg-do compile }
+
+struct S { int s; } s;
+
+void
+foo (void)
+{
+  #pragma omp parallel
+  {
+    #pragma omp cancel parallel if (s)	// { dg-error "could not convert 's' from 'S' to 'bool'" }
+  }
+}