diff options
Diffstat (limited to 'gcc/c/c-parser.cc')
-rw-r--r-- | gcc/c/c-parser.cc | 88 |
1 files changed, 65 insertions, 23 deletions
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 6923000..4342788 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -18814,32 +18814,71 @@ c_parser_oacc_wait (location_t loc, c_parser *parser, char *p_name) return stmt; } -/* OpenMP 5.0: - # pragma omp allocate (list) [allocator(allocator)] */ +/* OpenMP 5.x: + # pragma omp allocate (list) clauses + + OpenMP 5.0 clause: + allocator (omp_allocator_handle_t expression) + + OpenMP 5.1 additional clause: + align (constant-expression)] */ static void c_parser_omp_allocate (location_t loc, c_parser *parser) { + tree alignment = NULL_TREE; 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_COMMA) - && c_parser_peek_2nd_token (parser)->type == CPP_NAME) - c_parser_consume_token (parser); - if (c_parser_next_token_is (parser, CPP_NAME)) + do { + if (c_parser_next_token_is (parser, CPP_COMMA) + && c_parser_peek_2nd_token (parser)->type == CPP_NAME) + c_parser_consume_token (parser); + if (!c_parser_next_token_is (parser, CPP_NAME)) + break; 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 %<allocator%>"); - else if (parens.require_open (parser)) + location_t expr_loc = c_parser_peek_token (parser)->location; + if (strcmp ("align", p) != 0 && strcmp ("allocator", p) != 0) { - 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); + error_at (c_parser_peek_token (parser)->location, + "expected %<allocator%> or %<align%>"); + break; + } + if (!parens.require_open (parser)) + break; + + 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) + { + error_at (expr_loc, "too many %qs clauses", "align"); + break; + } + else if (p[2] == 'i') + { + alignment = c_fully_fold (expr.value, false, NULL); + if (TREE_CODE (alignment) != INTEGER_CST + || !INTEGRAL_TYPE_P (TREE_TYPE (alignment)) + || tree_int_cst_sgn (alignment) != 1 + || !integer_pow2p (alignment)) + { + error_at (expr_loc, "%<align%> clause argument needs to be " + "positive constant power of two integer " + "expression"); + alignment = NULL_TREE; + } + } + else if (allocator) + { + error_at (expr_loc, "too many %qs clauses", "allocator"); + break; + } + else + { + allocator = c_fully_fold (expr.value, false, NULL); tree orig_type = expr.original_type ? expr.original_type : TREE_TYPE (allocator); orig_type = TYPE_MAIN_VARIANT (orig_type); @@ -18848,20 +18887,23 @@ c_parser_omp_allocate (location_t loc, c_parser *parser) || TYPE_NAME (orig_type) != get_identifier ("omp_allocator_handle_t")) { - error_at (expr_loc, "%<allocator%> clause allocator expression " - "has type %qT rather than " - "%<omp_allocator_handle_t%>", - TREE_TYPE (allocator)); + error_at (expr_loc, + "%<allocator%> clause allocator expression has type " + "%qT rather than %<omp_allocator_handle_t%>", + TREE_TYPE (allocator)); allocator = NULL_TREE; } - parens.skip_until_found_close (parser); } - } + parens.skip_until_found_close (parser); + } while (true); c_parser_skip_to_pragma_eol (parser); - if (allocator) + if (allocator || alignment) for (tree c = nl; c != NULL_TREE; c = OMP_CLAUSE_CHAIN (c)) - OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator; + { + OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator; + OMP_CLAUSE_ALLOCATE_ALIGN (c) = alignment; + } sorry_at (loc, "%<#pragma omp allocate%> not yet supported"); } |