diff options
Diffstat (limited to 'gcc/c/c-parser.cc')
-rw-r--r-- | gcc/c/c-parser.cc | 487 |
1 files changed, 317 insertions, 170 deletions
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 4a13fc0..566ab1b 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -2822,7 +2822,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, specs->constexpr_p, &richloc); /* A parameter is initialized, which is invalid. Don't attempt to instrument the initializer. */ - int flag_sanitize_save = flag_sanitize; + sanitize_code_type flag_sanitize_save = flag_sanitize; if (nested && !empty_ok) flag_sanitize = 0; init = c_parser_expr_no_commas (parser, NULL); @@ -2911,7 +2911,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, specs->constexpr_p, &richloc); /* A parameter is initialized, which is invalid. Don't attempt to instrument the initializer. */ - int flag_sanitize_save = flag_sanitize; + sanitize_code_type flag_sanitize_save = flag_sanitize; if (TREE_CODE (d) == PARM_DECL) flag_sanitize = 0; init = c_parser_initializer (parser, d); @@ -11876,12 +11876,9 @@ c_parser_postfix_expression (c_parser *parser) if (c_parser_next_token_is (parser, CPP_NAME)) { c_token *comp_tok = c_parser_peek_token (parser); - /* Ignore the counted_by attribute for reference inside - offsetof since the information is not useful at all. */ offsetof_ref = build_component_ref (loc, offsetof_ref, comp_tok->value, - comp_tok->location, UNKNOWN_LOCATION, - false); + comp_tok->location, UNKNOWN_LOCATION); c_parser_consume_token (parser); while (c_parser_next_token_is (parser, CPP_DOT) || c_parser_next_token_is (parser, @@ -11908,14 +11905,11 @@ c_parser_postfix_expression (c_parser *parser) break; } c_token *comp_tok = c_parser_peek_token (parser); - /* Ignore the counted_by attribute for reference inside - offsetof since the information is not useful. */ offsetof_ref = build_component_ref (loc, offsetof_ref, comp_tok->value, comp_tok->location, - UNKNOWN_LOCATION, - false); + UNKNOWN_LOCATION); c_parser_consume_token (parser); } else @@ -12701,7 +12695,7 @@ c_parser_postfix_expression (c_parser *parser) /* If the array ref is inside TYPEOF or ALIGNOF, the call to .ACCESS_WITH_SIZE was not generated by the routine build_component_ref by default, we should generate it here. */ - if ((in_typeof || in_alignof) && TREE_CODE (ref) == COMPONENT_REF) + if (TREE_CODE (ref) == COMPONENT_REF) ref = handle_counted_by_for_component_ref (loc, ref); if (has_counted_by_object (ref)) @@ -16659,7 +16653,7 @@ c_parser_omp_variable_list (c_parser *parser, || CONVERT_EXPR_P (decl)) decl = TREE_OPERAND (decl, 0); - tree u = build_omp_clause (clause_loc, kind); + tree u = build_omp_clause (loc, kind); OMP_CLAUSE_DECL (u) = decl; OMP_CLAUSE_CHAIN (u) = list; list = u; @@ -20072,7 +20066,7 @@ c_parser_omp_clause_doacross (c_parser *parser, tree list) map ( [map-type-modifier[,] ...] map-kind: variable-list ) map-type-modifier: - always | close */ + always | close | present | iterator (iterators-definition) */ static tree c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p) @@ -20087,15 +20081,35 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p) int pos = 1; int map_kind_pos = 0; - while (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_NAME) + int iterator_length = 0; + for (;;) { - if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COLON) + c_token *tok = c_parser_peek_nth_token_raw (parser, pos); + if (tok->type != CPP_NAME) + break; + + const char *p = IDENTIFIER_POINTER (tok->value); + c_token *next_tok = c_parser_peek_nth_token_raw (parser, pos + 1); + if (strcmp (p, "iterator") == 0 && next_tok->type == CPP_OPEN_PAREN) + { + unsigned n = pos + 2; + if (c_parser_check_balanced_raw_token_sequence (parser, &n) + && c_parser_peek_nth_token_raw (parser, n)->type + == CPP_CLOSE_PAREN) + { + iterator_length = n - pos + 1; + pos = n; + next_tok = c_parser_peek_nth_token_raw (parser, pos + 1); + } + } + + if (next_tok->type == CPP_COLON) { map_kind_pos = pos; break; } - if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA) + if (next_tok->type == CPP_COMMA) pos++; else if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_OPEN_PAREN) @@ -20117,6 +20131,7 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p) int present_modifier = 0; int mapper_modifier = 0; tree mapper_name = NULL_TREE; + tree iterators = NULL_TREE; for (int pos = 1; pos < map_kind_pos; ++pos) { c_token *tok = c_parser_peek_token (parser); @@ -20150,6 +20165,17 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p) close_modifier++; c_parser_consume_token (parser); } + else if (strcmp ("iterator", p) == 0) + { + if (iterators) + { + c_parser_error (parser, "too many %<iterator%> modifiers"); + parens.skip_until_found_close (parser); + return list; + } + iterators = c_parser_omp_iterators (parser); + pos += iterator_length - 1; + } else if (strcmp ("mapper", p) == 0) { c_parser_consume_token (parser); @@ -20223,8 +20249,8 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p) else { c_parser_error (parser, "%<map%> clause with map-type modifier other " - "than %<always%>, %<close%>, %<mapper%> or " - "%<present%>"); + "than %<always%>, %<close%>, %<iterator%>, " + "%<mapper%> or %<present%>"); parens.skip_until_found_close (parser); return list; } @@ -20273,9 +20299,19 @@ c_parser_omp_clause_map (c_parser *parser, tree list, bool declare_mapper_p) tree last_new = NULL_TREE; + if (iterators) + { + tree block = pop_scope (); + if (iterators == error_mark_node) + iterators = NULL_TREE; + else + TREE_VEC_ELT (iterators, 5) = block; + } + for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) { OMP_CLAUSE_SET_MAP_KIND (c, kind); + OMP_CLAUSE_ITERATORS (c) = iterators; last_new = c; } @@ -20534,8 +20570,11 @@ c_parser_omp_clause_device_type (c_parser *parser, tree list) to ( variable-list ) OpenMP 5.1: - from ( [present :] variable-list ) - to ( [present :] variable-list ) */ + from ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list ) + to ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list ) + + motion-modifier: + present | iterator (iterators-definition) */ static tree c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind, @@ -20546,18 +20585,85 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind, if (!parens.require_open (parser)) return list; + int pos = 1, colon_pos = 0; + int iterator_length = 0; + + while (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_NAME) + { + const char *identifier = + IDENTIFIER_POINTER (c_parser_peek_nth_token_raw (parser, pos)->value); + if (c_parser_peek_nth_token_raw (parser, pos + 1)->type + == CPP_OPEN_PAREN) + { + unsigned int npos = pos + 2; + if (c_parser_check_balanced_raw_token_sequence (parser, &npos) + && (c_parser_peek_nth_token_raw (parser, npos)->type + == CPP_CLOSE_PAREN)) + { + if (strcmp (identifier, "iterator") == 0) + iterator_length = npos - pos + 1; + pos = npos; + } + } + if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA) + pos += 2; + else + pos++; + if (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_COLON) + { + colon_pos = pos; + break; + } + } + bool present = false; - c_token *token = c_parser_peek_token (parser); + tree iterators = NULL_TREE; - if (token->type == CPP_NAME - && strcmp (IDENTIFIER_POINTER (token->value), "present") == 0 - && c_parser_peek_2nd_token (parser)->type == CPP_COLON) + for (int pos = 1; pos < colon_pos; ++pos) { - present = true; - c_parser_consume_token (parser); - c_parser_consume_token (parser); + c_token *token = c_parser_peek_token (parser); + if (token->type == CPP_COMMA) + { + c_parser_consume_token (parser); + continue; + } + const char *p = IDENTIFIER_POINTER (token->value); + if (strcmp ("present", p) == 0) + { + if (present) + { + c_parser_error (parser, "too many %<present%> modifiers"); + parens.skip_until_found_close (parser); + return list; + } + present = true; + c_parser_consume_token (parser); + } + else if (strcmp ("iterator", p) == 0) + { + if (iterators) + { + c_parser_error (parser, "too many %<iterator%> modifiers"); + parens.skip_until_found_close (parser); + return list; + } + iterators = c_parser_omp_iterators (parser); + pos += iterator_length - 1; + } + else + { + error_at (token->location, + "%qs clause with modifier other than %<iterator%> or " + "%<present%>", + kind == OMP_CLAUSE_TO ? "to" : "from"); + parens.skip_until_found_close (parser); + return list; + } } + if (colon_pos) + c_parser_require (parser, CPP_COLON, "expected %<:%>"); + tree nl = c_parser_omp_variable_list (parser, loc, kind, list); parens.skip_until_found_close (parser); @@ -20565,6 +20671,19 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind, for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) OMP_CLAUSE_MOTION_PRESENT (c) = 1; + if (iterators) + { + tree block = pop_scope (); + if (iterators == error_mark_node) + iterators = NULL_TREE; + else + TREE_VEC_ELT (iterators, 5) = block; + } + + if (iterators) + for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) + OMP_CLAUSE_ITERATORS (c) = iterators; + return nl; } @@ -27185,6 +27304,30 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms) undeclared_variable (token->location, token->value); variant = error_mark_node; } + else if (TREE_CODE (variant) != FUNCTION_DECL) + { + error_at (token->location, "variant %qD is not a function", + variant); + variant = error_mark_node; + } + else if (fndecl_built_in_p (variant) + && (strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)), + "__builtin_", strlen ("__builtin_")) == 0 + || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)), + "__sync_", strlen ("__sync_")) == 0 + || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)), + "__atomic_", strlen ("__atomic_")) == 0)) + { + error_at (token->location, "variant %qD is a built-in", + variant); + variant = error_mark_node; + } + else if (variant == fndecl) + { + error_at (token->location, "variant %qD is the same as base function", + variant); + variant = error_mark_node; + } c_parser_consume_token (parser); @@ -27258,30 +27401,6 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms) goto fail; ctx = omp_check_context_selector (match_loc, ctx, OMP_CTX_DECLARE_VARIANT); - if (ctx != error_mark_node && variant != error_mark_node) - { - if (TREE_CODE (variant) != FUNCTION_DECL) - { - error_at (token->location, "variant %qD is not a function", - variant); - variant = error_mark_node; - } - else if (fndecl_built_in_p (variant) - && (strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)), - "__builtin_", strlen ("__builtin_")) - == 0 - || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)), - "__sync_", strlen ("__sync_")) - == 0 - || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)), - "__atomic_", strlen ("__atomic_")) - == 0)) - { - error_at (token->location, "variant %qD is a built-in", - variant); - variant = error_mark_node; - } - } } else if (ccode == adjust_args) { @@ -27423,18 +27542,64 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms) parens.require_close (parser); } while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL)); + if (variant != error_mark_node && !has_match) + { + c_parser_error (parser, "expected %<match%> clause"); + variant = error_mark_node; + } c_parser_skip_to_pragma_eol (parser); - if ((ctx != error_mark_node && variant != error_mark_node) + /* At this point, we have completed parsing of the pragma, now it's + on to error checking. */ + if (variant == error_mark_node || ctx == error_mark_node) + /* Previously diagnosed error. */ + return; + + if ((has_adjust_args || append_args_tree) && !omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT, - OMP_TRAIT_CONSTRUCT_SIMD)) + OMP_TRAIT_CONSTRUCT_DISPATCH)) { - bool fail = false; - if (append_args_tree) + error_at (has_adjust_args ? adjust_args_loc : append_args_loc, + "an %qs clause can only be specified if the " + "%<dispatch%> selector of the %<construct%> selector " + "set appears in the %<match%> clause", + has_adjust_args ? "adjust_args" : "append_args"); + return; + } + + if (!omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT, + OMP_TRAIT_CONSTRUCT_SIMD)) + /* Check that the base and variant have compatible types. */ + { + tree base_type = TREE_TYPE (fndecl); + tree variant_type = TREE_TYPE (variant); + bool unprototyped_variant + = (TYPE_ARG_TYPES (variant_type) == NULL_TREE + && !TYPE_NO_NAMED_ARGS_STDARG_P (variant_type)); + + if (append_args_tree + && TYPE_ARG_TYPES (base_type) == NULL_TREE + && !TYPE_NO_NAMED_ARGS_STDARG_P (base_type)) + { + /* The base function is a pre-C23 unprototyped function. Without + a prototype, we don't know the offset where the append_args go. + That offset needs to be stored with the append_args in the + variant function attributes, so we cannot presently handle + this case. */ + sorry_at (append_args_loc, + "%<append_args%> with unprototyped base function " + "is not supported yet"); + inform (DECL_SOURCE_LOCATION (fndecl), + "base function %qD declared here", fndecl); + return; + } + else if (append_args_tree) { + /* Find nbase_args, the number of fixed arguments in the base + function. */ int nappend_args = 0; int nbase_args = 0; - for (tree t = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); + for (tree t = TYPE_ARG_TYPES (base_type); t && TREE_VALUE (t) != void_type_node; t = TREE_CHAIN (t)) nbase_args++; for (tree t = append_args_tree; t; t = TREE_CHAIN (t)) @@ -27445,135 +27610,117 @@ c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms) append_args_tree = build_tree_list (build_int_cst (integer_type_node, nbase_args), append_args_tree); - tree args, arg; - args = arg = TYPE_ARG_TYPES (TREE_TYPE (variant)); - for (int j = 0; j < nbase_args && arg; j++, arg = TREE_CHAIN (arg)) - args = arg; - for (int i = 0; i < nappend_args && arg; i++) - arg = TREE_CHAIN (arg); - tree saved_args; - if (nbase_args && args) - { - saved_args = TREE_CHAIN (args); - TREE_CHAIN (args) = arg; + + /* Give a specific diagnostic if the append_args parameters + of the variant are of the wrong type, or missing. The + compatible types test below could fail to detect this if + the variant is a varargs function. */ + if (!unprototyped_variant) + { + tree args = TYPE_ARG_TYPES (variant_type); + for (int i = 0; args && i < nbase_args; + i++, args = TREE_CHAIN (args)) + ; + for (int i = 0; i < nappend_args; i++, args = TREE_CHAIN (args)) + if (!args || !c_omp_interop_t_p (TREE_VALUE (args))) + { + error_at (DECL_SOURCE_LOCATION (variant), + "argument %d of %qD must be of " + "%<omp_interop_t%>", + nbase_args + i + 1, variant); + inform (append_args_loc, + "%<append_args%> specified here"); + return; + } } - else + + /* Perform the "implementation defined transformation" on the type + of the base function to add the append_args before checking it + for compatibility with the function variant's type. */ + tree args = TYPE_ARG_TYPES (base_type); + tree newargs = NULL_TREE; + tree lastarg = NULL_TREE; + for (int j = 0; j < nbase_args; j++, args = TREE_CHAIN (args)) { - saved_args = args; - TYPE_ARG_TYPES (TREE_TYPE (variant)) = arg; - TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (variant)) = 1; + tree t = tree_cons (TREE_PURPOSE (args), + TREE_VALUE (args), NULL_TREE); + if (lastarg) + TREE_CHAIN (lastarg) = t; + else + newargs = t; + lastarg = t; } - if (!comptypes (TREE_TYPE (fndecl), TREE_TYPE (variant))) - fail = true; - if (nbase_args && args) - TREE_CHAIN (args) = saved_args; - else + tree type = lookup_name (get_identifier ("omp_interop_t")); + type = type ? TREE_TYPE (type) : pointer_sized_int_node; + for (int j = 0; j < nappend_args; j++) { - TYPE_ARG_TYPES (TREE_TYPE (variant)) = saved_args; - TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (variant)) = 0; + tree t = tree_cons (NULL_TREE, type, NULL_TREE); + if (lastarg) + TREE_CHAIN (lastarg) = t; + else + newargs = t; + lastarg = t; } - arg = saved_args; - if (!fail) - for (int i = 0; i < nappend_args; i++, arg = TREE_CHAIN (arg)) - if (!arg || !c_omp_interop_t_p (TREE_VALUE (arg))) - { - error_at (DECL_SOURCE_LOCATION (variant), - "argument %d of %qD must be of %<omp_interop_t%>", - nbase_args + i + 1, variant); - inform (append_args_loc, "%<append_args%> specified here"); - break; - } - } - else - { - if (comptypes (TREE_TYPE (fndecl), TREE_TYPE (variant))) + TREE_CHAIN (lastarg) = args; + + /* Temporarily stuff newargs into the original base_type. */ + tree saveargs = TYPE_ARG_TYPES (base_type); + TYPE_ARG_TYPES (base_type) = newargs; + bool fail = !comptypes (base_type, variant_type); + TYPE_ARG_TYPES (base_type) = saveargs; + + if (fail) { - if (TYPE_ARG_TYPES (TREE_TYPE (variant)) == NULL_TREE - && TYPE_ARG_TYPES (TREE_TYPE (fndecl)) != NULL_TREE) - { - if (!append_args_tree) - TYPE_ARG_TYPES (TREE_TYPE (variant)) - = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); - else - { - tree new_args = NULL_TREE; - tree arg, last_arg = NULL_TREE; - for (arg = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); - arg && arg != void_type_node; arg = TREE_CHAIN (arg)) - { - if (new_args == NULL_TREE) - new_args = last_arg = copy_node (arg); - else - { - TREE_CHAIN (last_arg) = copy_node (arg); - last_arg = TREE_CHAIN (last_arg); - } - } - for (tree t3 = append_args_tree; t3; t3 = TREE_CHAIN (t3)) - { - tree type = lookup_name (get_identifier ("omp_interop_t")); - type = type ? TREE_TYPE (type) : ptr_type_node; - last_arg = tree_cons (NULL_TREE, type, last_arg); - } - TREE_CHAIN (last_arg) = arg; - TYPE_ARG_TYPES (TREE_TYPE (variant)) = new_args; - } - } + error_at (token->location, + "variant %qD and base %qD have incompatible types " + "after %<append_args%> adjustment", + variant, fndecl); + inform (DECL_SOURCE_LOCATION (variant), + "%<declare variant%> candidate %qD declared here", + variant); + return; } - else - fail = true; + else if (unprototyped_variant) + /* If we've got an unprototyped variant, copy the transformed + base arg types to the variant. This is needed later by + modify_call_for_omp_dispatch. */ + TYPE_ARG_TYPES (variant_type) = newargs; } - if (fail) - { - error_at (token->location, - "variant %qD and base %qD have incompatible types", - variant, fndecl); - variant = error_mark_node; - } - } - if (ctx != error_mark_node && variant != error_mark_node) - { - C_DECL_USED (variant) = 1; - tree construct = omp_get_context_selector_list (ctx, - OMP_TRAIT_SET_CONSTRUCT); - omp_mark_declare_variant (match_loc, variant, construct); - if (omp_context_selector_matches (ctx, NULL_TREE, false)) + else /* No append_args present. */ { - tree attr = tree_cons (get_identifier ("omp declare variant base"), - build_tree_list (variant, ctx), - DECL_ATTRIBUTES (fndecl)); - DECL_ATTRIBUTES (fndecl) = attr; + if (!comptypes (base_type, variant_type)) + { + error_at (token->location, + "variant %qD and base %qD have incompatible types", + variant, fndecl); + inform (DECL_SOURCE_LOCATION (variant), + "%<declare variant%> candidate %qD declared here", + variant); + return; + } + else if (TYPE_ARG_TYPES (variant_type) == NULL_TREE + && !TYPE_NO_NAMED_ARGS_STDARG_P (variant_type) + && TYPE_ARG_TYPES (base_type) != NULL_TREE) + /* If we've got an unprototyped variant but the base has + a prototype, copy the base arg types to the variant. */ + TYPE_ARG_TYPES (variant_type) = TYPE_ARG_TYPES (base_type); } } - if (has_adjust_args || append_args_tree) + /* If we made it here, store the parsed information. */ + C_DECL_USED (variant) = 1; + tree construct = omp_get_context_selector_list (ctx, + OMP_TRAIT_SET_CONSTRUCT); + omp_mark_declare_variant (match_loc, variant, construct); + if (omp_context_selector_matches (ctx, NULL_TREE, false)) { - if (!has_match) - { - error_at (has_adjust_args ? adjust_args_loc : append_args_loc, - "an %qs clause requires a %<match%> clause", - has_adjust_args ? "adjust_args" : "append_args"); - } - else if (ctx != error_mark_node && variant != error_mark_node) - { - tree attr = lookup_attribute ("omp declare variant base", - DECL_ATTRIBUTES (fndecl)); - if (attr != NULL_TREE) - { - tree ctx = TREE_VALUE (TREE_VALUE (attr)); - if (!omp_get_context_selector (ctx, OMP_TRAIT_SET_CONSTRUCT, - OMP_TRAIT_CONSTRUCT_DISPATCH)) - error_at (has_adjust_args ? adjust_args_loc : append_args_loc, - "an %qs clause can only be specified if the " - "%<dispatch%> selector of the %<construct%> selector " - "set appears in the %<match%> clause", - has_adjust_args ? "adjust_args" : "append_args"); - } - } + tree attr = tree_cons (get_identifier ("omp declare variant base"), + build_tree_list (variant, ctx), + DECL_ATTRIBUTES (fndecl)); + DECL_ATTRIBUTES (fndecl) = attr; } - if ((ctx != error_mark_node && variant != error_mark_node) - && (need_device_ptr_list || append_args_tree)) + if (need_device_ptr_list || append_args_tree) { tree variant_decl = tree_strip_nop_conversions (variant); tree t = build_tree_list (need_device_ptr_list, |