aboutsummaryrefslogtreecommitdiff
path: root/gcc/c/c-parser.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c/c-parser.cc')
-rw-r--r--gcc/c/c-parser.cc102
1 files changed, 61 insertions, 41 deletions
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 643ec02..b9a1b75 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -19343,6 +19343,61 @@ c_parser_oacc_wait (location_t loc, c_parser *parser, char *p_name)
return stmt;
}
+struct c_omp_loc_tree
+{
+ location_t loc;
+ tree var;
+};
+
+/* Check whether the expression used in the allocator clause is declared or
+ modified between the variable declaration and its allocate directive. */
+static tree
+c_check_omp_allocate_allocator_r (tree *tp, int *, void *data)
+{
+ tree var = ((struct c_omp_loc_tree *) data)->var;
+ location_t loc = ((struct c_omp_loc_tree *) data)->loc;
+ if (TREE_CODE (*tp) == VAR_DECL && c_check_in_current_scope (*tp))
+ {
+ if (linemap_location_before_p (line_table, DECL_SOURCE_LOCATION (var),
+ DECL_SOURCE_LOCATION (*tp)))
+ {
+ error_at (loc, "variable %qD used in the %<allocator%> clause must "
+ "be declared before %qD", *tp, var);
+ inform (DECL_SOURCE_LOCATION (*tp), "declared here");
+ inform (DECL_SOURCE_LOCATION (var),
+ "to be allocated variable declared here");
+ return *tp;
+ }
+ else
+ {
+ gcc_assert (cur_stmt_list
+ && TREE_CODE (cur_stmt_list) == STATEMENT_LIST);
+
+ tree_stmt_iterator l = tsi_last (cur_stmt_list);
+ while (!tsi_end_p (l))
+ {
+ if (linemap_location_before_p (line_table, EXPR_LOCATION (*l),
+ DECL_SOURCE_LOCATION (var)))
+ break;
+ if (TREE_CODE (*l) == MODIFY_EXPR
+ && TREE_OPERAND (*l, 0) == *tp)
+ {
+ error_at (loc,
+ "variable %qD used in the %<allocator%> clause "
+ "must not be modified between declaration of %qD "
+ "and its %<allocate%> directive", *tp, var);
+ inform (EXPR_LOCATION (*l), "modified here");
+ inform (DECL_SOURCE_LOCATION (var),
+ "to be allocated variable declared here");
+ return *tp;
+ }
+ --l;
+ }
+ }
+ }
+ return NULL_TREE;
+}
+
/* OpenMP 5.x:
# pragma omp allocate (list) clauses
@@ -19465,8 +19520,8 @@ c_parser_omp_allocate (c_parser *parser)
error_at (loc, "%<allocator%> clause required for "
"static variable %qD", var);
else if (allocator
- && (tree_int_cst_sgn (allocator) != 1
- || tree_to_shwi (allocator) > 8))
+ && (wi::to_widest (allocator) < 1
+ || wi::to_widest (allocator) > 8))
/* 8 = largest predefined memory allocator. */
error_at (allocator_loc,
"%<allocator%> clause requires a predefined allocator as "
@@ -19477,46 +19532,11 @@ c_parser_omp_allocate (c_parser *parser)
"%qD not yet supported", var);
continue;
}
- if (allocator
- && TREE_CODE (allocator) == VAR_DECL
- && c_check_in_current_scope (var))
+ if (allocator)
{
- if (linemap_location_before_p (line_table, DECL_SOURCE_LOCATION (var),
- DECL_SOURCE_LOCATION (allocator)))
- {
- error_at (OMP_CLAUSE_LOCATION (nl),
- "allocator variable %qD must be declared before %qD",
- allocator, var);
- inform (DECL_SOURCE_LOCATION (allocator),
- "allocator declared here");
- inform (DECL_SOURCE_LOCATION (var), "declared here");
- }
- else
- {
- gcc_assert (cur_stmt_list
- && TREE_CODE (cur_stmt_list) == STATEMENT_LIST);
- tree_stmt_iterator l = tsi_last (cur_stmt_list);
- while (!tsi_end_p (l))
- {
- if (linemap_location_before_p (line_table, EXPR_LOCATION (*l),
- DECL_SOURCE_LOCATION (var)))
- break;
- if (TREE_CODE (*l) == MODIFY_EXPR
- && TREE_OPERAND (*l, 0) == allocator)
- {
- error_at (EXPR_LOCATION (*l),
- "allocator variable %qD, used in the "
- "%<allocate%> directive for %qD, must not be "
- "modified between declaration of %qD and its "
- "%<allocate%> directive",
- allocator, var, var);
- inform (DECL_SOURCE_LOCATION (var), "declared here");
- inform (OMP_CLAUSE_LOCATION (nl), "used here");
- break;
- }
- --l;
- }
- }
+ struct c_omp_loc_tree data
+ = {EXPR_LOC_OR_LOC (allocator, OMP_CLAUSE_LOCATION (nl)), var};
+ walk_tree (&allocator, c_check_omp_allocate_allocator_r, &data, NULL);
}
DECL_ATTRIBUTES (var) = tree_cons (get_identifier ("omp allocate"),
build_tree_list (allocator, alignment),