aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/ChangeLog11
-rw-r--r--gcc/c/c-parser.c87
-rw-r--r--gcc/c/c-typeck.c65
3 files changed, 151 insertions, 12 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 5a0dabb..103634e 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,14 @@
+2019-06-10 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_pragma): Reject PRAGMA_OMP_SCAN.
+ (c_parser_omp_clause_reduction): Don't sorry_at on inscan reductions.
+ (c_parser_omp_scan_loop_body): New function.
+ (c_parser_omp_for_loop): Call c_parser_omp_scan_loop_body if there are
+ inscan reduction clauses.
+ * c-typeck.c (c_finish_omp_clauses): Reject mixing inscan with
+ non-inscan reductions on the same construct, or inscan reductions with
+ ordered or schedule clauses, or inscan array reductions.
+
2019-06-05 Martin Sebor <msebor@redhat.com>
PR c/90737
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 84ee576..df1a304 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -11494,6 +11494,13 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
c_parser_omp_end_declare_target (parser);
return false;
+ case PRAGMA_OMP_SCAN:
+ error_at (c_parser_peek_token (parser)->location,
+ "%<#pragma omp scan%> may only be used in "
+ "a loop construct with %<inscan%> %<reduction%> clause");
+ c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+ return false;
+
case PRAGMA_OMP_SECTION:
error_at (c_parser_peek_token (parser)->location,
"%<#pragma omp section%> may only be used in "
@@ -13558,11 +13565,7 @@ c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
if (strcmp (p, "task") == 0)
task = true;
else if (strcmp (p, "inscan") == 0)
- {
- inscan = true;
- sorry ("%<inscan%> modifier on %<reduction%> clause "
- "not supported yet");
- }
+ inscan = true;
if (task || inscan)
{
c_parser_consume_token (parser);
@@ -16738,6 +16741,71 @@ c_parser_omp_flush (c_parser *parser)
c_finish_omp_flush (loc, mo);
}
+/* OpenMP 5.0:
+
+ scan-loop-body:
+ { structured-block scan-directive structured-block } */
+
+static void
+c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed)
+{
+ tree substmt;
+ location_t loc;
+ tree clauses = NULL_TREE;
+
+ loc = c_parser_peek_token (parser)->location;
+ if (!open_brace_parsed
+ && !c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
+ {
+ /* Avoid skipping until the end of the block. */
+ parser->error = false;
+ return;
+ }
+
+ substmt = c_parser_omp_structured_block (parser, NULL);
+ substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
+ SET_EXPR_LOCATION (substmt, loc);
+ add_stmt (substmt);
+
+ loc = c_parser_peek_token (parser)->location;
+ if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SCAN)
+ {
+ enum omp_clause_code clause = OMP_CLAUSE_ERROR;
+
+ 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, "inclusive") == 0)
+ clause = OMP_CLAUSE_INCLUSIVE;
+ else if (strcmp (p, "exclusive") == 0)
+ clause = OMP_CLAUSE_EXCLUSIVE;
+ }
+ if (clause != OMP_CLAUSE_ERROR)
+ {
+ c_parser_consume_token (parser);
+ clauses = c_parser_omp_var_list_parens (parser, clause, NULL_TREE);
+ }
+ else
+ c_parser_error (parser, "expected %<inclusive%> or "
+ "%<exclusive%> clause");
+ c_parser_skip_to_pragma_eol (parser);
+ }
+ else
+ error ("expected %<#pragma omp scan%>");
+
+ clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
+ substmt = c_parser_omp_structured_block (parser, NULL);
+ substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses);
+ SET_EXPR_LOCATION (substmt, loc);
+ add_stmt (substmt);
+
+ c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
+ "expected %<}%>");
+}
+
/* Parse the restricted form of loop statements allowed by OpenACC and OpenMP.
The real trick here is to determine the loop control variable early
so that we can push a new decl if necessary to make it private.
@@ -16756,6 +16824,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
int i, collapse = 1, ordered = 0, count, nbraces = 0;
location_t for_loc;
bool tiling = false;
+ bool inscan = false;
vec<tree, va_gc> *for_block = make_tree_vector ();
for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
@@ -16772,6 +16841,10 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
ordered_cl = cl;
ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl));
}
+ else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_REDUCTION_INSCAN (cl)
+ && (code == OMP_SIMD || code == OMP_FOR))
+ inscan = true;
if (ordered && ordered < collapse)
{
@@ -16992,7 +17065,9 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
c_cont_label = NULL_TREE;
body = push_stmt_list ();
- if (open_brace_parsed)
+ if (inscan)
+ c_parser_omp_scan_loop_body (parser, open_brace_parsed);
+ else if (open_brace_parsed)
{
location_t here = c_parser_peek_token (parser)->location;
stmt = c_begin_compound_stmt (true);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 0dd86f0..6abfd10 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -13661,13 +13661,15 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
bool copyprivate_seen = false;
bool linear_variable_step_check = false;
tree *nowait_clause = NULL;
- bool ordered_seen = false;
+ tree ordered_clause = NULL_TREE;
tree schedule_clause = NULL_TREE;
bool oacc_async = false;
tree last_iterators = NULL_TREE;
bool last_iterators_remove = false;
tree *nogroup_seen = NULL;
- bool reduction_seen = false;
+ /* 1 if normal/task reduction has been seen, -1 if inscan reduction
+ has been seen, -2 if mixed inscan/normal reduction diagnosed. */
+ int reduction_seen = 0;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -13706,7 +13708,17 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
goto check_dup_generic;
case OMP_CLAUSE_REDUCTION:
- reduction_seen = true;
+ if (reduction_seen == 0)
+ reduction_seen = OMP_CLAUSE_REDUCTION_INSCAN (c) ? -1 : 1;
+ else if (reduction_seen != -2
+ && reduction_seen != (OMP_CLAUSE_REDUCTION_INSCAN (c)
+ ? -1 : 1))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inscan%> and non-%<inscan%> %<reduction%> clauses "
+ "on the same construct");
+ reduction_seen = -2;
+ }
/* FALLTHRU */
case OMP_CLAUSE_IN_REDUCTION:
case OMP_CLAUSE_TASK_REDUCTION:
@@ -13721,6 +13733,15 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
}
t = OMP_CLAUSE_DECL (c);
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_REDUCTION_INSCAN (c))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<inscan%> %<reduction%> clause with array "
+ "section");
+ remove = true;
+ break;
+ }
}
t = require_complete_type (OMP_CLAUSE_LOCATION (c), t);
if (t == error_mark_node)
@@ -14661,7 +14682,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
continue;
case OMP_CLAUSE_ORDERED:
- ordered_seen = true;
+ ordered_clause = c;
pc = &OMP_CLAUSE_CHAIN (c);
continue;
@@ -14688,6 +14709,20 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
pc = &OMP_CLAUSE_CHAIN (c);
continue;
+ case OMP_CLAUSE_INCLUSIVE:
+ case OMP_CLAUSE_EXCLUSIVE:
+ need_complete = true;
+ need_implicitly_determined = true;
+ t = OMP_CLAUSE_DECL (c);
+ if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in clause %qs", t,
+ omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
+ remove = true;
+ }
+ break;
+
default:
gcc_unreachable ();
}
@@ -14760,7 +14795,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
= OMP_CLAUSE_SAFELEN_EXPR (safelen);
}
- if (ordered_seen
+ if (ordered_clause
&& schedule_clause
&& (OMP_CLAUSE_SCHEDULE_KIND (schedule_clause)
& OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
@@ -14774,7 +14809,23 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
& ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
}
- if (linear_variable_step_check)
+ if (reduction_seen < 0 && ordered_clause)
+ {
+ error_at (OMP_CLAUSE_LOCATION (ordered_clause),
+ "%qs clause specified together with %<inscan%> "
+ "%<reduction%> clause", "ordered");
+ reduction_seen = -2;
+ }
+
+ if (reduction_seen < 0 && schedule_clause)
+ {
+ error_at (OMP_CLAUSE_LOCATION (schedule_clause),
+ "%qs clause specified together with %<inscan%> "
+ "%<reduction%> clause", "schedule");
+ reduction_seen = -2;
+ }
+
+ if (linear_variable_step_check || reduction_seen == -2)
for (pc = &clauses, c = clauses; c ; c = *pc)
{
bool remove = false;
@@ -14789,6 +14840,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
OMP_CLAUSE_LINEAR_STEP (c));
remove = true;
}
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+ OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
if (remove)
*pc = OMP_CLAUSE_CHAIN (c);