Hi! As expected, the C FE in this case was easier than C++, for #pragma omp declare reduction it will be the other way around, C will be much harder.
Committed to gomp-4_0-branch. 2013-05-13 Jakub Jelinek <ja...@redhat.com> * c-tree.h (c_finish_omp_declare_simd): New prototype. * c-typeck.c (c_finish_omp_clauses): Handle OMP_CLAUSE_LINEAR_STEP adjustments for pointer-types here. Diagnose inbranch notinbranch being used together. (c_finish_omp_declare_simd): New function. * c-parser.c (enum pragma_context): Add pragma_struct and pragma_param. (c_parser_declaration_or_fndef): Add omp_declare_simd_clauses argument. Call c_finish_omp_declare_simd if needed. (c_parser_external_declaration, c_parser_compound_statement_nostart, c_parser_label, c_parser_for_statement, c_parser_objc_methodprotolist, c_parser_omp_for_loop): Adjust c_parser_declaration_or_fndef callers. (c_parser_struct_or_union_specifier): Use pragma_struct instead of pragma_external. (c_parser_parameter_declaration): Use pragma_param instead of pragma_external. (c_parser_pragma): Handle PRAGMA_OMP_DECLARE_REDUCTION. Replace == pragma_external with != pragma_stmt && != pragma_compound test. (c_parser_omp_variable_list): Add declare_simd argument. Don't lookup vars if it is true, just store identifiers. (c_parser_omp_var_list_parens, c_parser_omp_clause_depend, c_parser_omp_clause_map): Adjust callers. (c_parser_omp_clause_reduction, c_parser_omp_clause_aligned): Add declare_simd argument, pass it through to c_parser_omp_variable_list. (c_parser_omp_clause_linear): Likewise. Don't handle OMP_CLAUSE_LINEAR_STEP adjustements for pointer-types here. (c_parser_omp_clause_uniform): Call c_parser_omp_variable_list instead of c_parser_omp_var_list_parens to pass true as declare_simd. (c_parser_omp_all_clauses): Add declare_simd argument, pass it through clause parsing routines as needed. Don't call c_finish_omp_clauses if set. (c_parser_omp_simd, c_parser_omp_for, c_parser_omp_sections, c_parser_omp_parallel, c_parser_omp_single, c_parser_omp_task, c_parser_omp_cancel, c_parser_omp_cancellation_point): Adjust callers. (OMP_DECLARE_SIMD_CLAUSE_MASK): Define. (c_parser_omp_declare_simd, c_parser_omp_declare): New functions. * gcc.dg/gomp/declare-simd-1.c: New test. * gcc.dg/gomp/declare-simd-2.c: New test. --- gcc/c/c-tree.h.jj 2013-04-24 16:53:21.000000000 +0200 +++ gcc/c/c-tree.h 2013-05-13 12:50:51.536759893 +0200 @@ -642,6 +642,7 @@ 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<tree>); 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-typeck.c.jj 2013-04-24 17:51:21.000000000 +0200 +++ gcc/c/c-typeck.c 2013-05-13 13:59:23.654460967 +0200 @@ -10670,6 +10670,7 @@ c_finish_omp_clauses (tree clauses) bitmap_head aligned_head; tree c, t, *pc = &clauses; const char *name; + bool branch_seen = false; bitmap_obstack_initialize (NULL); bitmap_initialize (&generic_head, &bitmap_default_obstack); @@ -10774,6 +10775,17 @@ c_finish_omp_clauses (tree clauses) remove = true; break; } + if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c))) == POINTER_TYPE) + { + tree s = OMP_CLAUSE_LINEAR_STEP (c); + s = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR, + OMP_CLAUSE_DECL (c), s); + s = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MINUS_EXPR, + sizetype, s, OMP_CLAUSE_DECL (c)); + if (s == error_mark_node) + s = size_one_node; + OMP_CLAUSE_LINEAR_STEP (c) = s; + } goto check_dup_generic; check_dup_generic: @@ -10919,8 +10931,6 @@ c_finish_omp_clauses (tree clauses) case OMP_CLAUSE_SIMDLEN: case OMP_CLAUSE_DEVICE: case OMP_CLAUSE_DIST_SCHEDULE: - case OMP_CLAUSE_INBRANCH: - case OMP_CLAUSE_NOTINBRANCH: case OMP_CLAUSE_PARALLEL: case OMP_CLAUSE_FOR: case OMP_CLAUSE_SECTIONS: @@ -10929,6 +10939,20 @@ c_finish_omp_clauses (tree clauses) pc = &OMP_CLAUSE_CHAIN (c); continue; + case OMP_CLAUSE_INBRANCH: + case OMP_CLAUSE_NOTINBRANCH: + if (branch_seen) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%<inbranch%> clause is incompatible with " + "%<notinbranch%>"); + remove = true; + break; + } + branch_seen = true; + pc = &OMP_CLAUSE_CHAIN (c); + continue; + default: gcc_unreachable (); } @@ -10987,6 +11011,93 @@ 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<tree> 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); + tree saved_arguments = DECL_ARGUMENTS (fndecl); + DECL_ARGUMENTS (fndecl) = parms; + cl = c_omp_declare_simd_clauses_to_numbers (fndecl, cl); + DECL_ARGUMENTS (fndecl) = saved_arguments; + for (c = lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (fndecl)); + c; c = lookup_attribute ("omp declare simd", TREE_CHAIN (c))) + if (omp_declare_simd_clauses_equal (TREE_VALUE (c), cl)) + break; + if (c) + continue; + 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-05-09 17:04:26.436047147 +0200 +++ gcc/c/c-parser.c 2013-05-13 13:05:56.063771052 +0200 @@ -1112,7 +1112,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 *); + bool, bool, tree *, vec<tree>); 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, @@ -1189,8 +1189,10 @@ static void c_parser_omp_taskyield (c_pa static void c_parser_omp_cancel (c_parser *); static void c_parser_omp_cancellation_point (c_parser *); -enum pragma_context { pragma_external, pragma_stmt, pragma_compound }; +enum pragma_context { pragma_external, pragma_struct, pragma_param, + pragma_stmt, pragma_compound }; static bool c_parser_pragma (c_parser *, enum pragma_context); +static void c_parser_omp_declare (c_parser *, enum pragma_context); /* These Objective-C parser functions are only ever called when compiling Objective-C. */ @@ -1361,7 +1363,8 @@ c_parser_external_declaration (c_parser an @interface or @protocol with prefix attributes). We can only tell which after parsing the declaration specifiers, if any, and the first declarator. */ - c_parser_declaration_or_fndef (parser, true, true, true, false, true, NULL); + c_parser_declaration_or_fndef (parser, true, true, true, false, true, + NULL, vNULL); break; } } @@ -1441,7 +1444,8 @@ static void c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, bool static_assert_ok, bool empty_ok, bool nested, bool start_attr_ok, - tree *objc_foreach_object_declaration) + tree *objc_foreach_object_declaration, + vec<tree> omp_declare_simd_clauses) { struct c_declspecs *specs; tree prefix_attrs; @@ -1611,6 +1616,9 @@ c_parser_declaration_or_fndef (c_parser C_DTR_NORMAL, &dummy); if (declarator == NULL) { + if (omp_declare_simd_clauses.exists ()) + c_finish_omp_declare_simd (NULL_TREE, NULL_TREE, + omp_declare_simd_clauses); c_parser_skip_to_end_of_block_or_statement (parser); return; } @@ -1647,6 +1655,9 @@ c_parser_declaration_or_fndef (c_parser chainon (postfix_attrs, all_prefix_attrs)); if (!d) d = error_mark_node; + if (omp_declare_simd_clauses.exists ()) + c_finish_omp_declare_simd (d, NULL_TREE, + omp_declare_simd_clauses); start_init (d, asm_name, global_bindings_p ()); init_loc = c_parser_peek_token (parser)->location; init = c_parser_initializer (parser); @@ -1663,6 +1674,24 @@ c_parser_declaration_or_fndef (c_parser tree d = start_decl (declarator, specs, false, chainon (postfix_attrs, all_prefix_attrs)); + if (omp_declare_simd_clauses.exists ()) + { + tree parms = NULL_TREE; + 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; + } + c_finish_omp_declare_simd (d, parms, + omp_declare_simd_clauses); + } if (d) finish_decl (d, UNKNOWN_LOCATION, NULL_TREE, NULL_TREE, asm_name); @@ -1752,8 +1781,11 @@ c_parser_declaration_or_fndef (c_parser while (c_parser_next_token_is_not (parser, CPP_EOF) && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE)) c_parser_declaration_or_fndef (parser, false, false, false, - true, false, NULL); + true, false, NULL, vNULL); store_parm_decls (); + if (omp_declare_simd_clauses.exists ()) + c_finish_omp_declare_simd (current_function_decl, NULL_TREE, + omp_declare_simd_clauses); DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus = c_parser_peek_token (parser)->location; fnbody = c_parser_compound_statement (parser); @@ -2480,7 +2512,7 @@ c_parser_struct_or_union_specifier (c_pa /* Accept #pragmas at struct scope. */ if (c_parser_next_token_is (parser, CPP_PRAGMA)) { - c_parser_pragma (parser, pragma_external); + c_parser_pragma (parser, pragma_struct); continue; } /* Parse some comma-separated declarations, but not the @@ -3311,7 +3343,7 @@ c_parser_parameter_declaration (c_parser /* Accept #pragmas between parameter declarations. */ while (c_parser_next_token_is (parser, CPP_PRAGMA)) - c_parser_pragma (parser, pragma_external); + c_parser_pragma (parser, pragma_param); if (!c_parser_next_token_starts_declspecs (parser)) { @@ -4161,7 +4193,8 @@ c_parser_compound_statement_nostart (c_p { last_label = false; mark_valid_location_for_stdc_pragma (false); - c_parser_declaration_or_fndef (parser, true, true, true, true, true, NULL); + c_parser_declaration_or_fndef (parser, true, true, true, true, + true, NULL, vNULL); if (last_stmt) pedwarn_c90 (loc, (pedantic && !flag_isoc99) @@ -4189,7 +4222,7 @@ c_parser_compound_statement_nostart (c_p last_label = false; mark_valid_location_for_stdc_pragma (false); c_parser_declaration_or_fndef (parser, true, true, true, true, - true, NULL); + true, NULL, vNULL); /* Following the old parser, __extension__ does not disable this diagnostic. */ restore_extension_diagnostics (ext); @@ -4327,7 +4360,8 @@ c_parser_label (c_parser *parser) c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false, /*static_assert_ok*/ true, /*empty_ok*/ true, /*nested*/ true, - /*start_attr_ok*/ true, NULL); + /*start_attr_ok*/ true, NULL, + vNULL); } } } @@ -4947,7 +4981,7 @@ c_parser_for_statement (c_parser *parser else if (c_parser_next_tokens_start_declaration (parser)) { c_parser_declaration_or_fndef (parser, true, true, true, true, true, - &object_expression); + &object_expression, vNULL); parser->objc_could_be_foreach_context = false; if (c_parser_next_token_is_keyword (parser, RID_IN)) @@ -4976,7 +5010,7 @@ c_parser_for_statement (c_parser *parser ext = disable_extension_diagnostics (); c_parser_consume_token (parser); c_parser_declaration_or_fndef (parser, true, true, true, true, - true, &object_expression); + true, &object_expression, vNULL); parser->objc_could_be_foreach_context = false; restore_extension_diagnostics (ext); @@ -7643,7 +7677,7 @@ c_parser_objc_methodprotolist (c_parser } else c_parser_declaration_or_fndef (parser, false, false, true, - false, true, NULL); + false, true, NULL, vNULL); break; } } @@ -8657,6 +8691,10 @@ c_parser_pragma (c_parser *parser, enum c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); return false; + case PRAGMA_OMP_DECLARE_REDUCTION: + c_parser_omp_declare (parser, context); + return false; + case PRAGMA_GCC_PCH_PREPROCESS: c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first"); c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL); @@ -8665,7 +8703,7 @@ c_parser_pragma (c_parser *parser, enum default: if (id < PRAGMA_FIRST_EXTERNAL) { - if (context == pragma_external) + if (context != pragma_stmt && context != pragma_compound) { bad_stmt: c_parser_error (parser, "expected declaration specifiers"); @@ -8890,7 +8928,7 @@ static tree c_parser_omp_variable_list (c_parser *parser, location_t clause_loc, enum omp_clause_code kind, - tree list) + tree list, bool declare_simd) { if (c_parser_next_token_is_not (parser, CPP_NAME) || c_parser_peek_token (parser)->id_kind != C_ID_ID) @@ -8899,7 +8937,12 @@ 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 = lookup_name (c_parser_peek_token (parser)->value); + tree t; + + if (declare_simd) + t = c_parser_peek_token (parser)->value; + else + t = lookup_name (c_parser_peek_token (parser)->value); if (t == NULL_TREE) undeclared_variable (c_parser_peek_token (parser)->location, @@ -8939,7 +8982,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); + list = c_parser_omp_variable_list (parser, loc, kind, list, false); c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); } return list; @@ -9239,7 +9282,7 @@ c_parser_omp_clause_private (c_parser *p One of: + * - & ^ | && || max min */ static tree -c_parser_omp_clause_reduction (c_parser *parser, tree list) +c_parser_omp_clause_reduction (c_parser *parser, tree list, bool declare_simd) { location_t clause_loc = c_parser_peek_token (parser)->location; if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) @@ -9301,7 +9344,8 @@ c_parser_omp_clause_reduction (c_parser tree nl, c; nl = c_parser_omp_variable_list (parser, clause_loc, - OMP_CLAUSE_REDUCTION, list); + OMP_CLAUSE_REDUCTION, list, + declare_simd); for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) OMP_CLAUSE_REDUCTION_CODE (c) = code; @@ -9531,7 +9575,7 @@ c_parser_omp_clause_num_teams (c_parser aligned ( variable-list : constant-expression ) */ static tree -c_parser_omp_clause_aligned (c_parser *parser, tree list) +c_parser_omp_clause_aligned (c_parser *parser, tree list, bool declare_simd) { location_t clause_loc = c_parser_peek_token (parser)->location; tree nl, c; @@ -9540,7 +9584,7 @@ c_parser_omp_clause_aligned (c_parser *p return list; nl = c_parser_omp_variable_list (parser, clause_loc, - OMP_CLAUSE_ALIGNED, list); + OMP_CLAUSE_ALIGNED, list, declare_simd); if (c_parser_next_token_is (parser, CPP_COLON)) { @@ -9570,7 +9614,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) +c_parser_omp_clause_linear (c_parser *parser, tree list, bool declare_simd) { location_t clause_loc = c_parser_peek_token (parser)->location; tree nl, c, step; @@ -9579,7 +9623,7 @@ c_parser_omp_clause_linear (c_parser *pa return list; nl = c_parser_omp_variable_list (parser, clause_loc, - OMP_CLAUSE_LINEAR, list); + OMP_CLAUSE_LINEAR, list, declare_simd); if (c_parser_next_token_is (parser, CPP_COLON)) { @@ -9600,16 +9644,7 @@ c_parser_omp_clause_linear (c_parser *pa for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) { - tree s = step; - if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c))) == POINTER_TYPE) - { - s = pointer_int_sum (clause_loc, PLUS_EXPR, OMP_CLAUSE_DECL (c), s); - s = fold_build2_loc (clause_loc, MINUS_EXPR, sizetype, s, - OMP_CLAUSE_DECL (c)); - if (s == error_mark_node) - s = size_one_node; - } - OMP_CLAUSE_LINEAR_STEP (c) = s; + OMP_CLAUSE_LINEAR_STEP (c) = step; } c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); @@ -9724,7 +9759,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); + OMP_CLAUSE_DEPEND, list, false); for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) OMP_CLAUSE_DEPEND_KIND (c) = kind; @@ -9780,7 +9815,7 @@ c_parser_omp_clause_map (c_parser *parse } nl = c_parser_omp_variable_list (parser, clause_loc, - OMP_CLAUSE_MAP, list); + OMP_CLAUSE_MAP, list, false); for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) OMP_CLAUSE_MAP_KIND (c) = kind; @@ -9934,7 +9969,16 @@ c_parser_omp_clause_from (c_parser *pars static tree c_parser_omp_clause_uniform (c_parser *parser, tree list) { - return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_UNIFORM, list); + /* The clauses location. */ + location_t loc = c_parser_peek_token (parser)->location; + + if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + { + list = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_UNIFORM, + list, true); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>"); + } + return list; } /* Parse all OpenMP clauses. The set clauses allowed by the directive @@ -9943,7 +9987,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) + const char *where, bool declare_simd) { tree clauses = NULL; bool first = true; @@ -10017,7 +10061,8 @@ c_parser_omp_all_clauses (c_parser *pars c_name = "private"; break; case PRAGMA_OMP_CLAUSE_REDUCTION: - clauses = c_parser_omp_clause_reduction (parser, clauses); + clauses = c_parser_omp_clause_reduction (parser, clauses, + declare_simd); c_name = "reduction"; break; case PRAGMA_OMP_CLAUSE_SCHEDULE: @@ -10083,11 +10128,12 @@ c_parser_omp_all_clauses (c_parser *pars c_name = "num_teams"; break; case PRAGMA_OMP_CLAUSE_ALIGNED: - clauses = c_parser_omp_clause_aligned (parser, clauses); + clauses = c_parser_omp_clause_aligned (parser, clauses, + declare_simd); c_name = "aligned"; break; case PRAGMA_OMP_CLAUSE_LINEAR: - clauses = c_parser_omp_clause_linear (parser, clauses); + clauses = c_parser_omp_clause_linear (parser, clauses, declare_simd); c_name = "linear"; break; case PRAGMA_OMP_CLAUSE_DEPEND: @@ -10135,6 +10181,9 @@ c_parser_omp_all_clauses (c_parser *pars saw_error: c_parser_skip_to_pragma_eol (parser); + if (declare_simd) + return clauses; + return c_finish_omp_clauses (clauses); } @@ -10677,7 +10726,8 @@ c_parser_omp_for_loop (location_t loc, c { if (i > 0) vec_safe_push (for_block, c_begin_compound_stmt (true)); - c_parser_declaration_or_fndef (parser, true, true, true, true, true, NULL); + c_parser_declaration_or_fndef (parser, true, true, true, true, true, + NULL, vNULL); decl = check_for_loop_decls (for_loc, flag_isoc99); if (decl == NULL) goto error_init; @@ -10942,7 +10992,7 @@ c_parser_omp_simd (location_t loc, c_par tree block, clauses, ret; clauses = c_parser_omp_all_clauses (parser, OMP_SIMD_CLAUSE_MASK, - "#pragma omp simd"); + "#pragma omp simd", false); block = c_begin_compound_stmt (true); ret = c_parser_omp_for_loop (loc, parser, OMP_SIMD, clauses, NULL); @@ -10994,7 +11044,7 @@ c_parser_omp_for (location_t loc, c_pars } } - clauses = c_parser_omp_all_clauses (parser, mask, p_name); + clauses = c_parser_omp_all_clauses (parser, mask, p_name, false); block = c_begin_compound_stmt (true); ret = c_parser_omp_for_loop (loc, parser, code, clauses, NULL); @@ -11140,7 +11190,7 @@ c_parser_omp_sections (location_t loc, c tree block, clauses, ret; clauses = c_parser_omp_all_clauses (parser, OMP_SECTIONS_CLAUSE_MASK, - "#pragma omp sections"); + "#pragma omp sections", false); block = c_begin_compound_stmt (true); ret = c_parser_omp_sections_scope (loc, parser); @@ -11212,7 +11262,7 @@ c_parser_omp_parallel (location_t loc, c } } - clauses = c_parser_omp_all_clauses (parser, mask, p_name); + clauses = c_parser_omp_all_clauses (parser, mask, p_name, false); switch (p_kind) { @@ -11278,7 +11328,7 @@ c_parser_omp_single (location_t loc, c_p OMP_SINGLE_CLAUSES (stmt) = c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK, - "#pragma omp single"); + "#pragma omp single", false); OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser); return add_stmt (stmt); @@ -11307,7 +11357,7 @@ c_parser_omp_task (location_t loc, c_par tree clauses, block; clauses = c_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK, - "#pragma omp task"); + "#pragma omp task", false); block = c_begin_omp_task (); c_parser_statement (parser); @@ -11377,7 +11427,7 @@ c_parser_omp_cancel (c_parser *parser) c_parser_consume_pragma (parser); tree clauses = c_parser_omp_all_clauses (parser, OMP_CANCEL_CLAUSE_MASK, - "#pragma omp cancel"); + "#pragma omp cancel", false); c_finish_omp_cancel (loc, clauses); } @@ -11420,11 +11470,142 @@ c_parser_omp_cancellation_point (c_parse clauses = c_parser_omp_all_clauses (parser, OMP_CANCELLATION_POINT_CLAUSE_MASK, - "#pragma omp cancellation point"); + "#pragma omp cancellation point", false); c_finish_omp_cancellation_point (loc, clauses); } +/* OpenMP 4.0: + # pragma omp declare simd declare-simd-clauses[optseq] new-line */ + +#define OMP_DECLARE_SIMD_CLAUSE_MASK \ + ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) \ + | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOTINBRANCH)) + +static void +c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context) +{ + vec<tree> clauses = vNULL; + tree cl = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK, + "#pragma omp declare simd", true); + clauses.safe_push (cl); + + while (c_parser_next_token_is (parser, CPP_PRAGMA)) + { + if (c_parser_peek_token (parser)->pragma_kind + != PRAGMA_OMP_DECLARE_REDUCTION + || c_parser_peek_2nd_token (parser)->type != CPP_NAME + || strcmp (IDENTIFIER_POINTER + (c_parser_peek_2nd_token (parser)->value), + "simd") != 0) + { + c_parser_error (parser, + "%<#pragma omp declare simd%> must be followed by " + "function declaration or definition or another " + "%<#pragma omp declare simd%>"); + clauses.release (); + 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", true); + clauses.safe_push (cl); + } + + switch (context) + { + case pragma_external: + if (c_parser_next_token_is (parser, CPP_KEYWORD) + && c_parser_peek_token (parser)->keyword == RID_EXTENSION) + { + int ext = disable_extension_diagnostics (); + do + c_parser_consume_token (parser); + while (c_parser_next_token_is (parser, CPP_KEYWORD) + && c_parser_peek_token (parser)->keyword == RID_EXTENSION); + c_parser_declaration_or_fndef (parser, true, true, true, false, true, + NULL, clauses); + restore_extension_diagnostics (ext); + } + else + c_parser_declaration_or_fndef (parser, true, true, true, false, true, + NULL, clauses); + break; + case pragma_struct: + case pragma_param: + c_parser_error (parser, "%<#pragma omp declare simd%> must be followed by " + "function declaration or definition"); + break; + case pragma_compound: + case pragma_stmt: + if (c_parser_next_token_is (parser, CPP_KEYWORD) + && c_parser_peek_token (parser)->keyword == RID_EXTENSION) + { + int ext = disable_extension_diagnostics (); + do + c_parser_consume_token (parser); + while (c_parser_next_token_is (parser, CPP_KEYWORD) + && c_parser_peek_token (parser)->keyword == RID_EXTENSION); + if (c_parser_next_tokens_start_declaration (parser)) + { + c_parser_declaration_or_fndef (parser, true, true, true, true, + true, NULL, clauses); + restore_extension_diagnostics (ext); + break; + } + restore_extension_diagnostics (ext); + } + else if (c_parser_next_tokens_start_declaration (parser)) + { + c_parser_declaration_or_fndef (parser, true, true, true, true, true, + NULL, clauses); + break; + } + c_parser_error (parser, "%<#pragma omp declare simd%> must be followed by " + "function declaration or definition"); + break; + default: + gcc_unreachable (); + } + clauses.release (); +} + +/* OpenMP 4.0 + #pragma omp declare simd declare-simd-clauses[optseq] new-line + #pragma omp declare reduction (reduction-id : typename-list : expression) \ + identity-clause[opt] new-line */ + +static void +c_parser_omp_declare (c_parser *parser, enum pragma_context context) +{ + c_parser_consume_pragma (parser); + if (c_parser_next_token_is (parser, CPP_NAME)) + { + const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + if (strcmp (p, "simd") == 0) + { + c_parser_consume_token (parser); + c_parser_omp_declare_simd (parser, context); + return; + } +/* if (strcmp (p, "reduction") == 0) + { + c_parser_consume_token (parser); + c_parser_omp_declare_reduction (parser); + return; + } */ + } + + c_parser_error (parser, "expected %<simd%> or %<reduction%>"); + c_parser_skip_to_pragma_eol (parser); +} + /* Main entry point to parsing most OpenMP pragmas. */ static void --- gcc/testsuite/gcc.dg/gomp/declare-simd-1.c.jj 2013-05-13 13:25:37.054132804 +0200 +++ gcc/testsuite/gcc.dg/gomp/declare-simd-1.c 2013-05-13 13:22:43.000000000 +0200 @@ -0,0 +1,82 @@ +/* Test parsing of #pragma omp declare simd */ +/* { dg-do compile } */ + +#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) \ + linear (c : 4) simdlen (8) notinbranch +#pragma omp declare simd uniform (c) aligned (b : 4 * sizeof (int)) linear (a \ + : 4) simdlen (4) inbranch +int f1 (int a, int *b, int c); + +#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8) +int f2 (int a, int *b, int c) +{ + return a + *b + c; +} + +#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (long long)) linear (c : 4) simdlen (8) +__extension__ +long long f3 (long long a, long long *b, long long c); + +int +f4 (int x) +{ + #pragma omp declare simd simdlen (8) aligned (b : 8 * sizeof (int)) + __extension__ __extension__ __extension__ + extern int f5 (int a, int *b, int c); + { + x++; + #pragma omp declare simd simdlen (4) linear (c) + extern int f6 (int a, int *b, int c); + } + return x; +} + +#pragma omp declare simd simdlen (16) +int +f7 (int x) +{ + #pragma omp declare simd simdlen (8) aligned (b : 8 * sizeof (int)) + extern int f8 (int a, int *b, int c); + return x; +} + +int +f9 (int x) +{ + if (x) + #pragma omp declare simd simdlen (8) aligned (b : 8 * sizeof (int)) + extern int f10 (int a, int *b, int c); + while (x < 10) + #pragma omp declare simd simdlen (8) aligned (b : 8 * sizeof (int)) + extern int f11 (int a, int *b, int c); + return x; +} + +#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8) +int f12 (int c; int *b; int a; int a, int *b, int c); + +#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8) +int +f13 (int c; int *b; int a; int a, int *b, int c) +{ + return a + *b + c; +} + +#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8) +int +f14 (a, b, c) + int a, c; + int *b; +{ + return a + *b + c; +} + +#pragma omp declare simd uniform (a) aligned (b : 8 * sizeof (int)) linear (c : 4) simdlen (8) +int +f15 (int a, int *b, int c) +{ + return a + *b + 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); --- gcc/testsuite/gcc.dg/gomp/declare-simd-2.c.jj 2013-05-13 13:25:39.876116620 +0200 +++ gcc/testsuite/gcc.dg/gomp/declare-simd-2.c 2013-05-13 14:00:42.113675965 +0200 @@ -0,0 +1,24 @@ +/* Test parsing of #pragma omp declare simd */ +/* { dg-do compile } */ + +#pragma omp declare simd +int a; /* { dg-error "not immediately followed by a function declaration or definition" } */ + +#pragma omp declare simd +int fn1 (int a), fn2 (int a); /* { dg-error "not immediately followed by a single function declaration or definition" } */ + +#pragma omp declare simd +int b, fn3 (int a); /* { dg-error "not immediately followed by a function declaration or definition" } */ + +#pragma omp declare simd linear (a) +int fn4 (int a), c; /* { dg-error "not immediately followed by a function declaration or definition" } */ + +int t; + +#pragma omp declare simd +#pragma omp declare simd +#pragma omp threadprivate(t) /* { dg-error "must be followed by function declaration or definition or another" } */ +int fn5 (int a); + +#pragma omp declare simd inbranch notinbranch /* { dg-error "clause is incompatible with" } */ +int fn6 (int); Jakub