This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[gomp5] Depend clause changes
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 9 May 2017 15:08:15 +0200
- Subject: [gomp5] Depend clause changes
- Authentication-results: sourceware.org; auth=none
- Authentication-results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com
- Authentication-results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=jakub at redhat dot com
- Dkim-filter: OpenDKIM Filter v2.11.0 mx1.redhat.com B2B21804EB
- Dmarc-filter: OpenDMARC Filter v1.3.2 mx1.redhat.com B2B21804EB
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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