OpenMP: C/C++ parse 'omp allocate' gcc/c-family/ChangeLog: * c-pragma.c (omp_pragmas): Add 'allocate'. * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_ALLOCATE. gcc/c/ChangeLog: * c-parser.c (c_parser_omp_allocate): New. (c_parser_omp_construct): Call it. gcc/cp/ChangeLog: * parser.c (cp_parser_omp_allocate): New. (cp_parser_omp_construct, cp_parser_pragma): Call it. gcc/testsuite/ChangeLog: * c-c++-common/gomp/allocate-5.c: New test. gcc/c-family/c-pragma.c | 1 + gcc/c-family/c-pragma.h | 1 + gcc/c/c-parser.c | 52 ++++++++++++++++++++++++++++ gcc/cp/parser.c | 43 ++++++++++++++++++++++- gcc/testsuite/c-c++-common/gomp/allocate-5.c | 41 ++++++++++++++++++++++ 5 files changed, 137 insertions(+), 1 deletion(-) diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c index d68985ca277..e80dcd7c0a1 100644 --- a/gcc/c-family/c-pragma.c +++ b/gcc/c-family/c-pragma.c @@ -1309,6 +1309,7 @@ static const struct omp_pragma_def oacc_pragmas[] = { { "wait", PRAGMA_OACC_WAIT } }; static const struct omp_pragma_def omp_pragmas[] = { + { "allocate", PRAGMA_OMP_ALLOCATE }, { "atomic", PRAGMA_OMP_ATOMIC }, { "barrier", PRAGMA_OMP_BARRIER }, { "cancel", PRAGMA_OMP_CANCEL }, diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index 5a493fe5175..e0e4da6b6b3 100644 --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -42,6 +42,7 @@ enum pragma_kind { PRAGMA_OACC_UPDATE, PRAGMA_OACC_WAIT, + PRAGMA_OMP_ALLOCATE, PRAGMA_OMP_ATOMIC, PRAGMA_OMP_BARRIER, PRAGMA_OMP_CANCEL, diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 7540a15d65d..fddd5c3c8c6 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -17255,6 +17255,55 @@ c_parser_oacc_wait (location_t loc, c_parser *parser, char *p_name) return stmt; } +/* OpenMP 5.0: + # pragma omp allocate (list) [allocator(allocator)] */ + +static void +c_parser_omp_allocate (location_t loc, c_parser *parser) +{ + tree allocator = NULL_TREE; + tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ALLOCATE, NULL_TREE); + if (c_parser_next_token_is (parser, CPP_NAME)) + { + matching_parens parens; + const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value); + c_parser_consume_token (parser); + if (strcmp ("allocator", p) != 0) + error_at (c_parser_peek_token (parser)->location, + "expected %"); + else if (parens.require_open (parser)) + { + location_t expr_loc = c_parser_peek_token (parser)->location; + c_expr expr = c_parser_expr_no_commas (parser, NULL); + expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true); + allocator = expr.value; + allocator = c_fully_fold (allocator, false, NULL); + tree orig_type + = expr.original_type ? expr.original_type : TREE_TYPE (allocator); + orig_type = TYPE_MAIN_VARIANT (orig_type); + if (!INTEGRAL_TYPE_P (TREE_TYPE (allocator)) + || TREE_CODE (orig_type) != ENUMERAL_TYPE + || TYPE_NAME (orig_type) + != get_identifier ("omp_allocator_handle_t")) + { + error_at (expr_loc, "% clause allocator expression " + "has type %qT rather than " + "%", + TREE_TYPE (allocator)); + allocator = NULL_TREE; + } + parens.skip_until_found_close (parser); + } + } + c_parser_skip_to_pragma_eol (parser); + + if (allocator) + for (tree c = nl; c != NULL_TREE; c = OMP_CLAUSE_CHAIN (c)) + OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator; + + sorry_at (loc, "%<#pragma omp allocate%> not yet supported"); +} + /* OpenMP 2.5: # pragma omp atomic new-line expression-stmt @@ -21542,6 +21591,9 @@ 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/cp/parser.c b/gcc/cp/parser.c index 88021243ee4..54e71e9743b 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -38136,6 +38136,42 @@ cp_parser_omp_structured_block (cp_parser *parser, bool *if_p) return finish_omp_structured_block (stmt); } +/* OpenMP 5.0: + # pragma omp allocate (list) [allocator(allocator)] */ + +static void +cp_parser_omp_allocate (cp_parser *parser, cp_token *pragma_tok) +{ + tree allocator = NULL_TREE; + location_t loc = pragma_tok->location; + tree nl = cp_parser_omp_var_list (parser, OMP_CLAUSE_ALLOCATE, NULL_TREE); + + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + matching_parens parens; + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + const char *p = IDENTIFIER_POINTER (id); + location_t cloc = cp_lexer_peek_token (parser->lexer)->location; + cp_lexer_consume_token (parser->lexer); + if (strcmp (p, "allocator") != 0) + error_at (cloc, "expected %"); + else if (parens.require_open (parser)) + { + allocator = cp_parser_assignment_expression (parser); + if (allocator == error_mark_node) + allocator = NULL_TREE; + parens.require_close (parser); + } + } + cp_parser_require_pragma_eol (parser, pragma_tok); + + if (allocator) + for (tree c = nl; c != NULL_TREE; c = OMP_CLAUSE_CHAIN (c)) + OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator; + + sorry_at (loc, "%<#pragma omp allocate%> not yet supported"); +} + /* OpenMP 2.5: # pragma omp atomic new-line expression-stmt @@ -43767,6 +43803,9 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p) case PRAGMA_OACC_WAIT: stmt = cp_parser_oacc_wait (parser, pragma_tok); break; + case PRAGMA_OMP_ALLOCATE: + cp_parser_omp_allocate (parser, pragma_tok); + return; case PRAGMA_OMP_ATOMIC: cp_parser_omp_atomic (parser, pragma_tok, false); return; @@ -44412,7 +44451,9 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p) goto bad_stmt; cp_parser_omp_construct (parser, pragma_tok, if_p); return true; - + case PRAGMA_OMP_ALLOCATE: + cp_parser_omp_allocate (parser, pragma_tok); + return false; case PRAGMA_OACC_ATOMIC: case PRAGMA_OACC_CACHE: case PRAGMA_OACC_DATA: diff --git a/gcc/testsuite/c-c++-common/gomp/allocate-5.c b/gcc/testsuite/c-c++-common/gomp/allocate-5.c new file mode 100644 index 00000000000..34dcb48c3d7 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/allocate-5.c @@ -0,0 +1,41 @@ +typedef enum omp_allocator_handle_t +#if __cplusplus >= 201103L +: __UINTPTR_TYPE__ +#endif +{ + omp_null_allocator = 0, + omp_default_mem_alloc = 1, + omp_large_cap_mem_alloc = 2, + omp_const_mem_alloc = 3, + omp_high_bw_mem_alloc = 4, + omp_low_lat_mem_alloc = 5, + omp_cgroup_mem_alloc = 6, + omp_pteam_mem_alloc = 7, + omp_thread_mem_alloc = 8, + __omp_allocator_handle_t_max__ = __UINTPTR_MAX__ +} omp_allocator_handle_t; + +void +foo () +{ + int a, b; + omp_allocator_handle_t my_allocator; +#pragma omp allocate (a) /* { dg-message "sorry, unimplemented: '#pragma omp allocate' not yet supported" } */ +#pragma omp allocate (b) allocator(my_allocator) /* { dg-message "sorry, unimplemented: '#pragma omp allocate' not yet supported" } */ +} + +void +bar () +{ + int a, b; + omp_allocator_handle_t my_allocator; +#pragma omp allocate /* { dg-error "expected '\\(' before end of line" } */ + /* { dg-message "sorry, unimplemented: '#pragma omp allocate' not yet supported" "" { target *-*-* } .-1 } */ +#pragma omp allocate allocator(my_allocator) /* { dg-error "expected '\\(' before 'allocator'" } */ + /* { dg-message "sorry, unimplemented: '#pragma omp allocate' not yet supported" "" { target *-*-* } .-1 } */ +#pragma omp allocate(a) foo(my_allocator) /* { dg-error "expected 'allocator'" } */ + /* { dg-error "expected end of line before '\\(' token" "" { target *-*-* } .-1 } */ + /* { dg-message "sorry, unimplemented: '#pragma omp allocate' not yet supported" "" { target *-*-* } .-2 } */ +#pragma omp allocate(a) allocator(b) /* { dg-error "'allocator' clause allocator expression has type 'int' rather than 'omp_allocator_handle_t'" "todo: cp/semantics.c" { xfail c++ } } */ + /* { dg-message "sorry, unimplemented: '#pragma omp allocate' not yet supported" "" { target *-*-* } .-1 } */ +}