diff options
Diffstat (limited to 'gcc/c')
-rw-r--r-- | gcc/c/ChangeLog | 214 | ||||
-rw-r--r-- | gcc/c/c-decl.cc | 237 | ||||
-rw-r--r-- | gcc/c/c-errors.cc | 63 | ||||
-rw-r--r-- | gcc/c/c-fold.cc | 20 | ||||
-rw-r--r-- | gcc/c/c-objc-common.cc | 2 | ||||
-rw-r--r-- | gcc/c/c-parser.cc | 542 | ||||
-rw-r--r-- | gcc/c/c-tree.h | 15 | ||||
-rw-r--r-- | gcc/c/c-typeck.cc | 495 |
8 files changed, 1056 insertions, 532 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index cb69b8c..bb0b8a9 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,217 @@ +2025-08-26 Sandra Loosemore <sloosemore@baylibre.com> + + PR middle-end/118839 + * c-parser.cc (c_finish_omp_declare_variant): Error if variant + is the same as base. + +2025-08-26 Sandra Loosemore <sloosemore@baylibre.com> + + * c-parser.cc (c_finish_omp_declare_variant): Rework diagnostic + code. Do not record variant if there are errors. Make check for + a missing "match" clause unconditional. + +2025-08-21 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + PR c/121478 + * c-fold.cc (c_fully_fold_internal): Fold nullptr_t ==/!= nullptr_t. + * c-typeck.cc (convert_arguments): Handle conversion from nullptr_t + for varargs. + (convert_for_assignment): Handle conversions from nullptr_t to + pointer type specially. + +2025-08-18 Indu Bhagat <indu.bhagat@oracle.com> + + * c-parser.cc (c_parser_declaration_or_fndef): Use + 'sanitize_code_type' instead of 'unsigned int'. + +2025-08-15 Jakub Jelinek <jakub@redhat.com> + + PR preprocessor/120778 + PR target/121520 + * c-decl.cc (c_init_decl_processing): Use cpp_warn instead of + cpp_lookup and NODE_WARN bit setting. + +2025-08-15 Qing Zhao <qing.zhao@oracle.com> + + * c-tree.h (handle_counted_by_for_component_ref): New prototype of + build_component_ref and handle_counted_by_for_component_ref. + * c-parser.cc (c_parser_postfix_expression): Call the new prototypes + of build_component_ref and handle_counted_by_for_component_ref, + update comments. + * c-typeck.cc (default_function_array_read_conversion): Likewise. + (convert_lvalue_to_rvalue): Likewise. + (default_conversion): Likewise. + (handle_counted_by_p): Update comments. + (handle_counted_by_for_component_ref): Delete one argument. + (build_component_ref): Delete one argument. Delete the call to + handle_counted_by_for_component_ref completely. + (build_array_ref): Generate call to .ACCESS_WITH_SIZE for array. + +2025-08-15 Qing Zhao <qing.zhao@oracle.com> + + * c-decl.cc (verify_counted_by_attribute): Change the 2nd argument + to a vector of fields with counted_by attribute. Verify all fields + in this vector. + (finish_struct): Collect all the fields with counted_by attribute + to a vector and pass this vector to verify_counted_by_attribute. + * c-tree.h (handle_counted_by_for_component_ref): New prototype of + handle_counted_by_form_component_ref. + * c-parser.cc (c_parser_postfix_expression): Call the new prototype + of handle_counted_by_for_component_ref. + * c-typeck.cc (default_function_array_read_conversion): Only generate + call to .ACCESS_WITH_SIZE for a pointer field when it's a read. + (convert_lvalue_to_rvalue): Likewise. + (default_conversion): Likewise. + (handle_counted_by_p): New routine. + (check_counted_by_attribute): New routine. + (build_counted_by_ref): Handle pointers with counted_by. + (build_access_with_size_for_counted_by): Handle pointers with counted_by. + (handle_counted_by_for_component_ref): Add one more argument. + (build_component_ref): Call the new prototype of + handle_counted_by_for_component_ref. + +2025-08-07 Jakub Jelinek <jakub@redhat.com> + + PR preprocessor/120778 + * c-decl.cc (c_init_decl_processing): Mark cpp nodes corresponding + to keywords as NODE_WARN if warn_keyword_macro. + +2025-08-06 Alexandre Oliva <oliva@adacore.com> + + * c-tree.h (C_BOOLEAN_TYPE_P): Cover hardbools as well. + * c-typeck.cc (convert_lvalue_to_rvalue): New overload and + wrapper. + (build_atomic_assign, build_modify_expr): Use it. + (build_asm_expr, handle_omp-array_sections_1): Simplify with + it. + (build_unary_op): Handle hardbools. + +2025-08-06 Martin Uecker <uecker@tugraz.at> + + PR c/108931 + * c-typeck.cc (composite_type_cond): Renamed from + composite_type with argument for condition + (composite_type): New function. + (composite_type_internal): Implement new logic. + (build_conditional_expr): Pass condition. + (common_pointer_type): Adapt. + (pointer_diff): Adapt. + (build_binary_op): Adapt. + +2025-08-06 Martin Uecker <uecker@tugraz.at> + + PR c/121217 + * c-typeck.cc (tagged_types_tu_compatible_p): Add check. + +2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com> + + * c-parser.cc (c_parser_omp_clause_from_to): Parse 'iterator' modifier. + * c-typeck.cc (c_finish_omp_clauses): Finish iterators for to/from + clauses. + +2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com> + Andrew Stubbs <ams@baylibre.com> + + * c-parser.cc (c_parser_omp_variable_list): Use location of the + map expression as the clause location. + (c_parser_omp_clause_map): Parse 'iterator' modifier. + * c-typeck.cc (c_finish_omp_clauses): Finish iterators. Apply + iterators to generated clauses. + +2025-08-02 Martin Uecker <uecker@tugraz.at> + + * c-decl.cc (get_parm_array_spec): Remove. + (push_parm_decl): Do not add `arg spec` attribute. + (build_arg_spec_attribute): New function. + (grokdeklarator): Add `arg spec` attribute. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * c-errors.cc: Update usage of "diagnostic_info" to explicitly + refer to "diagnostics::diagnostic_info". + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * c-errors.cc: Update for diagnostic_t becoming + enum class diagnostics::kind. + * c-parser.cc: Likewise. + * c-typeck.cc: Likewise. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * c-decl.cc: Update for renaming of diagnostic_option_id to + diagnostics::option_id. + * c-errors.cc: Likewise. + * c-tree.h: Likewise. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * c-objc-common.cc: Update for diagnostic_context becoming + diagnostics::context. + * c-tree.h: Likewise. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * c-errors.cc: Update to add "m_" prefix to fields of + diagnostic_info throughout. + +2025-07-21 Stefan Schulze Frielinghaus <stefansf@gcc.gnu.org> + + * c-typeck.cc (build_asm_expr): Pass null pointer to + parse_{input,output}_constraint(). + +2025-07-16 Kwok Cheung Yeung <kcyeung@baylibre.com> + + * c-typeck.cc (handle_omp_array_sections): Use OMP_ITERATOR_DECL_P. + (c_finish_omp_clauses): Likewise. + +2025-07-15 Jakub Jelinek <jakub@redhat.com> + Jason Merrill <jason@redhat.com> + + PR c/44677 + * c-parser.cc (c_parser_unary_expression): Clear DECL_READ_P + after default_function_array_read_conversion for + -Wunused-but-set-{parameter,variable}={2,3} on + PRE{IN,DE}CREMENT_EXPR argument. + (c_parser_postfix_expression_after_primary): Similarly for + POST{IN,DE}CREMENT_EXPR. + * c-decl.cc (pop_scope): Use OPT_Wunused_but_set_variable_ + instead of OPT_Wunused_but_set_variable. + (finish_function): Use OPT_Wunused_but_set_parameter_ + instead of OPT_Wunused_but_set_parameter. + * c-typeck.cc (mark_exp_read): Handle {PRE,POST}{IN,DE}CREMENT_EXPR + and don't handle it when cast to void. + (build_modify_expr): Clear DECL_READ_P after build_binary_op + for -Wunused-but-set-{parameter,variable}=3. + +2025-07-10 Qing Zhao <qing.zhao@oracle.com> + + * c-typeck.cc (build_access_with_size_for_counted_by): Update comments. + Adjust the arguments per the new design. + +2025-07-10 Qing Zhao <qing.zhao@oracle.com> + + PR middle-end/121000 + * c-typeck.cc (build_access_with_size_for_counted_by): Update comments. + Pass TYPE_SIZE_UNIT of the element as the 6th argument. + +2025-07-07 Qing Zhao <qing.zhao@oracle.com> + + Revert: + 2025-07-07 Qing Zhao <qing.zhao@oracle.com> + + * c-decl.cc (verify_counted_by_attribute): Change the 2nd argument + to a vector of fields with counted_by attribute. Verify all fields + in this vector. + (finish_struct): Collect all the fields with counted_by attribute + to a vector and pass this vector to verify_counted_by_attribute. + * c-typeck.cc (build_counted_by_ref): Handle pointers with counted_by. + Add one more argument, issue error when the pointee type is a structure + or union including a flexible array member. + (build_access_with_size_for_counted_by): Handle pointers with counted_by. + (handle_counted_by_for_component_ref): Call build_counted_by_ref + with the new prototype. + 2025-07-01 Qing Zhao <qing.zhao@oracle.com> * c-decl.cc (verify_counted_by_attribute): Change the 2nd argument diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc index 7e1c197..77006ca 100644 --- a/gcc/c/c-decl.cc +++ b/gcc/c/c-decl.cc @@ -1363,7 +1363,7 @@ pop_scope (void) case VAR_DECL: /* Warnings for unused variables. */ if ((!TREE_USED (p) || !DECL_READ_P (p)) - && !warning_suppressed_p (p, OPT_Wunused_but_set_variable) + && !warning_suppressed_p (p, OPT_Wunused_but_set_variable_) && !DECL_IN_SYSTEM_HEADER (p) && DECL_NAME (p) && !DECL_ARTIFICIAL (p) @@ -1377,7 +1377,7 @@ pop_scope (void) } else if (DECL_CONTEXT (p) == current_function_decl) warning_at (DECL_SOURCE_LOCATION (p), - OPT_Wunused_but_set_variable, + OPT_Wunused_but_set_variable_, "variable %qD set but not used", p); } @@ -4556,7 +4556,7 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind, location_t loc) /* Next, look for exact matches for builtin defines that would have been defined if the user had passed a command-line option (e.g. -fopenmp for "_OPENMP"). */ - diagnostic_option_id option_id + diagnostics::option_id option_id = get_option_for_builtin_define (IDENTIFIER_POINTER (name)); if (option_id.m_idx > 0) return name_hint @@ -4825,6 +4825,28 @@ c_init_decl_processing (void) make_fname_decl = c_make_fname_decl; start_fname_decls (); + + if (warn_keyword_macro) + { + for (unsigned int i = 0; i < num_c_common_reswords; ++i) + /* For C register keywords which don't start with underscore + or start with just single underscore. Don't complain about + ObjC or Transactional Memory keywords. */ + if (c_common_reswords[i].word[0] == '_' + && c_common_reswords[i].word[1] == '_') + continue; + else if (c_common_reswords[i].disable + & (D_TRANSMEM | D_OBJC | D_CXX_OBJC)) + continue; + else + { + tree id = get_identifier (c_common_reswords[i].word); + if (C_IS_RESERVED_WORD (id) + && C_RID_CODE (id) != RID_CXX_COMPAT_WARN) + cpp_warn (parse_in, IDENTIFIER_POINTER (id), + IDENTIFIER_LENGTH (id)); + } + } } /* Create the VAR_DECL at LOC for __FUNCTION__ etc. ID is the name to @@ -6208,184 +6230,7 @@ grokparm (const struct c_parm *parm, tree *expr) return decl; } -/* Return attribute "arg spec" corresponding to an array/VLA parameter - described by PARM, concatenated onto attributes ATTRS. - The spec consists of one dollar symbol for each specified variable - bound, one asterisk for each unspecified variable bound, followed - by at most one specification of the most significant bound of - an ordinary array parameter. For ordinary arrays the specification - is either the constant bound itself, or the space character for - an array with an unspecified bound (the [] form). Finally, a chain - of specified variable bounds is appended to the spec, starting with - the most significant bound. For example, the PARM T a[2][m][3][n] - will produce __attribute__((arg spec ("[$$2]", m, n)). - For T a typedef for an array with variable bounds, the bounds are - included in the specification in the expected order. - No "arg spec" is created for parameters of pointer types, making - a distinction between T(*)[N] (or, equivalently, T[][N]) and - the T[M][N] form, all of which have the same type and are represented - the same, but only the last of which gets an "arg spec" describing - the most significant bound M. */ - -static tree -get_parm_array_spec (const struct c_parm *parm, tree attrs) -{ - /* The attribute specification string, minor bound first. */ - std::string spec; - - /* A list of VLA variable bounds, major first, or null if unspecified - or not a VLA. */ - tree vbchain = NULL_TREE; - /* True for a pointer parameter. */ - bool pointer = false; - /* True for an ordinary array with an unpecified bound. */ - bool nobound = false; - - /* Create a string representation for the bounds of the array/VLA. */ - for (c_declarator *pd = parm->declarator, *next; pd; pd = next) - { - next = pd->declarator; - while (next && next->kind == cdk_attrs) - next = next->declarator; - - /* Remember if a pointer has been seen to avoid storing the constant - bound. */ - if (pd->kind == cdk_pointer) - pointer = true; - - if ((pd->kind == cdk_pointer || pd->kind == cdk_function) - && (!next || next->kind == cdk_id)) - { - /* Do nothing for the common case of a pointer. The fact that - the parameter is one can be deduced from the absence of - an arg spec for it. */ - return attrs; - } - - if (pd->kind == cdk_id) - { - if (pointer - || !parm->specs->type - || TREE_CODE (parm->specs->type) != ARRAY_TYPE - || !TYPE_DOMAIN (parm->specs->type) - || !TYPE_MAX_VALUE (TYPE_DOMAIN (parm->specs->type))) - continue; - - tree max = TYPE_MAX_VALUE (TYPE_DOMAIN (parm->specs->type)); - if (!vbchain - && TREE_CODE (max) == INTEGER_CST) - { - /* Extract the upper bound from a parameter of an array type - unless the parameter is an ordinary array of unspecified - bound in which case a next iteration of the loop will - exit. */ - if (spec.empty () || spec.end ()[-1] != ' ') - { - if (!tree_fits_shwi_p (max)) - continue; - - /* The upper bound is the value of the largest valid - index. */ - HOST_WIDE_INT n = tree_to_shwi (max) + 1; - char buf[40]; - sprintf (buf, HOST_WIDE_INT_PRINT_UNSIGNED, n); - spec += buf; - } - continue; - } - - /* For a VLA typedef, create a list of its variable bounds and - append it in the expected order to VBCHAIN. */ - tree tpbnds = NULL_TREE; - for (tree type = parm->specs->type; TREE_CODE (type) == ARRAY_TYPE; - type = TREE_TYPE (type)) - { - tree nelts_minus_one = array_type_nelts_minus_one (type); - if (error_operand_p (nelts_minus_one)) - return attrs; - if (TREE_CODE (nelts_minus_one) != INTEGER_CST) - { - /* Each variable VLA bound is represented by the dollar - sign. */ - spec += "$"; - tpbnds = tree_cons (NULL_TREE, nelts_minus_one, tpbnds); - } - } - tpbnds = nreverse (tpbnds); - vbchain = chainon (vbchain, tpbnds); - continue; - } - - if (pd->kind != cdk_array) - continue; - - if (pd->u.array.vla_unspec_p) - { - /* Each unspecified bound is represented by a star. There - can be any number of these in a declaration (but none in - a definition). */ - spec += '*'; - continue; - } - - tree nelts = pd->u.array.dimen; - if (!nelts) - { - /* Ordinary array of unspecified size. There can be at most - one for the most significant bound. Exit on the next - iteration which determines whether or not PARM is declared - as a pointer or an array. */ - nobound = true; - continue; - } - - if (pd->u.array.static_p) - spec += 's'; - - if (!INTEGRAL_TYPE_P (TREE_TYPE (nelts))) - /* Avoid invalid NELTS. */ - return attrs; - - STRIP_NOPS (nelts); - nelts = c_fully_fold (nelts, false, nullptr); - if (TREE_CODE (nelts) == INTEGER_CST) - { - /* Skip all constant bounds except the most significant one. - The interior ones are included in the array type. */ - if (next && (next->kind == cdk_array || next->kind == cdk_pointer)) - continue; - - if (!tree_fits_uhwi_p (nelts)) - /* Bail completely on invalid bounds. */ - return attrs; - - char buf[40]; - unsigned HOST_WIDE_INT n = tree_to_uhwi (nelts); - sprintf (buf, HOST_WIDE_INT_PRINT_UNSIGNED, n); - spec += buf; - break; - } - - /* Each variable VLA bound is represented by a dollar sign. */ - spec += "$"; - vbchain = tree_cons (NULL_TREE, nelts, vbchain); - } - - if (spec.empty () && !nobound) - return attrs; - spec.insert (0, "["); - if (nobound) - /* Ordinary array of unspecified bound is represented by a space. - It must be last in the spec. */ - spec += ' '; - spec += ']'; - - tree acsstr = build_string (spec.length () + 1, spec.c_str ()); - tree args = tree_cons (NULL_TREE, acsstr, vbchain); - tree name = get_identifier ("arg spec"); - return tree_cons (name, args, attrs); -} /* Given a parsed parameter declaration, decode it into a PARM_DECL and push that on the current scope. EXPR is a pointer to an @@ -6401,7 +6246,6 @@ push_parm_decl (const struct c_parm *parm, tree *expr) if (decl && DECL_P (decl)) DECL_SOURCE_LOCATION (decl) = parm->loc; - attrs = get_parm_array_spec (parm, attrs); decl_attributes (&decl, attrs, 0); decl = pushdecl (decl); @@ -6775,6 +6619,25 @@ add_decl_expr (location_t loc, tree type, tree *expr, bool set_name_p) } } + +/* Add attribute "arg spec" to ATTRS corresponding to an array/VLA parameter + declared with type TYPE. The attribute has two arguments. The first is + a string that encodes the presence of the static keyword. The second is + the declared type of the array before adjustment, i.e. as an array type + including the outermost bound. */ + +static tree +build_arg_spec_attribute (tree type, bool static_p, tree attrs) +{ + tree vbchain = tree_cons (NULL_TREE, type, NULL_TREE); + tree acsstr = static_p ? build_string (7, "static") : + build_string (1, ""); + tree args = tree_cons (NULL_TREE, acsstr, vbchain); + tree name = get_identifier ("arg spec"); + return tree_cons (name, args, attrs); +} + + /* Given declspecs and a declarator, determine the name and type of the object declared and construct a ..._DECL node for it. @@ -6834,6 +6697,7 @@ grokdeclarator (const struct c_declarator *declarator, bool funcdef_flag = false; bool funcdef_syntax = false; bool size_varies = false; + bool size_error = false; tree decl_attr = declspecs->decl_attr; int array_ptr_quals = TYPE_UNQUALIFIED; tree array_ptr_attrs = NULL_TREE; @@ -7326,6 +7190,7 @@ grokdeclarator (const struct c_declarator *declarator, "size of unnamed array has non-integer type"); size = integer_one_node; size_int_const = true; + size_error = true; } /* This can happen with enum forward declaration. */ else if (!COMPLETE_TYPE_P (TREE_TYPE (size))) @@ -7338,6 +7203,7 @@ grokdeclarator (const struct c_declarator *declarator, "type"); size = integer_one_node; size_int_const = true; + size_error = true; } size = c_fully_fold (size, false, &size_maybe_const); @@ -7363,6 +7229,7 @@ grokdeclarator (const struct c_declarator *declarator, error_at (loc, "size of unnamed array is negative"); size = integer_one_node; size_int_const = true; + size_error = true; } /* Handle a size folded to an integer constant but not an integer constant expression. */ @@ -7978,6 +7845,10 @@ grokdeclarator (const struct c_declarator *declarator, if (TREE_CODE (type) == ARRAY_TYPE) { + if (!size_error) + *decl_attrs = build_arg_spec_attribute (type, array_parm_static, + *decl_attrs); + /* Transfer const-ness of array into that of type pointed to. */ type = TREE_TYPE (type); if (orig_qual_type != NULL_TREE) @@ -11478,9 +11349,9 @@ finish_function (location_t end_loc) && !DECL_READ_P (decl) && DECL_NAME (decl) && !DECL_ARTIFICIAL (decl) - && !warning_suppressed_p (decl, OPT_Wunused_but_set_parameter)) + && !warning_suppressed_p (decl, OPT_Wunused_but_set_parameter_)) warning_at (DECL_SOURCE_LOCATION (decl), - OPT_Wunused_but_set_parameter, + OPT_Wunused_but_set_parameter_, "parameter %qD set but not used", decl); } diff --git a/gcc/c/c-errors.cc b/gcc/c/c-errors.cc index 4682dca..e2c74fe 100644 --- a/gcc/c/c-errors.cc +++ b/gcc/c/c-errors.cc @@ -33,10 +33,10 @@ along with GCC; see the file COPYING3. If not see bool pedwarn_c23 (location_t location, - diagnostic_option_id option_id, + diagnostics::option_id option_id, const char *gmsgid, ...) { - diagnostic_info diagnostic; + diagnostics::diagnostic_info diagnostic; va_list ap; bool warned = false; rich_location richloc (line_table, location); @@ -48,8 +48,9 @@ pedwarn_c23 (location_t location, { diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, (pedantic && !flag_isoc2y) - ? DK_PEDWARN : DK_WARNING); - diagnostic.option_id = OPT_Wc23_c2y_compat; + ? diagnostics::kind::pedwarn + : diagnostics::kind::warning); + diagnostic.m_option_id = OPT_Wc23_c2y_compat; warned = diagnostic_report_diagnostic (global_dc, &diagnostic); } /* -Wno-c23-c2y-compat suppresses even the pedwarns. */ @@ -58,8 +59,9 @@ pedwarn_c23 (location_t location, /* For -pedantic outside C2Y, issue a pedwarn. */ else if (pedantic && !flag_isoc2y) { - diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN); - diagnostic.option_id = option_id; + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, + diagnostics::kind::pedwarn); + diagnostic.m_option_id = option_id; warned = diagnostic_report_diagnostic (global_dc, &diagnostic); } va_end (ap); @@ -77,10 +79,10 @@ pedwarn_c23 (location_t location, bool pedwarn_c11 (location_t location, - diagnostic_option_id option_id, + diagnostics::option_id option_id, const char *gmsgid, ...) { - diagnostic_info diagnostic; + diagnostics::diagnostic_info diagnostic; va_list ap; bool warned = false; rich_location richloc (line_table, location); @@ -93,11 +95,12 @@ pedwarn_c11 (location_t location, { diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, (pedantic && !flag_isoc23) - ? DK_PEDWARN : DK_WARNING); + ? diagnostics::kind::pedwarn + : diagnostics::kind::warning); if (option_id == OPT_Wpedantic) - diagnostic.option_id = OPT_Wc11_c23_compat; + diagnostic.m_option_id = OPT_Wc11_c23_compat; else - diagnostic.option_id = option_id; + diagnostic.m_option_id = option_id; warned = diagnostic_report_diagnostic (global_dc, &diagnostic); } /* -Wno-c11-c23-compat suppresses even the pedwarns. */ @@ -106,8 +109,9 @@ pedwarn_c11 (location_t location, /* For -pedantic outside C23, issue a pedwarn. */ else if (pedantic && !flag_isoc23) { - diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN); - diagnostic.option_id = option_id; + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, + diagnostics::kind::pedwarn); + diagnostic.m_option_id = option_id; warned = diagnostic_report_diagnostic (global_dc, &diagnostic); } va_end (ap); @@ -122,10 +126,10 @@ pedwarn_c11 (location_t location, bool pedwarn_c99 (location_t location, - diagnostic_option_id option_id, + diagnostics::option_id option_id, const char *gmsgid, ...) { - diagnostic_info diagnostic; + diagnostics::diagnostic_info diagnostic; va_list ap; bool warned = false; rich_location richloc (line_table, location); @@ -137,8 +141,9 @@ pedwarn_c99 (location_t location, { diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, (pedantic && !flag_isoc11) - ? DK_PEDWARN : DK_WARNING); - diagnostic.option_id = OPT_Wc99_c11_compat; + ? diagnostics::kind::pedwarn + : diagnostics::kind::warning); + diagnostic.m_option_id = OPT_Wc99_c11_compat; warned = diagnostic_report_diagnostic (global_dc, &diagnostic); } /* -Wno-c99-c11-compat suppresses even the pedwarns. */ @@ -147,8 +152,9 @@ pedwarn_c99 (location_t location, /* For -pedantic outside C11, issue a pedwarn. */ else if (pedantic && !flag_isoc11) { - diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN); - diagnostic.option_id = option_id; + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, + diagnostics::kind::pedwarn); + diagnostic.m_option_id = option_id; warned = diagnostic_report_diagnostic (global_dc, &diagnostic); } va_end (ap); @@ -164,10 +170,10 @@ pedwarn_c99 (location_t location, bool pedwarn_c90 (location_t location, - diagnostic_option_id option_id, + diagnostics::option_id option_id, const char *gmsgid, ...) { - diagnostic_info diagnostic; + diagnostics::diagnostic_info diagnostic; va_list ap; bool warned = false; rich_location richloc (line_table, location); @@ -183,8 +189,9 @@ pedwarn_c90 (location_t location, { diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, (pedantic && !flag_isoc99) - ? DK_PEDWARN : DK_WARNING); - diagnostic.option_id = option_id; + ? diagnostics::kind::pedwarn + : diagnostics::kind::warning); + diagnostic.m_option_id = option_id; diagnostic_report_diagnostic (global_dc, &diagnostic); warned = true; goto out; @@ -196,8 +203,9 @@ pedwarn_c90 (location_t location, { diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, (pedantic && !flag_isoc99) - ? DK_PEDWARN : DK_WARNING); - diagnostic.option_id = OPT_Wc90_c99_compat; + ? diagnostics::kind::pedwarn + : diagnostics::kind::warning); + diagnostic.m_option_id = OPT_Wc90_c99_compat; diagnostic_report_diagnostic (global_dc, &diagnostic); } /* -Wno-c90-c99-compat suppresses the pedwarns. */ @@ -206,8 +214,9 @@ pedwarn_c90 (location_t location, /* For -pedantic outside C99, issue a pedwarn. */ else if (pedantic && !flag_isoc99) { - diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_PEDWARN); - diagnostic.option_id = option_id; + diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, + diagnostics::kind::pedwarn); + diagnostic.m_option_id = option_id; diagnostic_report_diagnostic (global_dc, &diagnostic); warned = true; } diff --git a/gcc/c/c-fold.cc b/gcc/c/c-fold.cc index d54ab3c..3f6e4b46 100644 --- a/gcc/c/c-fold.cc +++ b/gcc/c/c-fold.cc @@ -369,7 +369,25 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands, || TREE_CODE (op1) != INTEGER_CST)) goto out; - if (op0 != orig_op0 || op1 != orig_op1 || in_init) + if (TREE_CODE_CLASS (code) == tcc_comparison + && TREE_CODE (TREE_TYPE (op0)) == NULLPTR_TYPE + && TREE_CODE (TREE_TYPE (op1)) == NULLPTR_TYPE) + { + switch (code) + { + case EQ_EXPR: + ret = constant_boolean_node (true, TREE_TYPE (expr)); + break; + case NE_EXPR: + ret = constant_boolean_node (false, TREE_TYPE (expr)); + break; + default: + gcc_unreachable (); + } + ret = omit_two_operands_loc (loc, TREE_TYPE (expr), ret, + op0, op1); + } + else if (op0 != orig_op0 || op1 != orig_op1 || in_init) ret = in_init ? fold_build2_initializer_loc (loc, code, TREE_TYPE (expr), op0, op1) : fold_build2_loc (loc, code, TREE_TYPE (expr), op0, op1); diff --git a/gcc/c/c-objc-common.cc b/gcc/c/c-objc-common.cc index d574bc7..5c50983 100644 --- a/gcc/c/c-objc-common.cc +++ b/gcc/c/c-objc-common.cc @@ -414,7 +414,7 @@ has_c_linkage (const_tree decl ATTRIBUTE_UNUSED) } void -c_initialize_diagnostics (diagnostic_context *context) +c_initialize_diagnostics (diagnostics::context *context) { context->set_pretty_printer (std::make_unique<c_pretty_printer> ()); c_common_diagnostics_set_defaults (context); diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 0c3e3e2..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); @@ -10547,15 +10547,31 @@ c_parser_unary_expression (c_parser *parser) c_parser_consume_token (parser); exp_loc = c_parser_peek_token (parser)->location; op = c_parser_cast_expression (parser, NULL); - - op = default_function_array_read_conversion (exp_loc, op); + if ((VAR_P (op.value) || TREE_CODE (op.value) == PARM_DECL) + && !DECL_READ_P (op.value) + && (VAR_P (op.value) ? warn_unused_but_set_variable + : warn_unused_but_set_parameter) > 1) + { + op = default_function_array_read_conversion (exp_loc, op); + DECL_READ_P (op.value) = 0; + } + else + op = default_function_array_read_conversion (exp_loc, op); return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op); case CPP_MINUS_MINUS: c_parser_consume_token (parser); exp_loc = c_parser_peek_token (parser)->location; op = c_parser_cast_expression (parser, NULL); - - op = default_function_array_read_conversion (exp_loc, op); + if ((VAR_P (op.value) || TREE_CODE (op.value) == PARM_DECL) + && !DECL_READ_P (op.value) + && (VAR_P (op.value) ? warn_unused_but_set_variable + : warn_unused_but_set_parameter) > 1) + { + op = default_function_array_read_conversion (exp_loc, op); + DECL_READ_P (op.value) = 0; + } + else + op = default_function_array_read_conversion (exp_loc, op); return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op); case CPP_AND: c_parser_consume_token (parser); @@ -11860,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, @@ -11892,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 @@ -12685,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)) @@ -13933,7 +13943,17 @@ c_parser_postfix_expression_after_primary (c_parser *parser, start = expr.get_start (); finish = c_parser_peek_token (parser)->get_finish (); c_parser_consume_token (parser); - expr = default_function_array_read_conversion (expr_loc, expr); + if ((VAR_P (expr.value) || TREE_CODE (expr.value) == PARM_DECL) + && !DECL_READ_P (expr.value) + && (VAR_P (expr.value) ? warn_unused_but_set_variable + : warn_unused_but_set_parameter) > 1 + && TREE_CODE (TREE_TYPE (expr.value)) != ARRAY_TYPE) + { + expr = default_function_array_read_conversion (expr_loc, expr); + DECL_READ_P (expr.value) = 0; + } + else + expr = default_function_array_read_conversion (expr_loc, expr); expr.value = build_unary_op (op_loc, POSTINCREMENT_EXPR, expr.value, false); set_c_expr_source_range (&expr, start, finish); @@ -13945,7 +13965,17 @@ c_parser_postfix_expression_after_primary (c_parser *parser, start = expr.get_start (); finish = c_parser_peek_token (parser)->get_finish (); c_parser_consume_token (parser); - expr = default_function_array_read_conversion (expr_loc, expr); + if ((VAR_P (expr.value) || TREE_CODE (expr.value) == PARM_DECL) + && !DECL_READ_P (expr.value) + && (VAR_P (expr.value) ? warn_unused_but_set_variable + : warn_unused_but_set_parameter) > 1 + && TREE_CODE (TREE_TYPE (expr.value)) != ARRAY_TYPE) + { + expr = default_function_array_read_conversion (expr_loc, expr); + DECL_READ_P (expr.value) = 0; + } + else + expr = default_function_array_read_conversion (expr_loc, expr); expr.value = build_unary_op (op_loc, POSTDECREMENT_EXPR, expr.value, false); set_c_expr_source_range (&expr, start, finish); @@ -16623,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; @@ -20036,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) @@ -20051,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) @@ -20081,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); @@ -20114,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); @@ -20187,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; } @@ -20237,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; } @@ -20498,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, @@ -20510,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); @@ -20529,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; } @@ -27149,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); @@ -27222,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) { @@ -27387,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)) @@ -27409,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, @@ -29126,11 +29309,14 @@ c_parser_omp_error (c_parser *parser, enum pragma_context context) if (msg == NULL) msg = _("<message unknown at compile time>"); } + const enum diagnostics::kind diag_kind = (severity_fatal + ? diagnostics::kind::error + : diagnostics::kind::warning); if (msg) - emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0, + emit_diagnostic (diag_kind, loc, 0, "%<pragma omp error%> encountered: %s", msg); else - emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0, + emit_diagnostic (diag_kind, loc, 0, "%<pragma omp error%> encountered"); return false; } diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index 364f51d..afec03e2 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -163,7 +163,8 @@ along with GCC; see the file COPYING3. If not see (TREE_CODE (TYPE) == BOOLEAN_TYPE \ || (TREE_CODE (TYPE) == ENUMERAL_TYPE \ && ENUM_UNDERLYING_TYPE (TYPE) != NULL_TREE \ - && TREE_CODE (ENUM_UNDERLYING_TYPE (TYPE)) == BOOLEAN_TYPE)) + && (TREE_CODE (ENUM_UNDERLYING_TYPE (TYPE)) == BOOLEAN_TYPE \ + || c_hardbool_type_attr (TYPE)))) /* Record parser information about an expression that is irrelevant for code generation alongside a tree representing its value. */ @@ -757,7 +758,7 @@ extern tree c_finish_bc_name (location_t, tree, bool); extern bool c_objc_common_init (void); extern bool c_missing_noreturn_ok_p (tree); extern bool c_warn_unused_global_decl (const_tree); -extern void c_initialize_diagnostics (diagnostic_context *); +extern void c_initialize_diagnostics (diagnostics::context *); extern bool c_var_mod_p (tree x, tree fn); extern alias_set_type c_get_alias_set (tree); extern int c_type_dwarf_attribute (const_tree, int); @@ -820,7 +821,7 @@ extern void mark_exp_read (tree); extern tree composite_type (tree, tree); extern tree lookup_field (const_tree, tree); extern tree build_component_ref (location_t, tree, tree, location_t, - location_t, bool = true); + location_t); extern tree handle_counted_by_for_component_ref (location_t, tree); extern tree build_array_ref (location_t, tree, tree); extern tree build_omp_array_section (location_t, tree, tree, tree); @@ -960,13 +961,13 @@ extern void c_bind (location_t, tree, bool); extern bool tag_exists_p (enum tree_code, tree); /* In c-errors.cc */ -extern bool pedwarn_c90 (location_t, diagnostic_option_id, const char *, ...) +extern bool pedwarn_c90 (location_t, diagnostics::option_id, const char *, ...) ATTRIBUTE_GCC_DIAG(3,4); -extern bool pedwarn_c99 (location_t, diagnostic_option_id, const char *, ...) +extern bool pedwarn_c99 (location_t, diagnostics::option_id, const char *, ...) ATTRIBUTE_GCC_DIAG(3,4); -extern bool pedwarn_c11 (location_t, diagnostic_option_id, const char *, ...) +extern bool pedwarn_c11 (location_t, diagnostics::option_id, const char *, ...) ATTRIBUTE_GCC_DIAG(3,4); -extern bool pedwarn_c23 (location_t, diagnostic_option_id, const char *, ...) +extern bool pedwarn_c23 (location_t, diagnostics::option_id, const char *, ...) ATTRIBUTE_GCC_DIAG(3,4); extern void add_note_about_new_keyword (location_t loc, tree keyword_id); diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 7948106..6a08fcd 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -137,6 +137,7 @@ static void record_maybe_used_decl (tree); static bool comptypes_internal (const_tree, const_tree, struct comptypes_data *data); static bool comptypes_check_for_composite (tree t1, tree t2); +static bool handle_counted_by_p (tree); /* Return true if EXP is a null pointer constant, false otherwise. */ @@ -641,7 +642,8 @@ struct composite_cache { }; tree -composite_type_internal (tree t1, tree t2, struct composite_cache* cache) +composite_type_internal (tree t1, tree t2, tree cond, + struct composite_cache* cache) { enum tree_code code1; enum tree_code code2; @@ -686,8 +688,8 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache) { tree pointed_to_1 = TREE_TYPE (t1); tree pointed_to_2 = TREE_TYPE (t2); - tree target = composite_type_internal (pointed_to_1, - pointed_to_2, cache); + tree target = composite_type_internal (pointed_to_1, pointed_to_2, + cond, cache); t1 = c_build_pointer_type_for_mode (target, TYPE_MODE (t1), false); t1 = c_build_type_attribute_variant (t1, attributes); return qualify_type (t1, t2); @@ -695,25 +697,20 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache) case ARRAY_TYPE: { - tree elt = composite_type_internal (TREE_TYPE (t1), TREE_TYPE (t2), - cache); - int quals; - tree unqual_elt; tree d1 = TYPE_DOMAIN (t1); tree d2 = TYPE_DOMAIN (t2); - bool d1_variable, d2_variable; - bool d1_zero, d2_zero; - bool t1_complete, t2_complete; /* We should not have any type quals on arrays at all. */ gcc_assert (!TYPE_QUALS_NO_ADDR_SPACE (t1) && !TYPE_QUALS_NO_ADDR_SPACE (t2)); - t1_complete = COMPLETE_TYPE_P (t1); - t2_complete = COMPLETE_TYPE_P (t2); + bool t1_complete = COMPLETE_TYPE_P (t1); + bool t2_complete = COMPLETE_TYPE_P (t2); - d1_zero = d1 == NULL_TREE || !TYPE_MAX_VALUE (d1); - d2_zero = d2 == NULL_TREE || !TYPE_MAX_VALUE (d2); + bool d1_zero = d1 == NULL_TREE || !TYPE_MAX_VALUE (d1); + bool d2_zero = d2 == NULL_TREE || !TYPE_MAX_VALUE (d2); + + bool d1_variable, d2_variable; d1_variable = (!d1_zero && (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST @@ -722,10 +719,8 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache) && (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST || TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST)); - bool use1 = TYPE_DOMAIN (t1) - && (d2_variable || d2_zero || !d1_variable); - bool use2 = TYPE_DOMAIN (t2) - && (d1_variable || d1_zero || !d2_variable); + bool use1 = d1 && (d2_variable || d2_zero || !d1_variable); + bool use2 = d2 && (d1_variable || d1_zero || !d2_variable); /* If the first is an unspecified size pick the other one. */ if (d2_variable && c_type_unspecified_p (t1)) @@ -734,25 +729,53 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache) use1 = false; } - /* Save space: see if the result is identical to one of the args. */ - if (elt == TREE_TYPE (t1) && use1) - return c_build_type_attribute_variant (t1, attributes); - if (elt == TREE_TYPE (t2) && use2) - return c_build_type_attribute_variant (t2, attributes); + /* If both are VLAs but not unspecified and we are in the + conditional operator, we create a conditional to select + the size of the active branch. */ + bool use0 = cond && d1_variable && !c_type_unspecified_p (t1) + && d2_variable && !c_type_unspecified_p (t2); + + tree td; + tree elt = composite_type_internal (TREE_TYPE (t1), TREE_TYPE (t2), + cond, cache); + + if (!use0) + { + /* Save space: see if the result is identical to one of the args. */ + if (elt == TREE_TYPE (t1) && use1) + return c_build_type_attribute_variant (t1, attributes); + if (elt == TREE_TYPE (t2) && use2) + return c_build_type_attribute_variant (t2, attributes); + + if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1)) + return c_build_type_attribute_variant (t1, attributes); + if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1)) + return c_build_type_attribute_variant (t2, attributes); + + td = TYPE_DOMAIN (use1 ? t1 : t2); + } + else + { + /* Not used in C. */ + gcc_assert (size_zero_node == TYPE_MIN_VALUE (d1)); + gcc_assert (size_zero_node == TYPE_MIN_VALUE (d2)); - if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1)) - return c_build_type_attribute_variant (t1, attributes); - if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1)) - return c_build_type_attribute_variant (t2, attributes); + tree d = fold_build3_loc (UNKNOWN_LOCATION, COND_EXPR, sizetype, + cond, TYPE_MAX_VALUE (d1), + TYPE_MAX_VALUE (d2)); + + td = build_index_type (d); + } /* Merge the element types, and have a size if either arg has one. We may have qualifiers on the element types. To set up TYPE_MAIN_VARIANT correctly, we need to form the composite of the unqualified types and add the qualifiers back at the end. */ - quals = TYPE_QUALS (strip_array_types (elt)); - unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED); - t1 = c_build_array_type (unqual_elt, TYPE_DOMAIN (use1 ? t1 : t2)); + int quals = TYPE_QUALS (strip_array_types (elt)); + tree unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED); + + t1 = c_build_array_type (unqual_elt, td); /* Check that a type which has a varying outermost dimension got marked has having a variable size. */ @@ -819,7 +842,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache) gcc_assert (DECL_NAME (a) == DECL_NAME (b)); gcc_checking_assert (!DECL_NAME (a) || comptypes (ta, tb)); - tree t = composite_type_internal (ta, tb, cache); + tree t = composite_type_internal (ta, tb, cond, cache); tree f = build_decl (input_location, FIELD_DECL, DECL_NAME (a), t); DECL_PACKED (f) = DECL_PACKED (a); @@ -876,8 +899,8 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache) /* Function types: prefer the one that specified arg types. If both do, merge the arg types. Also merge the return types. */ { - tree valtype = composite_type_internal (TREE_TYPE (t1), - TREE_TYPE (t2), cache); + tree valtype = composite_type_internal (TREE_TYPE (t1), TREE_TYPE (t2), + cond, cache); tree p1 = TYPE_ARG_TYPES (t1); tree p2 = TYPE_ARG_TYPES (t2); int len; @@ -956,7 +979,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache) { TREE_VALUE (n) = composite_type_internal (TREE_TYPE (memb), TREE_VALUE (p2), - cache); + cond, cache); pedwarn (input_location, OPT_Wpedantic, "function types not truly compatible in ISO C"); goto parm_done; @@ -979,14 +1002,14 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache) TREE_VALUE (n) = composite_type_internal (TREE_TYPE (memb), TREE_VALUE (p1), - cache); + cond, cache); pedwarn (input_location, OPT_Wpedantic, "function types not truly compatible in ISO C"); goto parm_done; } } } - TREE_VALUE (n) = composite_type_internal (mv1, mv2, cache); + TREE_VALUE (n) = composite_type_internal (mv1, mv2, cond, cache); parm_done: ; } @@ -1001,18 +1024,25 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache) } tree -composite_type (tree t1, tree t2) +composite_type_cond (tree t1, tree t2, tree cond) { gcc_checking_assert (comptypes_check_for_composite (t1, t2)); struct composite_cache cache = { }; - tree n = composite_type_internal (t1, t2, &cache); + tree n = composite_type_internal (t1, t2, cond, &cache); gcc_checking_assert (comptypes_check_for_composite (n, t1)); gcc_checking_assert (comptypes_check_for_composite (n, t2)); return n; } + +tree +composite_type (tree t1, tree t2) +{ + return composite_type_cond (t1, t2, NULL_TREE); +} + /* Return the type of a conditional expression between pointers to possibly differently qualified versions of compatible types. @@ -1020,7 +1050,7 @@ composite_type (tree t1, tree t2) true; if that isn't so, this may crash. */ static tree -common_pointer_type (tree t1, tree t2) +common_pointer_type (tree t1, tree t2, tree cond) { tree attributes; unsigned target_quals; @@ -1047,8 +1077,8 @@ common_pointer_type (tree t1, tree t2) qualifiers of the two types' targets. */ tree pointed_to_1 = TREE_TYPE (t1); tree pointed_to_2 = TREE_TYPE (t2); - tree target = composite_type (TYPE_MAIN_VARIANT (pointed_to_1), - TYPE_MAIN_VARIANT (pointed_to_2)); + tree target = composite_type_cond (TYPE_MAIN_VARIANT (pointed_to_1), + TYPE_MAIN_VARIANT (pointed_to_2), cond); /* Strip array types to get correct qualifier for pointers to arrays */ quals1 = TYPE_QUALS_NO_ADDR_SPACE (strip_array_types (pointed_to_1)); @@ -1970,6 +2000,9 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2, ft2 = DECL_BIT_FIELD_TYPE (s2); } + if (!ft1 || !ft2) + return false; + if (TREE_CODE (ft1) == ERROR_MARK || TREE_CODE (ft2) == ERROR_MARK) return false; @@ -2310,14 +2343,30 @@ mark_exp_read (tree exp) case PARM_DECL: DECL_READ_P (exp) = 1; break; + CASE_CONVERT: + if (VOID_TYPE_P (TREE_TYPE (exp))) + switch (TREE_CODE (TREE_OPERAND (exp, 0))) + { + case PREINCREMENT_EXPR: + case PREDECREMENT_EXPR: + case POSTINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + return; + default: + break; + } + /* FALLTHRU */ case ARRAY_REF: case COMPONENT_REF: case MODIFY_EXPR: case REALPART_EXPR: case IMAGPART_EXPR: - CASE_CONVERT: case ADDR_EXPR: case VIEW_CONVERT_EXPR: + case PREINCREMENT_EXPR: + case PREDECREMENT_EXPR: + case POSTINCREMENT_EXPR: + case POSTDECREMENT_EXPR: mark_exp_read (TREE_OPERAND (exp, 0)); break; case COMPOUND_EXPR: @@ -2438,6 +2487,10 @@ struct c_expr default_function_array_read_conversion (location_t loc, struct c_expr exp) { mark_exp_read (exp.value); + /* We only generate a call to .ACCESS_WITH_SIZE when it is a read. */ + if (TREE_CODE (exp.value) == COMPONENT_REF + && handle_counted_by_p (exp.value)) + exp.value = handle_counted_by_for_component_ref (loc, exp.value); return default_function_array_conversion (loc, exp); } @@ -2539,6 +2592,11 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr exp, bool force_non_npc = false; if (read_p) mark_exp_read (exp.value); + /* We only generate a call to .ACCESS_WITH_SIZE when it is a read. */ + if (read_p && TREE_CODE (exp.value) == COMPONENT_REF + && handle_counted_by_p (exp.value)) + exp.value = handle_counted_by_for_component_ref (loc, exp.value); + if (convert_p) exp = default_function_array_conversion (loc, exp); if (!VOID_TYPE_P (TREE_TYPE (exp.value))) @@ -2632,6 +2690,20 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr exp, return exp; } +/* Wrapper for the overload above, same arguments but for tree rather than + c_expr. This is important for hardbools to decay to bools. */ + +static inline tree +convert_lvalue_to_rvalue (location_t loc, tree val, + bool convert_p, bool read_p, bool for_init = false) +{ + struct c_expr expr; + memset (&expr, 0, sizeof (expr)); + expr.value = val; + expr = convert_lvalue_to_rvalue (loc, expr, convert_p, read_p, for_init); + return expr.value; +} + /* EXP is an expression of integer type. Apply the integer promotions to it and return the promoted value. */ @@ -2702,6 +2774,10 @@ default_conversion (tree exp) tree promoted_type; mark_exp_read (exp); + /* We only generate a call to .ACCESS_WITH_SIZE when it is a read. */ + if (TREE_CODE (exp) == COMPONENT_REF + && handle_counted_by_p (exp)) + exp = handle_counted_by_for_component_ref (EXPR_LOCATION (exp), exp); /* Functions and arrays have been converted during parsing. */ gcc_assert (code != FUNCTION_TYPE); @@ -2920,10 +2996,63 @@ should_suggest_deref_p (tree datum_type) return false; } -/* For a SUBDATUM field of a structure or union DATUM, generate a REF to - the object that represents its counted_by per the attribute counted_by - attached to this field if it's a flexible array member or a pointer - field, otherwise return NULL_TREE. +/* Give a component ref REF, decide whether we should handle its counted_by + attribute based on its context: + Do not handle counted_by when in offsetof, typeof and alignof operator. */ + +static bool +handle_counted_by_p (tree ref) +{ + gcc_assert (TREE_CODE (ref) == COMPONENT_REF); + tree datum = TREE_OPERAND (ref, 0); + /* If the component_ref is build for a offsetof, i.e., the datum + of the component_ref is a indirect_ref of null_pointer_node, + we should not generate call to .ACCESS_WITH_SIZE. */ + if (TREE_CODE (datum) == INDIRECT_REF + && TREE_OPERAND (datum, 0) == null_pointer_node) + return false; + if (in_typeof || in_alignof) + return false; + return true; +} + +/* Given a component ref REF, if there is a counted_by attribute attached, + issue error when the element_type is a structure or union including a + flexible array member. */ + +static void +check_counted_by_attribute (location_t loc, tree ref) +{ + tree subdatum = TREE_OPERAND (ref, 1); + tree sub_type = TREE_TYPE (subdatum); + + if (!c_flexible_array_member_type_p (sub_type) + && TREE_CODE (sub_type) != POINTER_TYPE) + return; + + tree element_type = TREE_TYPE (sub_type); + + tree attr_counted_by = lookup_attribute ("counted_by", + DECL_ATTRIBUTES (subdatum)); + if (attr_counted_by) + { + /* Issue error when the element_type is a structure or + union including a flexible array member. */ + if (RECORD_OR_UNION_TYPE_P (element_type) + && TYPE_INCLUDES_FLEXARRAY (element_type)) + { + error_at (loc, + "%<counted_by%> attribute is not allowed for a pointer to" + " structure or union with flexible array member"); + return; + } + } +} + +/* For a SUBDATUM field of a structure or union DATUM, generate a REF + to the object that represents its counted_by per the attribute + counted_by attached to this field if it's a flexible array member + or a pointer field, otherwise return NULL_TREE. Set COUNTED_BY_TYPE to the TYPE of the counted_by field. For example, if: @@ -2938,10 +3067,10 @@ should_suggest_deref_p (tree datum_type) the ref to the object that represents its element count will be: &(p->k) - */ + static tree -build_counted_by_ref (location_t loc, tree datum, tree subdatum, +build_counted_by_ref (tree datum, tree subdatum, tree *counted_by_type) { tree type = TREE_TYPE (datum); @@ -2950,25 +3079,12 @@ build_counted_by_ref (location_t loc, tree datum, tree subdatum, && TREE_CODE (sub_type) != POINTER_TYPE) return NULL_TREE; - tree element_type = TREE_TYPE (sub_type); - tree attr_counted_by = lookup_attribute ("counted_by", DECL_ATTRIBUTES (subdatum)); tree counted_by_ref = NULL_TREE; *counted_by_type = NULL_TREE; if (attr_counted_by) { - /* Issue error when the element_type is a structure or - union including a flexible array member. */ - if (RECORD_OR_UNION_TYPE_P (element_type) - && TYPE_INCLUDES_FLEXARRAY (element_type)) - { - error_at (loc, - "%<counted_by%> attribute is not allowed for a pointer to" - " structure or union with flexible array member"); - return error_mark_node; - } - tree field_id = TREE_VALUE (TREE_VALUE (attr_counted_by)); counted_by_ref = build_component_ref (UNKNOWN_LOCATION, @@ -2994,26 +3110,41 @@ build_counted_by_ref (location_t loc, tree datum, tree subdatum, COUNTED_BY_REF, and the COUNTED_BY_TYPE, generate the corresponding call to the internal function .ACCESS_WITH_SIZE. - Generate an INDIRECT_REF to a call to the internal function - .ACCESS_WITH_SIZE. + A: For the Flexible Array Member, Generate an INDIRECT_REF to a call to + the internal function .ACCESS_WITH_SIZE. REF to: - (*.ACCESS_WITH_SIZE (REF, COUNTED_BY_REF, 1, (TYPE_OF_SIZE)0, -1, - (TYPE_OF_ARRAY *)0)) + (*.ACCESS_WITH_SIZE (REF, COUNTED_BY_REF, (* TYPE_OF_SIZE)0, + TYPE_SIZE_UNIT for element) NOTE: The return type of this function is the POINTER type pointing - to the original flexible array type or the original pointer type. - Then the type of the INDIRECT_REF is the original flexible array type - or the original pointer type. + to the original flexible array type. Then the type of the INDIRECT_REF + is the original flexible array type. + The type of the first argument of this function is a POINTER type + to the original flexible array type. + + B: For pointers with counted_by, generate a call to the internal function + .ACCESS_WITH_SIZE. + + REF + + to: + + .ACCESS_WITH_SIZE (REF, COUNTED_BY_REF, (* TYPE_OF_SIZE)0, + TYPE_SIZE_UNIT for element) - The 4th argument of the call is a constant 0 with the TYPE of the - object pointed by COUNTED_BY_REF. + NOTE: The return type of this function is the original pointer type. + The type of the first argument of this function is the original + pointer type. - The 6th argument of the call is a constant 0 of the same TYPE as - the return type of the call. + The 3rd argument of the call is a constant 0 with the pointer TYPE whose + pointee type is the TYPE of the object pointed by COUNTED_BY_REF. + + The 4th argument of the call is the TYPE_SIZE_UNIT of the element TYPE + of the array. */ static tree @@ -3023,28 +3154,35 @@ build_access_with_size_for_counted_by (location_t loc, tree ref, { gcc_assert (c_flexible_array_member_type_p (TREE_TYPE (ref)) || TREE_CODE (TREE_TYPE (ref)) == POINTER_TYPE); + bool is_fam = c_flexible_array_member_type_p (TREE_TYPE (ref)); - tree first_param = is_fam ? array_to_pointer_conversion (loc, ref) - : build_unary_op (loc, ADDR_EXPR, ref, false); - /* The result type of the call is a pointer to the original type - of the ref. */ - tree result_type = c_build_pointer_type (TREE_TYPE (ref)); - first_param = c_fully_fold (first_param, false, NULL); + /* The result type of the call is a pointer to the flexible array type; + or is the original ponter type to the pointer field with counted_by. */ + tree result_type = is_fam ? c_build_pointer_type (TREE_TYPE (ref)) + : TREE_TYPE (ref); + + tree element_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ref))); + + tree first_param = is_fam + ? c_fully_fold (array_to_pointer_conversion (loc, ref), + false, NULL) + : ref; tree second_param = c_fully_fold (counted_by_ref, false, NULL); + tree third_param = build_int_cst (c_build_pointer_type (counted_by_type), 0); tree call = build_call_expr_internal_loc (loc, IFN_ACCESS_WITH_SIZE, - result_type, 6, + result_type, 4, first_param, second_param, - build_int_cst (integer_type_node, 1), - build_int_cst (counted_by_type, 0), - build_int_cst (integer_type_node, -1), - build_int_cst (result_type, 0)); - /* Wrap the call with an INDIRECT_REF with the original type of the ref. */ - call = build1 (INDIRECT_REF, TREE_TYPE (ref), call); + third_param, + element_size); + + /* Wrap the call with an INDIRECT_REF with the flexible array type. */ + if (is_fam) + call = build1 (INDIRECT_REF, TREE_TYPE (ref), call); SET_EXPR_LOCATION (call, loc); return call; } @@ -3061,7 +3199,12 @@ handle_counted_by_for_component_ref (location_t loc, tree ref) tree datum = TREE_OPERAND (ref, 0); tree subdatum = TREE_OPERAND (ref, 1); tree counted_by_type = NULL_TREE; - tree counted_by_ref = build_counted_by_ref (loc, datum, subdatum, + + if (!(c_flexible_array_member_type_p (TREE_TYPE (ref)) + || TREE_CODE (TREE_TYPE (ref)) == POINTER_TYPE)) + return ref; + + tree counted_by_ref = build_counted_by_ref (datum, subdatum, &counted_by_type); if (counted_by_ref) ref = build_access_with_size_for_counted_by (loc, ref, @@ -3080,8 +3223,7 @@ handle_counted_by_for_component_ref (location_t loc, tree ref) tree build_component_ref (location_t loc, tree datum, tree component, - location_t component_loc, location_t arrow_loc, - bool handle_counted_by) + location_t component_loc, location_t arrow_loc) { tree type = TREE_TYPE (datum); enum tree_code code = TREE_CODE (type); @@ -3153,8 +3295,6 @@ build_component_ref (location_t loc, tree datum, tree component, int quals; tree subtype; bool use_datum_quals; - /* Do not handle counted_by when in typeof and alignof operator. */ - handle_counted_by = handle_counted_by && !in_typeof && !in_alignof; if (TREE_TYPE (subdatum) == error_mark_node) return error_mark_node; @@ -3175,8 +3315,7 @@ build_component_ref (location_t loc, tree datum, tree component, NULL_TREE); SET_EXPR_LOCATION (ref, loc); - if (handle_counted_by) - ref = handle_counted_by_for_component_ref (loc, ref); + check_counted_by_attribute (loc, ref); if (TREE_READONLY (subdatum) || (use_datum_quals && TREE_READONLY (datum))) @@ -3363,6 +3502,11 @@ build_array_ref (location_t loc, tree array, tree index) bool was_vector = VECTOR_TYPE_P (TREE_TYPE (array)); bool non_lvalue = convert_vector_to_array_for_subscript (loc, &array, index); + /* We only generate a call to .ACCESS_WITH_SIZE when it is a read. */ + if (TREE_CODE (array) == COMPONENT_REF + && handle_counted_by_p (array)) + array = handle_counted_by_for_component_ref (loc, array); + if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE) { tree rval, type; @@ -4535,6 +4679,9 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree fntype, val, valtype, npc, rname, parmnum, argnum, excess_precision, 0); } + /* A NULLPTR type is just a nullptr always. */ + else if (TREE_CODE (TREE_TYPE (val)) == NULLPTR_TYPE) + parmval = omit_one_operand_loc (ploc, TREE_TYPE (val), nullptr_node, val); else if (promote_float_arg) { if (type_generic) @@ -4930,7 +5077,7 @@ pointer_diff (location_t loc, tree op0, tree op1, tree *instrument_expr) if (!addr_space_superset (as0, as1, &as_common)) gcc_unreachable (); - common_type = common_pointer_type (TREE_TYPE (op0), TREE_TYPE (op1)); + common_type = common_pointer_type (TREE_TYPE (op0), TREE_TYPE (op1), NULL_TREE); op0 = convert (common_type, op0); op1 = convert (common_type, op1); } @@ -5275,7 +5422,9 @@ cas_loop: /* newval = old + val; */ if (rhs_type != rhs_semantic_type) val = build1 (EXCESS_PRECISION_EXPR, nonatomic_rhs_semantic_type, val); - rhs = build_binary_op (loc, modifycode, old, val, true); + rhs = build_binary_op (loc, modifycode, + convert_lvalue_to_rvalue (loc, old, true, true), + val, true); if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR) { tree eptype = TREE_TYPE (rhs); @@ -5731,7 +5880,48 @@ build_unary_op (location_t location, enum tree_code code, tree xarg, goto return_build_unary_op; } - if (C_BOOLEAN_TYPE_P (TREE_TYPE (arg))) + tree true_res; + if (c_hardbool_type_attr (TREE_TYPE (arg), NULL, &true_res)) + { + tree larg = stabilize_reference (arg); + tree sarg = save_expr (larg); + switch (code) + { + case PREINCREMENT_EXPR: + val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, true_res); + val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), sarg, val); + break; + case POSTINCREMENT_EXPR: + val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, true_res); + val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), val, sarg); + val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), sarg, val); + break; + case PREDECREMENT_EXPR: + { + tree rarg = convert_lvalue_to_rvalue (location, sarg, + true, true); + rarg = invert_truthvalue_loc (location, rarg); + rarg = convert (TREE_TYPE (sarg), rarg); + val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, rarg); + } + break; + case POSTDECREMENT_EXPR: + { + tree rarg = convert_lvalue_to_rvalue (location, sarg, + true, true); + rarg = invert_truthvalue_loc (location, rarg); + tree iarg = convert (TREE_TYPE (larg), rarg); + val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, iarg); + val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), val, sarg); + val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), sarg, val); + } + break; + default: + gcc_unreachable (); + } + TREE_SIDE_EFFECTS (val) = 1; + } + else if (C_BOOLEAN_TYPE_P (TREE_TYPE (arg))) val = boolean_increment (code, arg); else val = build2 (code, TREE_TYPE (arg), arg, inc); @@ -6384,7 +6574,10 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, addr_space_t as_common; if (comp_target_types (colon_loc, type1, type2)) - result_type = common_pointer_type (type1, type2); + { + ifexp = save_expr (ifexp); + result_type = common_pointer_type (type1, type2, ifexp); + } else if (null_pointer_constant_p (orig_op1)) result_type = type2; else if (null_pointer_constant_p (orig_op2)) @@ -6437,14 +6630,16 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp, else { int qual = ENCODE_QUAL_ADDR_SPACE (as_common); - diagnostic_t kind = DK_PERMERROR; + enum diagnostics::kind kind = diagnostics::kind::permerror; if (!flag_isoc99) /* This downgrade to a warning ensures that -std=gnu89 -pedantic-errors does not flag these mismatches between - builtins as errors (as DK_PERMERROR would). ISO C99 - and later do not have implicit function declarations, + builtins as errors (as diagnostics::kind::permerror would) + ISO C99 and later do not have implicit function declarations, so the mismatch cannot occur naturally there. */ - kind = bltin1 && bltin2 ? DK_WARNING : DK_PEDWARN; + kind = (bltin1 && bltin2 + ? diagnostics::kind::warning + : diagnostics::kind::pedwarn); if (emit_diagnostic (kind, colon_loc, OPT_Wincompatible_pointer_types, "pointer type mismatch " "in conditional expression")) @@ -7328,8 +7523,23 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype, newrhs = build1 (EXCESS_PRECISION_EXPR, TREE_TYPE (rhs), newrhs); } - newrhs = build_binary_op (location, - modifycode, lhs, newrhs, true); + bool clear_decl_read = false; + if ((VAR_P (lhs) || TREE_CODE (lhs) == PARM_DECL) + && !DECL_READ_P (lhs) + && (VAR_P (lhs) ? warn_unused_but_set_variable + : warn_unused_but_set_parameter) > 2) + { + mark_exp_read (newrhs); + if (!DECL_READ_P (lhs)) + clear_decl_read = true; + } + + newrhs = build_binary_op (location, modifycode, + convert_lvalue_to_rvalue (location, lhs, + true, true), + newrhs, true); + if (clear_decl_read) + DECL_READ_P (lhs) = 0; /* The original type of the right hand side is no longer meaningful. */ @@ -7589,7 +7799,8 @@ error_init (location_t loc, const char *gmsgid, ...) /* The gmsgid may be a format string with %< and %>. */ va_list ap; va_start (ap, gmsgid); - bool warned = emit_diagnostic_valist (DK_ERROR, loc, -1, gmsgid, &ap); + bool warned = emit_diagnostic_valist (diagnostics::kind::error, + loc, -1, gmsgid, &ap); va_end (ap); ofwhat = print_spelling ((char *) alloca (spelling_length () + 1)); @@ -7601,7 +7812,7 @@ error_init (location_t loc, const char *gmsgid, ...) static bool ATTRIBUTE_GCC_DIAG (3,0) pedwarn_permerror_init (location_t loc, int opt, const char *gmsgid, - va_list *ap, diagnostic_t kind) + va_list *ap, enum diagnostics::kind kind) { /* Use the location where a macro was expanded rather than where it was defined to make sure macros defined in system headers @@ -7628,7 +7839,8 @@ pedwarn_init (location_t loc, int opt, const char *gmsgid, ...) { va_list ap; va_start (ap, gmsgid); - bool warned = pedwarn_permerror_init (loc, opt, gmsgid, &ap, DK_PEDWARN); + bool warned = pedwarn_permerror_init (loc, opt, gmsgid, &ap, + diagnostics::kind::pedwarn); va_end (ap); return warned; } @@ -7640,7 +7852,8 @@ permerror_init (location_t loc, int opt, const char *gmsgid, ...) { va_list ap; va_start (ap, gmsgid); - bool warned = pedwarn_permerror_init (loc, opt, gmsgid, &ap, DK_PERMERROR); + bool warned = pedwarn_permerror_init (loc, opt, gmsgid, &ap, + diagnostics::kind::permerror); va_end (ap); return warned; } @@ -8773,11 +8986,13 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, && coder == INTEGER_TYPE) warning_at (location, OPT_Wzero_as_null_pointer_constant, "zero as null pointer constant"); - + /* A NULLPTR type is just a nullptr always. */ + if (coder == NULLPTR_TYPE) + return omit_one_operand_loc (expr_loc, type, nullptr_node, rhs); /* An explicit constant 0 or type nullptr_t can convert to a pointer, or one that results from arithmetic, even including a cast to integer type. */ - if (!null_pointer_constant && coder != NULLPTR_TYPE) + else if (!null_pointer_constant) switch (errtype) { case ic_argpass: @@ -12637,7 +12852,8 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs, oconstraints[i] = constraint; if (parse_output_constraint (&constraint, i, ninputs, noutputs, - &allows_mem, &allows_reg, &is_inout)) + &allows_mem, &allows_reg, &is_inout, + nullptr)) { /* If the operand is going to end up in memory, mark it addressable. */ @@ -12698,7 +12914,8 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs, input = TREE_VALUE (tail); if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0, - oconstraints, &allows_mem, &allows_reg)) + oconstraints, &allows_mem, &allows_reg, + nullptr)) { /* If the operand is going to end up in memory, mark it addressable. */ @@ -12714,11 +12931,9 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs, } else { - struct c_expr expr; - memset (&expr, 0, sizeof (expr)); - expr.value = input; - expr = convert_lvalue_to_rvalue (loc, expr, true, false); - input = c_fully_fold (expr.value, false, NULL); + input = c_fully_fold (convert_lvalue_to_rvalue (loc, input, + true, false), + false, NULL); if (input != error_mark_node && VOID_TYPE_P (TREE_TYPE (input))) { @@ -12880,7 +13095,9 @@ c_finish_return (location_t loc, tree retval, tree origtype, bool musttail_p) && valtype != NULL_TREE && TREE_CODE (valtype) != VOID_TYPE) { no_warning = true; - if (emit_diagnostic (flag_isoc99 ? DK_PERMERROR : DK_WARNING, + if (emit_diagnostic (flag_isoc99 + ? diagnostics::kind::permerror + : diagnostics::kind::warning, loc, OPT_Wreturn_mismatch, "%<return%> with no value," " in function returning non-void")) @@ -14372,7 +14589,7 @@ build_binary_op (location_t location, enum tree_code code, Otherwise, the targets must be compatible and both must be object or both incomplete. */ if (comp_target_types (location, type0, type1)) - result_type = common_pointer_type (type0, type1); + result_type = common_pointer_type (type0, type1, NULL_TREE); else if (!addr_space_superset (as0, as1, &as_common)) { error_at (location, "comparison of pointers to " @@ -14511,7 +14728,7 @@ build_binary_op (location_t location, enum tree_code code, if (comp_target_types (location, type0, type1)) { - result_type = common_pointer_type (type0, type1); + result_type = common_pointer_type (type0, type1, NULL_TREE); if (!COMPLETE_TYPE_P (TREE_TYPE (type0)) != !COMPLETE_TYPE_P (TREE_TYPE (type1))) pedwarn_c99 (location, OPT_Wpedantic, @@ -15338,12 +15555,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types, /* If the array section is pointer based and the pointer itself is _Atomic qualified, we need to atomically load the pointer. */ - c_expr expr; - memset (&expr, 0, sizeof (expr)); - expr.value = ret; - expr = convert_lvalue_to_rvalue (OMP_CLAUSE_LOCATION (c), - expr, false, false); - ret = expr.value; + ret = convert_lvalue_to_rvalue (OMP_CLAUSE_LOCATION (c), + ret, false, false); } return ret; } @@ -15628,9 +15841,7 @@ handle_omp_array_sections (tree &c, enum c_omp_region_type ort) tree *tp = &OMP_CLAUSE_DECL (c); if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY) - && TREE_CODE (*tp) == TREE_LIST - && TREE_PURPOSE (*tp) - && TREE_CODE (TREE_PURPOSE (*tp)) == TREE_VEC) + && OMP_ITERATOR_DECL_P (*tp)) tp = &TREE_VALUE (*tp); tree first = handle_omp_array_sections_1 (c, *tp, types, maybe_zero_len, first_non_one, @@ -16188,7 +16399,14 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) /* We've reached the end of a list of expanded nodes. Reset the group start pointer. */ if (c == grp_sentinel) - grp_start_p = NULL; + { + if (grp_start_p + && OMP_CLAUSE_HAS_ITERATORS (*grp_start_p)) + for (tree gc = *grp_start_p; gc != grp_sentinel; + gc = OMP_CLAUSE_CHAIN (gc)) + OMP_CLAUSE_ITERATORS (gc) = OMP_CLAUSE_ITERATORS (*grp_start_p); + grp_start_p = NULL; + } switch (OMP_CLAUSE_CODE (c)) { @@ -16827,9 +17045,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) /* FALLTHRU */ case OMP_CLAUSE_AFFINITY: t = OMP_CLAUSE_DECL (c); - if (TREE_CODE (t) == TREE_LIST - && TREE_PURPOSE (t) - && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC) + if (OMP_ITERATOR_DECL_P (t)) { if (TREE_PURPOSE (t) != last_iterators) last_iterators_remove @@ -16929,10 +17145,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) break; } } - if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST - && TREE_PURPOSE (OMP_CLAUSE_DECL (c)) - && (TREE_CODE (TREE_PURPOSE (OMP_CLAUSE_DECL (c))) - == TREE_VEC)) + if (OMP_ITERATOR_DECL_P (OMP_CLAUSE_DECL (c))) TREE_VALUE (OMP_CLAUSE_DECL (c)) = t; else OMP_CLAUSE_DECL (c) = t; @@ -16951,6 +17164,13 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) /* FALLTHRU */ case OMP_CLAUSE_TO: case OMP_CLAUSE_FROM: + if (OMP_CLAUSE_ITERATORS (c) + && c_omp_finish_iterators (OMP_CLAUSE_ITERATORS (c))) + { + t = error_mark_node; + break; + } + /* FALLTHRU */ case OMP_CLAUSE__CACHE_: { using namespace omp_addr_tokenizer; @@ -17679,6 +17899,11 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) pc = &OMP_CLAUSE_CHAIN (c); } + if (grp_start_p + && OMP_CLAUSE_HAS_ITERATORS (*grp_start_p)) + for (tree gc = *grp_start_p; gc; gc = OMP_CLAUSE_CHAIN (gc)) + OMP_CLAUSE_ITERATORS (gc) = OMP_CLAUSE_ITERATORS (*grp_start_p); + if (simdlen && safelen && tree_int_cst_lt (OMP_CLAUSE_SAFELEN_EXPR (safelen), |