This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[gomp4] #pragma omp declare simd C parsing
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 13 May 2013 15:01:29 +0200
- Subject: [gomp4] #pragma omp declare simd C parsing
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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 <jakub@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