aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
authorTobias Burnus <tobias@codesourcery.com>2023-09-12 09:19:04 +0200
committerTobias Burnus <tobias@codesourcery.com>2023-09-12 09:19:04 +0200
commit35f498d8dfc8e579eaba2ff2d2b96769c632fd58 (patch)
treef3e2f5b948ee20d3990a57e8a137212e5df60530 /gcc/c
parentb90a4c3dd502974f352084c23a6cdfd767e1340b (diff)
downloadgcc-35f498d8dfc8e579eaba2ff2d2b96769c632fd58.zip
gcc-35f498d8dfc8e579eaba2ff2d2b96769c632fd58.tar.gz
gcc-35f498d8dfc8e579eaba2ff2d2b96769c632fd58.tar.bz2
OpenMP (C only): omp allocate - extend parsing support, improve diagnostic
The 'allocate' directive can be used for both stack and static variables. While the parser in C and C++ was pre-existing, it missed several diagnostics, which this commit adds - for now only for C. While the "sorry, unimplemented" for static variables is still issues during parsing, the sorry for stack variables is now issued in the middle end, preparing for the actual implementation. (Again: only for C.) gcc/c/ChangeLog: * c-parser.cc (c_parser_omp_construct): Move call to c_parser_omp_allocate to ... (c_parser_pragma): ... here. (c_parser_omp_allocate): Avoid ICE is allocator could not be parsed; set 'omp allocate' attribute for stack/automatic variables and only reject static variables; add several additional restriction checks. * c-tree.h (c_mark_decl_jump_unsafe_in_current_scope): New prototype. * c-decl.cc (decl_jump_unsafe): Return true for omp-allocated decls. (c_mark_decl_jump_unsafe_in_current_scope): New. (warn_about_goto, c_check_switch_jump_warnings): Add error for omp-allocated decls. gcc/ChangeLog: * gimplify.cc (gimplify_bind_expr): Check for insertion after variable cleanup. Convert 'omp allocate' var-decl attribute to GOMP_alloc/GOMP_free calls. gcc/testsuite/ChangeLog: * c-c++-common/gomp/allocate-5.c: Fix testcase; make some dg-messages for 'sorry' as c++, only. * c-c++-common/gomp/directive-1.c: Make a 'sorry' c++ only. * c-c++-common/gomp/allocate-9.c: New test. * c-c++-common/gomp/allocate-11.c: New test. * c-c++-common/gomp/allocate-12.c: New test. * c-c++-common/gomp/allocate-14.c: New test. * c-c++-common/gomp/allocate-15.c: New test. * c-c++-common/gomp/allocate-16.c: New test.
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/c-decl.cc26
-rw-r--r--gcc/c/c-parser.cc115
-rw-r--r--gcc/c/c-tree.h1
3 files changed, 129 insertions, 13 deletions
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 649c5ae6..5822faf 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -681,6 +681,11 @@ decl_jump_unsafe (tree decl)
if (VAR_P (decl) && C_DECL_COMPOUND_LITERAL_P (decl))
return false;
+ if (flag_openmp
+ && VAR_P (decl)
+ && lookup_attribute ("omp allocate", DECL_ATTRIBUTES (decl)))
+ return true;
+
/* Always warn about crossing variably modified types. */
if ((VAR_P (decl) || TREE_CODE (decl) == TYPE_DECL)
&& c_type_variably_modified_p (TREE_TYPE (decl)))
@@ -724,6 +729,15 @@ c_print_identifier (FILE *file, tree node, int indent)
c_binding_oracle = save;
}
+/* Establish that the scope contains declarations that are sensitive to
+ jumps that cross a binding. Together with decl_jump_unsafe, this is
+ used to diagnose such jumps. */
+void
+c_mark_decl_jump_unsafe_in_current_scope ()
+{
+ current_scope->has_jump_unsafe_decl = 1;
+}
+
/* Establish a binding between NAME, an IDENTIFIER_NODE, and DECL,
which may be any of several kinds of DECL or TYPE or error_mark_node,
in the scope SCOPE. */
@@ -3974,6 +3988,9 @@ warn_about_goto (location_t goto_loc, tree label, tree decl)
if (c_type_variably_modified_p (TREE_TYPE (decl)))
error_at (goto_loc,
"jump into scope of identifier with variably modified type");
+ else if (flag_openmp
+ && lookup_attribute ("omp allocate", DECL_ATTRIBUTES (decl)))
+ error_at (goto_loc, "jump skips OpenMP %<allocate%> allocation");
else
if (!warning_at (goto_loc, OPT_Wjump_misses_init,
"jump skips variable initialization"))
@@ -4253,6 +4270,15 @@ c_check_switch_jump_warnings (struct c_spot_bindings *switch_bindings,
"variably modified type"));
emitted = true;
}
+ else if (flag_openmp
+ && lookup_attribute ("omp allocate",
+ DECL_ATTRIBUTES (b->decl)))
+ {
+ saw_error = true;
+ error_at (case_loc,
+ "switch jumps over OpenMP %<allocate%> allocation");
+ emitted = true;
+ }
else
emitted
= warning_at (case_loc, OPT_Wjump_misses_init,
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index c04962d..643ec02 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -1681,6 +1681,7 @@ static bool c_parser_omp_declare (c_parser *, enum pragma_context);
static void c_parser_omp_requires (c_parser *);
static bool c_parser_omp_error (c_parser *, enum pragma_context);
static void c_parser_omp_assumption_clauses (c_parser *, bool);
+static void c_parser_omp_allocate (c_parser *);
static void c_parser_omp_assumes (c_parser *);
static bool c_parser_omp_ordered (c_parser *, enum pragma_context, bool *);
static void c_parser_oacc_routine (c_parser *, enum pragma_context);
@@ -13649,6 +13650,10 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
c_parser_omp_requires (parser);
return false;
+ case PRAGMA_OMP_ALLOCATE:
+ c_parser_omp_allocate (parser);
+ return false;
+
case PRAGMA_OMP_ASSUMES:
if (context != pragma_external)
{
@@ -19348,10 +19353,13 @@ c_parser_oacc_wait (location_t loc, c_parser *parser, char *p_name)
align (constant-expression)] */
static void
-c_parser_omp_allocate (location_t loc, c_parser *parser)
+c_parser_omp_allocate (c_parser *parser)
{
tree alignment = NULL_TREE;
tree allocator = NULL_TREE;
+ c_parser_consume_pragma (parser);
+ location_t loc = c_parser_peek_token (parser)->location;
+ location_t allocator_loc = UNKNOWN_LOCATION;
tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ALLOCATE, NULL_TREE);
do
{
@@ -19376,7 +19384,9 @@ c_parser_omp_allocate (location_t loc, c_parser *parser)
c_expr expr = c_parser_expr_no_commas (parser, NULL);
expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
expr_loc = c_parser_peek_token (parser)->location;
- if (p[2] == 'i' && alignment)
+ if (expr.value == error_mark_node)
+ ;
+ else if (p[2] == 'i' && alignment)
{
error_at (expr_loc, "too many %qs clauses", "align");
break;
@@ -19403,6 +19413,7 @@ c_parser_omp_allocate (location_t loc, c_parser *parser)
else
{
allocator = c_fully_fold (expr.value, false, NULL);
+ allocator_loc = expr_loc;
tree orig_type
= expr.original_type ? expr.original_type : TREE_TYPE (allocator);
orig_type = TYPE_MAIN_VARIANT (orig_type);
@@ -19422,14 +19433,95 @@ c_parser_omp_allocate (location_t loc, c_parser *parser)
} while (true);
c_parser_skip_to_pragma_eol (parser);
- if (allocator || alignment)
- for (tree c = nl; c != NULL_TREE; c = OMP_CLAUSE_CHAIN (c))
- {
- OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
- OMP_CLAUSE_ALLOCATE_ALIGN (c) = alignment;
- }
-
- sorry_at (loc, "%<#pragma omp allocate%> not yet supported");
+ c_mark_decl_jump_unsafe_in_current_scope ();
+ for (tree c = nl; c != NULL_TREE; c = OMP_CLAUSE_CHAIN (c))
+ {
+ tree var = OMP_CLAUSE_DECL (c);
+ if (TREE_CODE (var) == PARM_DECL)
+ {
+ error_at (OMP_CLAUSE_LOCATION (nl),
+ "function parameter %qD may not appear as list item in an "
+ "%<allocate%> directive", var);
+ continue;
+ }
+ if (!c_check_in_current_scope (var))
+ {
+ error_at (OMP_CLAUSE_LOCATION (nl),
+ "%<allocate%> directive must be in the same scope as %qD",
+ var);
+ inform (DECL_SOURCE_LOCATION (var), "declared here");
+ continue;
+ }
+ if (lookup_attribute ("omp allocate", DECL_ATTRIBUTES (var)))
+ {
+ error_at (OMP_CLAUSE_LOCATION (nl),
+ "%qD already appeared as list item in an "
+ "%<allocate%> directive", var);
+ continue;
+ }
+ if (TREE_STATIC (var))
+ {
+ if (allocator == NULL_TREE && allocator_loc == UNKNOWN_LOCATION)
+ 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))
+ /* 8 = largest predefined memory allocator. */
+ error_at (allocator_loc,
+ "%<allocator%> clause requires a predefined allocator as "
+ "%qD is static", var);
+ else
+ sorry_at (OMP_CLAUSE_LOCATION (nl),
+ "%<#pragma omp allocate%> for static variables like "
+ "%qD not yet supported", var);
+ continue;
+ }
+ if (allocator
+ && TREE_CODE (allocator) == VAR_DECL
+ && c_check_in_current_scope (var))
+ {
+ 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;
+ }
+ }
+ }
+ DECL_ATTRIBUTES (var) = tree_cons (get_identifier ("omp allocate"),
+ build_tree_list (allocator, alignment),
+ DECL_ATTRIBUTES (var));
+ }
}
/* OpenMP 2.5:
@@ -24926,9 +25018,6 @@ c_parser_omp_construct (c_parser *parser, bool *if_p)
strcpy (p_name, "#pragma wait");
stmt = c_parser_oacc_wait (loc, parser, p_name);
break;
- case PRAGMA_OMP_ALLOCATE:
- c_parser_omp_allocate (loc, parser);
- return;
case PRAGMA_OMP_ATOMIC:
c_parser_omp_atomic (loc, parser, false);
return;
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index f928137..2664354 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -626,6 +626,7 @@ extern unsigned int start_underspecified_init (location_t, tree);
extern void finish_underspecified_init (tree, unsigned int);
extern void push_scope (void);
extern tree pop_scope (void);
+extern void c_mark_decl_jump_unsafe_in_current_scope ();
extern void c_bindings_start_stmt_expr (struct c_spot_bindings *);
extern void c_bindings_end_stmt_expr (struct c_spot_bindings *);