From patchwork Sat Jul 20 01:24:33 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 260380 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 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 1088D2C0097 for ; Sat, 20 Jul 2013 11:25:01 +1000 (EST) 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:cc:subject:message-id:reply-to:mime-version :content-type; q=dns; s=default; b=BCJ7l81vpy92WYvrRKQMpccUHPAFh CZeAtuCQ5Gkia67iGaV9QL0nprMQDKyF6mU6ga71f1mJgQlGPP8ZBdhzhki88MZ2 sYuzi7LGAQM1Ioq/Z3aNMPTubl7DiTQcaGctO8OU4iMkmQAM81FvFICtF+gtpOf5 EsVE/Vk+QGxQsA= 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:cc:subject:message-id:reply-to:mime-version :content-type; s=default; bh=5glVJYbM7n/9qvlJEPol1xkz+Dg=; b=l9c vwWWMnlcSPnaRNgU6QTtlzgodNM+EkfoneL7s9+QyyNe+4bhc60t68EGA9V1h3Yx hDwV4wmqYqsPIZm9LhJKdRUr3Cu3En5QI9tJw7dYxar8W1Ef4ygc+OFv367x432i lTX6De4sL/v86kuwIA4gVXJhHtH5zRByWX5CyUBk= Received: (qmail 20892 invoked by alias); 20 Jul 2013 01:24:53 -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 20866 invoked by uid 89); 20 Jul 2013 01:24:53 -0000 X-Spam-SWARE-Status: No, score=-3.7 required=5.0 tests=AWL, BAYES_50, KAM_STOCKGEN, RCVD_IN_HOSTKARMA_W, RCVD_IN_HOSTKARMA_WL, RDNS_NONE, SPF_HELO_PASS, SPF_PASS, TW_TM autolearn=no version=3.3.1 Received: from Unknown (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Sat, 20 Jul 2013 01:24:51 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r6K1OgSM012899 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 19 Jul 2013 21:24:42 -0400 Received: from localhost.localdomain (vpn1-5-29.ams2.redhat.com [10.36.5.29]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r6K1OcCC024635 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 19 Jul 2013 21:24:40 -0400 Received: from localhost.localdomain (localhost [127.0.0.1]) by localhost.localdomain (8.14.7/8.14.7) with ESMTP id r6K1OZc9003758; Sat, 20 Jul 2013 03:24:36 +0200 Received: (from jakub@localhost) by localhost.localdomain (8.14.7/8.14.7/Submit) id r6K1OXTV003757; Sat, 20 Jul 2013 03:24:33 +0200 Date: Sat, 20 Jul 2013 03:24:33 +0200 From: Jakub Jelinek To: "Joseph S. Myers" Cc: gcc-patches@gcc.gnu.org Subject: [gomp4] Fix up C #pragma omp declare simd parsing Message-ID: <20130720012433.GC23578@laptop.redhat.com> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Hi! This is the C FE counterpart of the http://gcc.gnu.org/ml/gcc-patches/2013-07/msg00520.html changes. The OpenMP 4.0 standard in the end requires that the #pragma omp declare simd clauses are parsed at the scope of the function parameters, but lexically comes before the function return type, so we need to remember it and parse only later. The C++ FE had support for saving tokens and parsing them later, but the C FE didn't. So, while most of the patch is just OpenMP specific stuff, the struct c_parser, c_parser_consume_{token,pragma} and c_parse_file changes affect all C users. I've bootstrapped/regtested just those changes alone and didn't find measurable differences, both in bootstrap time and on some larger C sources. I'll need this support also for #pragma omp declare reduction parsing later on. Additionally, while for the function definitions arguments are pushed again into scope, for function prototypes this doesn't happen, so I had to write utility functions in c-decl.c to do that temporarily and undo that afterwards. Joseph, any comments? 2013-07-20 Jakub Jelinek * c-typeck.c (c_finish_omp_declare_simd): Moved to... * c-parser.c (c_finish_omp_declare_simd): ... here. Add first c_parser * argument and change last argument to vec. Parse clauses here from the saved c_tokens. (struct c_parser): Change tokens to c_token *. Add tokens_buf field. Change tokens_avail type to unsigned int. (c_parser_consume_token): If parser->tokens isn't &parser->tokens_buf[0], increment parser->tokens. (c_parser_consume_pragma): Likewise (c_parser_declaration_or_fndef): Change last argument to vec. Pass parser as first argument to c_finish_omp_declare_simd. For prototypes, fix code indentation and call temp_store_parm_decls and temp_pop_parm_decls around c_finish_omp_declare_simd. (c_parser_omp_variable_list): Remove declare_simd argument, call lookup_name unconditionally. (c_parser_omp_var_list_parens, c_parser_omp_clause_reduction, c_parser_omp_clause_depend, c_parser_omp_clause_map, c_parser_omp_clause_uniform): Adjust c_parser_omp_variable_list callers. (c_parser_omp_clause_aligned, c_parser_omp_clause_linear): Likewise. Remove declare_simd argument. (c_parser_omp_all_clauses): Remove declare_simd argument. Adjust c_parser_omp_clause_aligned and c_parser_omp_clause_linear callers. (c_parser_omp_declare_simd): Don't parse declare simd clauses here, instead push the clause c_tokens starting with simd token up to CPP_PRAGMA_EOL for each #pragma omp declare simd into a vector. (c_parser_omp_declare): Don't consume simd token here. (c_parse_file): Initialize tparser.tokens and the_parser->tokens here. * c-decl.c (temp_store_parm_decls, temp_pop_parm_decls): New functions. * c-tree.h (temp_store_parm_decls, temp_pop_parm_decls): New prototypes. (c_finish_omp_declare_simd): Remove prototype. * gcc.dg/gomp/declare-simd-1.c (f16, f17, f18): New tests. Jakub --- gcc/c/c-typeck.c.jj 2013-07-14 19:43:18.000000000 +0200 +++ gcc/c/c-typeck.c 2013-07-19 22:30:39.552293476 +0200 @@ -11587,84 +11587,6 @@ c_finish_omp_clauses (tree clauses) return clauses; } -/* Finalize #pragma omp declare simd clauses after FNDECL has been parsed, - and put that into "omp declare simd" attribute. */ - -void -c_finish_omp_declare_simd (tree fndecl, tree parms, vec clauses) -{ - tree cl; - int i; - - if (clauses[0] == error_mark_node) - return; - if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL) - { - error ("%<#pragma omp declare simd%> not immediately followed by " - "a function declaration or definition"); - clauses[0] = error_mark_node; - return; - } - if (clauses[0] == integer_zero_node) - { - error_at (DECL_SOURCE_LOCATION (fndecl), - "%<#pragma omp declare simd%> not immediately followed by " - "a single function declaration or definition"); - clauses[0] = error_mark_node; - return; - } - - if (parms == NULL_TREE) - parms = DECL_ARGUMENTS (fndecl); - - FOR_EACH_VEC_ELT (clauses, i, cl) - { - tree c, *pc, decl, name; - for (pc = &cl, c = cl; c; c = *pc) - { - bool remove = false; - switch (OMP_CLAUSE_CODE (c)) - { - case OMP_CLAUSE_UNIFORM: - case OMP_CLAUSE_LINEAR: - case OMP_CLAUSE_ALIGNED: - case OMP_CLAUSE_REDUCTION: - name = OMP_CLAUSE_DECL (c); - if (name == error_mark_node) - remove = true; - else - { - for (decl = parms; decl; decl = TREE_CHAIN (decl)) - if (DECL_NAME (decl) == name) - break; - if (decl == NULL_TREE) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is not a function parameter", name); - remove = true; - } - else - OMP_CLAUSE_DECL (c) = decl; - } - break; - default: - break; - } - if (remove) - *pc = OMP_CLAUSE_CHAIN (c); - else - pc = &OMP_CLAUSE_CHAIN (c); - } - cl = c_finish_omp_clauses (cl); - cl = c_omp_declare_simd_clauses_to_numbers (parms, cl); - c = build_tree_list (get_identifier ("omp declare simd"), cl); - TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl); - DECL_ATTRIBUTES (fndecl) = c; - } - - clauses[0] = integer_zero_node; -} - /* Create a transaction node. */ tree --- gcc/c/c-parser.c.jj 2013-07-08 10:08:48.000000000 +0200 +++ gcc/c/c-parser.c 2013-07-20 01:23:38.992911552 +0200 @@ -163,9 +163,12 @@ typedef struct GTY (()) c_token { tokens of look-ahead; more are not needed for C. */ typedef struct GTY(()) c_parser { /* The look-ahead tokens. */ - c_token tokens[2]; - /* How many look-ahead tokens are available (0, 1 or 2). */ - short tokens_avail; + c_token * GTY((skip)) tokens; + /* Buffer for look-ahead tokens. */ + c_token tokens_buf[2]; + /* How many look-ahead tokens are available (0, 1 or 2, or + more if parsing from pre-lexed tokens). */ + unsigned int tokens_avail; /* True if a syntax error is being recovered from; false otherwise. c_parser_error sets this flag. It should clear this flag when enough tokens have been consumed to recover from the error. */ @@ -737,7 +740,9 @@ c_parser_consume_token (c_parser *parser gcc_assert (parser->tokens[0].type != CPP_EOF); gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL); gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA); - if (parser->tokens_avail == 2) + if (parser->tokens != &parser->tokens_buf[0]) + parser->tokens++; + else if (parser->tokens_avail == 2) parser->tokens[0] = parser->tokens[1]; parser->tokens_avail--; } @@ -751,7 +756,9 @@ c_parser_consume_pragma (c_parser *parse gcc_assert (!parser->in_pragma); gcc_assert (parser->tokens_avail >= 1); gcc_assert (parser->tokens[0].type == CPP_PRAGMA); - if (parser->tokens_avail == 2) + if (parser->tokens != &parser->tokens_buf[0]) + parser->tokens++; + else if (parser->tokens_avail == 2) parser->tokens[0] = parser->tokens[1]; parser->tokens_avail--; parser->in_pragma = true; @@ -1113,7 +1120,7 @@ enum c_parser_prec { static void c_parser_external_declaration (c_parser *); static void c_parser_asm_definition (c_parser *); static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool, - bool, bool, tree *, vec); + bool, bool, tree *, vec); static void c_parser_static_assert_declaration_no_semi (c_parser *); static void c_parser_static_assert_declaration (c_parser *); static void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool, @@ -1374,6 +1381,8 @@ c_parser_external_declaration (c_parser } } +static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec); + /* Parse a declaration or function definition (C90 6.5, 6.7.1, C99 6.7, 6.9.1). If FNDEF_OK is true, a function definition is accepted; otherwise (old-style parameter declarations) only other @@ -1450,7 +1459,7 @@ c_parser_declaration_or_fndef (c_parser bool static_assert_ok, bool empty_ok, bool nested, bool start_attr_ok, tree *objc_foreach_object_declaration, - vec omp_declare_simd_clauses) + vec omp_declare_simd_clauses) { struct c_declspecs *specs; tree prefix_attrs; @@ -1621,7 +1630,7 @@ c_parser_declaration_or_fndef (c_parser if (declarator == NULL) { if (omp_declare_simd_clauses.exists ()) - c_finish_omp_declare_simd (NULL_TREE, NULL_TREE, + c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE, omp_declare_simd_clauses); c_parser_skip_to_end_of_block_or_statement (parser); return; @@ -1660,7 +1669,7 @@ c_parser_declaration_or_fndef (c_parser if (!d) d = error_mark_node; if (omp_declare_simd_clauses.exists ()) - c_finish_omp_declare_simd (d, NULL_TREE, + c_finish_omp_declare_simd (parser, d, NULL_TREE, omp_declare_simd_clauses); start_init (d, asm_name, global_bindings_p ()); init_loc = c_parser_peek_token (parser)->location; @@ -1684,17 +1693,21 @@ c_parser_declaration_or_fndef (c_parser if (d && TREE_CODE (d) == FUNCTION_DECL) { struct c_declarator *ce = declarator; - while (ce != NULL) - if (ce->kind == cdk_function) - { - parms = ce->u.arg_info->parms; - break; - } - else - ce = ce->declarator; + while (ce != NULL) + if (ce->kind == cdk_function) + { + parms = ce->u.arg_info->parms; + break; + } + else + ce = ce->declarator; } - c_finish_omp_declare_simd (d, parms, + if (parms) + temp_store_parm_decls (d, parms); + c_finish_omp_declare_simd (parser, d, parms, omp_declare_simd_clauses); + if (parms) + temp_pop_parm_decls (); } if (d) finish_decl (d, UNKNOWN_LOCATION, NULL_TREE, @@ -1788,7 +1801,7 @@ c_parser_declaration_or_fndef (c_parser true, false, NULL, vNULL); store_parm_decls (); if (omp_declare_simd_clauses.exists ()) - c_finish_omp_declare_simd (current_function_decl, NULL_TREE, + c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE, omp_declare_simd_clauses); DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus = c_parser_peek_token (parser)->location; @@ -9058,8 +9071,7 @@ check_no_duplicate_clause (tree clauses, static tree c_parser_omp_variable_list (c_parser *parser, location_t clause_loc, - enum omp_clause_code kind, - tree list, bool declare_simd) + 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) @@ -9068,12 +9080,7 @@ c_parser_omp_variable_list (c_parser *pa while (c_parser_next_token_is (parser, CPP_NAME) && c_parser_peek_token (parser)->id_kind == C_ID_ID) { - tree t; - - if (declare_simd) - t = c_parser_peek_token (parser)->value; - else - t = lookup_name (c_parser_peek_token (parser)->value); + tree t = lookup_name (c_parser_peek_token (parser)->value); if (t == NULL_TREE) { @@ -9161,7 +9168,7 @@ c_parser_omp_var_list_parens (c_parser * if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { - list = c_parser_omp_variable_list (parser, loc, kind, list, false); + list = c_parser_omp_variable_list (parser, loc, kind, list); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); } return list; @@ -9523,7 +9530,7 @@ c_parser_omp_clause_reduction (c_parser tree nl, c; nl = c_parser_omp_variable_list (parser, clause_loc, - OMP_CLAUSE_REDUCTION, list, false); + OMP_CLAUSE_REDUCTION, list); for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) OMP_CLAUSE_REDUCTION_CODE (c) = code; @@ -9781,7 +9788,7 @@ c_parser_omp_clause_thread_limit (c_pars aligned ( variable-list : constant-expression ) */ static tree -c_parser_omp_clause_aligned (c_parser *parser, tree list, bool declare_simd) +c_parser_omp_clause_aligned (c_parser *parser, tree list) { location_t clause_loc = c_parser_peek_token (parser)->location; tree nl, c; @@ -9790,7 +9797,7 @@ c_parser_omp_clause_aligned (c_parser *p return list; nl = c_parser_omp_variable_list (parser, clause_loc, - OMP_CLAUSE_ALIGNED, list, declare_simd); + OMP_CLAUSE_ALIGNED, list); if (c_parser_next_token_is (parser, CPP_COLON)) { @@ -9820,7 +9827,7 @@ c_parser_omp_clause_aligned (c_parser *p linear ( variable-list : expression ) */ static tree -c_parser_omp_clause_linear (c_parser *parser, tree list, bool declare_simd) +c_parser_omp_clause_linear (c_parser *parser, tree list) { location_t clause_loc = c_parser_peek_token (parser)->location; tree nl, c, step; @@ -9829,7 +9836,7 @@ c_parser_omp_clause_linear (c_parser *pa return list; nl = c_parser_omp_variable_list (parser, clause_loc, - OMP_CLAUSE_LINEAR, list, declare_simd); + OMP_CLAUSE_LINEAR, list); if (c_parser_next_token_is (parser, CPP_COLON)) { @@ -9965,7 +9972,7 @@ c_parser_omp_clause_depend (c_parser *pa goto resync_fail; nl = c_parser_omp_variable_list (parser, clause_loc, - OMP_CLAUSE_DEPEND, list, false); + OMP_CLAUSE_DEPEND, list); for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) OMP_CLAUSE_DEPEND_KIND (c) = kind; @@ -10020,8 +10027,7 @@ c_parser_omp_clause_map (c_parser *parse c_parser_consume_token (parser); } - nl = c_parser_omp_variable_list (parser, clause_loc, - OMP_CLAUSE_MAP, list, false); + nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_MAP, list); for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) OMP_CLAUSE_MAP_KIND (c) = kind; @@ -10181,7 +10187,7 @@ c_parser_omp_clause_uniform (c_parser *p if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) { list = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_UNIFORM, - list, true); + list); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); } return list; @@ -10193,8 +10199,7 @@ c_parser_omp_clause_uniform (c_parser *p static tree c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask, - const char *where, bool finish_p = true, - bool declare_simd = false) + const char *where, bool finish_p = true) { tree clauses = NULL; bool first = true; @@ -10350,12 +10355,11 @@ c_parser_omp_all_clauses (c_parser *pars c_name = "thread_limit"; break; case PRAGMA_OMP_CLAUSE_ALIGNED: - clauses = c_parser_omp_clause_aligned (parser, clauses, - declare_simd); + clauses = c_parser_omp_clause_aligned (parser, clauses); c_name = "aligned"; break; case PRAGMA_OMP_CLAUSE_LINEAR: - clauses = c_parser_omp_clause_linear (parser, clauses, declare_simd); + clauses = c_parser_omp_clause_linear (parser, clauses); c_name = "linear"; break; case PRAGMA_OMP_CLAUSE_DEPEND: @@ -11976,10 +11980,21 @@ c_parser_omp_target (c_parser *parser, e static void c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context) { - vec clauses = vNULL; - tree cl = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK, - "#pragma omp declare simd", false, true); - clauses.safe_push (cl); + vec clauses = vNULL; + while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) + { + c_token *token = c_parser_peek_token (parser); + if (token->type == CPP_EOF) + { + c_parser_skip_to_pragma_eol (parser); + clauses.release (); + return; + } + clauses.safe_push (*token); + c_parser_consume_token (parser); + } + clauses.safe_push (*c_parser_peek_token (parser)); + c_parser_skip_to_pragma_eol (parser); while (c_parser_next_token_is (parser, CPP_PRAGMA)) { @@ -11998,12 +12013,29 @@ c_parser_omp_declare_simd (c_parser *par return; } c_parser_consume_pragma (parser); - c_parser_consume_token (parser); - cl = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK, - "#pragma omp declare simd", false, true); - clauses.safe_push (cl); + while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)) + { + c_token *token = c_parser_peek_token (parser); + if (token->type == CPP_EOF) + { + c_parser_skip_to_pragma_eol (parser); + clauses.release (); + return; + } + clauses.safe_push (*token); + c_parser_consume_token (parser); + } + clauses.safe_push (*c_parser_peek_token (parser)); + c_parser_skip_to_pragma_eol (parser); } + /* 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; + clauses.safe_push (eof_token); + clauses.safe_push (eof_token); + switch (context) { case pragma_external: @@ -12062,6 +12094,65 @@ c_parser_omp_declare_simd (c_parser *par clauses.release (); } +/* Finalize #pragma omp declare simd clauses after FNDECL has been parsed, + and put that into "omp declare simd" attribute. */ + +static void +c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms, + vec clauses) +{ + /* Normally first token is CPP_NAME "simd". CPP_EOF there indicates + error has been reported and CPP_PRAGMA that c_finish_omp_declare_simd + has already processed the tokens. */ + if (clauses[0].type == CPP_EOF) + return; + if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL) + { + error ("%<#pragma omp declare simd%> not immediately followed by " + "a function declaration or definition"); + clauses[0].type = CPP_EOF; + return; + } + if (clauses[0].type != CPP_NAME) + { + error_at (DECL_SOURCE_LOCATION (fndecl), + "%<#pragma omp declare simd%> not immediately followed by " + "a single function declaration or definition"); + clauses[0].type = CPP_EOF; + return; + } + + if (parms == NULL_TREE) + parms = DECL_ARGUMENTS (fndecl); + + unsigned int tokens_avail = parser->tokens_avail; + gcc_assert (parser->tokens == &parser->tokens_buf[0]); + parser->tokens = clauses.address (); + parser->tokens_avail = clauses.length (); + + /* c_parser_omp_declare_simd pushed 2 extra CPP_EOF tokens at the end. */ + while (parser->tokens_avail > 3) + { + c_token *token = c_parser_peek_token (parser); + gcc_assert (token->type == CPP_NAME + && strcmp (IDENTIFIER_POINTER (token->value), "simd") == 0); + c_parser_consume_token (parser); + parser->in_pragma = true; + + tree c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK, + "#pragma omp declare simd"); + c = c_omp_declare_simd_clauses_to_numbers (parms, c); + c = build_tree_list (get_identifier ("omp declare simd"), c); + TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl); + DECL_ATTRIBUTES (fndecl) = c; + } + + parser->tokens = &parser->tokens_buf[0]; + parser->tokens_avail = tokens_avail; + clauses[0].type = CPP_PRAGMA; +} + + /* OpenMP 4.0: # pragma omp declare target new-line declarations and definitions @@ -12124,7 +12215,8 @@ c_parser_omp_declare (c_parser *parser, const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); if (strcmp (p, "simd") == 0) { - c_parser_consume_token (parser); + /* c_parser_consume_token (parser); done in + c_parser_omp_declare_simd. */ c_parser_omp_declare_simd (parser, context); return; } @@ -12495,6 +12587,7 @@ c_parse_file (void) c_parser tparser; memset (&tparser, 0, sizeof tparser); + tparser.tokens = &tparser.tokens_buf[0]; the_parser = &tparser; if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS) @@ -12502,6 +12595,8 @@ c_parse_file (void) the_parser = ggc_alloc_c_parser (); *the_parser = tparser; + if (tparser.tokens == &tparser.tokens_buf[0]) + the_parser->tokens = &the_parser->tokens_buf[0]; /* Initialize EH, if we've been told to do so. */ if (flag_exceptions) --- gcc/c/c-tree.h.jj 2013-06-04 20:55:40.000000000 +0200 +++ gcc/c/c-tree.h 2013-07-19 22:31:08.685298840 +0200 @@ -526,6 +526,8 @@ extern tree start_struct (location_t, en struct c_struct_parse_info **); extern void store_parm_decls (void); extern void store_parm_decls_from (struct c_arg_info *); +extern void temp_store_parm_decls (tree, tree); +extern void temp_pop_parm_decls (void); extern tree xref_tag (enum tree_code, tree); extern struct c_typespec parser_xref_tag (location_t, enum tree_code, tree); extern struct c_parm *build_c_parm (struct c_declspecs *, tree, @@ -642,7 +644,6 @@ extern void c_finish_omp_taskgroup (loca extern void c_finish_omp_cancel (location_t, tree); extern void c_finish_omp_cancellation_point (location_t, tree); extern tree c_finish_omp_clauses (tree); -extern void c_finish_omp_declare_simd (tree, tree, vec); extern tree c_build_va_arg (location_t, tree, tree); extern tree c_finish_transaction (location_t, tree, int); extern bool c_tree_equal (tree, tree); --- gcc/c/c-decl.c.jj 2013-07-08 10:08:48.000000000 +0200 +++ gcc/c/c-decl.c 2013-07-20 02:30:12.904762092 +0200 @@ -8353,6 +8353,44 @@ store_parm_decls (void) if (arg_info->pending_sizes) add_stmt (arg_info->pending_sizes); } + +/* Store PARM_DECLs in PARMS into scope temporarily. Used for + c_finish_omp_declare_simd for function prototypes. No diagnostics + should be done. */ + +void +temp_store_parm_decls (tree fndecl, tree parms) +{ + push_scope (); + for (tree p = parms; p; p = DECL_CHAIN (p)) + { + DECL_CONTEXT (p) = fndecl; + if (DECL_NAME (p)) + bind (DECL_NAME (p), p, current_scope, + /*invisible=*/false, /*nested=*/false, + UNKNOWN_LOCATION); + } +} + +/* Undo what temp_store_parm_decls did. */ + +void +temp_pop_parm_decls (void) +{ + /* Clear all bindings in this temporary scope, so that + pop_scope doesn't create a BLOCK. */ + struct c_binding *b = current_scope->bindings; + current_scope->bindings = NULL; + for (; b; b = free_binding_and_advance (b)) + { + gcc_assert (TREE_CODE (b->decl) == PARM_DECL); + gcc_assert (I_SYMBOL_BINDING (b->id) == b); + I_SYMBOL_BINDING (b->id) = b->shadowed; + if (b->shadowed && b->shadowed->u.type) + TREE_TYPE (b->shadowed->decl) = b->shadowed->u.type; + } + pop_scope (); +} /* Finish up a function declaration and compile that function --- gcc/testsuite/gcc.dg/gomp/declare-simd-1.c.jj 2013-06-04 20:57:49.000000000 +0200 +++ gcc/testsuite/gcc.dg/gomp/declare-simd-1.c 2013-07-20 02:48:35.622014339 +0200 @@ -80,3 +80,21 @@ f15 (int a, int *b, int c) #pragma omp declare simd uniform (d) aligned (e : 8 * sizeof (int)) linear (f : 4) simdlen (8) int f15 (int d, int *e, int f); + +#pragma omp declare simd aligned (g : sizeof (*g)) linear (h : 2 * sizeof (g[0]) + sizeof (h)) simdlen (4) +int f16 (long *g, int h); + +#pragma omp declare simd aligned (h : sizeof (*h)) linear (g : 2 * sizeof (h[0]) + sizeof (g)) simdlen (4) +int f17 (int g, long *h) +{ + return g + h[0]; +} + +#pragma omp declare simd aligned (i : sizeof (*i)) linear (j : 2 * sizeof (i[0]) + sizeof (j)) simdlen (4) +int +f18 (j, i) + long *i; + int j; +{ + return j + i[0]; +}