diff options
author | Ian Lance Taylor <iant@golang.org> | 2021-09-13 10:37:49 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2021-09-13 10:37:49 -0700 |
commit | e252b51ccde010cbd2a146485d8045103cd99533 (patch) | |
tree | e060f101cdc32bf5e520de8e5275db9d4236b74c /gcc/c-family | |
parent | f10c7c4596dda99d2ee872c995ae4aeda65adbdf (diff) | |
parent | 104c05c5284b7822d770ee51a7d91946c7e56d50 (diff) | |
download | gcc-e252b51ccde010cbd2a146485d8045103cd99533.zip gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.gz gcc-e252b51ccde010cbd2a146485d8045103cd99533.tar.bz2 |
Merge from trunk revision 104c05c5284b7822d770ee51a7d91946c7e56d50.
Diffstat (limited to 'gcc/c-family')
-rw-r--r-- | gcc/c-family/ChangeLog | 463 | ||||
-rw-r--r-- | gcc/c-family/c-ada-spec.c | 396 | ||||
-rw-r--r-- | gcc/c-family/c-attribs.c | 224 | ||||
-rw-r--r-- | gcc/c-family/c-common.c | 181 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 39 | ||||
-rw-r--r-- | gcc/c-family/c-cppbuiltin.c | 81 | ||||
-rw-r--r-- | gcc/c-family/c-format.c | 174 | ||||
-rw-r--r-- | gcc/c-family/c-gimplify.c | 31 | ||||
-rw-r--r-- | gcc/c-family/c-lex.c | 21 | ||||
-rw-r--r-- | gcc/c-family/c-omp.c | 425 | ||||
-rw-r--r-- | gcc/c-family/c-opts.c | 30 | ||||
-rw-r--r-- | gcc/c-family/c-pch.c | 15 | ||||
-rw-r--r-- | gcc/c-family/c-pragma.c | 22 | ||||
-rw-r--r-- | gcc/c-family/c-pragma.h | 11 | ||||
-rw-r--r-- | gcc/c-family/c-target.def | 70 | ||||
-rw-r--r-- | gcc/c-family/c-warn.c | 51 | ||||
-rw-r--r-- | gcc/c-family/c.opt | 52 | ||||
-rw-r--r-- | gcc/c-family/known-headers.cc | 7 |
18 files changed, 1833 insertions, 460 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index d1ce4b4..684d7d0 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,466 @@ +2021-09-10 Jakub Jelinek <jakub@redhat.com> + + * c-common.h (c_finish_omp_atomic): Add r and weak arguments. + * c-omp.c: Include gimple-fold.h. + (c_finish_omp_atomic): Add r and weak arguments. Add support for + OpenMP 5.1 atomics. + +2021-09-09 qing zhao <qing.zhao@oracle.com> + + * c-attribs.c (handle_uninitialized_attribute): New function. + (c_common_attribute_table): Add "uninitialized" attribute. + +2021-09-08 liuhongt <hongtao.liu@intel.com> + + * c-common.c (excess_precision_mode_join): Update below comments. + (c_ts18661_flt_eval_method): Set excess_precision_type to + EXCESS_PRECISION_TYPE_FLOAT16 when -fexcess-precision=16. + * c-cppbuiltin.c (cpp_atomic_builtins): Update below comments. + (c_cpp_flt_eval_method_iec_559): Set excess_precision_type to + EXCESS_PRECISION_TYPE_FLOAT16 when -fexcess-precision=16. + +2021-09-07 Marcel Vollweiler <marcel@codesourcery.com> + + * c-omp.c (c_finish_omp_flush): Handle MEMMODEL_SEQ_CST. + +2021-09-03 Eric Botcazou <ebotcazou@adacore.com> + + * c-ada-spec.c (dump_ads): Generate pragmas to disable style checks + and -gnatwu warning for the package specification. + +2021-09-01 Iain Sandoe <iain@sandoe.co.uk> + + * c-attribs.c (handle_unavailable_attribute): New. + +2021-08-30 Jason Merrill <jason@redhat.com> + + * c.opt: Add -Wmissing-requires. + +2021-08-25 Lewis Hyatt <lhyatt@gmail.com> + + PR other/93067 + * c-opts.c (c_common_input_charset_cb): New function. + (c_common_post_options): Call new function + diagnostic_initialize_input_context(). + +2021-08-20 Tobias Burnus <tobias@codesourcery.com> + + * c-format.c (gcc_gfc_length_specs): Add 'll' and 'w'. + (gcc_gfc_char_table): Add T9L_LL and T9L_ULL to + "di" and "u", respecitively; fill with BADLEN to match + size of 'types'. + (get_init_dynamic_hwi): Split off from ... + (init_dynamic_diag_info): ... here. Call it. + (init_dynamic_gfc_info): Call it. + +2021-08-20 Jakub Jelinek <jakub@redhat.com> + + * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_ERROR. + * c-pragma.c (omp_pragmas): Add error directive. + * c-omp.c (omp_directives): Uncomment error directive entry. + +2021-08-18 Jakub Jelinek <jakub@redhat.com> + + * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_NOTHING. + * c-pragma.c (omp_pragmas): Add nothing directive. + * c-omp.c (omp_directives): Uncomment nothing directive entry. + +2021-08-17 Jakub Jelinek <jakub@redhat.com> + + PR c++/101539 + * c-common.h (enum rid): Add RID_IS_LAYOUT_COMPATIBLE. + * c-common.c (c_common_reswords): Add __is_layout_compatible. + +2021-08-17 Matt Jacobson <mhjacobson@me.com> + + * c-opts.c (c_common_post_options): Default to + flag_objc_sjlj_exceptions = 1 only when flag_objc_abi < 2. + +2021-08-17 Jakub Jelinek <jakub@redhat.com> + + * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_SCOPE. + * c-pragma.c (omp_pragmas): Add scope construct. + * c-omp.c (omp_directives): Uncomment scope directive entry. + +2021-08-16 Sebastian Huber <sebastian.huber@embedded-brains.de> + + * c-cppbuiltin.c (c_cpp_builtins): Define + __LIBGCC_GCOV_TYPE_SIZE if flag_building_libgcc is true. + +2021-08-12 Jakub Jelinek <jakub@redhat.com> + + * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_MASKED. + (enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_FILTER. + * c-pragma.c (omp_pragmas_simd): Add masked construct. + * c-common.h (enum c_omp_clause_split): Add C_OMP_CLAUSE_SPLIT_MASKED + enumerator. + (c_finish_omp_masked): Declare. + * c-omp.c (c_finish_omp_masked): New function. + (c_omp_split_clauses): Handle combined masked constructs. + +2021-07-30 Jakub Jelinek <jakub@redhat.com> + + PR c++/101539 + * c-common.h (enum rid): Add RID_IS_POINTER_INTERCONVERTIBLE_BASE_OF. + * c-common.c (c_common_reswords): Add + __is_pointer_interconvertible_base_of. + +2021-07-29 Richard Biener <rguenther@suse.de> + + PR c/101512 + * c-common.c (c_common_mark_addressable_vec): Look through + C_MAYBE_CONST_EXPR even if not at the toplevel. + +2021-07-27 Martin Sebor <msebor@redhat.com> + + PR c/101585 + * c-warn.c (warn_parm_ptrarray_mismatch): Use OEP_DECL_NAME. + +2021-07-23 Jakub Jelinek <jakub@redhat.com> + + * c-lex.c (c_common_has_attribute): Call canonicalize_attr_name also + on attr_id. Return 1 for omp::directive or omp::sequence in C++11 + and later. + +2021-07-23 Jakub Jelinek <jakub@redhat.com> + + * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP__START_ and + PRAGMA_OMP__LAST_ enumerators. + +2021-07-21 Thomas Schwinge <thomas@codesourcery.com> + Joseph Myers <joseph@codesourcery.com> + Cesar Philippidis <cesar@codesourcery.com> + + * c-pragma.h (pragma_omp_clause): Add 'PRAGMA_OACC_CLAUSE_NOHOST'. + +2021-07-20 Martin Sebor <msebor@redhat.com> + + * c-common.c (c_build_shufflevector): Adjust by-value argument to + by-const-reference. + * c-common.h (c_build_shufflevector): Same. + +2021-07-16 Andrew Pinski <apinski@marvell.com> + + PR c/101453 + * c-common.c (parse_optimize_options): Use the correct + size for buffer. + +2021-07-15 Martin Sebor <msebor@redhat.com> + + PR c/101289 + PR c/97548 + * c-warn.c (warn_parm_array_mismatch): Use OEP_DECL_NAME. + +2021-07-14 Jason Merrill <jason@redhat.com> + + * c-opts.c (c_common_post_options): Set -fdelete-dead-exceptions. + +2021-07-06 Martin Sebor <msebor@redhat.com> + + * c-format.c (gcc_tdiag_char_table): Remove support for %G and %K. + (gcc_cdiag_char_table): Same. + (gcc_cxxdiag_char_table): Same. + +2021-07-02 Jakub Jelinek <jakub@redhat.com> + + * c-common.h (enum c_omp_directive_kind): New enum. + (struct c_omp_directive): New type. + (c_omp_categorize_directive): Declare. + * c-omp.c (omp_directives): New variable. + (c_omp_categorize_directive): New function. + +2021-07-01 Eric Botcazou <ebotcazou@adacore.com> + + * c-ada-spec.c (packed_layout): New global variable. + (dump_ada_declaration): Set it upon seeing a packed record type. + Do not put the "aliased" keyword if it is set. + (dump_ada_structure): Add Pack aspect if it is set and clear it. + +2021-07-01 Eric Botcazou <ebotcazou@adacore.com> + + * c-ada-spec.c (check_name): Rename into... + (check_type_name_conflict): ...this. Minor tweak. + (dump_ada_function_declaration): Adjust to above renaming. + (dump_ada_array_domains): Fix oversight. + (dump_ada_declaration): Call check_type_name_conflict for variables. + +2021-06-25 Martin Sebor <msebor@redhat.com> + + * c-common.c (c_wrap_maybe_const): Remove TREE_NO_WARNING. + (c_common_truthvalue_conversion): Replace direct uses of + TREE_NO_WARNING with warning_suppressed_p, suppress_warning, and + copy_no_warning. + (check_function_arguments_recurse): Same. + * c-gimplify.c (c_gimplify_expr): Same. + * c-warn.c (overflow_warning): Same. + (warn_logical_operator): Same. + (warn_if_unused_value): Same. + (do_warn_unused_parameter): Same. + +2021-06-24 Jakub Jelinek <jakub@redhat.com> + + * c-common.h (enum c_omp_region_type): Add C_ORT_TARGET and + C_ORT_OMP_TARGET. + * c-omp.c (c_omp_split_clauses): For OMP_CLAUSE_IN_REDUCTION on + combined target constructs also add map (always, tofrom:) clause. + +2021-06-15 Robin Dapp <rdapp@linux.ibm.com> + + * c-attribs.c (common_handle_aligned_attribute): Remove short + circuit and dead code. + +2021-06-14 Jonathan Wakely <jwakely@redhat.com> + + PR c++/101052 + * known-headers.cc (get_stdlib_header_for_name): Add known + headers for EXIT_FAILURE, EXIT_SUCCESS, abort, atexit, calloc, + exit, and getenv. + +2021-06-12 Jason Merrill <jason@redhat.com> + + * c-attribs.c (handle_unused_attribute): Handle FIELD_DECL. + +2021-06-11 Jakub Jelinek <jakub@redhat.com> + + PR c++/100974 + * c-cppbuiltin.c (c_cpp_builtins): Predefine __cpp_if_consteval for + -std=c++2b for P1938R3 consteval if support. + +2021-06-09 Jason Merrill <jason@redhat.com> + + PR c++/100879 + * c-warn.c (warn_for_sign_compare): Remove C++ enum mismatch + warning. + +2021-06-07 Martin Liska <mliska@suse.cz> + + * c-target.def: Split long lines and replace them + with '\n\'. + +2021-06-04 Martin Sebor <msebor@redhat.com> + + PR c/100783 + * c-attribs.c (positional_argument): Bail on erroneous types. + +2021-06-04 Martin Sebor <msebor@redhat.com> + + * c-warn.c (warn_parm_array_mismatch): Check TREE_PURPOSE to test + for element presence. + +2021-06-03 Eric Botcazou <ebotcazou@adacore.com> + + * c-ada-spec.c (dump_ada_macros): Minor tweaks. + (dump_ada_decl_name): Likewise. + (dump_anonymous_type_name): Remove parent parameter and adjust. + (dump_sloc): Minor tweak. + (dump_ada_array_type): Remove type parameter and adjust. + (dump_ada_enum_type): Remove parent parameter and adjust. + (dump_ada_node): Adjust calls to above functions. + (dumped_anonymous_types): New global variable. + (dump_nested_types_1): Rename into... + (dump_nested_types): ...this. + (dump_nested_type): Remove parent and dumped_types parameters. + <ARRAY_TYPE>: Replace dumped_types with dumped_anonymous_types. + Adjust calls to dump_anonymous_type_name and dump_ada_array_type. + (dump_ada_specs): Initialize and free dumped_anonymous_types. + +2021-06-03 Eric Botcazou <ebotcazou@adacore.com> + + * c-ada-spec.c (pp_ada_tree_identifier): Tidy up. + (dump_ada_node) <POINTER_TYPE>: Deal specially with external subtypes. + +2021-06-03 Eric Botcazou <ebotcazou@adacore.com> + + * c-ada-spec.c (dump_ada_enum_type): Dump a prefix for constants. + (htable_t): New typedef. + (overloaded_names): Use it. + (add_name): New function. + (init_overloaded_names): Use add_name to populate the table and add + special cases for sigaction and stat. + (overloaded_name_p): Rename into... + (overloading_index): ...this. Do not initialize overloaded_names table + here. Return the index or zero. + (dump_ada_declaration): Minor tweaks. Do not skip overloaded functions + but add an overloading suffix instead. + (dump_ada_specs): Initialize overloaded_names tables here. + +2021-06-01 Martin Liska <mliska@suse.cz> + + PR other/100759 + * c-attribs.c (handle_optimize_attribute): Limit sanity check + to a situation where we are not in processing of an optimize + pragma. + * c-pragma.c (handle_pragma_pop_options): Restore target + options. + +2021-05-31 Indu Bhagat <indu.bhagat@oracle.com> + + PR testsuite/100749 + * c-pch.c (c_common_valid_pch): Use xstrdup for debug format set names. + +2021-05-31 Richard Biener <rguenther@suse.de> + + PR c++/88601 + * c-common.c: Include tree-vector-builder.h and + vec-perm-indices.h. + (c_common_reswords): Add __builtin_shufflevector. + (c_build_shufflevector): New funtion. + * c-common.h (enum rid): Add RID_BUILTIN_SHUFFLEVECTOR. + (c_build_shufflevector): Declare. + +2021-05-28 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/99928 + * c-omp.c (c_omp_split_clauses): For reduction clause if combined with + target add a map tofrom clause with OMP_CLAUSE_MAP_IMPLICIT. + +2021-05-28 Tobias Burnus <tobias@codesourcery.com> + + * c-pragma.h (enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_AFFINITY. + +2021-05-25 Martin Liska <mliska@suse.cz> + + PR tree-optimization/92860 + PR target/99592 + * c-attribs.c (handle_optimize_attribute): Save target node + before calling parse_optimize_options and save it in case + it changes. + * c-pragma.c (handle_pragma_target): Similarly for pragma. + (handle_pragma_pop_options): Likewise here. + +2021-05-25 Martin Liska <mliska@suse.cz> + + * c-attribs.c (handle_no_sanitize_coverage_attribute): New. + +2021-05-25 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/99928 + * c-omp.c (c_omp_split_clauses): Copy reduction to teams when teams is + combined with simd and not with taskloop or for. + +2021-05-21 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/99928 + * c-omp.c (c_omp_split_clauses): Set OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT + on firstprivate clause copy going to target construct, and for + target simd set also OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET bit. + +2021-05-20 Jonathan Wakely <jwakely@redhat.com> + + * c.opt (Wc++11-extensions, Wc++14-extensions) + (Wc++17-extensions, Wc++20-extensions, Wc++23-extensions): New + options. + +2021-05-20 Indu Bhagat <indu.bhagat@oracle.com> + + * c-lex.c (init_c_lex): Use dwarf_debuginfo_p. + +2021-05-20 Indu Bhagat <indu.bhagat@oracle.com> + + * c-opts.c (c_common_post_options): Adjust access to debug_type_names. + * c-pch.c (struct c_pch_validity): Use type uint32_t. + (pch_init): Renamed member. + (c_common_valid_pch): Adjust access to debug_type_names. + +2021-05-19 Martin Sebor <msebor@redhat.com> + + PR c/100619 + * c-attribs.c (build_attr_access_from_parms): Handle arbitrarily many + bounds. + +2021-05-18 Richard Biener <rguenther@suse.de> + + PR c/100547 + * c-attribs.c (type_valid_for_vector_size): Reject too large nunits. + Reword existing nunit diagnostic. + +2021-05-17 Joern Rennecke <joern.rennecke@embecosm.com> + + * c-common.c (braced_list_to_string): Return CTOR unchanged + if host and target character sizes don't match. + +2021-05-14 Martin Liska <mliska@suse.cz> + + * c.opt: Add Warning keyword for 2 options. + +2021-05-13 Martin Liska <mliska@suse.cz> + + PR middle-end/100504 + * c-attribs.c (handle_target_clones_attribute): Expect a string + argument to target_clone argument. + +2021-05-11 Joseph Myers <joseph@codesourcery.com> + + * c-lex.c (interpret_float): Handle digit separators for C2X. + +2021-05-10 Martin Liska <mliska@suse.cz> + + * c-ada-spec.c (print_destructor): Use startswith + function instead of strncmp. + (dump_ada_declaration): Likewise. + * c-common.c (disable_builtin_function): Likewise. + (def_builtin_1): Likewise. + * c-format.c (check_tokens): Likewise. + (check_plain): Likewise. + (convert_format_name_to_system_name): Likewise. + +2021-04-28 Patrick McGehearty <patrick.mcgehearty@oracle.com> + + * c-cppbuiltin.c (c_cpp_builtins): Add supporting macros for new + complex divide + +2021-04-26 Thomas Schwinge <thomas@codesourcery.com> + Nathan Sidwell <nathan@codesourcery.com> + Tom de Vries <vries@codesourcery.com> + Julian Brown <julian@codesourcery.com> + Kwok Cheung Yeung <kcy@codesourcery.com> + + * c.opt (Wopenacc-parallelism): New. + +2021-04-19 Thomas Schwinge <thomas@codesourcery.com> + + * c.opt (fopenacc-kernels=): Remove. + +2021-04-08 Jakub Jelinek <jakub@redhat.com> + + * c-warn.c (do_warn_double_promotion): Fix comment typo, + occured -> occurred. + (check_alignment_of_packed_member): Fix a comment typo, + memeber -> member. + (warn_parm_ptrarray_mismatch): Fix comment typos, os -> of + and onless -> unless. + (warn_parm_array_mismatch): Fix comment typos, declaratation + -> declaration and woud -> would. Fix up comment indentation. + +2021-04-08 Martin Sebor <msebor@redhat.com> + + PR middle-end/99883 + * c.opt (Wmismatched-new-delete): Correct spelling. + +2021-04-05 Eric Botcazou <ebotcazou@adacore.com> + + * c-ada-spec.c (is_simple_enum): Minor tweaks. + (dump_ada_enum_type): Add TYPE and PARENT parameters. For non-simple + enumeral types use again the type name for the enumeration constants. + (dump_ada_node): Adjust call to dump_ada_enum_type. + (dump_nested_type): Likewise. + +2021-04-01 Jason Merrill <jason@redhat.com> + + PR c++/98481 + * c-opts.c (c_common_post_options): Bump latest_abi_version. + +2021-03-25 Jakub Jelinek <jakub@redhat.com> + + PR c++/99565 + * c-warn.c (do_warn_duplicated_branches): Pass also + OEP_ADDRESS_OF_SAME_FIELD to operand_equal_p. + +2021-03-20 Jakub Jelinek <jakub@redhat.com> + + PR debug/99230 + * c-gimplify.c (c_genericize_control_stmt): Handle STATEMENT_LIST. + 2021-03-05 Eric Botcazou <ebotcazou@adacore.com> * c-ada-spec.c (dump_ada_declaration) <TYPE_DECL>: Dump nested types diff --git a/gcc/c-family/c-ada-spec.c b/gcc/c-family/c-ada-spec.c index dd8e8bb..b197d55 100644 --- a/gcc/c-family/c-ada-spec.c +++ b/gcc/c-family/c-ada-spec.c @@ -408,8 +408,8 @@ dump_ada_macros (pretty_printer *pp, const char* file) } else { - chars_seen = sprintf - ((char *) buffer, "Character'Val (%d)", (int) c); + chars_seen = sprintf ((char *) buffer, + "Character'Val (%d)", (int) c); buffer += chars_seen; } } @@ -611,7 +611,7 @@ dump_ada_macros (pretty_printer *pp, const char* file) pp_string (pp, "; -- "); pp_string (pp, sloc.file); pp_colon (pp); - pp_scalar (pp, "%d", sloc.line); + pp_decimal_int (pp, sloc.line); pp_newline (pp); } else @@ -1341,49 +1341,46 @@ pp_ada_tree_identifier (pretty_printer *buffer, tree node, tree type, char *s = to_ada_name (name, &space_found); tree decl = get_underlying_decl (type); - /* If the entity comes from another file, generate a package prefix. */ if (decl) { - expanded_location xloc = expand_location (decl_sloc (decl, false)); + /* If the entity comes from another file, generate a package prefix. */ + const expanded_location xloc = expand_location (decl_sloc (decl, false)); - if (xloc.file && xloc.line) + if (xloc.line && xloc.file && xloc.file != current_source_file) { - if (xloc.file != current_source_file) + switch (TREE_CODE (type)) { - switch (TREE_CODE (type)) - { - case ENUMERAL_TYPE: - case INTEGER_TYPE: - case REAL_TYPE: - case FIXED_POINT_TYPE: - case BOOLEAN_TYPE: - case REFERENCE_TYPE: - case POINTER_TYPE: - case ARRAY_TYPE: - case RECORD_TYPE: - case UNION_TYPE: - case TYPE_DECL: - if (package_prefix) - { - char *s1 = get_ada_package (xloc.file); - append_withs (s1, limited_access); - pp_string (buffer, s1); - pp_dot (buffer); - free (s1); - } - break; - default: - break; - } + case ENUMERAL_TYPE: + case INTEGER_TYPE: + case REAL_TYPE: + case FIXED_POINT_TYPE: + case BOOLEAN_TYPE: + case REFERENCE_TYPE: + case POINTER_TYPE: + case ARRAY_TYPE: + case RECORD_TYPE: + case UNION_TYPE: + case TYPE_DECL: + if (package_prefix) + { + char *s1 = get_ada_package (xloc.file); + append_withs (s1, limited_access); + pp_string (buffer, s1); + pp_dot (buffer); + free (s1); + } + break; + default: + break; + } - /* Generate the additional package prefix for C++ classes. */ - if (separate_class_package (decl)) - { - pp_string (buffer, "Class_"); - pp_string (buffer, s); - pp_dot (buffer); - } - } + /* Generate the additional package prefix for C++ classes. */ + if (separate_class_package (decl)) + { + pp_string (buffer, "Class_"); + pp_string (buffer, s); + pp_dot (buffer); + } } } @@ -1467,28 +1464,21 @@ dump_ada_decl_name (pretty_printer *buffer, tree decl, bool limited_access) { pp_string (buffer, "anon"); if (TREE_CODE (decl) == FIELD_DECL) - pp_scalar (buffer, "%d", DECL_UID (decl)); + pp_decimal_int (buffer, DECL_UID (decl)); else - pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (decl))); + pp_decimal_int (buffer, TYPE_UID (TREE_TYPE (decl))); } else if (TREE_CODE (type_name) == IDENTIFIER_NODE) pp_ada_tree_identifier (buffer, type_name, decl, limited_access); } } -/* Dump in BUFFER a name for the type T, which is a _TYPE without TYPE_NAME. - PARENT is the parent node of T. */ +/* Dump in BUFFER a name for the type T, which is a TYPE without TYPE_NAME. */ static void -dump_anonymous_type_name (pretty_printer *buffer, tree t, tree parent) +dump_anonymous_type_name (pretty_printer *buffer, tree t) { - if (DECL_NAME (parent)) - pp_ada_tree_identifier (buffer, DECL_NAME (parent), parent, false); - else - { - pp_string (buffer, "anon"); - pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (parent))); - } + pp_string (buffer, "anon"); switch (TREE_CODE (t)) { @@ -1509,7 +1499,7 @@ dump_anonymous_type_name (pretty_printer *buffer, tree t, tree parent) break; } - pp_scalar (buffer, "%d", TYPE_UID (t)); + pp_decimal_int (buffer, TYPE_UID (t)); } /* Dump in BUFFER aspect Import on a given node T. SPC is the current @@ -1550,9 +1540,8 @@ dump_ada_import (pretty_printer *buffer, tree t, int spc) otherwise in BUFFER. */ static void -check_name (pretty_printer *buffer, tree t) +check_type_name_conflict (pretty_printer *buffer, tree t) { - const char *s; tree tmp = TREE_TYPE (t); while (TREE_CODE (tmp) == POINTER_TYPE && !TYPE_NAME (tmp)) @@ -1560,6 +1549,8 @@ check_name (pretty_printer *buffer, tree t) if (TREE_CODE (tmp) != FUNCTION_TYPE) { + const char *s; + if (TREE_CODE (tmp) == IDENTIFIER_NODE) s = IDENTIFIER_POINTER (tmp); else if (!TYPE_NAME (tmp)) @@ -1651,7 +1642,7 @@ dump_ada_function_declaration (pretty_printer *buffer, tree func, { if (DECL_NAME (arg)) { - check_name (buffer, arg); + check_type_name_conflict (buffer, arg); pp_ada_tree_identifier (buffer, DECL_NAME (arg), NULL_TREE, false); pp_string (buffer, " : "); @@ -1720,7 +1711,8 @@ dump_ada_function_declaration (pretty_printer *buffer, tree func, static void dump_ada_array_domains (pretty_printer *buffer, tree node, int spc) { - int first = 1; + bool first = true; + pp_left_paren (buffer); for (; TREE_CODE (node) == ARRAY_TYPE; node = TREE_TYPE (node)) @@ -1734,7 +1726,7 @@ dump_ada_array_domains (pretty_printer *buffer, tree node, int spc) if (!first) pp_string (buffer, ", "); - first = 0; + first = false; if (min) dump_ada_node (buffer, min, NULL_TREE, spc, false, true); @@ -1748,7 +1740,10 @@ dump_ada_array_domains (pretty_printer *buffer, tree node, int spc) pp_string (buffer, "0"); } else - pp_string (buffer, "size_t"); + { + pp_string (buffer, "size_t"); + first = false; + } } pp_right_paren (buffer); } @@ -1760,12 +1755,12 @@ dump_sloc (pretty_printer *buffer, tree node) { expanded_location xloc; - xloc.file = NULL; - if (DECL_P (node)) xloc = expand_location (DECL_SOURCE_LOCATION (node)); else if (EXPR_HAS_LOCATION (node)) xloc = expand_location (EXPR_LOCATION (node)); + else + xloc.file = NULL; if (xloc.file) { @@ -1793,11 +1788,11 @@ is_char_array (tree t) && id_equal (DECL_NAME (TYPE_NAME (t)), "char"); } -/* Dump in BUFFER an array type NODE of type TYPE in Ada syntax. SPC is the - indentation level. */ +/* Dump in BUFFER an array type NODE in Ada syntax. SPC is the indentation + level. */ static void -dump_ada_array_type (pretty_printer *buffer, tree node, tree type, int spc) +dump_ada_array_type (pretty_printer *buffer, tree node, int spc) { const bool char_array = is_char_array (node); @@ -1826,8 +1821,8 @@ dump_ada_array_type (pretty_printer *buffer, tree node, tree type, int spc) || (!RECORD_OR_UNION_TYPE_P (tmp) && TREE_CODE (tmp) != ENUMERAL_TYPE)) dump_ada_node (buffer, tmp, node, spc, false, true); - else if (type) - dump_anonymous_type_name (buffer, tmp, type); + else + dump_anonymous_type_name (buffer, tmp); } } @@ -1932,8 +1927,8 @@ dump_ada_template (pretty_printer *buffer, tree t, int spc) return num_inst > 0; } -/* Return true if NODE is a simple enum types, that can be mapped to an - Ada enum type directly. */ +/* Return true if NODE is a simple enumeral type that can be mapped to an + Ada enumeration type directly. */ static bool is_simple_enum (tree node) @@ -1947,9 +1942,7 @@ is_simple_enum (tree node) if (TREE_CODE (int_val) != INTEGER_CST) int_val = DECL_INITIAL (int_val); - if (!tree_fits_shwi_p (int_val)) - return false; - else if (tree_to_shwi (int_val) != count) + if (!tree_fits_shwi_p (int_val) || tree_to_shwi (int_val) != count) return false; count++; @@ -1958,11 +1951,11 @@ is_simple_enum (tree node) return true; } -/* Dump in BUFFER an enumeral type NODE in Ada syntax. SPC is the indentation - level. */ +/* Dump in BUFFER the declaration of enumeral NODE of type TYPE in Ada syntax. + SPC is the indentation level. */ static void -dump_ada_enum_type (pretty_printer *buffer, tree node, int spc) +dump_ada_enum_type (pretty_printer *buffer, tree node, tree type, int spc) { if (is_simple_enum (node)) { @@ -1993,25 +1986,37 @@ dump_ada_enum_type (pretty_printer *buffer, tree node, int spc) pp_string (buffer, "unsigned"); else pp_string (buffer, "int"); + for (tree value = TYPE_VALUES (node); value; value = TREE_CHAIN (value)) { + tree int_val = TREE_VALUE (value); + + if (TREE_CODE (int_val) != INTEGER_CST) + int_val = DECL_INITIAL (int_val); + pp_semicolon (buffer); newline_and_indent (buffer, spc); + if (TYPE_NAME (node)) + dump_ada_node (buffer, node, NULL_TREE, spc, false, true); + else if (type) + dump_ada_node (buffer, type, NULL_TREE, spc, false, true); + else + dump_anonymous_type_name (buffer, node); + pp_underscore (buffer); pp_ada_tree_identifier (buffer, TREE_PURPOSE (value), node, false); + pp_string (buffer, " : constant "); - if (TYPE_UNSIGNED (node)) - pp_string (buffer, "unsigned"); + if (TYPE_NAME (node)) + dump_ada_node (buffer, node, NULL_TREE, spc, false, true); + else if (type) + dump_ada_node (buffer, type, NULL_TREE, spc, false, true); else - pp_string (buffer, "int"); + dump_anonymous_type_name (buffer, node); pp_string (buffer, " := "); - dump_ada_node (buffer, - TREE_CODE (TREE_VALUE (value)) == INTEGER_CST - ? TREE_VALUE (value) - : DECL_INITIAL (TREE_VALUE (value)), - node, spc, false, true); + dump_ada_node (buffer, int_val, node, spc, false, true); } } } @@ -2033,6 +2038,7 @@ is_float128 (tree node) } static bool bitfield_used = false; +static bool packed_layout = false; /* Recursively dump in BUFFER Ada declarations corresponding to NODE of type TYPE. SPC is the indentation level. LIMITED_ACCESS indicates whether NODE @@ -2098,7 +2104,7 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc, if (name_only) dump_ada_node (buffer, TYPE_NAME (node), node, spc, false, true); else - dump_ada_enum_type (buffer, node, spc); + dump_ada_enum_type (buffer, node, type, spc); break; case REAL_TYPE: @@ -2108,6 +2114,7 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc, pp_string (buffer, "Extensions.Float_128"); break; } + /* fallthrough */ case INTEGER_TYPE: @@ -2209,6 +2216,24 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc, { tree type_name = TYPE_NAME (TREE_TYPE (node)); + /* Generate "access <type>" instead of "access <subtype>" + if the subtype comes from another file, because subtype + declarations do not contribute to the limited view of a + package and thus subtypes cannot be referenced through + a limited_with clause. */ + if (type_name + && TREE_CODE (type_name) == TYPE_DECL + && DECL_ORIGINAL_TYPE (type_name) + && TYPE_NAME (DECL_ORIGINAL_TYPE (type_name))) + { + const expanded_location xloc + = expand_location (decl_sloc (type_name, false)); + if (xloc.line + && xloc.file + && xloc.file != current_source_file) + type_name = DECL_ORIGINAL_TYPE (type_name); + } + /* For now, handle access-to-access as System.Address. */ if (TREE_CODE (TREE_TYPE (node)) == POINTER_TYPE) { @@ -2230,8 +2255,8 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc, { if (!type || TREE_CODE (type) != FUNCTION_DECL) { - pp_string (buffer, "access "); is_access = true; + pp_string (buffer, "access "); if (quals & TYPE_QUAL_CONST) pp_string (buffer, "constant "); @@ -2272,7 +2297,7 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc, dump_ada_node (buffer, TYPE_NAME (node), node, spc, limited_access, true); else - dump_ada_array_type (buffer, node, type, spc); + dump_ada_array_type (buffer, node, spc); break; case RECORD_TYPE: @@ -2464,7 +2489,12 @@ dump_forward_type (pretty_printer *buffer, tree type, tree t, int spc) TREE_VISITED (decl) = 1; } -static void dump_nested_type (pretty_printer *, tree, tree, tree, bitmap, int); +/* Bitmap of anonymous types already dumped. Anonymous array types are shared + throughout the compilation so it needs to be global. */ + +static bitmap dumped_anonymous_types; + +static void dump_nested_type (pretty_printer *, tree, tree, int); /* Dump in BUFFER anonymous types nested inside T's definition. PARENT is the parent node of T. DUMPED_TYPES is the bitmap of already dumped types. SPC @@ -2480,8 +2510,7 @@ static void dump_nested_type (pretty_printer *, tree, tree, tree, bitmap, int); pass on the nested TYPE_DECLs and a second pass on the unnamed types. */ static void -dump_nested_types_1 (pretty_printer *buffer, tree t, tree parent, - bitmap dumped_types, int spc) +dump_nested_types (pretty_printer *buffer, tree t, int spc) { tree type, field; @@ -2495,31 +2524,18 @@ dump_nested_types_1 (pretty_printer *buffer, tree t, tree parent, && DECL_NAME (field) != DECL_NAME (t) && !DECL_ORIGINAL_TYPE (field) && TYPE_NAME (TREE_TYPE (field)) != TYPE_NAME (type)) - dump_nested_type (buffer, field, t, parent, dumped_types, spc); + dump_nested_type (buffer, field, t, spc); for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) if (TREE_CODE (field) == FIELD_DECL && !TYPE_NAME (TREE_TYPE (field))) - dump_nested_type (buffer, field, t, parent, dumped_types, spc); + dump_nested_type (buffer, field, t, spc); } -/* Likewise, but to be invoked only at top level. We dump each anonymous type - nested inside T's definition exactly once, even if it is referenced several - times in it (typically an array type), with a name prefixed by that of T. */ - -static void -dump_nested_types (pretty_printer *buffer, tree t, int spc) -{ - auto_bitmap dumped_types; - dump_nested_types_1 (buffer, t, t, dumped_types, spc); -} - -/* Dump in BUFFER the anonymous type of FIELD inside T. PARENT is the parent - node of T. DUMPED_TYPES is the bitmap of already dumped types. SPC is the - indentation level. */ +/* Dump in BUFFER the anonymous type of FIELD inside T. SPC is the indentation + level. */ static void -dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent, - bitmap dumped_types, int spc) +dump_nested_type (pretty_printer *buffer, tree field, tree t, int spc) { tree field_type = TREE_TYPE (field); tree decl, tmp; @@ -2533,7 +2549,7 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent, case ARRAY_TYPE: /* Anonymous array types are shared. */ - if (!bitmap_set_bit (dumped_types, TYPE_UID (field_type))) + if (!bitmap_set_bit (dumped_anonymous_types, TYPE_UID (field_type))) return; /* Recurse on the element type if need be. */ @@ -2547,7 +2563,7 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent, && !TREE_VISITED (decl)) { /* Generate full declaration. */ - dump_nested_type (buffer, decl, t, parent, dumped_types, spc); + dump_nested_type (buffer, decl, t, spc); TREE_VISITED (decl) = 1; } else if (!decl && TREE_CODE (tmp) == POINTER_TYPE) @@ -2559,9 +2575,9 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent, else pp_string (buffer, "type "); - dump_anonymous_type_name (buffer, field_type, parent); + dump_anonymous_type_name (buffer, field_type); pp_string (buffer, " is "); - dump_ada_array_type (buffer, field_type, parent, spc); + dump_ada_array_type (buffer, field_type, spc); pp_semicolon (buffer); newline_and_indent (buffer, spc); break; @@ -2575,23 +2591,23 @@ dump_nested_type (pretty_printer *buffer, tree field, tree t, tree parent, if (TYPE_NAME (field_type)) dump_ada_node (buffer, field_type, NULL_TREE, spc, false, true); else - dump_anonymous_type_name (buffer, field_type, parent); + dump_anonymous_type_name (buffer, field_type); pp_string (buffer, " is "); - dump_ada_enum_type (buffer, field_type, spc); + dump_ada_enum_type (buffer, field_type, NULL_TREE, spc); pp_semicolon (buffer); newline_and_indent (buffer, spc); break; case RECORD_TYPE: case UNION_TYPE: - dump_nested_types_1 (buffer, field, parent, dumped_types, spc); + dump_nested_types (buffer, field, spc); pp_string (buffer, "type "); if (TYPE_NAME (field_type)) dump_ada_node (buffer, field_type, NULL_TREE, spc, false, true); else - dump_anonymous_type_name (buffer, field_type, parent); + dump_anonymous_type_name (buffer, field_type); if (TREE_CODE (field_type) == UNION_TYPE) pp_string (buffer, " (discr : unsigned := 0)"); @@ -2625,11 +2641,31 @@ struct overloaded_name_hasher : delete_ptr_hash<overloaded_name_hash> { return a->name == b->name; } }; -static hash_table<overloaded_name_hasher> *overloaded_names; +typedef hash_table<overloaded_name_hasher> htable_t; + +static htable_t *overloaded_names; + +/* Add an overloaded NAME with N occurrences to TABLE. */ + +static void +add_name (const char *name, unsigned int n, htable_t *table) +{ + struct overloaded_name_hash in, *h, **slot; + tree id = get_identifier (name); + hashval_t hash = htab_hash_pointer (id); + in.hash = hash; + in.name = id; + slot = table->find_slot_with_hash (&in, hash, INSERT); + h = new overloaded_name_hash; + h->hash = hash; + h->name = id; + h->n = n; + *slot = h; +} /* Initialize the table with the problematic overloaded names. */ -static hash_table<overloaded_name_hasher> * +static htable_t * init_overloaded_names (void) { static const char *names[] = @@ -2637,41 +2673,31 @@ init_overloaded_names (void) { "memchr", "rawmemchr", "memrchr", "strchr", "strrchr", "strchrnul", "strpbrk", "strstr", "strcasestr", "index", "rindex", "basename" }; - hash_table<overloaded_name_hasher> *table - = new hash_table<overloaded_name_hasher> (64); + htable_t *table = new htable_t (64); for (unsigned int i = 0; i < ARRAY_SIZE (names); i++) - { - struct overloaded_name_hash in, *h, **slot; - tree id = get_identifier (names[i]); - hashval_t hash = htab_hash_pointer (id); - in.hash = hash; - in.name = id; - slot = table->find_slot_with_hash (&in, hash, INSERT); - h = new overloaded_name_hash; - h->hash = hash; - h->name = id; - h->n = 0; - *slot = h; - } + add_name (names[i], 0, table); + + /* Consider that sigaction() is overloaded by struct sigaction for QNX. */ + add_name ("sigaction", 1, table); + + /* Consider that stat() is overloaded by struct stat for QNX. */ + add_name ("stat", 1, table); return table; } -/* Return whether NAME cannot be supported as overloaded name. */ +/* Return the overloading index of NAME or 0 if NAME is not overloaded. */ -static bool -overloaded_name_p (tree name) +static unsigned int +overloading_index (tree name) { - if (!overloaded_names) - overloaded_names = init_overloaded_names (); - struct overloaded_name_hash in, *h; hashval_t hash = htab_hash_pointer (name); in.hash = hash; in.name = name; h = overloaded_names->find_with_hash (&in, hash); - return h && ++h->n > 1; + return h ? ++h->n : 0; } /* Dump in BUFFER constructor spec corresponding to T for TYPE. */ @@ -2693,7 +2719,7 @@ print_destructor (pretty_printer *buffer, tree t, tree type) tree decl_name = DECL_NAME (TYPE_NAME (type)); pp_string (buffer, "Delete_"); - if (strncmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__dt_del", 8) == 0) + if (startswith (IDENTIFIER_POINTER (DECL_NAME (t)), "__dt_del")) pp_string (buffer, "And_Free_"); pp_ada_tree_identifier (buffer, decl_name, t, false); } @@ -2795,14 +2821,17 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) } /* Skip unnamed or anonymous structs/unions/enum types. */ - if (!orig && !decl_name && !name + if (!orig && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)) - || TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)) + || TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE) + && !decl_name + && !name) return 0; - /* Skip anonymous enum types (duplicates of real types). */ + /* Skip duplicates of structs/unions/enum types built in C++. */ if (!orig - && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE + && (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)) + || TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE) && decl_name && (*IDENTIFIER_POINTER (decl_name) == '.' || *IDENTIFIER_POINTER (decl_name) == '$')) @@ -2823,24 +2852,14 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) return 1; } - if (decl_name - && (*IDENTIFIER_POINTER (decl_name) == '.' - || *IDENTIFIER_POINTER (decl_name) == '$')) - { - pp_string (buffer, "-- skipped anonymous struct "); - dump_ada_node (buffer, t, type, spc, false, true); - TREE_VISITED (t) = 1; - return 1; - } - - /* ??? Packed record layout is not supported. */ + /* Packed record layout is not fully supported. */ if (TYPE_PACKED (TREE_TYPE (t))) { - warning_at (DECL_SOURCE_LOCATION (t), 0, - "unsupported record layout"); + warning_at (DECL_SOURCE_LOCATION (t), 0, "packed layout"); pp_string (buffer, "pragma Compile_Time_Warning (True, "); - pp_string (buffer, "\"probably incorrect record layout\");"); + pp_string (buffer, "\"packed layout may be incorrect\");"); newline_and_indent (buffer, spc); + packed_layout = true; } if (orig && TYPE_NAME (orig)) @@ -2866,7 +2885,11 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) case POINTER_TYPE: case REFERENCE_TYPE: dump_forward_type (buffer, TREE_TYPE (TREE_TYPE (t)), t, spc); - /* fallthrough */ + if (orig && TYPE_NAME (orig)) + pp_string (buffer, "subtype "); + else + pp_string (buffer, "type "); + break; case ARRAY_TYPE: if ((orig && TYPE_NAME (orig)) || is_char_array (TREE_TYPE (t))) @@ -2920,7 +2943,7 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) if (orig && TYPE_NAME (orig)) dump_ada_node (buffer, TYPE_NAME (orig), type, spc, false, true); else - dump_ada_array_type (buffer, TREE_TYPE (t), type, spc); + dump_ada_array_type (buffer, TREE_TYPE (t), spc); } else { @@ -2929,22 +2952,23 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) pp_string (buffer, " : "); - if (TREE_CODE (TREE_TYPE (TREE_TYPE (t))) != POINTER_TYPE) + if (TREE_CODE (TREE_TYPE (TREE_TYPE (t))) != POINTER_TYPE + && !packed_layout) pp_string (buffer, "aliased "); if (TYPE_NAME (TREE_TYPE (t))) dump_ada_node (buffer, TREE_TYPE (t), type, spc, false, true); else if (type) - dump_anonymous_type_name (buffer, TREE_TYPE (t), type); + dump_anonymous_type_name (buffer, TREE_TYPE (t)); else - dump_ada_array_type (buffer, TREE_TYPE (t), type, spc); + dump_ada_array_type (buffer, TREE_TYPE (t), spc); } } else if (TREE_CODE (t) == FUNCTION_DECL) { + tree decl_name = DECL_NAME (t); bool is_abstract_class = false; bool is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE; - tree decl_name = DECL_NAME (t); bool is_abstract = false; bool is_assignment_operator = false; bool is_constructor = false; @@ -2952,7 +2976,7 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) bool is_copy_constructor = false; bool is_move_constructor = false; - if (!decl_name || overloaded_name_p (decl_name)) + if (!decl_name) return 0; if (cpp_check) @@ -2977,9 +3001,9 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) return 0; /* Only consider complete constructors and deleting destructors. */ - if (strncmp (IDENTIFIER_POINTER (decl_name), "__ct_comp", 9) != 0 - && strncmp (IDENTIFIER_POINTER (decl_name), "__dt_comp", 9) != 0 - && strncmp (IDENTIFIER_POINTER (decl_name), "__dt_del", 8) != 0) + if (!startswith (IDENTIFIER_POINTER (decl_name), "__ct_comp") + && !startswith (IDENTIFIER_POINTER (decl_name), "__dt_comp") + && !startswith (IDENTIFIER_POINTER (decl_name), "__dt_del")) return 0; } @@ -3015,7 +3039,12 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) else if (is_assignment_operator) print_assignment_operator (buffer, t, type); else - dump_ada_decl_name (buffer, t, false); + { + const unsigned int suffix = overloading_index (decl_name); + pp_ada_tree_identifier (buffer, decl_name, t, false); + if (suffix > 1) + pp_decimal_int (buffer, suffix); + } dump_ada_function_declaration (buffer, t, is_method, is_constructor, is_destructor, spc); @@ -3130,8 +3159,9 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) if (need_indent) INDENT (spc); - if (TREE_CODE (t) == FIELD_DECL && DECL_NAME (t)) - check_name (buffer, t); + if ((TREE_CODE (t) == FIELD_DECL || TREE_CODE (t) == VAR_DECL) + && DECL_NAME (t)) + check_type_name_conflict (buffer, t); /* Print variable/type's name. */ dump_ada_node (buffer, t, t, spc, false, true); @@ -3157,7 +3187,8 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE && (TYPE_NAME (TREE_TYPE (t)) || (TREE_CODE (TREE_TYPE (t)) != INTEGER_TYPE - && TREE_CODE (TREE_TYPE (t)) != ENUMERAL_TYPE))) + && TREE_CODE (TREE_TYPE (t)) != ENUMERAL_TYPE)) + && !packed_layout) pp_string (buffer, "aliased "); if (TREE_READONLY (t) && TREE_CODE (t) != FIELD_DECL) @@ -3168,7 +3199,7 @@ dump_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) && TREE_CODE (TREE_TYPE (t)) != ENUMERAL_TYPE)) dump_ada_node (buffer, TREE_TYPE (t), t, spc, false, true); else if (type) - dump_anonymous_type_name (buffer, TREE_TYPE (t), type); + dump_anonymous_type_name (buffer, TREE_TYPE (t)); } } @@ -3324,7 +3355,7 @@ dump_ada_structure (pretty_printer *buffer, tree node, tree type, bool nested, pp_string (buffer, "Unchecked_Union => True"); } - if (bitfield_used) + if (bitfield_used || packed_layout) { char buf[32]; pp_comma (buffer); @@ -3335,6 +3366,7 @@ dump_ada_structure (pretty_printer *buffer, tree node, tree type, bool nested, sprintf (buf, "Alignment => %d", TYPE_ALIGN (node) / BITS_PER_UNIT); pp_string (buffer, buf); bitfield_used = false; + packed_layout = false; } if (nested) @@ -3408,11 +3440,12 @@ dump_ads (const char *source_file, dump_ada_nodes (&pp, source_file); /* We require Ada 2012 syntax, so generate corresponding pragma. */ - fputs ("pragma Ada_2012;\n", f); + fputs ("pragma Ada_2012;\n\n", f); /* Disable style checks and warnings on unused entities since this file is auto-generated and always has a with clause for Interfaces.C. */ - fputs ("pragma Style_Checks (Off);\npragma Warnings (\"U\");\n\n", f); + fputs ("pragma Style_Checks (Off);\n", f); + fputs ("pragma Warnings (Off, \"-gnatwu\");\n\n", f); /* Dump withs. */ dump_ada_withs (f); @@ -3420,7 +3453,10 @@ dump_ads (const char *source_file, fprintf (f, "\npackage %s is\n\n", pkg_name); pp_write_text_to_stream (&pp); /* ??? need to free pp */ - fprintf (f, "end %s;\n", pkg_name); + fprintf (f, "end %s;\n\n", pkg_name); + + fputs ("pragma Style_Checks (On);\n", f); + fputs ("pragma Warnings (On, \"-gnatwu\");\n", f); fclose (f); } @@ -3474,9 +3510,15 @@ dump_ada_specs (void (*collect_all_refs)(const char *), { bitmap_obstack_initialize (NULL); + overloaded_names = init_overloaded_names (); + /* Iterate over the list of files to dump specs for. */ for (int i = 0; i < source_refs_used; i++) - dump_ads (source_refs[i], collect_all_refs, check); + { + dumped_anonymous_types = BITMAP_ALLOC (NULL); + dump_ads (source_refs[i], collect_all_refs, check); + BITMAP_FREE (dumped_anonymous_types); + } /* Free various tables. */ free (source_refs); diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index c1f652d..007b928 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -62,6 +62,8 @@ static tree handle_no_address_safety_analysis_attribute (tree *, tree, tree, int, bool *); static tree handle_no_sanitize_undefined_attribute (tree *, tree, tree, int, bool *); +static tree handle_no_sanitize_coverage_attribute (tree *, tree, tree, int, + bool *); static tree handle_asan_odr_indicator_attribute (tree *, tree, tree, int, bool *); static tree handle_stack_protect_attribute (tree *, tree, tree, int, bool *); @@ -81,6 +83,7 @@ static tree handle_artificial_attribute (tree *, tree, tree, int, bool *); static tree handle_flatten_attribute (tree *, tree, tree, int, bool *); static tree handle_error_attribute (tree *, tree, tree, int, bool *); static tree handle_used_attribute (tree *, tree, tree, int, bool *); +static tree handle_uninitialized_attribute (tree *, tree, tree, int, bool *); static tree handle_externally_visible_attribute (tree *, tree, tree, int, bool *); static tree handle_no_reorder_attribute (tree *, tree, tree, int, @@ -121,6 +124,8 @@ static tree handle_pure_attribute (tree *, tree, tree, int, bool *); static tree handle_tm_attribute (tree *, tree, tree, int, bool *); static tree handle_tm_wrap_attribute (tree *, tree, tree, int, bool *); static tree handle_novops_attribute (tree *, tree, tree, int, bool *); +static tree handle_unavailable_attribute (tree *, tree, tree, int, + bool *); static tree handle_vector_size_attribute (tree *, tree, tree, int, bool *) ATTRIBUTE_NONNULL(3); static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *); @@ -329,6 +334,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_used_attribute, NULL }, { "unused", 0, 0, false, false, false, false, handle_unused_attribute, NULL }, + { "uninitialized", 0, 0, true, false, false, false, + handle_uninitialized_attribute, NULL }, { "retain", 0, 0, true, false, false, false, handle_retain_attribute, NULL }, { "externally_visible", 0, 0, true, false, false, false, @@ -404,6 +411,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_novops_attribute, NULL }, { "deprecated", 0, 1, false, false, false, false, handle_deprecated_attribute, NULL }, + { "unavailable", 0, 1, false, false, false, false, + handle_unavailable_attribute, NULL }, { "vector_size", 1, 1, false, true, false, true, handle_vector_size_attribute, NULL }, { "visibility", 1, 1, false, false, false, false, @@ -449,6 +458,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_no_sanitize_thread_attribute, NULL }, { "no_sanitize_undefined", 0, 0, true, false, false, false, handle_no_sanitize_undefined_attribute, NULL }, + { "no_sanitize_coverage", 0, 0, true, false, false, false, + handle_no_sanitize_coverage_attribute, NULL }, { "asan odr indicator", 0, 0, true, false, false, false, handle_asan_odr_indicator_attribute, NULL }, { "warning", 1, 1, true, false, false, false, @@ -694,6 +705,9 @@ positional_argument (const_tree fntype, const_tree atname, tree pos, if (tree argtype = type_argument_type (fntype, ipos)) { + if (argtype == error_mark_node) + return NULL_TREE; + if (flags & POSARG_ELLIPSIS) { if (argno < 1) @@ -1211,6 +1225,22 @@ handle_no_sanitize_undefined_attribute (tree *node, tree name, tree, int, return NULL_TREE; } +/* Handle a "no_sanitize_coverage" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_no_sanitize_coverage_attribute (tree *node, tree name, tree, int, + bool *no_add_attrs) +{ + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + /* Handle an "asan odr indicator" attribute; arguments as in struct attribute_spec.handler. */ @@ -1545,6 +1575,7 @@ handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args), || VAR_OR_FUNCTION_DECL_P (decl) || TREE_CODE (decl) == LABEL_DECL || TREE_CODE (decl) == CONST_DECL + || TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == TYPE_DECL) { TREE_USED (decl) = 1; @@ -1589,6 +1620,30 @@ handle_retain_attribute (tree *pnode, tree name, tree ARG_UNUSED (args), return NULL_TREE; } +/* Handle an "uninitialized" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_uninitialized_attribute (tree *node, tree name, tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + tree decl = *node; + if (!VAR_P (decl)) + { + warning (OPT_Wattributes, "%qE attribute ignored because %qD " + "is not a variable", name, decl); + *no_add_attrs = true; + } + else if (TREE_STATIC (decl) || DECL_EXTERNAL (decl)) + { + warning (OPT_Wattributes, "%qE attribute ignored because %qD " + "is not a local variable", name, decl); + *no_add_attrs = true; + } + + return NULL_TREE; +} + /* Handle a "externally_visible" attribute; arguments as in struct attribute_spec.handler. */ @@ -2314,14 +2369,17 @@ common_handle_aligned_attribute (tree *node, tree name, tree args, int flags, *no_add_attrs = true; } else if (TREE_CODE (decl) == FUNCTION_DECL - && ((curalign = DECL_ALIGN (decl)) > bitalign - || ((lastalign = DECL_ALIGN (last_decl)) > bitalign))) + && (((curalign = DECL_ALIGN (decl)) > bitalign) + | ((lastalign = DECL_ALIGN (last_decl)) > bitalign))) { /* Either a prior attribute on the same declaration or one on a prior declaration of the same function specifies stricter alignment than this attribute. */ - bool note = lastalign != 0; - if (lastalign) + bool note = (lastalign > curalign + || (lastalign == curalign + && (DECL_USER_ALIGN (last_decl) + > DECL_USER_ALIGN (decl)))); + if (note) curalign = lastalign; curalign /= BITS_PER_UNIT; @@ -2366,25 +2424,6 @@ common_handle_aligned_attribute (tree *node, tree name, tree args, int flags, This formally comes from the c++11 specification but we are doing it for the GNU attribute syntax as well. */ *no_add_attrs = true; - else if (!warn_if_not_aligned_p - && TREE_CODE (decl) == FUNCTION_DECL - && DECL_ALIGN (decl) > bitalign) - { - /* Don't warn for function alignment here if warn_if_not_aligned_p - is true. It will be warned about later. */ - if (DECL_USER_ALIGN (decl)) - { - /* Only reject attempts to relax/override an alignment - explicitly specified previously and accept declarations - that appear to relax the implicit function alignment for - the target. Both increasing and increasing the alignment - set by -falign-functions setting is permitted. */ - error ("alignment for %q+D was previously specified as %d " - "and may not be decreased", decl, - DECL_ALIGN (decl) / BITS_PER_UNIT); - *no_add_attrs = true; - } - } else if (warn_if_not_aligned_p && TREE_CODE (decl) == FIELD_DECL && !DECL_C_BIT_FIELD (decl)) @@ -4114,6 +4153,71 @@ handle_deprecated_attribute (tree *node, tree name, return NULL_TREE; } +/* Handle a "unavailable" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_unavailable_attribute (tree *node, tree name, + tree args, int flags, + bool *no_add_attrs) +{ + tree type = NULL_TREE; + int warn = 0; + tree what = NULL_TREE; + + if (!args) + *no_add_attrs = true; + else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST) + { + error ("the message attached to %<unavailable%> is not a string"); + *no_add_attrs = true; + } + + if (DECL_P (*node)) + { + tree decl = *node; + type = TREE_TYPE (decl); + + if (TREE_CODE (decl) == TYPE_DECL + || TREE_CODE (decl) == PARM_DECL + || VAR_OR_FUNCTION_DECL_P (decl) + || TREE_CODE (decl) == FIELD_DECL + || TREE_CODE (decl) == CONST_DECL + || objc_method_decl (TREE_CODE (decl))) + TREE_UNAVAILABLE (decl) = 1; + else + warn = 1; + } + else if (TYPE_P (*node)) + { + if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + *node = build_variant_type_copy (*node); + TREE_UNAVAILABLE (*node) = 1; + type = *node; + } + else + warn = 1; + + if (warn) + { + *no_add_attrs = true; + if (type && TYPE_NAME (type)) + { + if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) + what = TYPE_NAME (*node); + else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL + && DECL_NAME (TYPE_NAME (type))) + what = DECL_NAME (TYPE_NAME (type)); + } + if (what) + warning (OPT_Wattributes, "%qE attribute ignored for %qE", name, what); + else + warning (OPT_Wattributes, "%qE attribute ignored", name); + } + + return NULL_TREE; +} + /* Return the "base" type from TYPE that is suitable to apply attribute vector_size to by stripping arrays, function types, etc. */ static tree @@ -4245,10 +4349,22 @@ type_valid_for_vector_size (tree type, tree atname, tree args, if (nunits & (nunits - 1)) { if (error_p) - error ("number of components of the vector not a power of two"); + error ("number of vector components %wu not a power of two", nunits); + else + warning (OPT_Wattributes, + "number of vector components %wu not a power of two", nunits); + return NULL_TREE; + } + + if (nunits >= (unsigned HOST_WIDE_INT)INT_MAX) + { + if (error_p) + error ("number of vector components %wu exceeds %d", + nunits, INT_MAX - 1); else warning (OPT_Wattributes, - "number of components of the vector not a power of two"); + "number of vector components %wu exceeds %d", + nunits, INT_MAX - 1); return NULL_TREE; } @@ -5031,16 +5147,25 @@ build_attr_access_from_parms (tree parms, bool skip_voidptr) /* Create the attribute access string from the arg spec string, optionally followed by position of the VLA bound argument if it is one. */ - char specbuf[80]; - int len = snprintf (specbuf, sizeof specbuf, "%c%u%s", - attr_access::mode_chars[access_deferred], - argpos, s); - gcc_assert ((size_t) len < sizeof specbuf); - - if (!spec.length ()) - spec += '+'; + { + size_t specend = spec.length (); + if (!specend) + { + spec = '+'; + specend = 1; + } - spec += specbuf; + /* Format the access string in place. */ + int len = snprintf (NULL, 0, "%c%u%s", + attr_access::mode_chars[access_deferred], + argpos, s); + spec.resize (specend + len + 1); + sprintf (&spec[specend], "%c%u%s", + attr_access::mode_chars[access_deferred], + argpos, s); + /* Trim the trailing NUL. */ + spec.resize (specend + len); + } /* The (optional) list of expressions denoting the VLA bounds N in ARGTYPE <arg>[Ni]...[Nj]...[Nk]. */ @@ -5065,8 +5190,13 @@ build_attr_access_from_parms (tree parms, bool skip_voidptr) { /* BOUND previously seen in the parameter list. */ TREE_PURPOSE (vb) = size_int (*psizpos); - sprintf (specbuf, "$%u", *psizpos); - spec += specbuf; + /* Format the position string in place. */ + int len = snprintf (NULL, 0, "$%u", *psizpos); + size_t specend = spec.length (); + spec.resize (specend + len + 1); + sprintf (&spec[specend], "$%u", *psizpos); + /* Trim the trailing NUL. */ + spec.resize (specend + len); } else { @@ -5288,7 +5418,12 @@ handle_target_clones_attribute (tree *node, tree name, tree ARG_UNUSED (args), /* Ensure we have a function type. */ if (TREE_CODE (*node) == FUNCTION_DECL) { - if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (*node))) + if (TREE_CODE (TREE_VALUE (args)) != STRING_CST) + { + error ("%qE attribute argument not a string constant", name); + *no_add_attrs = true; + } + else if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (*node))) { warning (OPT_Wattributes, "%qE attribute ignored due to conflict " "with %qs attribute", name, "always_inline"); @@ -5332,11 +5467,17 @@ handle_optimize_attribute (tree *node, tree name, tree args, /* Save current options. */ cl_optimization_save (&cur_opts, &global_options, &global_options_set); + tree prev_target_node = build_target_option_node (&global_options, + &global_options_set); /* If we previously had some optimization options, use them as the default. */ gcc_options *saved_global_options = NULL; - if (flag_checking) + + /* When #pragma GCC optimize pragma is used, it modifies global_options + without calling targetm.override_options_after_change. That can leave + target flags inconsistent for comparison. */ + if (flag_checking && optimization_current_node == optimization_default_node) { saved_global_options = XNEW (gcc_options); *saved_global_options = global_options; @@ -5350,10 +5491,17 @@ handle_optimize_attribute (tree *node, tree name, tree args, parse_optimize_options (args, true); DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node) = build_optimization_node (&global_options, &global_options_set); + tree target_node = build_target_option_node (&global_options, + &global_options_set); + if (prev_target_node != target_node) + DECL_FUNCTION_SPECIFIC_TARGET (*node) = target_node; /* Restore current options. */ cl_optimization_restore (&global_options, &global_options_set, &cur_opts); + cl_target_option_restore (&global_options, &global_options_set, + TREE_TARGET_OPTION (prev_target_node)); + if (saved_global_options != NULL) { cl_optimization_compare (saved_global_options, &global_options); diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index d227686..c6757f0 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -51,6 +51,8 @@ along with GCC; see the file COPYING3. If not see #include "c-spellcheck.h" #include "selftest.h" #include "debug.h" +#include "tree-vector-builder.h" +#include "vec-perm-indices.h" cpp_reader *parse_in; /* Declared in c-pragma.h. */ @@ -383,6 +385,7 @@ const struct c_common_resword c_common_reswords[] = { "__builtin_has_attribute", RID_BUILTIN_HAS_ATTRIBUTE, 0 }, { "__builtin_launder", RID_BUILTIN_LAUNDER, D_CXXONLY }, { "__builtin_shuffle", RID_BUILTIN_SHUFFLE, 0 }, + { "__builtin_shufflevector", RID_BUILTIN_SHUFFLEVECTOR, 0 }, { "__builtin_tgmath", RID_BUILTIN_TGMATH, D_CONLY }, { "__builtin_offsetof", RID_OFFSETOF, 0 }, { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, D_CONLY }, @@ -417,7 +420,10 @@ const struct c_common_resword c_common_reswords[] = { "__is_empty", RID_IS_EMPTY, D_CXXONLY }, { "__is_enum", RID_IS_ENUM, D_CXXONLY }, { "__is_final", RID_IS_FINAL, D_CXXONLY }, + { "__is_layout_compatible", RID_IS_LAYOUT_COMPATIBLE, D_CXXONLY }, { "__is_literal_type", RID_IS_LITERAL_TYPE, D_CXXONLY }, + { "__is_pointer_interconvertible_base_of", + RID_IS_POINTER_INTERCONVERTIBLE_BASE_OF, D_CXXONLY }, { "__is_pod", RID_IS_POD, D_CXXONLY }, { "__is_polymorphic", RID_IS_POLYMORPHIC, D_CXXONLY }, { "__is_same", RID_IS_SAME_AS, D_CXXONLY }, @@ -1108,6 +1114,142 @@ c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask, return ret; } +/* Build a VEC_PERM_EXPR if V0, V1 are not error_mark_nodes + and have vector types, V0 has the same element type as V1, and the + number of elements the result is that of MASK. */ +tree +c_build_shufflevector (location_t loc, tree v0, tree v1, + const vec<tree> &mask, bool complain) +{ + tree ret; + bool wrap = true; + bool maybe_const = false; + + if (v0 == error_mark_node || v1 == error_mark_node) + return error_mark_node; + + if (!gnu_vector_type_p (TREE_TYPE (v0)) + || !gnu_vector_type_p (TREE_TYPE (v1))) + { + if (complain) + error_at (loc, "%<__builtin_shufflevector%> arguments must be vectors"); + return error_mark_node; + } + + /* ??? In principle one could select a constant part of a variable size + vector but things get a bit awkward with trying to support this here. */ + unsigned HOST_WIDE_INT v0n, v1n; + if (!TYPE_VECTOR_SUBPARTS (TREE_TYPE (v0)).is_constant (&v0n) + || !TYPE_VECTOR_SUBPARTS (TREE_TYPE (v1)).is_constant (&v1n)) + { + if (complain) + error_at (loc, "%<__builtin_shufflevector%> arguments must be constant" + " size vectors"); + return error_mark_node; + } + + if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (v0))) + != TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (v1)))) + { + if (complain) + error_at (loc, "%<__builtin_shufflevector%> argument vectors must " + "have the same element type"); + return error_mark_node; + } + + if (!pow2p_hwi (mask.length ())) + { + if (complain) + error_at (loc, "%<__builtin_shufflevector%> must specify a result " + "with a power of two number of elements"); + return error_mark_node; + } + + if (!c_dialect_cxx ()) + { + /* Avoid C_MAYBE_CONST_EXPRs inside VEC_PERM_EXPR. */ + v0 = c_fully_fold (v0, false, &maybe_const); + wrap &= maybe_const; + + v1 = c_fully_fold (v1, false, &maybe_const); + wrap &= maybe_const; + } + + unsigned HOST_WIDE_INT maskl = MAX (mask.length (), MAX (v0n, v1n)); + unsigned HOST_WIDE_INT pad = (v0n < maskl ? maskl - v0n : 0); + vec_perm_builder sel (maskl, maskl, 1); + unsigned i; + for (i = 0; i < mask.length (); ++i) + { + tree idx = mask[i]; + if (!tree_fits_shwi_p (idx)) + { + if (complain) + error_at (loc, "invalid element index %qE to " + "%<__builtin_shufflevector%>", idx); + return error_mark_node; + } + HOST_WIDE_INT iidx = tree_to_shwi (idx); + if (iidx < -1 + || (iidx != -1 + && (unsigned HOST_WIDE_INT) iidx >= v0n + v1n)) + { + if (complain) + error_at (loc, "invalid element index %qE to " + "%<__builtin_shufflevector%>", idx); + return error_mark_node; + } + /* ??? Our VEC_PERM_EXPR does not allow for -1 yet. */ + if (iidx == -1) + iidx = i; + /* ??? Our VEC_PERM_EXPR does not allow different sized inputs, + so pad out a smaller v0. */ + else if ((unsigned HOST_WIDE_INT) iidx >= v0n) + iidx += pad; + sel.quick_push (iidx); + } + /* ??? VEC_PERM_EXPR does not support a result that is smaller than + the inputs, so we have to pad id out. */ + for (; i < maskl; ++i) + sel.quick_push (i); + + vec_perm_indices indices (sel, 2, maskl); + + tree ret_type = build_vector_type (TREE_TYPE (TREE_TYPE (v0)), maskl); + tree mask_type = build_vector_type (build_nonstandard_integer_type + (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (ret_type))), 1), + maskl); + /* Pad out arguments to the common vector size. */ + if (v0n < maskl) + { + constructor_elt elt = { NULL_TREE, build_zero_cst (TREE_TYPE (v0)) }; + v0 = build_constructor_single (ret_type, NULL_TREE, v0); + for (i = 1; i < maskl / v0n; ++i) + vec_safe_push (CONSTRUCTOR_ELTS (v0), elt); + } + if (v1n < maskl) + { + constructor_elt elt = { NULL_TREE, build_zero_cst (TREE_TYPE (v1)) }; + v1 = build_constructor_single (ret_type, NULL_TREE, v1); + for (i = 1; i < maskl / v1n; ++i) + vec_safe_push (CONSTRUCTOR_ELTS (v1), elt); + } + ret = build3_loc (loc, VEC_PERM_EXPR, ret_type, v0, v1, + vec_perm_indices_to_tree (mask_type, indices)); + /* Get the lowpart we are interested in. */ + if (mask.length () < maskl) + { + tree lpartt = build_vector_type (TREE_TYPE (ret_type), mask.length ()); + ret = build3_loc (loc, BIT_FIELD_REF, + lpartt, ret, TYPE_SIZE (lpartt), bitsize_zero_node); + } + + if (!c_dialect_cxx () && !wrap) + ret = c_wrap_maybe_const (ret, true); + + return ret; +} + /* Build a VEC_CONVERT ifn for __builtin_convertvector builtin. */ tree @@ -3236,7 +3378,6 @@ pointer_int_sum (location_t loc, enum tree_code resultcode, tree c_wrap_maybe_const (tree expr, bool non_const) { - bool nowarning = TREE_NO_WARNING (expr); location_t loc = EXPR_LOCATION (expr); /* This should never be called for C++. */ @@ -3247,8 +3388,6 @@ c_wrap_maybe_const (tree expr, bool non_const) STRIP_TYPE_NOPS (expr); expr = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (expr), NULL, expr); C_MAYBE_CONST_EXPR_NON_CONST (expr) = non_const; - if (nowarning) - TREE_NO_WARNING (expr) = 1; protected_set_expr_location (expr, loc); return expr; @@ -3494,12 +3633,12 @@ c_common_truthvalue_conversion (location_t location, tree expr) break; case MODIFY_EXPR: - if (!TREE_NO_WARNING (expr) + if (!warning_suppressed_p (expr, OPT_Wparentheses) && warn_parentheses && warning_at (location, OPT_Wparentheses, "suggest parentheses around assignment used as " "truth value")) - TREE_NO_WARNING (expr) = 1; + suppress_warning (expr, OPT_Wparentheses); break; case CONST_DECL: @@ -4670,7 +4809,7 @@ static bool builtin_function_disabled_p (const char *); void disable_builtin_function (const char *name) { - if (strncmp (name, "__builtin_", strlen ("__builtin_")) == 0) + if (startswith (name, "__builtin_")) error ("cannot disable built-in function %qs", name); else { @@ -4718,8 +4857,7 @@ def_builtin_1 (enum built_in_function fncode, return; gcc_assert ((!both_p && !fallback_p) - || !strncmp (name, "__builtin_", - strlen ("__builtin_"))); + || startswith (name, "__builtin_")); libname = name + strlen ("__builtin_"); decl = add_builtin_function (name, fntype, fncode, fnclass, @@ -5663,7 +5801,7 @@ parse_optimize_options (tree args, bool attr_p) if (TREE_CODE (value) == INTEGER_CST) { - char buffer[20]; + char buffer[HOST_BITS_PER_LONG / 3 + 4]; sprintf (buffer, "-O%ld", (long) TREE_INT_CST_LOW (value)); vec_safe_push (optimize_args, ggc_strdup (buffer)); } @@ -5881,7 +6019,7 @@ check_function_arguments_recurse (void (*callback) void *ctx, tree param, unsigned HOST_WIDE_INT param_num) { - if (TREE_NO_WARNING (param)) + if (warning_suppressed_p (param)) return; if (CONVERT_EXPR_P (param) @@ -6759,10 +6897,13 @@ complete_flexible_array_elts (tree init) void c_common_mark_addressable_vec (tree t) { - if (TREE_CODE (t) == C_MAYBE_CONST_EXPR) - t = C_MAYBE_CONST_EXPR_EXPR (t); - while (handled_component_p (t)) - t = TREE_OPERAND (t, 0); + while (handled_component_p (t) || TREE_CODE (t) == C_MAYBE_CONST_EXPR) + { + if (TREE_CODE (t) == C_MAYBE_CONST_EXPR) + t = C_MAYBE_CONST_EXPR_EXPR (t); + else + t = TREE_OPERAND (t, 0); + } if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL && TREE_CODE (t) != COMPOUND_LITERAL_EXPR) @@ -8637,7 +8778,7 @@ excess_precision_mode_join (enum flt_eval_method x, This relates to the effective excess precision seen by the user, which is the join point of the precision the target requests for - -fexcess-precision={standard,fast} and the implicit excess precision + -fexcess-precision={standard,fast,16} and the implicit excess precision the target uses. */ static enum flt_eval_method @@ -8649,7 +8790,9 @@ c_ts18661_flt_eval_method (void) enum excess_precision_type flag_type = (flag_excess_precision == EXCESS_PRECISION_STANDARD ? EXCESS_PRECISION_TYPE_STANDARD - : EXCESS_PRECISION_TYPE_FAST); + : (flag_excess_precision == EXCESS_PRECISION_FLOAT16 + ? EXCESS_PRECISION_TYPE_FLOAT16 + : EXCESS_PRECISION_TYPE_FAST)); enum flt_eval_method requested = targetm.c.excess_precision (flag_type); @@ -9060,6 +9203,12 @@ braced_list_to_string (tree type, tree ctor, bool member) if (!member && !tree_fits_uhwi_p (typesize)) return ctor; + /* If the target char size differes from the host char size, we'd risk + loosing data and getting object sizes wrong by converting to + host chars. */ + if (TYPE_PRECISION (char_type_node) != CHAR_BIT) + return ctor; + /* If the array has an explicit bound, use it to constrain the size of the string. If it doesn't, be sure to create a string that's as long as implied by the index of the last zero specified via diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index f30b6c6..849cefa 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -107,7 +107,7 @@ enum rid RID_ASM, RID_TYPEOF, RID_ALIGNOF, RID_ATTRIBUTE, RID_VA_ARG, RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_CHOOSE_EXPR, RID_TYPES_COMPATIBLE_P, RID_BUILTIN_COMPLEX, RID_BUILTIN_SHUFFLE, - RID_BUILTIN_CONVERTVECTOR, RID_BUILTIN_TGMATH, + RID_BUILTIN_SHUFFLEVECTOR, RID_BUILTIN_CONVERTVECTOR, RID_BUILTIN_TGMATH, RID_BUILTIN_HAS_ATTRIBUTE, RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128, @@ -173,7 +173,9 @@ enum rid RID_IS_ABSTRACT, RID_IS_AGGREGATE, RID_IS_BASE_OF, RID_IS_CLASS, RID_IS_EMPTY, RID_IS_ENUM, - RID_IS_FINAL, RID_IS_LITERAL_TYPE, + RID_IS_FINAL, RID_IS_LAYOUT_COMPATIBLE, + RID_IS_LITERAL_TYPE, + RID_IS_POINTER_INTERCONVERTIBLE_BASE_OF, RID_IS_POD, RID_IS_POLYMORPHIC, RID_IS_SAME_AS, RID_IS_STD_LAYOUT, RID_IS_TRIVIAL, @@ -1048,6 +1050,8 @@ extern bool lvalue_p (const_tree); extern bool vector_targets_convertible_p (const_tree t1, const_tree t2); extern bool vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note); extern tree c_build_vec_perm_expr (location_t, tree, tree, tree, bool = true); +extern tree c_build_shufflevector (location_t, tree, tree, + const vec<tree> &, bool = true); extern tree c_build_vec_convert (location_t, tree, location_t, tree, bool = true); extern void init_c_lex (void); @@ -1198,7 +1202,8 @@ enum c_omp_clause_split C_OMP_CLAUSE_SPLIT_COUNT, C_OMP_CLAUSE_SPLIT_SECTIONS = C_OMP_CLAUSE_SPLIT_FOR, C_OMP_CLAUSE_SPLIT_TASKLOOP = C_OMP_CLAUSE_SPLIT_FOR, - C_OMP_CLAUSE_SPLIT_LOOP = C_OMP_CLAUSE_SPLIT_FOR + C_OMP_CLAUSE_SPLIT_LOOP = C_OMP_CLAUSE_SPLIT_FOR, + C_OMP_CLAUSE_SPLIT_MASKED = C_OMP_CLAUSE_SPLIT_DISTRIBUTE }; enum c_omp_region_type @@ -1206,17 +1211,20 @@ enum c_omp_region_type C_ORT_OMP = 1 << 0, C_ORT_ACC = 1 << 1, C_ORT_DECLARE_SIMD = 1 << 2, - C_ORT_OMP_DECLARE_SIMD = C_ORT_OMP | C_ORT_DECLARE_SIMD + C_ORT_TARGET = 1 << 3, + C_ORT_OMP_DECLARE_SIMD = C_ORT_OMP | C_ORT_DECLARE_SIMD, + C_ORT_OMP_TARGET = C_ORT_OMP | C_ORT_TARGET }; extern tree c_finish_omp_master (location_t, tree); +extern tree c_finish_omp_masked (location_t, tree, tree); extern tree c_finish_omp_taskgroup (location_t, tree, tree); extern tree c_finish_omp_critical (location_t, tree, tree, tree); extern tree c_finish_omp_ordered (location_t, tree, tree); extern void c_finish_omp_barrier (location_t); extern tree c_finish_omp_atomic (location_t, enum tree_code, enum tree_code, - tree, tree, tree, tree, tree, bool, - enum omp_memory_order, bool = false); + tree, tree, tree, tree, tree, tree, bool, + enum omp_memory_order, bool, bool = false); extern bool c_omp_depend_t_p (tree); extern void c_finish_omp_depobj (location_t, tree, enum omp_clause_depend_kind, tree); @@ -1242,6 +1250,25 @@ extern void c_omp_mark_declare_variant (location_t, tree, tree); extern const char *c_omp_map_clause_name (tree, bool); extern void c_omp_adjust_map_clauses (tree, bool); +enum c_omp_directive_kind { + C_OMP_DIR_STANDALONE, + C_OMP_DIR_CONSTRUCT, + C_OMP_DIR_DECLARATIVE, + C_OMP_DIR_UTILITY, + C_OMP_DIR_INFORMATIONAL +}; + +struct c_omp_directive { + const char *first, *second, *third; + unsigned int id; + enum c_omp_directive_kind kind; + bool simd; +}; + +extern const struct c_omp_directive *c_omp_categorize_directive (const char *, + const char *, + const char *); + /* Return next tree in the chain for chain_next walking of tree nodes. */ static inline tree c_tree_chain_next (tree t) diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c index 9f993c4..ce88e70 100644 --- a/gcc/c-family/c-cppbuiltin.c +++ b/gcc/c-family/c-cppbuiltin.c @@ -741,6 +741,20 @@ cpp_atomic_builtins (cpp_reader *pfile) builtin_define_with_int_value ("__GCC_ATOMIC_TEST_AND_SET_TRUEVAL", targetm.atomic_test_and_set_trueval); + /* Macros for C++17 hardware interference size constants. Either both or + neither should be set. */ + gcc_assert (!param_destruct_interfere_size + == !param_construct_interfere_size); + if (param_destruct_interfere_size) + { + /* FIXME The way of communicating these values to the library should be + part of the C++ ABI, whether macro or builtin. */ + builtin_define_with_int_value ("__GCC_DESTRUCTIVE_SIZE", + param_destruct_interfere_size); + builtin_define_with_int_value ("__GCC_CONSTRUCTIVE_SIZE", + param_construct_interfere_size); + } + /* ptr_type_node can't be used here since ptr_mode is only set when toplev calls backend_init which is not done with -E or pch. */ psize = POINTER_SIZE_UNITS; @@ -753,7 +767,7 @@ cpp_atomic_builtins (cpp_reader *pfile) /* Return TRUE if the implicit excess precision in which the back-end will compute floating-point calculations is not more than the explicit excess precision that the front-end will apply under - -fexcess-precision=[standard|fast]. + -fexcess-precision=[standard|fast|16]. More intuitively, return TRUE if the excess precision proposed by the front-end is the excess precision that will actually be used. */ @@ -764,7 +778,9 @@ c_cpp_flt_eval_method_iec_559 (void) enum excess_precision_type front_end_ept = (flag_excess_precision == EXCESS_PRECISION_STANDARD ? EXCESS_PRECISION_TYPE_STANDARD - : EXCESS_PRECISION_TYPE_FAST); + : (flag_excess_precision == EXCESS_PRECISION_FLOAT16 + ? EXCESS_PRECISION_TYPE_FLOAT16 + : EXCESS_PRECISION_TYPE_FAST)); enum flt_eval_method back_end = targetm.c.excess_precision (EXCESS_PRECISION_TYPE_IMPLICIT); @@ -1029,6 +1045,7 @@ c_cpp_builtins (cpp_reader *pfile) { /* Set feature test macros for C++23. */ cpp_define (pfile, "__cpp_size_t_suffix=202011L"); + cpp_define (pfile, "__cpp_if_consteval=202106L"); } if (flag_concepts) { @@ -1277,29 +1294,39 @@ c_cpp_builtins (cpp_reader *pfile) { scalar_float_mode mode = mode_iter.require (); const char *name = GET_MODE_NAME (mode); + const size_t name_len = strlen (name); + char float_h_prefix[16] = ""; char *macro_name - = (char *) alloca (strlen (name) - + sizeof ("__LIBGCC__MANT_DIG__")); + = XALLOCAVEC (char, name_len + sizeof ("__LIBGCC__MANT_DIG__")); sprintf (macro_name, "__LIBGCC_%s_MANT_DIG__", name); builtin_define_with_int_value (macro_name, REAL_MODE_FORMAT (mode)->p); if (!targetm.scalar_mode_supported_p (mode) || !targetm.libgcc_floating_mode_supported_p (mode)) continue; - macro_name = (char *) alloca (strlen (name) - + sizeof ("__LIBGCC_HAS__MODE__")); + macro_name = XALLOCAVEC (char, name_len + + sizeof ("__LIBGCC_HAS__MODE__")); sprintf (macro_name, "__LIBGCC_HAS_%s_MODE__", name); cpp_define (pfile, macro_name); - macro_name = (char *) alloca (strlen (name) - + sizeof ("__LIBGCC__FUNC_EXT__")); + macro_name = XALLOCAVEC (char, name_len + + sizeof ("__LIBGCC__FUNC_EXT__")); sprintf (macro_name, "__LIBGCC_%s_FUNC_EXT__", name); char suffix[20] = ""; if (mode == TYPE_MODE (double_type_node)) - ; /* Empty suffix correct. */ + { + /* Empty suffix correct. */ + memcpy (float_h_prefix, "DBL", 4); + } else if (mode == TYPE_MODE (float_type_node)) - suffix[0] = 'f'; + { + suffix[0] = 'f'; + memcpy (float_h_prefix, "FLT", 4); + } else if (mode == TYPE_MODE (long_double_type_node)) - suffix[0] = 'l'; + { + suffix[0] = 'l'; + memcpy (float_h_prefix, "LDBL", 5); + } else { bool found_suffix = false; @@ -1310,6 +1337,8 @@ c_cpp_builtins (cpp_reader *pfile) sprintf (suffix, "f%d%s", floatn_nx_types[i].n, floatn_nx_types[i].extended ? "x" : ""); found_suffix = true; + sprintf (float_h_prefix, "FLT%d%s", floatn_nx_types[i].n, + floatn_nx_types[i].extended ? "X" : ""); break; } gcc_assert (found_suffix); @@ -1347,11 +1376,33 @@ c_cpp_builtins (cpp_reader *pfile) default: gcc_unreachable (); } - macro_name = (char *) alloca (strlen (name) - + sizeof ("__LIBGCC__EXCESS_" - "PRECISION__")); + macro_name = XALLOCAVEC (char, name_len + + sizeof ("__LIBGCC__EXCESS_PRECISION__")); sprintf (macro_name, "__LIBGCC_%s_EXCESS_PRECISION__", name); builtin_define_with_int_value (macro_name, excess_precision); + + char val_name[64]; + + macro_name = XALLOCAVEC (char, name_len + + sizeof ("__LIBGCC__EPSILON__")); + sprintf (macro_name, "__LIBGCC_%s_EPSILON__", name); + sprintf (val_name, "__%s_EPSILON__", float_h_prefix); + builtin_define_with_value (macro_name, val_name, 0); + + macro_name = XALLOCAVEC (char, name_len + sizeof ("__LIBGCC__MAX__")); + sprintf (macro_name, "__LIBGCC_%s_MAX__", name); + sprintf (val_name, "__%s_MAX__", float_h_prefix); + builtin_define_with_value (macro_name, val_name, 0); + + macro_name = XALLOCAVEC (char, name_len + sizeof ("__LIBGCC__MIN__")); + sprintf (macro_name, "__LIBGCC_%s_MIN__", name); + sprintf (val_name, "__%s_MIN__", float_h_prefix); + builtin_define_with_value (macro_name, val_name, 0); + +#ifdef HAVE_adddf3 + builtin_define_with_int_value ("__LIBGCC_HAVE_HWDBL__", + HAVE_adddf3); +#endif } /* For libgcc crtstuff.c and libgcc2.c. */ @@ -1415,6 +1466,8 @@ c_cpp_builtins (cpp_reader *pfile) /* For libgcov. */ builtin_define_with_int_value ("__LIBGCC_VTABLE_USES_DESCRIPTORS__", TARGET_VTABLE_USES_DESCRIPTORS); + builtin_define_with_int_value ("__LIBGCC_GCOV_TYPE_SIZE", + targetm.gcov_type_size()); } /* For use in assembly language. */ diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c index 0a63cac..b4cb765a 100644 --- a/gcc/c-family/c-format.c +++ b/gcc/c-family/c-format.c @@ -546,10 +546,11 @@ static const format_length_info strfmon_length_specs[] = }; -/* For now, the Fortran front-end routines only use l as length modifier. */ +/* Length modifiers used by the fortran/error.c routines. */ static const format_length_info gcc_gfc_length_specs[] = { - { "l", FMT_LEN_l, STD_C89, NO_FMT, 0 }, + { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89, 0 }, + { "w", FMT_LEN_w, STD_C89, NO_FMT, 0 }, { NO_FMT, NO_FMT, 0 } }; @@ -781,10 +782,6 @@ static const format_char_info gcc_tdiag_char_table[] = /* These will require a "tree" at runtime. */ { "DFTV", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "'", NULL }, { "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL }, - { "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, - - /* G requires a "gimple*" argument at runtime. */ - { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } }; @@ -799,10 +796,6 @@ static const format_char_info gcc_cdiag_char_table[] = /* These will require a "tree" at runtime. */ { "DFTV", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "'", NULL }, { "E", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+", "", NULL }, - { "K", 1, STD_C89, { T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, - - /* G requires a "gimple*" argument at runtime. */ - { "G", 1, STD_C89, { T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, { "v", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL }, @@ -819,10 +812,6 @@ static const format_char_info gcc_cxxdiag_char_table[] = /* These will require a "tree" at runtime. */ { "ADFHISTVX",1,STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "'", NULL }, { "E", 1,STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "", NULL }, - { "K", 1, STD_C89,{ T89_T, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, - - /* G requires a "gimple*" argument at runtime. */ - { "G", 1, STD_C89,{ T89_G, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, /* These accept either an 'int' or an 'enum tree_code' (which is handled as an 'int'.) */ { "CLOPQ",0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, @@ -833,10 +822,10 @@ static const format_char_info gcc_cxxdiag_char_table[] = static const format_char_info gcc_gfc_char_table[] = { /* C89 conversion specifiers. */ - { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, - { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, - { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, - { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "cR", NULL }, + { "di", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, + { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, + { "c", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, + { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "cR", NULL }, /* gfc conversion specifiers. */ @@ -3097,7 +3086,7 @@ check_tokens (const token_t *tokens, unsigned ntoks, /* Allow this ugly warning for the time being. */ if (toklen == 2 && format_chars - orig_format_chars > 6 - && !strncmp (format_chars - 7, " count >= width of ", 19)) + && startswith (format_chars - 7, " count >= width of ")) return format_chars + 10; /* The token is a type if it ends in an alphabetic character. */ @@ -3127,7 +3116,7 @@ check_tokens (const token_t *tokens, unsigned ntoks, /* Diagnose unquoted __attribute__. Consider any parenthesized argument to the attribute to avoid redundant warnings for the double parentheses that might follow. */ - if (!strncmp (format_chars, "__attribute", sizeof "__attribute" - 1)) + if (startswith (format_chars, "__attribute")) { unsigned nchars = sizeof "__attribute" - 1; while ('_' == format_chars[nchars]) @@ -3178,9 +3167,9 @@ check_tokens (const token_t *tokens, unsigned ntoks, /* Diagnose unquoted built-ins. */ if (format_chars[0] == '_' && format_chars[1] == '_' - && (!strncmp (format_chars + 2, "atomic", sizeof "atomic" - 1) - || !strncmp (format_chars + 2, "builtin", sizeof "builtin" - 1) - || !strncmp (format_chars + 2, "sync", sizeof "sync" - 1))) + && (startswith (format_chars + 2, "atomic") + || startswith (format_chars + 2, "builtin") + || startswith (format_chars + 2, "sync"))) { format_warning_substr (format_string_loc, format_string_cst, fmtchrpos, fmtchrpos + wlen, opt, @@ -3267,7 +3256,7 @@ check_plain (location_t format_string_loc, tree format_string_cst, if (*format_chars == '%') { /* Diagnose %<%s%> and suggest using %qs instead. */ - if (!strncmp (format_chars, "%<%s%>", 6)) + if (startswith (format_chars, "%<%s%>")) format_warning_substr (format_string_loc, format_string_cst, fmtchrpos, fmtchrpos + 6, opt, "quoted %qs directive in format; " @@ -3593,7 +3582,7 @@ check_plain (location_t format_string_loc, tree format_string_cst, if (nchars == 1) { - if (!strncmp (format_chars, "\"%s\"", 4)) + if (startswith (format_chars, "\"%s\"")) { if (format_warning_substr (format_string_loc, format_string_cst, fmtchrpos, fmtchrpos + 4, opt, @@ -3621,7 +3610,7 @@ check_plain (location_t format_string_loc, tree format_string_cst, && format_chars[0] == '(') ; /* Text beginning in an open parenthesis. */ else if (nchars == 3 - && !strncmp (format_chars, "...", 3) + && startswith (format_chars, "...") && format_chars[3]) ; /* Text beginning in an ellipsis. */ else @@ -3663,7 +3652,7 @@ check_plain (location_t format_string_loc, tree format_string_cst, a period at the end of a capitalized sentence. */ else if (nchars == 3 && format_chars - orig_format_chars > 0 - && !strncmp (format_chars, "...", 3)) + && startswith (format_chars, "...")) ; /* Text ending in the ellipsis. */ else format_warning_substr (format_string_loc, format_string_cst, @@ -4855,12 +4844,73 @@ init_dynamic_asm_fprintf_info (void) } } +static const format_length_info* +get_init_dynamic_hwi (void) +{ + static tree hwi; + static format_length_info *diag_ls; + + if (!hwi) + { + unsigned int i; + + /* Find the underlying type for HOST_WIDE_INT. For the 'w' + length modifier to work, one must have issued: "typedef + HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code + prior to using that modifier. */ + if ((hwi = maybe_get_identifier ("__gcc_host_wide_int__"))) + { + hwi = identifier_global_value (hwi); + if (hwi) + { + if (TREE_CODE (hwi) != TYPE_DECL) + { + error ("%<__gcc_host_wide_int__%> is not defined as a type"); + hwi = 0; + } + else + { + hwi = DECL_ORIGINAL_TYPE (hwi); + gcc_assert (hwi); + if (hwi != long_integer_type_node + && hwi != long_long_integer_type_node) + { + error ("%<__gcc_host_wide_int__%> is not defined" + " as %<long%> or %<long long%>"); + hwi = 0; + } + } + } + } + if (!diag_ls) + diag_ls = (format_length_info *) + xmemdup (gcc_diag_length_specs, + sizeof (gcc_diag_length_specs), + sizeof (gcc_diag_length_specs)); + if (hwi) + { + /* HOST_WIDE_INT must be one of 'long' or 'long long'. */ + i = find_length_info_modifier_index (diag_ls, 'w'); + if (hwi == long_integer_type_node) + diag_ls[i].index = FMT_LEN_l; + else if (hwi == long_long_integer_type_node) + diag_ls[i].index = FMT_LEN_ll; + else + gcc_unreachable (); + } + } + return diag_ls; +} + /* Determine the type of a "locus" in the code being compiled for use in GCC's __gcc_gfc__ custom format attribute. You must have set dynamic_format_types before calling this function. */ static void init_dynamic_gfc_info (void) { + dynamic_format_types[gcc_gfc_format_type].length_char_specs + = get_init_dynamic_hwi (); + if (!locus) { static format_char_info *gfc_fci; @@ -4997,67 +5047,13 @@ init_dynamic_diag_info (void) || local_event_ptr_node == void_type_node) local_event_ptr_node = get_named_type ("diagnostic_event_id_t"); - static tree hwi; - - if (!hwi) - { - static format_length_info *diag_ls; - unsigned int i; - - /* Find the underlying type for HOST_WIDE_INT. For the 'w' - length modifier to work, one must have issued: "typedef - HOST_WIDE_INT __gcc_host_wide_int__;" in one's source code - prior to using that modifier. */ - if ((hwi = maybe_get_identifier ("__gcc_host_wide_int__"))) - { - hwi = identifier_global_value (hwi); - if (hwi) - { - if (TREE_CODE (hwi) != TYPE_DECL) - { - error ("%<__gcc_host_wide_int__%> is not defined as a type"); - hwi = 0; - } - else - { - hwi = DECL_ORIGINAL_TYPE (hwi); - gcc_assert (hwi); - if (hwi != long_integer_type_node - && hwi != long_long_integer_type_node) - { - error ("%<__gcc_host_wide_int__%> is not defined" - " as %<long%> or %<long long%>"); - hwi = 0; - } - } - } - } - - /* Assign the new data for use. */ - - /* All the GCC diag formats use the same length specs. */ - if (!diag_ls) - dynamic_format_types[gcc_diag_format_type].length_char_specs = - dynamic_format_types[gcc_tdiag_format_type].length_char_specs = - dynamic_format_types[gcc_cdiag_format_type].length_char_specs = - dynamic_format_types[gcc_cxxdiag_format_type].length_char_specs = - dynamic_format_types[gcc_dump_printf_format_type].length_char_specs = - diag_ls = (format_length_info *) - xmemdup (gcc_diag_length_specs, - sizeof (gcc_diag_length_specs), - sizeof (gcc_diag_length_specs)); - if (hwi) - { - /* HOST_WIDE_INT must be one of 'long' or 'long long'. */ - i = find_length_info_modifier_index (diag_ls, 'w'); - if (hwi == long_integer_type_node) - diag_ls[i].index = FMT_LEN_l; - else if (hwi == long_long_integer_type_node) - diag_ls[i].index = FMT_LEN_ll; - else - gcc_unreachable (); - } - } + /* All the GCC diag formats use the same length specs. */ + dynamic_format_types[gcc_diag_format_type].length_char_specs = + dynamic_format_types[gcc_tdiag_format_type].length_char_specs = + dynamic_format_types[gcc_cdiag_format_type].length_char_specs = + dynamic_format_types[gcc_cxxdiag_format_type].length_char_specs = + dynamic_format_types[gcc_dump_printf_format_type].length_char_specs + = get_init_dynamic_hwi (); /* It's safe to "re-initialize these to the same values. */ dynamic_format_types[gcc_diag_format_type].conversion_specs = @@ -5104,7 +5100,7 @@ convert_format_name_to_system_name (const char *attr_name) int i; if (attr_name == NULL || *attr_name == 0 - || strncmp (attr_name, "gcc_", 4) == 0) + || startswith (attr_name, "gcc_")) return attr_name; #ifdef TARGET_OVERRIDES_FORMAT_INIT TARGET_OVERRIDES_FORMAT_INIT (); diff --git a/gcc/c-family/c-gimplify.c b/gcc/c-family/c-gimplify.c index e1dfca2..0d38b70 100644 --- a/gcc/c-family/c-gimplify.c +++ b/gcc/c-family/c-gimplify.c @@ -497,6 +497,35 @@ c_genericize_control_stmt (tree *stmt_p, int *walk_subtrees, void *data, genericize_omp_for_stmt (stmt_p, walk_subtrees, data, func, lh); break; + case STATEMENT_LIST: + if (TREE_SIDE_EFFECTS (stmt)) + { + tree_stmt_iterator i; + int nondebug_stmts = 0; + bool clear_side_effects = true; + /* Genericization can clear TREE_SIDE_EFFECTS, e.g. when + transforming an IF_STMT into COND_EXPR. If such stmt + appears in a STATEMENT_LIST that contains only that + stmt and some DEBUG_BEGIN_STMTs, without -g where the + STATEMENT_LIST wouldn't be present at all the resulting + expression wouldn't have TREE_SIDE_EFFECTS set, so make sure + to clear it even on the STATEMENT_LIST in such cases. */ + for (i = tsi_start (stmt); !tsi_end_p (i); tsi_next (&i)) + { + tree t = tsi_stmt (i); + if (TREE_CODE (t) != DEBUG_BEGIN_STMT && nondebug_stmts < 2) + nondebug_stmts++; + walk_tree_1 (tsi_stmt_ptr (i), func, data, NULL, lh); + if (TREE_CODE (t) != DEBUG_BEGIN_STMT + && (nondebug_stmts > 1 || TREE_SIDE_EFFECTS (tsi_stmt (i)))) + clear_side_effects = false; + } + if (clear_side_effects) + TREE_SIDE_EFFECTS (stmt) = 0; + *walk_subtrees = 0; + } + break; + default: break; } @@ -684,7 +713,7 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED, && !TREE_STATIC (DECL_EXPR_DECL (*expr_p)) && (DECL_INITIAL (DECL_EXPR_DECL (*expr_p)) == DECL_EXPR_DECL (*expr_p)) && !warn_init_self) - TREE_NO_WARNING (DECL_EXPR_DECL (*expr_p)) = 1; + suppress_warning (DECL_EXPR_DECL (*expr_p), OPT_Winit_self); break; case PREINCREMENT_EXPR: diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c index 6374b72..4b04e71 100644 --- a/gcc/c-family/c-lex.c +++ b/gcc/c-family/c-lex.c @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see #include "stor-layout.h" #include "c-pragma.h" #include "debug.h" +#include "flags.h" #include "file-prefix-map.h" /* remap_macro_filename() */ #include "langhooks.h" #include "attribs.h" @@ -87,8 +88,7 @@ init_c_lex (void) /* Set the debug callbacks if we can use them. */ if ((debug_info_level == DINFO_LEVEL_VERBOSE - && (write_symbols == DWARF2_DEBUG - || write_symbols == VMS_AND_DWARF2_DEBUG)) + && dwarf_debuginfo_p ()) || flag_dump_go_spec != NULL) { cb->define = cb_define; @@ -338,7 +338,20 @@ c_common_has_attribute (cpp_reader *pfile, bool std_syntax) tree attr_id = get_identifier ((const char *) cpp_token_as_text (pfile, nxt_token)); - attr_name = build_tree_list (attr_ns, attr_id); + attr_id = canonicalize_attr_name (attr_id); + if (c_dialect_cxx ()) + { + /* OpenMP attributes need special handling. */ + if ((flag_openmp || flag_openmp_simd) + && is_attribute_p ("omp", attr_ns) + && (is_attribute_p ("directive", attr_id) + || is_attribute_p ("sequence", attr_id))) + result = 1; + } + if (result) + attr_name = NULL_TREE; + else + attr_name = build_tree_list (attr_ns, attr_id); } else { @@ -1001,7 +1014,7 @@ interpret_float (const cpp_token *token, unsigned int flags, } copy = (char *) alloca (copylen + 1); - if (cxx_dialect > cxx11) + if (c_dialect_cxx () ? cxx_dialect > cxx11 : flag_isoc2x) { size_t maxlen = 0; for (size_t i = 0; i < copylen; ++i) diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index fb1a0d6..75184a3 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see #include "gimplify.h" #include "langhooks.h" #include "bitmap.h" +#include "gimple-fold.h" /* Complete a #pragma oacc wait construct. LOC is the location of @@ -86,6 +87,20 @@ c_finish_omp_master (location_t loc, tree stmt) return t; } +/* Complete a #pragma omp masked construct. BODY is the structured-block + that follows the pragma. LOC is the location of the #pragma. */ + +tree +c_finish_omp_masked (location_t loc, tree body, tree clauses) +{ + tree stmt = make_node (OMP_MASKED); + TREE_TYPE (stmt) = void_type_node; + OMP_MASKED_BODY (stmt) = body; + OMP_MASKED_CLAUSES (stmt) = clauses; + SET_EXPR_LOCATION (stmt, loc); + return add_stmt (stmt); +} + /* Complete a #pragma omp taskgroup construct. BODY is the structured-block that follows the pragma. LOC is the location of the #pragma. */ @@ -201,15 +216,17 @@ c_finish_omp_taskyield (location_t loc) tree c_finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode, tree lhs, tree rhs, - tree v, tree lhs1, tree rhs1, bool swapped, - enum omp_memory_order memory_order, bool test) + tree v, tree lhs1, tree rhs1, tree r, bool swapped, + enum omp_memory_order memory_order, bool weak, + bool test) { - tree x, type, addr, pre = NULL_TREE; + tree x, type, addr, pre = NULL_TREE, rtmp = NULL_TREE, vtmp = NULL_TREE; HOST_WIDE_INT bitpos = 0, bitsize = 0; + enum tree_code orig_opcode = opcode; if (lhs == error_mark_node || rhs == error_mark_node || v == error_mark_node || lhs1 == error_mark_node - || rhs1 == error_mark_node) + || rhs1 == error_mark_node || r == error_mark_node) return error_mark_node; /* ??? According to one reading of the OpenMP spec, complex type are @@ -229,6 +246,12 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, error_at (loc, "%<_Atomic%> expression in %<#pragma omp atomic%>"); return error_mark_node; } + if (r && r != void_list_node && !INTEGRAL_TYPE_P (TREE_TYPE (r))) + { + error_at (loc, "%<#pragma omp atomic compare capture%> with non-integral " + "comparison result"); + return error_mark_node; + } if (opcode == RDIV_EXPR) opcode = TRUNC_DIV_EXPR; @@ -285,6 +308,7 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, x = build1 (OMP_ATOMIC_READ, type, addr); SET_EXPR_LOCATION (x, loc); OMP_ATOMIC_MEMORY_ORDER (x) = memory_order; + gcc_assert (!weak); if (blhs) x = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), x, bitsize_int (bitsize), bitsize_int (bitpos)); @@ -299,12 +323,29 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, { lhs = build3_loc (loc, BIT_FIELD_REF, TREE_TYPE (blhs), lhs, bitsize_int (bitsize), bitsize_int (bitpos)); - if (swapped) + if (opcode == COND_EXPR) + { + bool save = in_late_binary_op; + in_late_binary_op = true; + std::swap (rhs, rhs1); + rhs1 = build_binary_op (loc, EQ_EXPR, lhs, rhs1, true); + in_late_binary_op = save; + } + else if (swapped) rhs = build_binary_op (loc, opcode, rhs, lhs, true); else if (opcode != NOP_EXPR) rhs = build_binary_op (loc, opcode, lhs, rhs, true); opcode = NOP_EXPR; } + else if (opcode == COND_EXPR) + { + bool save = in_late_binary_op; + in_late_binary_op = true; + std::swap (rhs, rhs1); + rhs1 = build_binary_op (loc, EQ_EXPR, lhs, rhs1, true); + in_late_binary_op = save; + opcode = NOP_EXPR; + } else if (swapped) { rhs = build_binary_op (loc, opcode, rhs, lhs, true); @@ -329,6 +370,100 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, if (blhs) rhs = build3_loc (loc, BIT_INSERT_EXPR, type, new_lhs, rhs, bitsize_int (bitpos)); + if (orig_opcode == COND_EXPR) + { + if (error_operand_p (rhs1)) + return error_mark_node; + gcc_assert (TREE_CODE (rhs1) == EQ_EXPR); + tree cmptype = TREE_TYPE (TREE_OPERAND (rhs1, 0)); + if (SCALAR_FLOAT_TYPE_P (cmptype)) + { + bool clear_padding = false; + if (BITS_PER_UNIT == 8 && CHAR_BIT == 8) + { + HOST_WIDE_INT sz = int_size_in_bytes (cmptype), i; + gcc_assert (sz > 0); + unsigned char *buf = XALLOCAVEC (unsigned char, sz); + memset (buf, ~0, sz); + clear_type_padding_in_mask (cmptype, buf); + for (i = 0; i < sz; i++) + if (buf[i] != (unsigned char) ~0) + { + clear_padding = true; + break; + } + } + tree inttype = NULL_TREE; + if (!clear_padding && tree_fits_uhwi_p (TYPE_SIZE (cmptype))) + { + HOST_WIDE_INT prec = tree_to_uhwi (TYPE_SIZE (cmptype)); + inttype = c_common_type_for_size (prec, 1); + if (inttype + && (!tree_int_cst_equal (TYPE_SIZE (cmptype), + TYPE_SIZE (inttype)) + || TYPE_PRECISION (inttype) != prec)) + inttype = NULL_TREE; + } + if (inttype) + { + TREE_OPERAND (rhs1, 0) + = build1_loc (loc, VIEW_CONVERT_EXPR, inttype, + TREE_OPERAND (rhs1, 0)); + TREE_OPERAND (rhs1, 1) + = build1_loc (loc, VIEW_CONVERT_EXPR, inttype, + TREE_OPERAND (rhs1, 1)); + } + else + { + tree pcmptype = build_pointer_type (cmptype); + tree tmp1 = create_tmp_var_raw (cmptype); + TREE_ADDRESSABLE (tmp1) = 1; + DECL_CONTEXT (tmp1) = current_function_decl; + tmp1 = build4 (TARGET_EXPR, cmptype, tmp1, + TREE_OPERAND (rhs1, 0), NULL, NULL); + tmp1 = build1 (ADDR_EXPR, pcmptype, tmp1); + tree tmp2 = create_tmp_var_raw (cmptype); + TREE_ADDRESSABLE (tmp2) = 1; + DECL_CONTEXT (tmp2) = current_function_decl; + tmp2 = build4 (TARGET_EXPR, cmptype, tmp2, + TREE_OPERAND (rhs1, 1), NULL, NULL); + tmp2 = build1 (ADDR_EXPR, pcmptype, tmp2); + tree fndecl = builtin_decl_explicit (BUILT_IN_MEMCMP); + rhs1 = build_call_expr_loc (loc, fndecl, 3, tmp1, tmp2, + TYPE_SIZE_UNIT (cmptype)); + rhs1 = build2 (EQ_EXPR, boolean_type_node, rhs1, + integer_zero_node); + if (clear_padding) + { + fndecl = builtin_decl_explicit (BUILT_IN_CLEAR_PADDING); + tree cp1 = build_call_expr_loc (loc, fndecl, 1, tmp1); + tree cp2 = build_call_expr_loc (loc, fndecl, 1, tmp2); + rhs1 = omit_two_operands_loc (loc, boolean_type_node, + rhs1, cp2, cp1); + } + } + } + if (r) + { + tree var = create_tmp_var (boolean_type_node); + DECL_CONTEXT (var) = current_function_decl; + rtmp = build4 (TARGET_EXPR, boolean_type_node, var, + NULL, NULL, NULL); + save = in_late_binary_op; + in_late_binary_op = true; + x = build_modify_expr (loc, var, NULL_TREE, NOP_EXPR, + loc, rhs1, NULL_TREE); + in_late_binary_op = save; + if (x == error_mark_node) + return error_mark_node; + gcc_assert (TREE_CODE (x) == MODIFY_EXPR + && TREE_OPERAND (x, 0) == var); + TREE_OPERAND (x, 0) = rtmp; + rhs1 = omit_one_operand_loc (loc, boolean_type_node, x, rtmp); + } + rhs = build3_loc (loc, COND_EXPR, type, rhs1, rhs, new_lhs); + rhs1 = NULL_TREE; + } /* Punt the actual generation of atomic operations to common code. */ if (code == OMP_ATOMIC) @@ -336,6 +471,7 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, x = build2 (code, type, addr, rhs); SET_EXPR_LOCATION (x, loc); OMP_ATOMIC_MEMORY_ORDER (x) = memory_order; + OMP_ATOMIC_WEAK (x) = weak; /* Generally it is hard to prove lhs1 and lhs are the same memory location, just diagnose different variables. */ @@ -398,8 +534,25 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, bitsize_int (bitsize), bitsize_int (bitpos)); type = TREE_TYPE (blhs); } - x = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR, + if (r) + { + vtmp = create_tmp_var (TREE_TYPE (x)); + DECL_CONTEXT (vtmp) = current_function_decl; + } + else + vtmp = v; + x = build_modify_expr (loc, vtmp, NULL_TREE, NOP_EXPR, loc, x, NULL_TREE); + if (x == error_mark_node) + return error_mark_node; + if (r) + { + vtmp = build4 (TARGET_EXPR, boolean_type_node, vtmp, + NULL, NULL, NULL); + gcc_assert (TREE_CODE (x) == MODIFY_EXPR + && TREE_OPERAND (x, 0) == TARGET_EXPR_SLOT (vtmp)); + TREE_OPERAND (x, 0) = vtmp; + } if (rhs1 && rhs1 != orig_lhs) { tree rhs1addr = build_unary_op (loc, ADDR_EXPR, rhs1, false); @@ -432,6 +585,28 @@ c_finish_omp_atomic (location_t loc, enum tree_code code, if (pre) x = omit_one_operand_loc (loc, type, x, pre); + if (r && r != void_list_node) + { + in_late_binary_op = true; + tree x2 = build_modify_expr (loc, r, NULL_TREE, NOP_EXPR, + loc, rtmp, NULL_TREE); + in_late_binary_op = save; + if (x2 == error_mark_node) + return error_mark_node; + x = omit_one_operand_loc (loc, TREE_TYPE (x2), x2, x); + } + if (v && vtmp != v) + { + in_late_binary_op = true; + tree x2 = build_modify_expr (loc, v, NULL_TREE, NOP_EXPR, + loc, vtmp, NULL_TREE); + in_late_binary_op = save; + if (x2 == error_mark_node) + return error_mark_node; + x2 = build3_loc (loc, COND_EXPR, void_type_node, rtmp, + void_node, x2); + x = omit_one_operand_loc (loc, TREE_TYPE (x2), x2, x); + } return x; } @@ -592,7 +767,7 @@ c_finish_omp_flush (location_t loc, int mo) { tree x; - if (mo == MEMMODEL_LAST) + if (mo == MEMMODEL_LAST || mo == MEMMODEL_SEQ_CST) { x = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE); x = build_call_expr_loc (loc, x, 0); @@ -1542,11 +1717,16 @@ c_oacc_split_loop_clauses (tree clauses, tree *not_loop_clauses, #pragma omp distribute parallel for simd #pragma omp distribute simd #pragma omp for simd + #pragma omp masked taskloop + #pragma omp masked taskloop simd #pragma omp master taskloop #pragma omp master taskloop simd #pragma omp parallel for #pragma omp parallel for simd #pragma omp parallel loop + #pragma omp parallel masked + #pragma omp parallel masked taskloop + #pragma omp parallel masked taskloop simd #pragma omp parallel master #pragma omp parallel master taskloop #pragma omp parallel master taskloop simd @@ -1651,6 +1831,9 @@ c_omp_split_clauses (location_t loc, enum tree_code code, case OMP_CLAUSE_BIND: s = C_OMP_CLAUSE_SPLIT_LOOP; break; + case OMP_CLAUSE_FILTER: + s = C_OMP_CLAUSE_SPLIT_MASKED; + break; /* Duplicate this to all of taskloop, distribute, for, simd and loop. */ case OMP_CLAUSE_COLLAPSE: @@ -1700,10 +1883,10 @@ c_omp_split_clauses (location_t loc, enum tree_code code, else s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; break; - /* Private clause is supported on all constructs but master, - it is enough to put it on the innermost one other than master. For - #pragma omp {for,sections} put it on parallel though, - as that's what we did for OpenMP 3.1. */ + /* Private clause is supported on all constructs but master/masked, + it is enough to put it on the innermost one other than + master/masked. For #pragma omp {for,sections} put it on parallel + though, as that's what we did for OpenMP 3.1. */ case OMP_CLAUSE_PRIVATE: switch (code) { @@ -1713,14 +1896,15 @@ c_omp_split_clauses (location_t loc, enum tree_code code, case OMP_DISTRIBUTE: s = C_OMP_CLAUSE_SPLIT_DISTRIBUTE; break; case OMP_TEAMS: s = C_OMP_CLAUSE_SPLIT_TEAMS; break; case OMP_MASTER: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break; + case OMP_MASKED: s = C_OMP_CLAUSE_SPLIT_PARALLEL; break; case OMP_TASKLOOP: s = C_OMP_CLAUSE_SPLIT_TASKLOOP; break; case OMP_LOOP: s = C_OMP_CLAUSE_SPLIT_LOOP; break; default: gcc_unreachable (); } break; /* Firstprivate clause is supported on all constructs but - simd, master and loop. Put it on the outermost of those and - duplicate on teams and parallel. */ + simd, master, masked and loop. Put it on the outermost of those + and duplicate on teams and parallel. */ case OMP_CLAUSE_FIRSTPRIVATE: if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0) @@ -1733,10 +1917,21 @@ c_omp_split_clauses (location_t loc, enum tree_code code, { /* This must be #pragma omp target simd. */ s = C_OMP_CLAUSE_SPLIT_TARGET; + OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (clauses) = 1; + OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (clauses) = 1; break; } c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), OMP_CLAUSE_FIRSTPRIVATE); + /* firstprivate should not be applied to target if it is + also lastprivate or on the combined/composite construct, + or if it is mentioned in map clause. OMP_CLAUSE_DECLs + may need to go through FE handling though (instantiation, + C++ non-static data members, array section lowering), so + add the clause with OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT and + let *finish_omp_clauses and the gimplifier handle it + right. */ + OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) = 1; OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses); OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET]; cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c; @@ -1762,7 +1957,7 @@ c_omp_split_clauses (location_t loc, enum tree_code code, else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0) /* This must be - #pragma omp parallel master taskloop{, simd}. */ + #pragma omp parallel mas{ked,ter} taskloop{, simd}. */ s = C_OMP_CLAUSE_SPLIT_TASKLOOP; else /* This must be @@ -1794,9 +1989,10 @@ c_omp_split_clauses (location_t loc, enum tree_code code, else if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP)) != 0) { - /* This must be #pragma omp {,{,parallel }master }taskloop simd + /* This must be + #pragma omp {,{,parallel }mas{ked,ter} }taskloop simd or - #pragma omp {,parallel }master taskloop. */ + #pragma omp {,parallel }mas{ked,ter} taskloop. */ gcc_assert (code == OMP_SIMD || code == OMP_TASKLOOP); s = C_OMP_CLAUSE_SPLIT_TASKLOOP; } @@ -1978,6 +2174,16 @@ c_omp_split_clauses (location_t loc, enum tree_code code, "%<parallel for%>, %<parallel for simd%>"); OMP_CLAUSE_REDUCTION_INSCAN (clauses) = 0; } + if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0) + { + c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), + OMP_CLAUSE_MAP); + OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses); + OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM); + OMP_CLAUSE_MAP_IMPLICIT (c) = 1; + OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET]; + cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c; + } if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE)) != 0) { if (code == OMP_SIMD) @@ -2023,7 +2229,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code, } else if (code == OMP_SECTIONS || code == OMP_PARALLEL - || code == OMP_MASTER) + || code == OMP_MASTER + || code == OMP_MASKED) s = C_OMP_CLAUSE_SPLIT_PARALLEL; else if (code == OMP_TASKLOOP) s = C_OMP_CLAUSE_SPLIT_TASKLOOP; @@ -2048,12 +2255,42 @@ c_omp_split_clauses (location_t loc, enum tree_code code, OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP]; cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP] = c; } + else if ((mask & (OMP_CLAUSE_MASK_1 + << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) != 0) + { + c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), + OMP_CLAUSE_REDUCTION); + OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses); + OMP_CLAUSE_REDUCTION_CODE (c) + = OMP_CLAUSE_REDUCTION_CODE (clauses); + OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) + = OMP_CLAUSE_REDUCTION_PLACEHOLDER (clauses); + OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) + = OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (clauses); + OMP_CLAUSE_REDUCTION_INSCAN (c) + = OMP_CLAUSE_REDUCTION_INSCAN (clauses); + OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS]; + cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] = c; + } s = C_OMP_CLAUSE_SPLIT_SIMD; } else s = C_OMP_CLAUSE_SPLIT_TEAMS; break; case OMP_CLAUSE_IN_REDUCTION: + if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0) + { + /* When on target, map(always, tofrom: item) is added as + well. For non-combined target it is added in the FEs. */ + c = build_omp_clause (OMP_CLAUSE_LOCATION (clauses), + OMP_CLAUSE_MAP); + OMP_CLAUSE_DECL (c) = OMP_CLAUSE_DECL (clauses); + OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_TOFROM); + OMP_CLAUSE_CHAIN (c) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET]; + cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = c; + s = C_OMP_CLAUSE_SPLIT_TARGET; + break; + } /* in_reduction on taskloop simd becomes reduction on the simd and keeps being in_reduction on taskloop. */ if (code == OMP_SIMD) @@ -2404,7 +2641,8 @@ c_omp_split_clauses (location_t loc, enum tree_code code, gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TARGET] == NULL_TREE); if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS)) == 0) gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_TEAMS] == NULL_TREE); - if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0) + if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0 + && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)) == 0) gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE] == NULL_TREE); if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) == 0) gcc_assert (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] == NULL_TREE); @@ -2861,3 +3099,154 @@ c_omp_adjust_map_clauses (tree clauses, bool is_target) } } } + +static const struct c_omp_directive omp_directives[] = { + /* Keep this alphabetically sorted by the first word. Non-null second/third + if any should precede null ones. */ + { "allocate", nullptr, nullptr, PRAGMA_OMP_ALLOCATE, + C_OMP_DIR_DECLARATIVE, false }, + /* { "assume", nullptr, nullptr, PRAGMA_OMP_ASSUME, + C_OMP_DIR_INFORMATIONAL, false }, */ + /* { "assumes", nullptr, nullptr, PRAGMA_OMP_ASSUMES, + C_OMP_DIR_INFORMATIONAL, false }, */ + { "atomic", nullptr, nullptr, PRAGMA_OMP_ATOMIC, + C_OMP_DIR_CONSTRUCT, false }, + { "barrier", nullptr, nullptr, PRAGMA_OMP_BARRIER, + C_OMP_DIR_STANDALONE, false }, + /* { "begin", "assumes", nullptr, PRAGMA_OMP_BEGIN, + C_OMP_DIR_INFORMATIONAL, false }, */ + /* { "begin", "declare", "target", PRAGMA_OMP_BEGIN, + C_OMP_DIR_DECLARATIVE, false }, */ + /* { "begin", "declare", "variant", PRAGMA_OMP_BEGIN, + C_OMP_DIR_DECLARATIVE, false }, */ + /* { "begin", "metadirective", nullptr, PRAGMA_OMP_BEGIN, + C_OMP_DIR_???, ??? }, */ + { "cancel", nullptr, nullptr, PRAGMA_OMP_CANCEL, + C_OMP_DIR_STANDALONE, false }, + { "cancellation", "point", nullptr, PRAGMA_OMP_CANCELLATION_POINT, + C_OMP_DIR_STANDALONE, false }, + { "critical", nullptr, nullptr, PRAGMA_OMP_CRITICAL, + C_OMP_DIR_CONSTRUCT, false }, + /* { "declare", "mapper", nullptr, PRAGMA_OMP_DECLARE, + C_OMP_DIR_DECLARATIVE, false }, */ + { "declare", "reduction", nullptr, PRAGMA_OMP_DECLARE, + C_OMP_DIR_DECLARATIVE, true }, + { "declare", "simd", nullptr, PRAGMA_OMP_DECLARE, + C_OMP_DIR_DECLARATIVE, true }, + { "declare", "target", nullptr, PRAGMA_OMP_DECLARE, + C_OMP_DIR_DECLARATIVE, false }, + { "declare", "variant", nullptr, PRAGMA_OMP_DECLARE, + C_OMP_DIR_DECLARATIVE, false }, + { "depobj", nullptr, nullptr, PRAGMA_OMP_DEPOBJ, + C_OMP_DIR_STANDALONE, false }, + /* { "dispatch", nullptr, nullptr, PRAGMA_OMP_DISPATCH, + C_OMP_DIR_CONSTRUCT, false }, */ + { "distribute", nullptr, nullptr, PRAGMA_OMP_DISTRIBUTE, + C_OMP_DIR_CONSTRUCT, true }, + /* { "end", "assumes", nullptr, PRAGMA_OMP_END, + C_OMP_DIR_INFORMATIONAL, false }, */ + { "end", "declare", "target", PRAGMA_OMP_END_DECLARE_TARGET, + C_OMP_DIR_DECLARATIVE, false }, + /* { "end", "declare", "variant", PRAGMA_OMP_END, + C_OMP_DIR_DECLARATIVE, false }, */ + /* { "end", "metadirective", nullptr, PRAGMA_OMP_END, + C_OMP_DIR_???, ??? }, */ + /* error with at(execution) is C_OMP_DIR_STANDALONE. */ + { "error", nullptr, nullptr, PRAGMA_OMP_ERROR, + C_OMP_DIR_UTILITY, false }, + { "flush", nullptr, nullptr, PRAGMA_OMP_FLUSH, + C_OMP_DIR_STANDALONE, false }, + { "for", nullptr, nullptr, PRAGMA_OMP_FOR, + C_OMP_DIR_CONSTRUCT, true }, + /* { "interop", nullptr, nullptr, PRAGMA_OMP_INTEROP, + C_OMP_DIR_STANDALONE, false }, */ + { "loop", nullptr, nullptr, PRAGMA_OMP_LOOP, + C_OMP_DIR_CONSTRUCT, true }, + { "masked", nullptr, nullptr, PRAGMA_OMP_MASKED, + C_OMP_DIR_CONSTRUCT, true }, + { "master", nullptr, nullptr, PRAGMA_OMP_MASTER, + C_OMP_DIR_CONSTRUCT, true }, + /* { "metadirective", nullptr, nullptr, PRAGMA_OMP_METADIRECTIVE, + C_OMP_DIR_???, ??? }, */ + { "nothing", nullptr, nullptr, PRAGMA_OMP_NOTHING, + C_OMP_DIR_UTILITY, false }, + /* ordered with depend clause is C_OMP_DIR_STANDALONE. */ + { "ordered", nullptr, nullptr, PRAGMA_OMP_ORDERED, + C_OMP_DIR_CONSTRUCT, true }, + { "parallel", nullptr, nullptr, PRAGMA_OMP_PARALLEL, + C_OMP_DIR_CONSTRUCT, true }, + { "requires", nullptr, nullptr, PRAGMA_OMP_REQUIRES, + C_OMP_DIR_INFORMATIONAL, false }, + { "scan", nullptr, nullptr, PRAGMA_OMP_SCAN, + C_OMP_DIR_CONSTRUCT, true }, + { "scope", nullptr, nullptr, PRAGMA_OMP_SCOPE, + C_OMP_DIR_CONSTRUCT, false }, + { "section", nullptr, nullptr, PRAGMA_OMP_SECTION, + C_OMP_DIR_CONSTRUCT, false }, + { "sections", nullptr, nullptr, PRAGMA_OMP_SECTIONS, + C_OMP_DIR_CONSTRUCT, false }, + { "simd", nullptr, nullptr, PRAGMA_OMP_SIMD, + C_OMP_DIR_CONSTRUCT, true }, + { "single", nullptr, nullptr, PRAGMA_OMP_SINGLE, + C_OMP_DIR_CONSTRUCT, false }, + { "target", "data", nullptr, PRAGMA_OMP_TARGET, + C_OMP_DIR_CONSTRUCT, false }, + { "target", "enter", "data", PRAGMA_OMP_TARGET, + C_OMP_DIR_STANDALONE, false }, + { "target", "exit", "data", PRAGMA_OMP_TARGET, + C_OMP_DIR_STANDALONE, false }, + { "target", "update", nullptr, PRAGMA_OMP_TARGET, + C_OMP_DIR_STANDALONE, false }, + { "target", nullptr, nullptr, PRAGMA_OMP_TARGET, + C_OMP_DIR_CONSTRUCT, true }, + { "task", nullptr, nullptr, PRAGMA_OMP_TASK, + C_OMP_DIR_CONSTRUCT, false }, + { "taskgroup", nullptr, nullptr, PRAGMA_OMP_TASKGROUP, + C_OMP_DIR_CONSTRUCT, false }, + { "taskloop", nullptr, nullptr, PRAGMA_OMP_TASKLOOP, + C_OMP_DIR_CONSTRUCT, true }, + { "taskwait", nullptr, nullptr, PRAGMA_OMP_TASKWAIT, + C_OMP_DIR_STANDALONE, false }, + { "taskyield", nullptr, nullptr, PRAGMA_OMP_TASKYIELD, + C_OMP_DIR_STANDALONE, false }, + /* { "tile", nullptr, nullptr, PRAGMA_OMP_TILE, + C_OMP_DIR_CONSTRUCT, false }, */ + { "teams", nullptr, nullptr, PRAGMA_OMP_TEAMS, + C_OMP_DIR_CONSTRUCT, true }, + { "threadprivate", nullptr, nullptr, PRAGMA_OMP_THREADPRIVATE, + C_OMP_DIR_DECLARATIVE, false } + /* { "unroll", nullptr, nullptr, PRAGMA_OMP_UNROLL, + C_OMP_DIR_CONSTRUCT, false }, */ +}; + +/* Find (non-combined/composite) OpenMP directive (if any) which starts + with FIRST keyword and for multi-word directives has SECOND and + THIRD keyword after it. */ + +const struct c_omp_directive * +c_omp_categorize_directive (const char *first, const char *second, + const char *third) +{ + const size_t n_omp_directives = ARRAY_SIZE (omp_directives); + for (size_t i = 0; i < n_omp_directives; i++) + { + if ((unsigned char) omp_directives[i].first[0] + < (unsigned char) first[0]) + continue; + if ((unsigned char) omp_directives[i].first[0] + > (unsigned char) first[0]) + break; + if (strcmp (omp_directives[i].first, first)) + continue; + if (!omp_directives[i].second) + return &omp_directives[i]; + if (!second || strcmp (omp_directives[i].second, second)) + continue; + if (!omp_directives[i].third) + return &omp_directives[i]; + if (!third || strcmp (omp_directives[i].third, third)) + continue; + return &omp_directives[i]; + } + return NULL; +} diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c index bd15b9c..fdde082 100644 --- a/gcc/c-family/c-opts.c +++ b/gcc/c-family/c-opts.c @@ -188,6 +188,14 @@ c_common_diagnostics_set_defaults (diagnostic_context *context) context->opt_permissive = OPT_fpermissive; } +/* Input charset configuration for diagnostics. */ +static const char * +c_common_input_charset_cb (const char * /*filename*/) +{ + const char *cs = cpp_opts->input_charset; + return cpp_input_conversion_is_trivial (cs) ? nullptr : cs; +} + /* Whether options from all C-family languages should be accepted quietly. */ static bool accept_all_c_family_options = false; @@ -852,9 +860,9 @@ c_common_post_options (const char **pfilename) else if (!flag_gnu89_inline && !flag_isoc99) error ("%<-fno-gnu89-inline%> is only supported in GNU99 or C99 mode"); - /* Default to ObjC sjlj exception handling if NeXT runtime. */ + /* Default to ObjC sjlj exception handling if NeXT runtime < v2. */ if (flag_objc_sjlj_exceptions < 0) - flag_objc_sjlj_exceptions = flag_next_runtime; + flag_objc_sjlj_exceptions = (flag_next_runtime && flag_objc_abi < 2); if (flag_objc_exceptions && !flag_objc_sjlj_exceptions) flag_exceptions = 1; @@ -965,7 +973,7 @@ c_common_post_options (const char **pfilename) /* Change flag_abi_version to be the actual current ABI level, for the benefit of c_cpp_builtins, and to make comparison simpler. */ - const int latest_abi_version = 15; + const int latest_abi_version = 16; /* Generate compatibility aliases for ABI v11 (7.1) by default. */ const int abi_compat_default = 11; @@ -1015,6 +1023,10 @@ c_common_post_options (const char **pfilename) SET_OPTION_IF_UNSET (&global_options, &global_options_set, flag_finite_loops, optimize >= 2 && cxx_dialect >= cxx11); + /* It's OK to discard calls to pure/const functions that might throw. */ + SET_OPTION_IF_UNSET (&global_options, &global_options_set, + flag_delete_dead_exceptions, true); + if (cxx_dialect >= cxx11) { /* If we're allowing C++0x constructs, don't warn about C++98 @@ -1112,9 +1124,10 @@ c_common_post_options (const char **pfilename) /* Only -g0 and -gdwarf* are supported with PCH, for other debug formats we warn here and refuse to load any PCH files. */ if (write_symbols != NO_DEBUG && write_symbols != DWARF2_DEBUG) - warning (OPT_Wdeprecated, - "the %qs debug format cannot be used with " - "pre-compiled headers", debug_type_names[write_symbols]); + warning (OPT_Wdeprecated, + "the %qs debug info cannot be used with " + "pre-compiled headers", + debug_set_names (write_symbols & ~DWARF2_DEBUG)); } else if (write_symbols != NO_DEBUG && write_symbols != DWARF2_DEBUG) c_common_no_more_pch (); @@ -1131,6 +1144,11 @@ c_common_post_options (const char **pfilename) cpp_post_options (parse_in); init_global_opts_from_cpp (&global_options, cpp_get_options (parse_in)); + /* Let diagnostics infrastructure know how to convert input files the same + way libcpp will do it, namely using the configured input charset and + skipping a UTF-8 BOM if present. */ + diagnostic_initialize_input_context (global_dc, + c_common_input_charset_cb, true); input_location = UNKNOWN_LOCATION; *pfilename = this_input_filename diff --git a/gcc/c-family/c-pch.c b/gcc/c-family/c-pch.c index fd94c37..5da6042 100644 --- a/gcc/c-family/c-pch.c +++ b/gcc/c-family/c-pch.c @@ -52,7 +52,7 @@ enum { struct c_pch_validity { - unsigned char debug_info_type; + uint32_t pch_write_symbols; signed char match[MATCH_SIZE]; void (*pch_init) (void); size_t target_data_length; @@ -108,7 +108,7 @@ pch_init (void) pch_outfile = f; memset (&v, '\0', sizeof (v)); - v.debug_info_type = write_symbols; + v.pch_write_symbols = write_symbols; { size_t i; for (i = 0; i < MATCH_SIZE; i++) @@ -252,13 +252,16 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd) /* The allowable debug info combinations are that either the PCH file was built with the same as is being used now, or the PCH file was built for some kind of debug info but now none is in use. */ - if (v.debug_info_type != write_symbols + if (v.pch_write_symbols != write_symbols && write_symbols != NO_DEBUG) { + char *created_str = xstrdup (debug_set_names (v.pch_write_symbols)); + char *used_str = xstrdup (debug_set_names (write_symbols)); cpp_warning (pfile, CPP_W_INVALID_PCH, - "%s: created with -g%s, but used with -g%s", name, - debug_type_names[v.debug_info_type], - debug_type_names[write_symbols]); + "%s: created with '%s' debug info, but used with '%s'", name, + created_str, used_str); + free (created_str); + free (used_str); return 2; } diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c index 4f8e8e0..a9be8df 100644 --- a/gcc/c-family/c-pragma.c +++ b/gcc/c-family/c-pragma.c @@ -918,6 +918,12 @@ handle_pragma_target(cpp_reader *ARG_UNUSED(dummy)) if (targetm.target_option.pragma_parse (args, NULL_TREE)) current_target_pragma = chainon (current_target_pragma, args); + + /* A target pragma can also influence optimization options. */ + tree current_optimize + = build_optimization_node (&global_options, &global_options_set); + if (current_optimize != optimization_current_node) + optimization_current_node = current_optimize; } } @@ -1078,12 +1084,16 @@ handle_pragma_pop_options (cpp_reader *ARG_UNUSED(dummy)) target_option_current_node = p->target_binary; } + /* Always restore optimization options as optimization_current_node is + * overwritten by invoke_set_current_function_hook. */ + cl_optimization_restore (&global_options, &global_options_set, + TREE_OPTIMIZATION (p->optimize_binary)); + cl_target_option_restore (&global_options, &global_options_set, + TREE_TARGET_OPTION (p->target_binary)); + if (p->optimize_binary != optimization_current_node) { - tree old_optimize = optimization_current_node; - cl_optimization_restore (&global_options, &global_options_set, - TREE_OPTIMIZATION (p->optimize_binary)); - c_cpp_builtins_optimize_pragma (parse_in, old_optimize, + c_cpp_builtins_optimize_pragma (parse_in, optimization_current_node, p->optimize_binary); optimization_current_node = p->optimize_binary; } @@ -1316,9 +1326,12 @@ static const struct omp_pragma_def omp_pragmas[] = { { "cancellation", PRAGMA_OMP_CANCELLATION_POINT }, { "critical", PRAGMA_OMP_CRITICAL }, { "depobj", PRAGMA_OMP_DEPOBJ }, + { "error", PRAGMA_OMP_ERROR }, { "end", PRAGMA_OMP_END_DECLARE_TARGET }, { "flush", PRAGMA_OMP_FLUSH }, + { "nothing", PRAGMA_OMP_NOTHING }, { "requires", PRAGMA_OMP_REQUIRES }, + { "scope", PRAGMA_OMP_SCOPE }, { "section", PRAGMA_OMP_SECTION }, { "sections", PRAGMA_OMP_SECTIONS }, { "single", PRAGMA_OMP_SINGLE }, @@ -1333,6 +1346,7 @@ static const struct omp_pragma_def omp_pragmas_simd[] = { { "distribute", PRAGMA_OMP_DISTRIBUTE }, { "for", PRAGMA_OMP_FOR }, { "loop", PRAGMA_OMP_LOOP }, + { "masked", PRAGMA_OMP_MASKED }, { "master", PRAGMA_OMP_MASTER }, { "ordered", PRAGMA_OMP_ORDERED }, { "parallel", PRAGMA_OMP_PARALLEL }, diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index 6c34ffa..0c5b07a 100644 --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -42,7 +42,9 @@ enum pragma_kind { PRAGMA_OACC_UPDATE, PRAGMA_OACC_WAIT, + /* PRAGMA_OMP__START_ should be equal to the first PRAGMA_OMP_* code. */ PRAGMA_OMP_ALLOCATE, + PRAGMA_OMP__START_ = PRAGMA_OMP_ALLOCATE, PRAGMA_OMP_ATOMIC, PRAGMA_OMP_BARRIER, PRAGMA_OMP_CANCEL, @@ -51,15 +53,19 @@ enum pragma_kind { PRAGMA_OMP_DECLARE, PRAGMA_OMP_DEPOBJ, PRAGMA_OMP_DISTRIBUTE, + PRAGMA_OMP_ERROR, PRAGMA_OMP_END_DECLARE_TARGET, PRAGMA_OMP_FLUSH, PRAGMA_OMP_FOR, PRAGMA_OMP_LOOP, + PRAGMA_OMP_NOTHING, + PRAGMA_OMP_MASKED, PRAGMA_OMP_MASTER, PRAGMA_OMP_ORDERED, PRAGMA_OMP_PARALLEL, PRAGMA_OMP_REQUIRES, PRAGMA_OMP_SCAN, + PRAGMA_OMP_SCOPE, PRAGMA_OMP_SECTION, PRAGMA_OMP_SECTIONS, PRAGMA_OMP_SIMD, @@ -72,6 +78,8 @@ enum pragma_kind { PRAGMA_OMP_TASKYIELD, PRAGMA_OMP_THREADPRIVATE, PRAGMA_OMP_TEAMS, + /* PRAGMA_OMP__LAST_ should be equal to the last PRAGMA_OMP_* code. */ + PRAGMA_OMP__LAST_ = PRAGMA_OMP_TEAMS, PRAGMA_GCC_PCH_PREPROCESS, PRAGMA_IVDEP, @@ -86,6 +94,7 @@ enum pragma_kind { enum pragma_omp_clause { PRAGMA_OMP_CLAUSE_NONE = 0, + PRAGMA_OMP_CLAUSE_AFFINITY, PRAGMA_OMP_CLAUSE_ALIGNED, PRAGMA_OMP_CLAUSE_ALLOCATE, PRAGMA_OMP_CLAUSE_BIND, @@ -99,6 +108,7 @@ enum pragma_omp_clause { PRAGMA_OMP_CLAUSE_DEVICE, PRAGMA_OMP_CLAUSE_DEVICE_TYPE, PRAGMA_OMP_CLAUSE_DIST_SCHEDULE, + PRAGMA_OMP_CLAUSE_FILTER, PRAGMA_OMP_CLAUSE_FINAL, PRAGMA_OMP_CLAUSE_FIRSTPRIVATE, PRAGMA_OMP_CLAUSE_FOR, @@ -159,6 +169,7 @@ enum pragma_omp_clause { PRAGMA_OACC_CLAUSE_HOST, PRAGMA_OACC_CLAUSE_INDEPENDENT, PRAGMA_OACC_CLAUSE_NO_CREATE, + PRAGMA_OACC_CLAUSE_NOHOST, PRAGMA_OACC_CLAUSE_NUM_GANGS, PRAGMA_OACC_CLAUSE_NUM_WORKERS, PRAGMA_OACC_CLAUSE_PRESENT, diff --git a/gcc/c-family/c-target.def b/gcc/c-family/c-target.def index f2a1b7e..164f1b3 100644 --- a/gcc/c-family/c-target.def +++ b/gcc/c-family/c-target.def @@ -43,73 +43,73 @@ DEFHOOK DEFHOOK (objc_construct_string_object, - "Targets may provide a string object type that can be used within\ - and between C, C++ and their respective Objective-C dialects.\ - A string object might, for example, embed encoding and length information.\ - These objects are considered opaque to the compiler and handled as references.\ - An ideal implementation makes the composition of the string object\ - match that of the Objective-C @code{NSString} (@code{NXString} for GNUStep),\ - allowing efficient interworking between C-only and Objective-C code.\ - If a target implements string objects then this hook should return a\ - reference to such an object constructed from the normal `C' string\ - representation provided in @var{string}.\ - At present, the hook is used by Objective-C only, to obtain a\ + "Targets may provide a string object type that can be used within\n\ +and between C, C++ and their respective Objective-C dialects.\n\ +A string object might, for example, embed encoding and length information.\n\ +These objects are considered opaque to the compiler and handled as references.\n\ +An ideal implementation makes the composition of the string object\n\ +match that of the Objective-C @code{NSString} (@code{NXString} for GNUStep),\n\ +allowing efficient interworking between C-only and Objective-C code.\n\ +If a target implements string objects then this hook should return a\n\ +reference to such an object constructed from the normal `C' string\n\ +representation provided in @var{string}.\n\ +At present, the hook is used by Objective-C only, to obtain a\n\ common-format string object when the target provides one.", tree, (tree string), NULL) DEFHOOK (objc_declare_unresolved_class_reference, - "Declare that Objective C class @var{classname} is referenced\ - by the current TU.", + "Declare that Objective C class @var{classname} is referenced\n\ +by the current TU.", void, (const char *classname), NULL) DEFHOOK (objc_declare_class_definition, - "Declare that Objective C class @var{classname} is defined\ - by the current TU.", + "Declare that Objective C class @var{classname} is defined\n\ +by the current TU.", void, (const char *classname), NULL) DEFHOOK (string_object_ref_type_p, - "If a target implements string objects then this hook should return\ - @code{true} if @var{stringref} is a valid reference to such an object.", + "If a target implements string objects then this hook should return\n\ +@code{true} if @var{stringref} is a valid reference to such an object.", bool, (const_tree stringref), hook_bool_const_tree_false) DEFHOOK (check_string_object_format_arg, - "If a target implements string objects then this hook should should\ - provide a facility to check the function arguments in @var{args_list}\ - against the format specifiers in @var{format_arg} where the type of\ - @var{format_arg} is one recognized as a valid string reference type.", + "If a target implements string objects then this hook should should\n\ +provide a facility to check the function arguments in @var{args_list}\n\ +against the format specifiers in @var{format_arg} where the type of\n\ +@var{format_arg} is one recognized as a valid string reference type.", void, (tree format_arg, tree args_list), NULL) DEFHOOK (c_preinclude, - "Define this hook to return the name of a header file to be included at\ - the start of all compilations, as if it had been included with\ - @code{#include <@var{file}>}. If this hook returns @code{NULL}, or is\ - not defined, or the header is not found, or if the user specifies\ - @option{-ffreestanding} or @option{-nostdinc}, no header is included.\n\ + "Define this hook to return the name of a header file to be included at\n\ +the start of all compilations, as if it had been included with\n\ +@code{#include <@var{file}>}. If this hook returns @code{NULL}, or is\n\ +not defined, or the header is not found, or if the user specifies\n\ +@option{-ffreestanding} or @option{-nostdinc}, no header is included.\n\ \n\ - This hook can be used together with a header provided by the system C\ - library to implement ISO C requirements for certain macros to be\ - predefined that describe properties of the whole implementation rather\ - than just the compiler.", +This hook can be used together with a header provided by the system C\n\ +library to implement ISO C requirements for certain macros to be\n\ +predefined that describe properties of the whole implementation rather\n\ +than just the compiler.", const char *, (void), hook_constcharptr_void_null) DEFHOOK (cxx_implicit_extern_c, - "Define this hook to add target-specific C++ implicit extern C functions.\ - If this function returns true for the name of a file-scope function, that\ - function implicitly gets extern \"C\" linkage rather than whatever language\ - linkage the declaration would normally have. An example of such function\ - is WinMain on Win32 targets.", + "Define this hook to add target-specific C++ implicit extern C functions.\n\ +If this function returns true for the name of a file-scope function, that\n\ +function implicitly gets extern \"C\" linkage rather than whatever language\n\ +linkage the declaration would normally have. An example of such function\n\ +is WinMain on Win32 targets.", bool, (const char*), NULL) diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c index 2347e0b..84ad663 100644 --- a/gcc/c-family/c-warn.c +++ b/gcc/c-family/c-warn.c @@ -155,7 +155,7 @@ overflow_warning (location_t loc, tree value, tree expr) value); if (warned) - TREE_NO_WARNING (value) = 1; + suppress_warning (value, OPT_Woverflow); } /* Helper function for walk_tree. Unwrap C_MAYBE_CONST_EXPRs in an expression @@ -219,7 +219,7 @@ warn_logical_operator (location_t location, enum tree_code code, tree type, && INTEGRAL_TYPE_P (TREE_TYPE (op_left)) && !CONSTANT_CLASS_P (stripped_op_left) && TREE_CODE (stripped_op_left) != CONST_DECL - && !TREE_NO_WARNING (op_left) + && !warning_suppressed_p (op_left, OPT_Wlogical_op) && TREE_CODE (op_right) == INTEGER_CST && !integer_zerop (op_right) && !integer_onep (op_right)) @@ -234,7 +234,7 @@ warn_logical_operator (location_t location, enum tree_code code, tree type, = warning_at (location, OPT_Wlogical_op, "logical %<and%> applied to non-boolean constant"); if (warned) - TREE_NO_WARNING (op_left) = true; + suppress_warning (op_left, OPT_Wlogical_op); return; } @@ -588,7 +588,7 @@ bool warn_if_unused_value (const_tree exp, location_t locus, bool quiet) { restart: - if (TREE_USED (exp) || TREE_NO_WARNING (exp)) + if (TREE_USED (exp) || warning_suppressed_p (exp, OPT_Wunused_value)) return false; /* Don't warn about void constructs. This includes casting to void, @@ -2240,18 +2240,6 @@ warn_for_sign_compare (location_t location, int op1_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op1)); int unsignedp0, unsignedp1; - /* In C++, check for comparison of different enum types. */ - if (c_dialect_cxx() - && TREE_CODE (TREE_TYPE (orig_op0)) == ENUMERAL_TYPE - && TREE_CODE (TREE_TYPE (orig_op1)) == ENUMERAL_TYPE - && TYPE_MAIN_VARIANT (TREE_TYPE (orig_op0)) - != TYPE_MAIN_VARIANT (TREE_TYPE (orig_op1))) - { - warning_at (location, - OPT_Wsign_compare, "comparison between types %qT and %qT", - TREE_TYPE (orig_op0), TREE_TYPE (orig_op1)); - } - /* Do not warn if the comparison is being done in a signed type, since the signed type will only be chosen if it can represent all the values of the unsigned type. */ @@ -2394,7 +2382,7 @@ do_warn_double_promotion (tree result_type, tree type1, tree type2, warn about it. */ if (c_inhibit_evaluation_warnings) return; - /* If an invalid conversion has occured, don't warn. */ + /* If an invalid conversion has occurred, don't warn. */ if (result_type == error_mark_node) return; if (TYPE_MAIN_VARIANT (result_type) != double_type_node @@ -2422,7 +2410,7 @@ do_warn_unused_parameter (tree fn) decl; decl = DECL_CHAIN (decl)) if (!TREE_USED (decl) && TREE_CODE (decl) == PARM_DECL && DECL_NAME (decl) && !DECL_ARTIFICIAL (decl) - && !TREE_NO_WARNING (decl)) + && !warning_suppressed_p (decl, OPT_Wunused_parameter)) warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wunused_parameter, "unused parameter %qD", decl); } @@ -2779,7 +2767,8 @@ do_warn_duplicated_branches (tree expr) /* Compare the hashes. */ if (h0 == h1 - && operand_equal_p (thenb, elseb, OEP_LEXICOGRAPHIC) + && operand_equal_p (thenb, elseb, OEP_LEXICOGRAPHIC + | OEP_ADDRESS_OF_SAME_FIELD) /* Don't warn if any of the branches or their subexpressions comes from a macro. */ && !walk_tree_without_duplicates (&thenb, expr_from_macro_expansion_r, @@ -2899,7 +2888,7 @@ warn_for_multistatement_macros (location_t body_loc, location_t next_loc, "this %qs clause", guard_tinfo_to_string (keyword)); } -/* Return struct or union type if the alignment of data memeber, FIELD, +/* Return struct or union type if the alignment of data member, FIELD, is less than the alignment of TYPE. Otherwise, return NULL_TREE. If RVALUE is true, only arrays evaluate to pointers. */ @@ -3150,7 +3139,7 @@ vla_bound_parm_decl (tree expr) } /* Diagnose mismatches in VLA bounds between function parameters NEWPARMS - of pointer types on a redeclaration os a function previously declared + of pointer types on a redeclaration of a function previously declared with CURPARMS at ORIGLOC. */ static void @@ -3219,7 +3208,7 @@ warn_parm_ptrarray_mismatch (location_t origloc, tree curparms, tree newparms) if (origloc == UNKNOWN_LOCATION) origloc = newloc; - /* Issue -Warray-parameter onless one or more mismatches involves + /* Issue -Warray-parameter unless one or more mismatches involves a VLA bound; then issue -Wvla-parameter. */ int opt = OPT_Warray_parameter_; /* Traverse the two array types looking for variable bounds and @@ -3286,7 +3275,8 @@ warn_parm_ptrarray_mismatch (location_t origloc, tree curparms, tree newparms) /* Move on if the bounds look the same. */ if (!pcurbndpos && !pnewbndpos && curbnd && newbnd - && operand_equal_p (curbnd, newbnd, OEP_LEXICOGRAPHIC)) + && operand_equal_p (curbnd, newbnd, + OEP_DECL_NAME | OEP_LEXICOGRAPHIC)) continue; if ((curbnd && TREE_CODE (curbnd) != INTEGER_CST) @@ -3334,15 +3324,15 @@ expr_to_str (pretty_printer &pp, tree expr, const char *dflt) /* Detect and diagnose a mismatch between an attribute access specification on the original declaration of FNDECL and that on the parameters NEWPARMS - from its refeclaration. ORIGLOC is the location of the first declaration + from its redeclaration. ORIGLOC is the location of the first declaration (FNDECL's is set to the location of the redeclaration). */ void warn_parm_array_mismatch (location_t origloc, tree fndecl, tree newparms) { - /* The original parameter list (copied from the original declaration - into the current [re]declaration, FNDECL)). The two are equal if - and only if FNDECL is the first declaratation. */ + /* The original parameter list (copied from the original declaration + into the current [re]declaration, FNDECL)). The two are equal if + and only if FNDECL is the first declaration. */ tree curparms = DECL_ARGUMENTS (fndecl); if (!curparms || !newparms || curparms == newparms) return; @@ -3374,7 +3364,7 @@ warn_parm_array_mismatch (location_t origloc, tree fndecl, tree newparms) return; } /* ...otherwise, if at least one spec isn't empty there may be mismatches, - such as between f(T*) and f(T[1]), where the former mapping woud be + such as between f(T*) and f(T[1]), where the former mapping would be empty. */ /* Create an empty access specification and use it for pointers with @@ -3510,7 +3500,7 @@ warn_parm_array_mismatch (location_t origloc, tree fndecl, tree newparms) && newa->sizarg != UINT_MAX && newa->sizarg == cura->sizarg && newa->minsize == cura->minsize - && !TREE_CHAIN (newa->size) && !TREE_CHAIN (cura->size)) + && !TREE_PURPOSE (newa->size) && !TREE_PURPOSE (cura->size)) continue; if (newa->size || cura->size) @@ -3657,7 +3647,8 @@ warn_parm_array_mismatch (location_t origloc, tree fndecl, tree newparms) /* The VLA bounds don't refer to other function parameters. Compare them lexicographically to detect gross mismatches such as between T[foo()] and T[bar()]. */ - if (operand_equal_p (newbnd, curbnd, OEP_LEXICOGRAPHIC)) + if (operand_equal_p (newbnd, curbnd, + OEP_DECL_NAME | OEP_LEXICOGRAPHIC)) continue; if (warning_at (newloc, OPT_Wvla_parameter, diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 64e46e7..9c151d1 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -431,6 +431,26 @@ Wc++20-compat C++ ObjC++ Var(warn_cxx20_compat) Warning LangEnabledBy(C++ ObjC++,Wall) Warn about C++ constructs whose meaning differs between ISO C++ 2017 and ISO C++ 2020. +Wc++11-extensions +C++ ObjC++ Var(warn_cxx11_extensions) Warning LangEnabledBy(C++ ObjC++) Init(1) +Warn about C++11 constructs in code compiled with an older standard. + +Wc++14-extensions +C++ ObjC++ Var(warn_cxx14_extensions) Warning LangEnabledBy(C++ ObjC++) Init(1) +Warn about C++14 constructs in code compiled with an older standard. + +Wc++17-extensions +C++ ObjC++ Var(warn_cxx17_extensions) Warning LangEnabledBy(C++ ObjC++) Init(1) +Warn about C++17 constructs in code compiled with an older standard. + +Wc++20-extensions +C++ ObjC++ Var(warn_cxx20_extensions) Warning LangEnabledBy(C++ ObjC++) Init(1) +Warn about C++20 constructs in code compiled with an older standard. + +Wc++23-extensions +C++ ObjC++ Var(warn_cxx23_extensions) Warning LangEnabledBy(C++ ObjC++) Init(1) +Warn about C++23 constructs in code compiled with an older standard. + Wcast-function-type C ObjC C++ ObjC++ Var(warn_cast_function_type) Warning EnabledBy(Wextra) Warn about casts between incompatible function types. @@ -592,7 +612,7 @@ C ObjC RejectNegative Warning Alias(Werror=, implicit-function-declaration) This switch is deprecated; use -Werror=implicit-function-declaration instead. Wexceptions -C++ ObjC++ Var(warn_exceptions) Init(1) +C++ ObjC++ Var(warn_exceptions) Init(1) Warning Warn when an exception handler is shadowed by another handler. Wextra @@ -702,6 +722,11 @@ Winit-list-lifetime C++ ObjC++ Var(warn_init_list) Warning Init(1) Warn about uses of std::initializer_list that can result in dangling pointers. +Winterference-size +C++ ObjC++ Var(warn_interference_size) Warning Init(1) +Warn about nonsensical values of --param destructive-interference-size or +constructive-interference-size. + Wimplicit C ObjC Var(warn_implicit) Warning LangEnabledBy(C ObjC,Wall) Warn about implicit declarations. @@ -800,7 +825,7 @@ functions. Wmismatched-new-delete C++ ObjC++ Var(warn_mismatched_new_delete) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) -Warn for mismatches between calls to operator new or delete and the corrsponding +Warn for mismatches between calls to operator new or delete and the corresponding call to the allocation or deallocation function. Wmismatched-tags @@ -819,6 +844,10 @@ Wmissing-field-initializers C ObjC C++ ObjC++ Var(warn_missing_field_initializers) Warning EnabledBy(Wextra) Warn about missing fields in struct initializers. +Wmissing-requires +C++ ObjC++ Var(warn_missing_requires) Init(1) Warning +Warn about likely missing requires keyword. + Wmultistatement-macros C ObjC C++ ObjC++ Var(warn_multistatement_macros) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) Warn about unsafe macros expanding to multiple statements used as a body of a clause such as if, else, while, switch, or for. @@ -1037,6 +1066,10 @@ Wold-style-definition C ObjC Var(warn_old_style_definition) Init(-1) Warning Warn if an old-style parameter definition is used. +Wopenacc-parallelism +C C++ Var(warn_openacc_parallelism) Warning +Warn about potentially suboptimal choices related to OpenACC parallelism. + Wopenmp-simd C C++ Var(warn_openmp_simd) Warning LangEnabledBy(C C++,Wall) Warn if a simd directive is overridden by the vectorizer cost model. @@ -1737,7 +1770,7 @@ C++ ObjC Var(flag_module_version_ignore) Integer ; undocumented, Very dangerous, but occasionally useful Winvalid-imported-macros -C++ ObjC++ Var(warn_imported_macros) +C++ ObjC++ Var(warn_imported_macros) Warning Warn about macros that have conflicting header units definitions. flang-info-include-translate @@ -1873,19 +1906,6 @@ fopenacc-dim= C ObjC C++ ObjC++ LTO Joined Var(flag_openacc_dims) Specify default OpenACC compute dimensions. -fopenacc-kernels= -C ObjC C++ ObjC++ RejectNegative Joined Enum(openacc_kernels) Var(flag_openacc_kernels) Init(OPENACC_KERNELS_PARLOOPS) --fopenacc-kernels=[decompose|parloops] Specify mode of OpenACC 'kernels' constructs handling. - -Enum -Name(openacc_kernels) Type(enum openacc_kernels) - -EnumValue -Enum(openacc_kernels) String(decompose) Value(OPENACC_KERNELS_DECOMPOSE) - -EnumValue -Enum(openacc_kernels) String(parloops) Value(OPENACC_KERNELS_PARLOOPS) - fopenmp C ObjC C++ ObjC++ LTO Var(flag_openmp) Enable OpenMP (implies -frecursive in Fortran). diff --git a/gcc/c-family/known-headers.cc b/gcc/c-family/known-headers.cc index 8592471..a391246 100644 --- a/gcc/c-family/known-headers.cc +++ b/gcc/c-family/known-headers.cc @@ -162,7 +162,14 @@ get_stdlib_header_for_name (const char *name, enum stdlib lib) {"stdout", {"<stdio.h>", "<cstdio>"} }, /* <stdlib.h> and <cstdlib>. */ + {"EXIT_FAILURE", {"<stdlib.h>", "<cstdlib>"} }, + {"EXIT_SUCCESS", {"<stdlib.h>", "<cstdlib>"} }, + {"abort", {"<stdlib.h>", "<cstdlib>"} }, + {"atexit", {"<stdlib.h>", "<cstdlib>"} }, + {"calloc", {"<stdlib.h>", "<cstdlib>"} }, + {"exit", {"<stdlib.h>", "<cstdlib>"} }, {"free", {"<stdlib.h>", "<cstdlib>"} }, + {"getenv", {"<stdlib.h>", "<cstdlib>"} }, {"malloc", {"<stdlib.h>", "<cstdlib>"} }, {"realloc", {"<stdlib.h>", "<cstdlib>"} }, |