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]

[gomp5] Depend clause changes


Hi!

In OpenMP 5.0, depend clause operands are location list items, which
are either lvalue expressions, or array sections.  In C++ it is easy
to handle it with tentative parsing, in C I have to use similar hacks
to what is used for declare simd.

Tested on x86_64-linux, committed to gomp-5_0-branch.

2017-05-09  Jakub Jelinek  <jakub@redhat.com>

c/
	* c-parser.c (c_parser_omp_variable_list): For OMP_CLAUSE_DEPEND,
	parse clause operands as either an array section, or lvalue assignment
	expression.
	* c-typeck.c (c_finish_omp_clauses): Allow any lvalue as
	OMP_CLAUSE_DEPEND operand (besides array section), adjust diagnostics.
cp/
	* parser.c (cp_parser_omp_var_list_no_open): For OMP_CLAUSE_DEPEND,
	parse clause operands as either an array section, or lvalue assignment
	expression.
	* semantics.c (finish_omp_clauses): Allow any lvalue as
	OMP_CLAUSE_DEPEND operand (besides array section), adjust diagnostics.
testsuite/
	* c-c++-common/gomp/depend-5.c: New test.
	* c-c++-common/gomp/depend-6.c: New test.

--- gcc/c/c-parser.c.jj	2017-05-04 15:27:33.306131900 +0200
+++ gcc/c/c-parser.c	2017-05-09 14:05:46.874354097 +0200
@@ -10737,13 +10737,87 @@ c_parser_omp_variable_list (c_parser *pa
 			    location_t clause_loc,
 			    enum omp_clause_code kind, tree list)
 {
-  if (c_parser_next_token_is_not (parser, CPP_NAME)
-      || c_parser_peek_token (parser)->id_kind != C_ID_ID)
+  auto_vec<c_token> tokens;
+  unsigned int tokens_avail = 0;
+
+  if (kind != OMP_CLAUSE_DEPEND
+      && (c_parser_next_token_is_not (parser, CPP_NAME)
+	  || c_parser_peek_token (parser)->id_kind != C_ID_ID))
     c_parser_error (parser, "expected identifier");
 
-  while (c_parser_next_token_is (parser, CPP_NAME)
-	 && c_parser_peek_token (parser)->id_kind == C_ID_ID)
+  while (kind == OMP_CLAUSE_DEPEND
+	 || (c_parser_next_token_is (parser, CPP_NAME)
+	     && c_parser_peek_token (parser)->id_kind == C_ID_ID))
     {
+      bool array_section_p = false;
+      if (kind == OMP_CLAUSE_DEPEND)
+	{
+	  if (c_parser_next_token_is_not (parser, CPP_NAME)
+	      || c_parser_peek_token (parser)->id_kind != C_ID_ID)
+	    {
+	      struct c_expr expr = c_parser_expr_no_commas (parser, NULL);
+	      if (expr.value != error_mark_node)
+		{
+		  tree u = build_omp_clause (clause_loc, kind);
+		  OMP_CLAUSE_DECL (u) = expr.value;
+		  OMP_CLAUSE_CHAIN (u) = list;
+		  list = u;
+		}
+
+	      if (c_parser_next_token_is_not (parser, CPP_COMMA))
+		break;
+
+	      c_parser_consume_token (parser);
+	      continue;
+	    }
+
+	  tokens.truncate (0);
+	  unsigned int nesting_depth = 0;
+	  while (1)
+	    {
+	      c_token *token = c_parser_peek_token (parser);
+	      switch (token->type)
+		{
+		case CPP_EOF:
+		case CPP_PRAGMA_EOL:
+		  break;
+		case CPP_OPEN_BRACE:
+		case CPP_OPEN_PAREN:
+		case CPP_OPEN_SQUARE:
+		  ++nesting_depth;
+		  goto add;
+		case CPP_CLOSE_BRACE:
+		case CPP_CLOSE_PAREN:
+		case CPP_CLOSE_SQUARE:
+		  if (nesting_depth-- == 0)
+		    break;
+		  goto add;
+		case CPP_COMMA:
+		  if (nesting_depth == 0)
+		    break;
+		  goto add;
+		default:
+		add:
+		  tokens.safe_push (*token);
+		  c_parser_consume_token (parser);
+		  continue;
+		}
+	      break;
+	    }
+
+	  /* Make sure nothing tries to read past the end of the tokens.  */
+	  c_token eof_token;
+	  memset (&eof_token, 0, sizeof (eof_token));
+	  eof_token.type = CPP_EOF;
+	  tokens.safe_push (eof_token);
+	  tokens.safe_push (eof_token);
+
+	  tokens_avail = parser->tokens_avail;
+	  gcc_assert (parser->tokens == &parser->tokens_buf[0]);
+	  parser->tokens = tokens.address ();
+	  parser->tokens_avail = tokens.length ();
+	}
+
       tree t = lookup_name (c_parser_peek_token (parser)->value);
 
       if (t == NULL_TREE)
@@ -10819,6 +10893,7 @@ c_parser_omp_variable_list (c_parser *pa
 			  t = error_mark_node;
 			  break;
 			}
+		      array_section_p = true;
 		      if (!c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
 			{
 			  location_t expr_loc
@@ -10839,6 +10914,30 @@ c_parser_omp_variable_list (c_parser *pa
 
 		  t = tree_cons (low_bound, length, t);
 		}
+	      if (kind == OMP_CLAUSE_DEPEND
+		  && t != error_mark_node
+		  && parser->tokens_avail != 2)
+		{
+		  if (array_section_p)
+		    {
+		      error_at (c_parser_peek_token (parser)->location,
+				"expected %<)%> or %<,%>");
+		      t = error_mark_node;
+		    }
+		  else
+		    {
+		      parser->tokens = tokens.address ();
+		      parser->tokens_avail = tokens.length ();
+
+		      t = c_parser_expr_no_commas (parser, NULL).value;
+		      if (t != error_mark_node && parser->tokens_avail != 2)
+			{
+			  error_at (c_parser_peek_token (parser)->location,
+				    "expected %<)%> or %<,%>");
+			  t = error_mark_node;
+			}
+		    }
+		}
 	      break;
 	    default:
 	      break;
@@ -10855,6 +10954,11 @@ c_parser_omp_variable_list (c_parser *pa
       else
 	list = tree_cons (t, NULL_TREE, list);
 
+      if (kind == OMP_CLAUSE_DEPEND)
+	{
+	  parser->tokens = &parser->tokens_buf[0];
+	  parser->tokens_avail = tokens_avail;
+	}
       if (c_parser_next_token_is_not (parser, CPP_COMMA))
 	break;
 
--- gcc/c/c-typeck.c.jj	2017-05-04 15:05:06.000000000 +0200
+++ gcc/c/c-typeck.c	2017-05-09 13:54:44.092945431 +0200
@@ -13330,10 +13330,11 @@ c_finish_omp_clauses (tree clauses, enum
 	    }
 	  if (t == error_mark_node)
 	    remove = true;
-	  else if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+	  else if (!lvalue_p (t))
 	    {
 	      error_at (OMP_CLAUSE_LOCATION (c),
-			"%qE is not a variable in %<depend%> clause", t);
+			"%qE is not lvalue expression nor array section in "
+			"%<depend%> clause", t);
 	      remove = true;
 	    }
 	  else if (!c_mark_addressable (t))
--- gcc/cp/parser.c.jj	2017-05-04 15:28:27.000000000 +0200
+++ gcc/cp/parser.c	2017-05-09 09:53:42.314990410 +0200
@@ -30888,6 +30888,8 @@ cp_parser_omp_var_list_no_open (cp_parse
     {
       tree name, decl;
 
+      if (kind == OMP_CLAUSE_DEPEND)
+	cp_parser_parse_tentatively (parser);
       token = cp_lexer_peek_token (parser->lexer);
       if (kind != 0
 	  && current_class_ptr
@@ -30907,7 +30909,12 @@ cp_parser_omp_var_list_no_open (cp_parse
 					  /*declarator_p=*/false,
 					  /*optional_p=*/false);
 	  if (name == error_mark_node)
-	    goto skip_comma;
+	    {
+	      if (kind == OMP_CLAUSE_DEPEND
+		  && cp_parser_simulate_error (parser))
+		goto depend_lvalue;
+	      goto skip_comma;
+	    }
 
 	  decl = cp_parser_lookup_name_simple (parser, name, token->location);
 	  if (decl == error_mark_node)
@@ -30965,7 +30972,14 @@ cp_parser_omp_var_list_no_open (cp_parse
 		    {
 		      /* Look for `:'.  */
 		      if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
-			goto skip_comma;
+			{
+			  if (kind == OMP_CLAUSE_DEPEND
+			      && cp_parser_simulate_error (parser))
+			    goto depend_lvalue;
+			  goto skip_comma;
+			}
+		      if (kind == OMP_CLAUSE_DEPEND)
+			cp_parser_commit_to_tentative_parse (parser);
 		      if (!cp_lexer_next_token_is (parser->lexer,
 						   CPP_CLOSE_SQUARE))
 			length = cp_parser_expression (parser);
@@ -30973,7 +30987,12 @@ cp_parser_omp_var_list_no_open (cp_parse
 		  /* Look for the closing `]'.  */
 		  if (!cp_parser_require (parser, CPP_CLOSE_SQUARE,
 					  RT_CLOSE_SQUARE))
-		    goto skip_comma;
+		    {
+		      if (kind == OMP_CLAUSE_DEPEND
+			  && cp_parser_simulate_error (parser))
+			goto depend_lvalue;
+		      goto skip_comma;
+		    }
 
 		  decl = tree_cons (low_bound, length, decl);
 		}
@@ -30982,6 +31001,21 @@ cp_parser_omp_var_list_no_open (cp_parse
 	      break;
 	    }
 
+	  if (kind == OMP_CLAUSE_DEPEND)
+	    {
+	      if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)
+		  && cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
+		  && cp_parser_simulate_error (parser))
+		{
+		depend_lvalue:
+		  cp_parser_abort_tentative_parse (parser);
+		  decl = cp_parser_assignment_expression (parser, NULL,
+							  false, false);
+		}
+	      else
+		cp_parser_parse_definitely (parser);
+	    }
+
 	  tree u = build_omp_clause (token->location, kind);
 	  OMP_CLAUSE_DECL (u) = decl;
 	  OMP_CLAUSE_CHAIN (u) = list;
--- gcc/cp/semantics.c.jj	2017-05-04 15:05:49.000000000 +0200
+++ gcc/cp/semantics.c	2017-05-09 14:43:34.772324756 +0200
@@ -6626,24 +6626,25 @@ finish_omp_clauses (tree clauses, enum c
 	    }
 	  if (t == error_mark_node)
 	    remove = true;
-	  else if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
-	    {
-	      if (processing_template_decl)
-		break;
-	      if (DECL_P (t))
-		error ("%qD is not a variable in %<depend%> clause", t);
-	      else
-		error ("%qE is not a variable in %<depend%> clause", t);
-	      remove = true;
-	    }
 	  else if (t == current_class_ptr)
 	    {
 	      error ("%<this%> allowed in OpenMP only in %<declare simd%>"
 		     " clauses");
 	      remove = true;
 	    }
-	  else if (!processing_template_decl
-		   && !cxx_mark_addressable (t))
+          else if (processing_template_decl)
+	    break;
+	  else if (!lvalue_p (t))
+	    {
+	      if (DECL_P (t))
+		error ("%qD is not lvalue expression nor array section "
+		       "in %<depend%> clause", t);
+	      else
+		error ("%qE is not lvalue expression nor array section "
+		       "in %<depend%> clause", t);
+	      remove = true;
+	    }
+	  else if (!cxx_mark_addressable (t))
 	    remove = true;
 	  break;
 
--- gcc/testsuite/c-c++-common/gomp/depend-5.c.jj	2017-05-09 14:13:32.889516537 +0200
+++ gcc/testsuite/c-c++-common/gomp/depend-5.c	2017-05-09 14:13:50.058294285 +0200
@@ -0,0 +1,48 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+struct T { int c[3]; };
+struct S { int a; struct T *b; struct T g; };
+struct S d[10];
+struct S *e[10];
+struct S *f;
+struct S h;
+
+void
+foo (void)
+{
+  #pragma omp task depend(inout: d)
+  ;
+  #pragma omp task depend(out: d[2])
+  ;
+  #pragma omp task depend(in: d[:])
+  ;
+  #pragma omp task depend(in: d[2:2])
+  ;
+  #pragma omp task depend(in: d[:2])
+  ;
+  #pragma omp task depend(inout: d[1].b->c[2])
+  ;
+  #pragma omp task depend(out: d[0].a)
+  ;
+  #pragma omp task depend(in: e[3]->a)
+  ;
+  #pragma omp task depend(inout: e[2]->b->c)
+  ;
+  #pragma omp task depend(in: e[1]->b->c[2])
+  ;
+  #pragma omp task depend(out: (*f).a)
+  ;
+  #pragma omp task depend(inout: f->b->c[0])
+  ;
+  #pragma omp task depend(in: f)
+  ;
+  #pragma omp task depend(out: *f)
+  ;
+  #pragma omp task depend(inout: f[0])
+  ;
+  #pragma omp task depend(in: f[0].a)
+  ;
+  #pragma omp task depend(inout: h.g.c[2])
+  ;
+}
--- gcc/testsuite/c-c++-common/gomp/depend-6.c.jj	2017-05-09 14:13:35.869477961 +0200
+++ gcc/testsuite/c-c++-common/gomp/depend-6.c	2017-05-09 14:13:58.002191451 +0200
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+struct T { int c[3]; };
+struct S { int a; struct T *b; struct T g; };
+struct S d[10];
+struct S *e[10];
+struct S *f;
+struct S h;
+
+void
+foo (void)
+{
+  #pragma omp task depend(in: d[:2].b->c[2])	/* { dg-error "expected" } */
+  ;
+  #pragma omp task depend(inout: d[1:].b->c[2])	/* { dg-error "expected" } */
+  ;
+  #pragma omp task depend(out: d[0:1].a)	/* { dg-error "expected" } */
+  ;
+  #pragma omp task depend(in: e[3:2]->a)	/* { dg-error "expected" } */
+  ;
+  #pragma omp task depend(inout: e[2:2]->b->c)	/* { dg-error "expected" } */
+  ;
+  #pragma omp task depend(in: e[1]->b->c[2:1])	/* { dg-error "expected" } */
+  ;
+  #pragma omp task depend(out: f + 0)		/* { dg-error "not lvalue expression" } */
+  ;
+  #pragma omp task depend(inout: f[0:1].a)	/* { dg-error "expected" } */
+  ;
+  #pragma omp task depend(inout: h.g.c[2:1])	/* { dg-error "expected" } */
+  ;
+}

	Jakub


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