From patchwork Tue May 9 13:08:15 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 760108 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3wMfnm1kFmz9s5L for ; Tue, 9 May 2017 23:08:44 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="OMHzd44G"; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:reply-to:mime-version:content-type; q=dns; s=default; b=ciKAsF60iPzCRTIzLtGkZ6c3XNPUeBrn3UHvJFRvI1I L+z6EbshMDQn4rVmqbzRKt/rk1lBfPtPEs2l01PXoA7/q8Ag8GC9jqdaFDrhylHD oQ9FNTMikPjicaiAtAj99kiSSPfp/VM968jgYxs/WzLj7+kEVBdU/k/sG1rxIT+w = DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:reply-to:mime-version:content-type; s=default; bh=x8kiH8REdBFUgkIz1TKlK3gcmMA=; b=OMHzd44G7m4iwWyCW a80E1Qb9xMBtAaSKNrjRItGRHpoqPznsA4GktuhKQ6mlIveUA1OCWFBTuNmMda7g ysKrsU81Lvgg9Z3GulNt8hX2rgYc3A7iq4lz/38FGD5YjqWX1kdpVp2xbk58s7Aj RS5E9uDt5GeUnYUrI1bY6iEraQ= Received: (qmail 76381 invoked by alias); 9 May 2017 13:08:20 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 76148 invoked by uid 89); 9 May 2017 13:08:19 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-11.9 required=5.0 tests=BAYES_00, GIT_PATCH_2, GIT_PATCH_3, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 09 May 2017 13:08:17 +0000 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B2B21804EB for ; Tue, 9 May 2017 13:08:18 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com B2B21804EB 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@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com B2B21804EB Received: from tucnak.zalov.cz (ovpn-116-29.ams2.redhat.com [10.36.116.29]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 33B397DFDB for ; Tue, 9 May 2017 13:08:18 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.15.2/8.15.2) with ESMTP id v49D8FGe011338 for ; Tue, 9 May 2017 15:08:16 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id v49D8FWp011337 for gcc-patches@gcc.gnu.org; Tue, 9 May 2017 15:08:15 +0200 Date: Tue, 9 May 2017 15:08:15 +0200 From: Jakub Jelinek To: gcc-patches@gcc.gnu.org Subject: [gomp5] Depend clause changes Message-ID: <20170509130815.GN1809@tucnak> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.7.1 (2016-10-04) X-IsSubscribed: yes 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 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. Jakub --- 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 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 % clause", t); + "%qE is not lvalue expression nor array section in " + "% 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 % clause", t); - else - error ("%qE is not a variable in % clause", t); - remove = true; - } else if (t == current_class_ptr) { error ("% allowed in OpenMP only in %" " 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 % clause", t); + else + error ("%qE is not lvalue expression nor array section " + "in % 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" } */ + ; +}