diff options
Diffstat (limited to 'gcc/c-family')
| -rw-r--r-- | gcc/c-family/ChangeLog | 664 | ||||
| -rw-r--r-- | gcc/c-family/c-ada-spec.cc | 26 | ||||
| -rw-r--r-- | gcc/c-family/c-attribs.cc | 389 | ||||
| -rw-r--r-- | gcc/c-family/c-common.cc | 249 | ||||
| -rw-r--r-- | gcc/c-family/c-common.def | 9 | ||||
| -rw-r--r-- | gcc/c-family/c-common.h | 21 | ||||
| -rw-r--r-- | gcc/c-family/c-cppbuiltin.cc | 81 | ||||
| -rw-r--r-- | gcc/c-family/c-format.cc | 27 | ||||
| -rw-r--r-- | gcc/c-family/c-format.h | 1 | ||||
| -rw-r--r-- | gcc/c-family/c-gimplify.cc | 38 | ||||
| -rw-r--r-- | gcc/c-family/c-indentation.cc | 21 | ||||
| -rw-r--r-- | gcc/c-family/c-lex.cc | 2 | ||||
| -rw-r--r-- | gcc/c-family/c-omp.cc | 351 | ||||
| -rw-r--r-- | gcc/c-family/c-opts.cc | 114 | ||||
| -rw-r--r-- | gcc/c-family/c-pch.cc | 12 | ||||
| -rw-r--r-- | gcc/c-family/c-pragma.cc | 19 | ||||
| -rw-r--r-- | gcc/c-family/c-pragma.h | 1 | ||||
| -rw-r--r-- | gcc/c-family/c-pretty-print.cc | 77 | ||||
| -rw-r--r-- | gcc/c-family/c-pretty-print.h | 8 | ||||
| -rw-r--r-- | gcc/c-family/c-ubsan.cc | 333 | ||||
| -rw-r--r-- | gcc/c-family/c-warn.cc | 592 | ||||
| -rw-r--r-- | gcc/c-family/c.opt | 138 | ||||
| -rw-r--r-- | gcc/c-family/c.opt.urls | 52 | ||||
| -rw-r--r-- | gcc/c-family/known-headers.cc | 7 | ||||
| -rw-r--r-- | gcc/c-family/known-headers.h | 4 |
25 files changed, 2650 insertions, 586 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 1572c8b..87c06f6 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,667 @@ +2025-12-05 Tobias Burnus <tburnus@baylibre.com> + + * c-omp.cc (c_omp_split_clauses): Handle + OMP_CLAUSE_DYN_GROUPPRIVATE, sort target clauses + alphabetically. + * c-pragma.h (enum pragma_omp_clause): Add + PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE. + +2025-11-30 Andrew Pinski <andrew.pinski@oss.qualcomm.com> + + * c.opt.urls: Regenerate. + +2025-11-26 Alejandro Colomar <alx@kernel.org> + + * c-common.cc (c_common_reswords): Add _Maxof & _Minof keywords. + (c_maxof_type, c_minof_type): New functions. + * c-common.def (MAXOF_EXPR, MINOF_EXPR): New trees. + * c-common.h (enum rid): Add RID_MAXOF & RID_MINOF constants. + (c_maxof_type, c_minof_type): New prototypes. + +2025-11-26 Jakub Jelinek <jakub@redhat.com> + + * c-opts.cc (c_common_init_options): Call set_std_cxx20 rather than + set_std_cxx17. + * c.opt (std=c++2a): Change description to deprecated option wording. + (std=c++20): Remove experimental support part. + (std=c++2b): Change description to deprecated option wording. + (std=gnu++2a): Likewise. + (std=gnu++20): Remove experimental support part. + (std=gnu++2b): Change description to deprecated option wording. + +2025-11-25 Jason Merrill <jason@redhat.com> + + * c.opt: Add --compile-std-module. + +2025-11-25 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/120052 + * c-ubsan.cc (ubsan_instrument_bounds): For VLAs use + 1 instead of 0 as first IFN_UBSAN_BOUNDS argument and only + use the addend without TYPE_MAX_VALUE (TYPE_DOMAIN (type)) + in the 3rd argument. + +2025-11-25 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/122624 + * c-common.cc (c_common_get_alias_set): Fix up handling of BITINT_TYPE + and non-standard INTEGER_TYPEs. For unsigned _BitInt(1) always return + -1. For other unsigned types set TYPE_ALIAS_SET to get_alias_set of + corresponding signed type and return that. For signed types check if + corresponding unsigned type has TYPE_ALIAS_SET_KNOWN_P and if so copy + its TYPE_ALIAS_SET and return that. + +2025-11-25 Kito Cheng <kito.cheng@sifive.com> + + * c-opts.cc (c_common_post_options): Skip register_include_chains + when cpp_opts->preprocessed is set. + +2025-11-22 Sandra Loosemore <sloosemore@baylibre.com> + Julian Brown <julian@codesourcery.com> + waffl3x <waffl3x@baylibre.com> + + * c-omp.cc (c_omp_directives): Uncomment "begin declare variant" + and "end declare variant". + +2025-11-11 Alejandro Colomar <alx@kernel.org> + + * c-warn.cc (warn_parms_array_mismatch): Split out body of + per-pair in parameter lists iteration into... + (warn_parm_array_mismatch): ...this new function. + +2025-11-11 Alejandro Colomar <alx@kernel.org> + + * c-warn.cc (warn_parms_array_mismatch): Reduce scope of local + variable. + +2025-11-10 Sandra Loosemore <sloosemore@baylibre.com> + + PR other/122243 + * c.opt.urls: Regenerated. + +2025-11-10 Alejandro Colomar <alx@kernel.org> + + PR c/122591 + * c-common.cc (c_countof_type): Convert return value to size_t. + +2025-11-10 Sandra Loosemore <sloosemore@baylibre.com> + + PR other/122243 + * c.opt (fmodule-version-ignore): Mark as "Undocumented". + +2025-11-10 Sandra Loosemore <sloosemore@baylibre.com> + + PR other/122243 + * c.opt: (fdeps-format=): Add RejectNegative. + (fdeps-file=): Likewise. + (fdeps-target=): Likewise. + (Walloc-size-larger-than=): Likewise. + (Wno-alloc-size-larger-than): Likewise. + (Walloca-larger-than=): Likewise. + (Wno-alloca-larger-than): Likewise. + (Woverloaded-virtual=): Likewise. + (Wvla-larger-than=): Likewise. + (Wno-vla-larger-than): Likewise. + (fopenacc-dim=): Likewise. + (femit-struct-debug-baseonly): Likewise. + (femit-struct-debug-reduced): Likewise. + (femit-struct-debug-detailed=): Likewise. + +2025-11-10 Sandra Loosemore <sloosemore@baylibre.com> + + PR other/122243 + * c.opt (Wsynth): Mark as "Ignore". + +2025-11-10 Tejas Belagod <tejas.belagod@arm.com> + + * c-common.cc (c_build_vec_convert): Support vector boolean + types for __builtin_convertvector (). + +2025-11-10 Jakub Jelinek <jakub@redhat.com> + + PR c++/119064 + * c-cppbuiltin.cc (c_cpp_builtins): Revert 2025-07-11 + changes. + +2025-11-10 Lewis Hyatt <lhyatt@gmail.com> + + PR preprocessor/105608 + * c-opts.cc (c_finish_options): Set new member + line_table->cmdline_location. + * c-pch.cc (c_common_read_pch): Adapt linemap usage to changes in + libcpp pch.cc; it is now possible that the linemap is in a different + file after returning from cpp_read_state(). + +2025-11-05 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/121574 + * c.opt: New warning '-Wexpose-global-module-tu-local'. + * c.opt.urls: Regenerate. + +2025-11-04 Alejandro Colomar <alx@kernel.org> + + * c-warn.cc (warn_parms_array_mismatch): Fix typos in comment. + +2025-11-04 Alejandro Colomar <alx@kernel.org> + + * c-common.h (warn_parm_array_mismatch): + Rename warn_parm_array_mismatch => warn_parms_array_mismatch. + * c-warn.cc (warn_parm_array_mismatch): + Rename warn_parm_array_mismatch => warn_parms_array_mismatch. + +2025-10-30 Qing Zhao <qing.zhao@oracle.com> + + * c-attribs.cc (handle_counted_by_attribute): Allow counted_by for + void pointer. Issue warnings when -Wpointer-arith is present. + +2025-10-27 Richard Biener <rguenther@suse.de> + + PR middle-end/122325 + * c-opts.cc (c_common_init_options_struct): Remove set of + flag_default_complex_method. + +2025-10-22 Jakub Jelinek <jakub@redhat.com> + + PR c++/122302 + * c-common.cc (braced_list_to_string): Call copy_node on RAW_DATA_CST + before changing RAW_DATA_POINTER and RAW_DATA_LENGTH on it. + +2025-10-21 Tobias Burnus <tburnus@baylibre.com> + + * c-omp.cc (c_omp_directives): Uncomment 'declare mapper', + add comment to 'begin metadirective', add 6.x unimplemented + directives as comment-out entries. + +2025-10-17 Josef Melcr <jmelcr02@gmail.com> + + * c-attribs.cc: Define callback attr. + +2025-10-14 Jakub Jelinek <jakub@redhat.com> + + * c.opt (Wflex-array-member-not-at-end, Wignored-qualifiers, + Wopenacc-parallelism, Wstrict-flex-arrays, Wsync-nand, + fstrict-flex-arrays, fstrict-flex-arrays=): Enable also for ObjC and + ObjC++ next to C and C++. + (Wmisleading-indentation, Wopenmp-simd): Likewise. Also change + LangEnabledBy from just C C++ to C ObjC C++ ObjC++. + (Wplacement-new, Wplacement-new=, fcontract-assumption-mode=, + fcontract-build-level=, fcontract-strict-declarations=, + fcontract-mode=, fcontract-continuation-mode=, fcontract-role=, + fcontract-semantic=, fcoroutines, flang-info-include-translate, + flang-info-include-translate-not, flang-info-include-translate=, + flang-info-module-cmi, flang-info-module-cmi=): Enable also + for ObjC++ next to C++. + +2025-10-13 Iain Sandoe <iain@sandoe.co.uk> + + * c.opt: Enable Wignored-attributes for Objective-C and + Objective-C++. + +2025-10-09 David Faust <david.faust@oracle.com> + + * c-attribs.cc (c_common_attribute_table): Add btf_decl_tag and + btf_type_tag attributes. + (handle_btf_decl_tag_attribute): New handler for btf_decl_tag. + (hanlde_btf_type_tag_attribute): New handler for btf_type_tag. + (btf_tag_args_ok): Helper for new attribute handlers. + +2025-10-09 Jakub Jelinek <jakub@redhat.com> + + * c-common.h (D_CXX26): Define. + * c-common.cc (c_common_resword): Add D_CXX26 to + __builtin_c23_va_start flags, mention D_CXX26 in comment. + +2025-10-09 Jakub Jelinek <jakub@redhat.com> + + PR c/122188 + * c-gimplify.cc (c_gimplify_expr): Also gimplify the second operand + before the COND_EXPR and use in COND_EXPR result of gimplification. + +2025-10-09 David Malcolm <dmalcolm@redhat.com> + + * c-opts.cc: Define INCLUDE_VECTOR. + +2025-10-08 Jakub Jelinek <jakub@redhat.com> + + PR c/122188 + * c-gimplify.cc (c_gimplify_expr): Gimplify CALL_EXPR_ARG (*expr_p, 0) + instead of calling save_expr on it. + +2025-10-04 Jakub Jelinek <jakub@redhat.com> + + PR c++/114457 + * c-opts.cc (c_common_post_options): For C++26 set + flag_auto_var_init to AUTO_INIT_CXX26 if not specified explicitly. + For C++ disable warn_trivial_auto_var_init. + +2025-10-04 Nathaniel Shead <nathanieloshead@gmail.com> + + PR c++/117658 + * c.opt: New flag '-Wexternal-tu-local'. + * c.opt.urls: Regenerate. + +2025-10-02 Alfie Richards <alfie.richards@arm.com> + + * c-attribs.cc (attr_target_clones_exclusions): Add simd and omp + exclusions. + (attr_target_version_exclusions): New definition with simd and omp + exclusions. + (attr_omp_declare_simd_exclusions): New definition with target_version + and clones exclusions. + (attr_simd_exclusions): Ditto. + (c_common_gnu_attributes): Add new target_version, simd, and omp + declare simd variables. + +2025-10-01 Alejandro Colomar <alx@kernel.org> + + * c.opt.urls: Regenerate + +2025-09-26 Alejandro Colomar <alx@kernel.org> + + * c.opt: Add -Wmultiple-parameter-fwd-decl-lists + +2025-09-23 Alfie Richards <alfie.richards@arm.com> + + * c-attribs.cc: Add support for target_version and target_clone mixing. + +2025-09-23 Alfie Richards <alfie.richards@arm.com> + + * c-pretty-print.cc (pp_c_function_target_version): New function. + (pp_c_function_target_clones): New function. + (pp_c_maybe_whitespace): Move to c-pretty-print.h. + * c-pretty-print.h (pp_c_function_target_version): New function. + (pp_c_function_target_clones): New function. + (pp_c_maybe_whitespace): Moved here from c-pretty-print.cc. + +2025-09-23 Alfie Richards <alfie.richards@arm.com> + + * c-attribs.cc (handle_target_clones_attribute): Update to use new hook. + +2025-09-08 Eric Botcazou <ebotcazou@adacore.com> + + PR ada/121544 + * c-ada-spec.cc (dump_ada_node) <POINTER_TYPE>: Dump the name of + anonymous tagged pointed-to types specially. + (dump_nested_type) <POINTER_TYPE>: Recurse on anonymous pointed-to + types declared in the same file. + Set TREE_VISITED on the underlying DECL of the field type, if any. + +2025-08-27 Jakub Jelinek <jakub@redhat.com> + + PR target/121520 + * c-cppbuiltin.cc (c_cpp_builtins): Properly call cpp_warn + for __STDCPP_FLOAT<NN>_T__ if FLOATN_NX_TYPE_NODE (i) is NULL + for C++23 for non-extended types and don't call cpp_warn for + extended types. + +2025-08-18 Indu Bhagat <indu.bhagat@oracle.com> + + * c-attribs.cc (add_no_sanitize_value): Use 'sanitize_code_type' + instead of 'unsigned int'. + (handle_no_sanitize_attribute): Likewise. + (handle_no_sanitize_address_attribute): Likewise. + (handle_no_sanitize_thread_attribute): Likewise. + (handle_no_address_safety_analysis_attribute): Likewise. + * c-common.h (add_no_sanitize_value): Likewise. + +2025-08-15 Jakub Jelinek <jakub@redhat.com> + + PR c++/121552 + * c.opt (Wnon-c-typedef-for-linkage): New option. + * c.opt.urls: Regenerate. + +2025-08-15 Jakub Jelinek <jakub@redhat.com> + + PR preprocessor/120778 + PR target/121520 + * c-cppbuiltin.cc (c_cpp_builtins): Implement C++26 DR 2581. Add + cpp_define_warn lambda and use it as well as cpp_warn where needed. + In the if (c_dialect_cxx ()) block with __cpp_* predefinitions add + cpp_define lambda. Formatting fixes. + +2025-08-15 Qing Zhao <qing.zhao@oracle.com> + + * c-gimplify.cc (is_address_with_access_with_size): New function. + (ubsan_walk_array_refs_r): Instrument an INDIRECT_REF whose base + address is .ACCESS_WITH_SIZE or an address computation whose base + address is .ACCESS_WITH_SIZE. + * c-ubsan.cc (ubsan_instrument_bounds_pointer_address): New function. + (struct factor_t): New structure. + (get_factors_from_mul_expr): New function. + (get_index_from_offset): New function. + (get_index_from_pointer_addr_expr): New function. + (is_instrumentable_pointer_array_address): New function. + (ubsan_array_ref_instrumented_p): Change prototype. + Handle MEM_REF in addtional to ARRAY_REF. + (ubsan_maybe_instrument_array_ref): Handle MEM_REF in addtional + to ARRAY_REF. + +2025-08-15 Qing Zhao <qing.zhao@oracle.com> + + * c-attribs.cc (handle_counted_by_attribute): Accept counted_by + attribute for pointer fields. + +2025-08-13 Jakub Jelinek <jakub@redhat.com> + + PR c++/120776 + * c-cppbuiltin.cc (c_cpp_builtins): Predefine + __cpp_expansion_statements=202506L for C++26. + +2025-08-08 David Malcolm <dmalcolm@redhat.com> + + * c-indentation.cc (should_warn_for_misleading_indentation): + Update for moving diagnostics::context::m_tabstop into + diagnostics::column_options. + * c-opts.cc (c_common_post_options): Likewise. + +2025-08-07 Jakub Jelinek <jakub@redhat.com> + + PR c++/117783 + * c-cppbuiltin.cc (c_cpp_builtins): Change __cpp_structured_bindings + predefined value for C++26 from 202403L to 202411L. + +2025-08-07 Jakub Jelinek <jakub@redhat.com> + + PR preprocessor/120778 + * c.opt (Wkeyword-macro): New option. + * c.opt.urls: Regenerate. + * c-common.h (cxx_dialect): Comment formatting fix. + * c-opts.cc (c_common_post_options): Default to + -Wkeyword-macro for C++26 if pedantic. + +2025-08-06 Alexandre Oliva <oliva@adacore.com> + + * c-attribs.cc (handle_hardbool_attribute): Create distinct + enumeration types, with structural equality. Handle + base type qualifiers. + +2025-08-02 Martin Uecker <uecker@tugraz.at> + + * c-attribs.cc (handle_argspec_attribute): Update. + (build_arg_spec): New function. + (build_attr_access_from_parms): Rewrite `arg spec' handling. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * c-common.cc: Make diagnostics::context::m_source_printing + private. + * c-format.cc: Likewise. + * c-opts.cc: Likewise. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * c-common.cc: Update usage of "diagnostic_info" to explicitly + refer to "diagnostics::diagnostic_info". + * c-opts.cc: Likewise. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * c-format.cc: Update for file_cache and char_span moving from + input.h to diagnostics/file-cache.h and into the "diagnostics::" + namespace. + * c-indentation.cc: Likewise. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * c-common.cc (c_family_tests): Add include of + "diagnostics/diagnostics-selftests.h". Replace + c_diagnostic_cc_tests with + diagnostics::selftest::context_cc_tests. + * c-common.h: Drop c_diagnostic_cc_tests decl. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * c-common.cc: Update for diagnostic_t becoming + enum class diagnostics::kind. + * c-format.cc: Likewise. + * c-lex.cc: Likewise. + * c-opts.cc: Likewise. + * c-pragma.cc: Likewise. + * c-warn.cc: Likewise. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * c-common.cc: Update for renaming of diagnostic_option_id to + diagnostics::option_id. + * c-common.h: Likewise. + * c-cppbuiltin.cc: Likewise. + * known-headers.cc: Likewise. + * known-headers.h: Likewise. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * c-common.cc: Update comment for renaming of edit_context. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * c-format.cc (test_type_mismatch_range_labels): Update for + move of selftest::test_diagnostic_context to + diagnostics::selftest::test_context. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * c-format.cc: Update for move of selftest-diagnostic.h to + diagnostics/selftest-context.h. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * c-common.h: Update for diagnostic_context becoming + diagnostics::context. + * c-opts.cc: Likewise. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * c-opts.cc (c_diagnostic_text_finalizer): Add "m_" prefix to + fields of diagnostic_info. + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * c-opts.cc: Update for move of "diagnostic-macro-unwinding.h" + to "diagnostics/macro-unwinding.h". + +2025-07-25 David Malcolm <dmalcolm@redhat.com> + + * c-opts.cc: Update for move of diagnostics output formats into + namespace "diagnostics" as "sinks". + +2025-07-16 Kwok Cheung Yeung <kcyeung@baylibre.com> + + * c-omp.cc (c_finish_omp_depobj): Use OMP_ITERATOR_DECL_P. + +2025-07-16 Alfie Richards <alfie.richards@arm.com> + + * c-attribs.cc (handle_target_clones_attribute): Change to use + get_clone_versions. + +2025-07-16 Alfie Richards <alfie.richards@arm.com> + + * c-format.cc (local_string_slice_node): New node type. + (asm_fprintf_char_table): New entry. + (init_dynamic_diag_info): Add support for string_slice. + * c-format.h (T_STRING_SLICE): New node type. + +2025-07-15 Jakub Jelinek <jakub@redhat.com> + Jason Merrill <jason@redhat.com> + + PR c/44677 + * c-opts.cc (c_common_post_options): Change + warn_unused_but_set_parameter and warn_unused_but_set_variable + from 1 to 3 if they were set only implicitly. + * c-attribs.cc (build_attr_access_from_parms): Remove unused + but set variable nelts. + +2025-07-11 Jakub Jelinek <jakub@redhat.com> + + PR c++/119064 + * c.opt (Wc++26-compat): New option. + * c.opt.urls: Regenerate. + * c-opts.cc (c_common_post_options): Clear warn_cxx26_compat for + C++26 or later. + * c-cppbuiltin.cc (c_cpp_builtins): For C++26 predefine + __cpp_trivial_relocatability=202502L. + +2025-07-10 Jakub Jelinek <jakub@redhat.com> + + PR c++/117785 + * c-cppbuiltin.cc (c_cpp_builtins): Predefine + __cpp_constexpr_exceptions=202411L for C++26. + +2025-07-10 Qing Zhao <qing.zhao@oracle.com> + + * c-ubsan.cc (get_bound_from_access_with_size): Adjust the position + of the arguments per the new design. + +2025-07-07 Qing Zhao <qing.zhao@oracle.com> + + Revert: + 2025-07-01 Qing Zhao <qing.zhao@oracle.com> + + * c-attribs.cc (handle_counted_by_attribute): Accept counted_by + attribute for pointer fields. + +2025-07-07 Qing Zhao <qing.zhao@oracle.com> + + Revert: + 2025-07-01 Qing Zhao <qing.zhao@oracle.com> + + * c-gimplify.cc (is_address_with_access_with_size): New function. + (ubsan_walk_array_refs_r): Instrument an INDIRECT_REF whose base + address is .ACCESS_WITH_SIZE or an address computation whose base + address is .ACCESS_WITH_SIZE. + * c-ubsan.cc (ubsan_instrument_bounds_pointer_address): New function. + (struct factor_t): New structure. + (get_factors_from_mul_expr): New function. + (get_index_from_offset): New function. + (get_index_from_pointer_addr_expr): New function. + (is_instrumentable_pointer_array_address): New function. + (ubsan_array_ref_instrumented_p): Change prototype. + Handle MEM_REF in addtional to ARRAY_REF. + (ubsan_maybe_instrument_array_ref): Handle MEM_REF in addtional + to ARRAY_REF. + +2025-07-07 Jason Merrill <jason@redhat.com> + + PR c++/120917 + * c.opt: Add -Wno-abbreviated-auto-in-template-arg. + * c.opt.urls: Regenerate. + +2025-07-04 Jakub Jelinek <jakub@redhat.com> + + PR c/120837 + * c-common.cc (pointer_int_sum): Rewrite the intop PLUS_EXPR or + MINUS_EXPR optimization into extension of both intop operands, + their separate multiplication and then addition/subtraction followed + by rest of pointer_int_sum handling after the multiplication. + +2025-07-01 Qing Zhao <qing.zhao@oracle.com> + + * c-gimplify.cc (is_address_with_access_with_size): New function. + (ubsan_walk_array_refs_r): Instrument an INDIRECT_REF whose base + address is .ACCESS_WITH_SIZE or an address computation whose base + address is .ACCESS_WITH_SIZE. + * c-ubsan.cc (ubsan_instrument_bounds_pointer_address): New function. + (struct factor_t): New structure. + (get_factors_from_mul_expr): New function. + (get_index_from_offset): New function. + (get_index_from_pointer_addr_expr): New function. + (is_instrumentable_pointer_array_address): New function. + (ubsan_array_ref_instrumented_p): Change prototype. + Handle MEM_REF in addtional to ARRAY_REF. + (ubsan_maybe_instrument_array_ref): Handle MEM_REF in addtional + to ARRAY_REF. + +2025-07-01 Qing Zhao <qing.zhao@oracle.com> + + * c-attribs.cc (handle_counted_by_attribute): Accept counted_by + attribute for pointer fields. + +2025-06-30 Jakub Jelinek <jakub@redhat.com> + + PR c/120520 + PR c/117023 + * c-attribs.cc (c_common_gnu_attributes): Allow 2 or 3 arguments for + nonnull_if_nonzero attribute instead of only 2. + (handle_nonnull_if_nonzero_attribute): Handle 3 argument + nonnull_if_nonzero. + * c-common.cc (struct nonnull_arg_ctx): Rename other member to other1, + add other2 member. + (check_function_nonnull): Clear a if nonnull attribute has an + argument. Adjust for nonnull_arg_ctx changes. Handle 3 argument + nonnull_if_nonzero attribute. + (check_nonnull_arg): Adjust for nonnull_arg_ctx changes, emit different + diagnostics for 3 argument nonnull_if_nonzero attributes. + (check_function_arguments): Adjust ctx var initialization. + +2025-06-27 Jakub Jelinek <jakub@redhat.com> + + PR c++/120777 + * c-cppbuiltin.cc (c_cpp_builtins): Predefine + __cpp_constexpr_virtual_inheritance=202506L for C++26. + +2025-06-26 David Malcolm <dmalcolm@redhat.com> + + * c-opts.cc (c_common_diagnostics_set_defaults): Use + diagnostic_context::set_permissive_option. + +2025-06-23 Tobias Burnus <tburnus@baylibre.com> + + * c-omp.cc (c_finish_oacc_wait): Handle if clause. + +2025-06-16 Jason Merrill <jason@redhat.com> + + * c.opt: Add -Wsfinae-incomplete. + * c.opt.urls: Regenerate. + +2025-06-12 Gwenole Beauchesne <gb.devel@gmail.com> + Andrew Pinski <quic_apinski@quicinc.com> + + PR c++/41201 + PR c++/48026 + * c-pragma.cc (init_pragma): Use c_register_pragma_with_early_handler + instead of c_register_pragma for `#pragma GCC optimize`. + +2025-06-03 Martin Uecker <uecker@tugraz.at> + + PR c/120078 + * c.opt (Wjump-misses-init): Fix typo. + +2025-05-30 Julian Brown <julian@codesourcery.com> + Tobias Burnus <tburnus@baylibre.com> + + * c-common.h (c_omp_region_type): Add C_ORT_DECLARE_MAPPER and + C_ORT_OMP_DECLARE_MAPPER codes. + (omp_mapper_list): Add forward declaration. + (c_omp_find_nested_mappers, c_omp_instantiate_mappers): Add prototypes. + * c-omp.cc (c_omp_find_nested_mappers): New function. + (remap_mapper_decl_info): New struct. + (remap_mapper_decl_1, omp_instantiate_mapper, + c_omp_instantiate_mappers): New functions. + +2025-05-27 Alejandro Colomar <alx@kernel.org> + Martin Uecker <uecker@tugraz.at> + + PR c/117025 + * c-common.h (enum rid): Add RID_COUNTOF. + (c_countof_type): New function prototype. + * c-common.def (COUNTOF_EXPR): New tree. + * c-common.cc (c_common_reswords): Add RID_COUNTOF entry. + (c_countof_type): New function. + +2025-05-23 Jason Merrill <jason@redhat.com> + + * c-format.cc (flag_chars_t::validate): Control quoting warnings + with -Wformat-diag. + +2025-05-15 Jason Merrill <jason@redhat.com> + + * c-opts.cc (c_common_post_options): Set flag_coroutines. + (set_std_cxx20, set_std_cxx23, set_std_cxx26): Not here. + +2025-05-03 Jason Merrill <jason@redhat.com> + + * c-opts.cc (c_common_post_options): Let plain -Wabi warn + about changes in a future version. + 2025-04-28 David Malcolm <dmalcolm@redhat.com> * c-pretty-print.cc: Drop include of "make-unique.h". diff --git a/gcc/c-family/c-ada-spec.cc b/gcc/c-family/c-ada-spec.cc index c7ae032..42d75b4 100644 --- a/gcc/c-family/c-ada-spec.cc +++ b/gcc/c-family/c-ada-spec.cc @@ -2442,8 +2442,14 @@ dump_ada_node (pretty_printer *pp, tree node, tree type, int spc, break; } - dump_ada_node (pp, ref_type, ref_type, spc, is_access, - true); + /* Dump anonymous tagged types specially. */ + if (TYPE_NAME (ref_type) + || (!RECORD_OR_UNION_TYPE_P (ref_type) + && TREE_CODE (ref_type) != ENUMERAL_TYPE)) + dump_ada_node (pp, ref_type, ref_type, spc, is_access, + true); + else + dump_anonymous_type_name (pp, ref_type); } } } @@ -2699,7 +2705,16 @@ dump_nested_type (pretty_printer *pp, tree field, tree t, int spc) { case POINTER_TYPE: tmp = TREE_TYPE (field_type); - dump_forward_type (pp, tmp, t, spc); + decl = get_underlying_decl (tmp); + if (TYPE_NAME (tmp) || !decl || DECL_NAME (decl)) + dump_forward_type (pp, tmp, t, spc); + else if (DECL_SOURCE_FILE (decl) == DECL_SOURCE_FILE (t) + && !TREE_VISITED (decl)) + { + /* Generate full declaration. */ + dump_nested_type (pp, decl, t, spc); + TREE_VISITED (decl) = 1; + } break; case ARRAY_TYPE: @@ -2773,6 +2788,11 @@ dump_nested_type (pretty_printer *pp, tree field, tree t, int spc) default: break; } + + /* Make sure not to output the nested type twice in C++. */ + decl = get_underlying_decl (field_type); + if (decl) + TREE_VISITED (decl) = 1; } /* Hash table of overloaded names that we cannot support. It is needed even diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index 5a0e3d3..28a034f 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-pretty-print.h" #include "gcc-rich-location.h" #include "gcc-urlifier.h" +#include "attr-callback.h" static tree handle_packed_attribute (tree *, tree, tree, int, bool *); static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *); @@ -189,6 +190,9 @@ static tree handle_fd_arg_attribute (tree *, tree, tree, int, bool *); static tree handle_flag_enum_attribute (tree *, tree, tree, int, bool *); static tree handle_null_terminated_string_arg_attribute (tree *, tree, tree, int, bool *); +static tree handle_btf_decl_tag_attribute (tree *, tree, tree, int, bool *); +static tree handle_btf_type_tag_attribute (tree *, tree, tree, int, bool *); + /* Helper to define attribute exclusions. */ #define ATTR_EXCL(name, function, type, variable) \ { name, function, type, variable } @@ -249,12 +253,28 @@ static const struct attribute_spec::exclusions attr_target_clones_exclusions[] = ATTR_EXCL ("always_inline", true, true, true), ATTR_EXCL ("target", TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE), - ATTR_EXCL ("target_version", true, true, true), + ATTR_EXCL ("omp declare simd", true, true, true), + ATTR_EXCL ("simd", true, true, true), ATTR_EXCL (NULL, false, false, false), }; static const struct attribute_spec::exclusions attr_target_version_exclusions[] = { + ATTR_EXCL ("omp declare simd", true, true, true), + ATTR_EXCL ("simd", true, true, true), + ATTR_EXCL (NULL, false, false, false), +}; + +static const struct attribute_spec::exclusions attr_omp_declare_simd_exclusions[] = +{ + ATTR_EXCL ("target_version", true, true, true), + ATTR_EXCL ("target_clones", true, true, true), + ATTR_EXCL (NULL, false, false, false), +}; + +static const struct attribute_spec::exclusions attr_simd_exclusions[] = +{ + ATTR_EXCL ("target_version", true, true, true), ATTR_EXCL ("target_clones", true, true, true), ATTR_EXCL (NULL, false, false, false), }; @@ -465,6 +485,8 @@ const struct attribute_spec c_common_gnu_attributes[] = handle_tm_attribute, NULL }, { "transaction_may_cancel_outer", 0, 0, false, true, false, false, handle_tm_attribute, NULL }, + { CALLBACK_ATTR_IDENT, 1, -1, true, false, false, false, + handle_callback_attribute, NULL }, /* ??? These two attributes didn't make the transition from the Intel language document to the multi-vendor language document. */ { "transaction_pure", 0, 0, false, true, false, false, @@ -489,7 +511,7 @@ const struct attribute_spec c_common_gnu_attributes[] = handle_tls_model_attribute, NULL }, { "nonnull", 0, -1, false, true, true, false, handle_nonnull_attribute, NULL }, - { "nonnull_if_nonzero", 2, 2, false, true, true, false, + { "nonnull_if_nonzero", 2, 3, false, true, true, false, handle_nonnull_if_nonzero_attribute, NULL }, { "nonstring", 0, 0, true, false, false, false, handle_nonstring_attribute, NULL }, @@ -543,7 +565,7 @@ const struct attribute_spec c_common_gnu_attributes[] = attr_target_exclusions }, { "target_version", 1, 1, true, false, false, false, handle_target_version_attribute, - attr_target_version_exclusions }, + attr_target_version_exclusions}, { "target_clones", 1, -1, true, false, false, false, handle_target_clones_attribute, attr_target_clones_exclusions }, @@ -570,7 +592,8 @@ const struct attribute_spec c_common_gnu_attributes[] = { "returns_nonnull", 0, 0, false, true, true, false, handle_returns_nonnull_attribute, NULL }, { "omp declare simd", 0, -1, true, false, false, false, - handle_omp_declare_simd_attribute, NULL }, + handle_omp_declare_simd_attribute, + attr_omp_declare_simd_exclusions }, { "omp declare variant base", 0, -1, true, false, false, false, handle_omp_declare_variant_attribute, NULL }, { "omp declare variant variant", 0, -1, true, false, false, false, @@ -579,7 +602,7 @@ const struct attribute_spec c_common_gnu_attributes[] = false, false, handle_omp_declare_variant_attribute, NULL }, { "simd", 0, 1, true, false, false, false, - handle_simd_attribute, NULL }, + handle_simd_attribute, attr_simd_exclusions }, { "omp declare target", 0, -1, true, false, false, false, handle_omp_declare_target_attribute, NULL }, { "omp declare target link", 0, 0, true, false, false, false, @@ -640,7 +663,11 @@ const struct attribute_spec c_common_gnu_attributes[] = { "flag_enum", 0, 0, false, true, false, false, handle_flag_enum_attribute, NULL }, { "null_terminated_string_arg", 1, 1, false, true, true, false, - handle_null_terminated_string_arg_attribute, NULL} + handle_null_terminated_string_arg_attribute, NULL}, + { "btf_type_tag", 1, 1, false, true, false, false, + handle_btf_type_tag_attribute, NULL}, + { "btf_decl_tag", 1, 1, true, false, false, false, + handle_btf_decl_tag_attribute, NULL} }; const struct scoped_attribute_specs c_common_gnu_attribute_table = @@ -1128,11 +1155,16 @@ handle_hardbool_attribute (tree *node, tree name, tree args, } tree orig = *node; - *node = build_duplicate_type (orig); + /* Drop qualifiers from the base type. Keep attributes, so that, in the odd + chance attributes are applicable and relevant to the base type, if they + are specified first, or through a typedef, they wouldn't be dropped on the + floor here. */ + tree unqual = build_qualified_type (orig, TYPE_UNQUALIFIED); + *node = build_distinct_type_copy (unqual); TREE_SET_CODE (*node, ENUMERAL_TYPE); - ENUM_UNDERLYING_TYPE (*node) = orig; - TYPE_CANONICAL (*node) = TYPE_CANONICAL (orig); + ENUM_UNDERLYING_TYPE (*node) = unqual; + SET_TYPE_STRUCTURAL_EQUALITY (*node); tree false_value; if (args) @@ -1191,7 +1223,13 @@ handle_hardbool_attribute (tree *node, tree name, tree args, gcc_checking_assert (!TYPE_CACHED_VALUES_P (*node)); TYPE_VALUES (*node) = values; - TYPE_NAME (*node) = orig; + TYPE_NAME (*node) = unqual; + + if (TYPE_QUALS (orig) != TYPE_QUALS (*node)) + { + *node = build_qualified_type (*node, TYPE_QUALS (orig)); + TYPE_NAME (*node) = orig; + } return NULL_TREE; } @@ -1409,23 +1447,24 @@ handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args), /* Add FLAGS for a function NODE to no_sanitize_flags in DECL_ATTRIBUTES. */ void -add_no_sanitize_value (tree node, unsigned int flags) +add_no_sanitize_value (tree node, sanitize_code_type flags) { tree attr = lookup_attribute ("no_sanitize", DECL_ATTRIBUTES (node)); if (attr) { - unsigned int old_value = tree_to_uhwi (TREE_VALUE (attr)); + sanitize_code_type old_value = + tree_to_sanitize_code_type (TREE_VALUE (attr)); flags |= old_value; if (flags == old_value) return; - TREE_VALUE (attr) = build_int_cst (unsigned_type_node, flags); + TREE_VALUE (attr) = build_int_cst (uint64_type_node, flags); } else DECL_ATTRIBUTES (node) = tree_cons (get_identifier ("no_sanitize"), - build_int_cst (unsigned_type_node, flags), + build_int_cst (uint64_type_node, flags), DECL_ATTRIBUTES (node)); } @@ -1436,7 +1475,7 @@ static tree handle_no_sanitize_attribute (tree *node, tree name, tree args, int, bool *no_add_attrs) { - unsigned int flags = 0; + sanitize_code_type flags = 0; *no_add_attrs = true; if (TREE_CODE (*node) != FUNCTION_DECL) { @@ -1473,7 +1512,7 @@ handle_no_sanitize_address_attribute (tree *node, tree name, tree, int, if (TREE_CODE (*node) != FUNCTION_DECL) warning (OPT_Wattributes, "%qE attribute ignored", name); else - add_no_sanitize_value (*node, SANITIZE_ADDRESS); + add_no_sanitize_value (*node, (sanitize_code_type) SANITIZE_ADDRESS); return NULL_TREE; } @@ -1489,7 +1528,7 @@ handle_no_sanitize_thread_attribute (tree *node, tree name, tree, int, if (TREE_CODE (*node) != FUNCTION_DECL) warning (OPT_Wattributes, "%qE attribute ignored", name); else - add_no_sanitize_value (*node, SANITIZE_THREAD); + add_no_sanitize_value (*node, (sanitize_code_type) SANITIZE_THREAD); return NULL_TREE; } @@ -1506,7 +1545,7 @@ handle_no_address_safety_analysis_attribute (tree *node, tree name, tree, int, if (TREE_CODE (*node) != FUNCTION_DECL) warning (OPT_Wattributes, "%qE attribute ignored", name); else - add_no_sanitize_value (*node, SANITIZE_ADDRESS); + add_no_sanitize_value (*node, (sanitize_code_type) SANITIZE_ADDRESS); return NULL_TREE; } @@ -2906,22 +2945,55 @@ handle_counted_by_attribute (tree *node, tree name, " declaration %q+D", name, decl); *no_add_attrs = true; } - /* This attribute only applies to field with array type. */ - else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE) + /* This attribute only applies to a field with array type or pointer type. */ + else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE + && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE) { error_at (DECL_SOURCE_LOCATION (decl), - "%qE attribute is not allowed for a non-array field", - name); + "%qE attribute is not allowed for a non-array" + " or non-pointer field", name); *no_add_attrs = true; } /* This attribute only applies to a C99 flexible array member type. */ - else if (! c_flexible_array_member_type_p (TREE_TYPE (decl))) + else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE + && !c_flexible_array_member_type_p (TREE_TYPE (decl))) { error_at (DECL_SOURCE_LOCATION (decl), "%qE attribute is not allowed for a non-flexible" " array member field", name); *no_add_attrs = true; } + /* This attribute can be applied to a pointer to void type, but issue + warning when -Wpointer-arith is presenting. */ + else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == VOID_TYPE) + { + if (warn_pointer_arith) + warning_at (DECL_SOURCE_LOCATION (decl), + OPT_Wpointer_arith, + "%qE attribute is used for a pointer to void", + name); + } + /* This attribute cannot be applied to a pointer to function type. */ + else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == FUNCTION_TYPE) + { + error_at (DECL_SOURCE_LOCATION (decl), + "%qE attribute is not allowed for a pointer to" + " function", name); + *no_add_attrs = true; + } + /* This attribute cannot be applied to a pointer to structure or union + with flexible array member. */ + else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE + && RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_TYPE (decl))) + && TYPE_INCLUDES_FLEXARRAY (TREE_TYPE (TREE_TYPE (decl)))) + { + error_at (DECL_SOURCE_LOCATION (decl), + "%qE attribute is not allowed for a pointer to" + " structure or union with flexible array member", name); + *no_add_attrs = true; + } /* The argument should be an identifier. */ else if (TREE_CODE (argval) != IDENTIFIER_NODE) { @@ -2930,7 +3002,8 @@ handle_counted_by_attribute (tree *node, tree name, *no_add_attrs = true; } /* Issue error when there is a counted_by attribute with a different - field as the argument for the same flexible array member field. */ + field as the argument for the same flexible array member or + pointer field. */ else if (old_counted_by != NULL_TREE) { tree old_fieldname = TREE_VALUE (TREE_VALUE (old_counted_by)); @@ -4120,10 +4193,11 @@ handle_argspec_attribute (tree *, tree, tree args, int, bool *) { /* Verify the attribute has one or two arguments and their kind. */ gcc_assert (args && TREE_CODE (TREE_VALUE (args)) == STRING_CST); - for (tree next = TREE_CHAIN (args); next; next = TREE_CHAIN (next)) + if (TREE_CHAIN (args)) { - tree val = TREE_VALUE (next); - gcc_assert (DECL_P (val) || EXPR_P (val)); + tree val = TREE_VALUE (TREE_CHAIN (args)); + gcc_assert (!TREE_CHAIN (TREE_CHAIN (args))); + gcc_assert (TYPE_P (val)); } return NULL_TREE; } @@ -5034,12 +5108,21 @@ handle_nonnull_if_nonzero_attribute (tree *node, tree name, tree type = *node; tree pos = TREE_VALUE (args); tree pos2 = TREE_VALUE (TREE_CHAIN (args)); + tree chain2 = TREE_CHAIN (TREE_CHAIN (args)); + tree pos3 = NULL_TREE; + if (chain2) + pos3 = TREE_VALUE (chain2); tree val = positional_argument (type, name, pos, POINTER_TYPE, 1); tree val2 = positional_argument (type, name, pos2, INTEGER_TYPE, 2); - if (val && val2) + tree val3 = NULL_TREE; + if (chain2) + val3 = positional_argument (type, name, pos3, INTEGER_TYPE, 3); + if (val && val2 && (!chain2 || val3)) { TREE_VALUE (args) = val; TREE_VALUE (TREE_CHAIN (args)) = val2; + if (chain2) + TREE_VALUE (chain2) = val3; } else *no_add_attrs = true; @@ -5101,6 +5184,107 @@ handle_null_terminated_string_arg_attribute (tree *node, tree name, tree args, return NULL_TREE; } +/* Common argument checking for btf_type_tag and btf_decl_tag. + Return true if the ARGS are valid, otherwise emit an error and + return false. */ + +static bool +btf_tag_args_ok (tree name, tree args) +{ + if (!args) /* Correct number of args (1) is checked for us. */ + return false; + else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST) + { + error ("%qE attribute requires a string argument", name); + return false; + } + + /* Only narrow character strings are accepted. */ + tree argtype = TREE_TYPE (TREE_TYPE (TREE_VALUE (args))); + if (!(argtype == char_type_node + || argtype == char8_type_node + || argtype == signed_char_type_node + || argtype == unsigned_char_type_node)) + { + error ("unsupported wide string type argument in %qE attribute", name); + return false; + } + + return true; +} + +/* Handle the "btf_decl_tag" attribute. */ + +static tree +handle_btf_decl_tag_attribute (tree * ARG_UNUSED (node), tree name, tree args, + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + if (!btf_tag_args_ok (name, args)) + *no_add_attrs = true; + + return NULL_TREE; +} + +/* Handle the "btf_type_tag" attribute. */ + +static tree +handle_btf_type_tag_attribute (tree *node, tree name, tree args, + int flags, bool *no_add_attrs) +{ + if (!btf_tag_args_ok (name, args)) + { + *no_add_attrs = true; + return NULL_TREE; + } + + if (TREE_CODE (*node) == FUNCTION_TYPE || TREE_CODE (*node) == METHOD_TYPE) + { + warning (OPT_Wattributes, + "%qE attribute does not apply to functions", name); + *no_add_attrs = true; + return NULL_TREE; + } + + /* Ensure a variant type is always created to hold the type_tag, + unless ATTR_FLAG_IN_PLACE is set. Same logic as in + common_handle_aligned_attribute. */ + tree decl = NULL_TREE; + tree *type = NULL; + bool is_type = false; + + if (DECL_P (*node)) + { + decl = *node; + type = &TREE_TYPE (decl); + is_type = TREE_CODE (*node) == TYPE_DECL; + } + else if (TYPE_P (*node)) + type = node, is_type = true; + + if (is_type) + { + if ((flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + /* OK, modify the type in place. */; + + /* If we have a TYPE_DECL, then copy the type, so that we + don't accidentally modify a builtin type. See pushdecl. */ + else if (decl && TREE_TYPE (decl) != error_mark_node + && DECL_ORIGINAL_TYPE (decl) == NULL_TREE) + { + tree tt = TREE_TYPE (decl); + *type = build_variant_type_copy (*type); + DECL_ORIGINAL_TYPE (decl) = tt; + TYPE_NAME (*type) = decl; + TREE_USED (*type) = TREE_USED (decl); + TREE_TYPE (decl) = *type; + } + else + *type = build_variant_type_copy (*type); + } + + return NULL_TREE; +} + /* Handle the "nonstring" variable attribute. */ static tree @@ -5727,6 +5911,71 @@ handle_access_attribute (tree node[3], tree name, tree args, int flags, return NULL_TREE; } + +/* This function builds a string which is concatenated to SPEC and returns + list of variably bounds corresponding to an array/VLA parameter with + type TYPE. The string consists of one dollar symbol for each specified + variable bound, one asterisk for each unspecified variable bound, + a space for an array of unknown size (only possibly for the outermost), + and a zero for a zero-sized array. + + The chainof variable bounds starts with the most significant bound. + For example, the TYPE T[2][m][3][n] will produce "$$" and (m, (n, nil)). */ + +static tree +build_arg_spec (tree type, std::string *spec) +{ + while (POINTER_TYPE_P (type)) + type = TREE_TYPE (type); + + if (TREE_CODE (type) != ARRAY_TYPE) + return NULL_TREE; + + tree list = build_arg_spec (TREE_TYPE (type), spec); + + if (!COMPLETE_TYPE_P (type)) + { + (*spec) += ' '; + return list; + } + + tree mval = TYPE_MAX_VALUE (TYPE_DOMAIN (type)); + + if (!mval) + { + (*spec) += '0'; + return list; + } + + if (TREE_CODE (mval) == COMPOUND_EXPR + && integer_zerop (TREE_OPERAND (mval, 0)) + && integer_zerop (TREE_OPERAND (mval, 1))) + { + (*spec) += '*'; + return list; + } + + if (TREE_CODE (mval) == INTEGER_CST) + return list; + + /* A variable bound. */ + (*spec) += '$'; + + mval = array_type_nelts_top (type); + + /* Remove NOP_EXPR and SAVE_EXPR to uncover possible PARM_DECLS. */ + if (TREE_CODE (mval) == NOP_EXPR) + mval = TREE_OPERAND (mval, 0); + if (TREE_CODE (mval) == SAVE_EXPR) + { + mval = TREE_OPERAND (mval, 0); + if (TREE_CODE (mval) == NOP_EXPR) + mval = TREE_OPERAND (mval, 0); + } + + return tree_cons (NULL_TREE, mval, list); +} + /* Extract attribute "arg spec" from each FNDECL argument that has it, build a single attribute access corresponding to all the arguments, and return the result. SKIP_VOIDPTR set to ignore void* parameters @@ -5803,15 +6052,16 @@ build_attr_access_from_parms (tree parms, bool skip_voidptr) argspec = TREE_VALUE (argspec); /* The attribute arg spec string. */ - tree str = TREE_VALUE (argspec); - const char *s = TREE_STRING_POINTER (str); + const char *s = TREE_STRING_POINTER (TREE_VALUE (argspec)); + bool static_p = s && (0 == strcmp("static", s)); /* Collect the list of nonnull arguments which use "[static ..]". */ - if (s != NULL && s[0] == '[' && s[1] == 's') + if (static_p) nnlist = tree_cons (NULL_TREE, build_int_cst (integer_type_node, argpos + 1), nnlist); - /* Create the attribute access string from the arg spec string, + tree argvbs; + /* Create the attribute access string from the arg spec data, optionally followed by position of the VLA bound argument if it is one. */ { @@ -5822,21 +6072,52 @@ build_attr_access_from_parms (tree parms, bool skip_voidptr) specend = 1; } - /* 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); + spec += attr_access::mode_chars[access_deferred]; + spec += std::to_string (argpos); + spec += '['; + tree type = TREE_VALUE (TREE_CHAIN (argspec)); + argvbs = build_arg_spec (type, &spec); + + /* Postprocess the string to bring it in the format expected + by the code handling the access attribute. First, we + add 's' if the array was declared as [static ...]. */ + if (static_p) + { + size_t send = spec.length(); + + if (spec[send - 1] == '[') + { + spec += 's'; + } + else + { + /* If there is a symbol, we need to swap the order. */ + spec += spec[send - 1]; + spec[send - 1] = 's'; + } + } + + /* If the outermost bound is an integer constant, we need to write + the size if it is constant. */ + if (type && TYPE_DOMAIN (type)) + { + tree mval = TYPE_MAX_VALUE (TYPE_DOMAIN (type)); + if (mval && TREE_CODE (mval) == INTEGER_CST) + { + char buf[40]; + unsigned HOST_WIDE_INT n = tree_to_uhwi (mval) + 1; + sprintf (buf, HOST_WIDE_INT_PRINT_UNSIGNED, n); + spec += buf; + } + } + spec += ']'; + /* Trim the trailing NUL. */ - spec.resize (specend + len); + spec.resize (spec.length ()); } /* The (optional) list of expressions denoting the VLA bounds N in ARGTYPE <arg>[Ni]...[Nj]...[Nk]. */ - tree argvbs = TREE_CHAIN (argspec); if (argvbs) { spec += ','; @@ -5849,8 +6130,7 @@ build_attr_access_from_parms (tree parms, bool skip_voidptr) order. */ vblist = tree_cons (NULL_TREE, argvbs, vblist); - unsigned nelts = 0; - for (tree vb = argvbs; vb; vb = TREE_CHAIN (vb), ++nelts) + for (tree vb = argvbs; vb; vb = TREE_CHAIN (vb)) { tree bound = TREE_VALUE (vb); if (const unsigned *psizpos = arg2pos.get (bound)) @@ -6132,10 +6412,25 @@ handle_target_clones_attribute (tree *node, tree name, tree ARG_UNUSED (args), } } - if (get_target_clone_attr_len (args) == -1) + int num_defaults = 0; + auto_vec<string_slice> versions = get_clone_attr_versions + (args, + &num_defaults, + false); + + for (auto v : versions) + targetm.check_target_clone_version + (v, &DECL_SOURCE_LOCATION (*node)); + + /* Lone target_clones version is always ignored for target attr semantics. + Only ignore under target_version semantics if it is a default + version. */ + if (versions.length () == 1 + && (TARGET_HAS_FMV_TARGET_ATTRIBUTE || num_defaults == 1)) { - warning (OPT_Wattributes, - "single %<target_clones%> attribute is ignored"); + if (TARGET_HAS_FMV_TARGET_ATTRIBUTE) + warning (OPT_Wattributes, + "single %<target_clones%> attribute is ignored"); *no_add_attrs = true; } else diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc index 587d764..3cec729 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -56,6 +56,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-pretty-print-markup.h" #include "gcc-rich-location.h" #include "gcc-urlifier.h" +#include "diagnostics/diagnostics-selftests.h" cpp_reader *parse_in; /* Declared in c-pragma.h. */ @@ -375,9 +376,10 @@ static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT); C --std=c17: D_C23 | D_CXXONLY | D_OBJC C --std=c23: D_CXXONLY | D_OBJC ObjC is like C except that D_OBJC and D_CXX_OBJC are not set - C++ --std=c++98: D_CONLY | D_CXX11 | D_CXX20 | D_OBJC - C++ --std=c++11: D_CONLY | D_CXX20 | D_OBJC - C++ --std=c++20: D_CONLY | D_OBJC + C++ --std=c++98: D_CONLY | D_CXX11 | D_CXX20 | D_CXX26 | D_OBJC + C++ --std=c++11: D_CONLY | D_CXX20 | D_CXX26 | D_OBJC + C++ --std=c++20: D_CONLY | D_CXX26 | D_OBJC + C++ --std=c++26: D_CONLY | D_OBJC ObjC++ is like C++ except that D_OBJC is not set If -fno-asm is used, D_ASM is added to the mask. If @@ -394,6 +396,9 @@ const struct c_common_resword c_common_reswords[] = { { "_Alignas", RID_ALIGNAS, D_CONLY }, { "_Alignof", RID_ALIGNOF, D_CONLY }, + { "_Countof", RID_COUNTOF, D_CONLY }, + { "_Maxof", RID_MAXOF, D_CONLY }, + { "_Minof", RID_MINOF, D_CONLY }, { "_Atomic", RID_ATOMIC, D_CONLY }, { "_BitInt", RID_BITINT, D_CONLY }, { "_Bool", RID_BOOL, D_CONLY }, @@ -460,7 +465,7 @@ const struct c_common_resword c_common_reswords[] = { "__builtin_tgmath", RID_BUILTIN_TGMATH, D_CONLY }, { "__builtin_offsetof", RID_OFFSETOF, 0 }, { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, D_CONLY }, - { "__builtin_c23_va_start", RID_C23_VA_START, D_C23 }, + { "__builtin_c23_va_start", RID_C23_VA_START, D_C23 | D_CXX26 }, { "__builtin_va_arg", RID_VA_ARG, 0 }, { "__complex", RID_COMPLEX, 0 }, { "__complex__", RID_COMPLEX, 0 }, @@ -1309,6 +1314,7 @@ c_build_vec_convert (location_t loc1, tree expr, location_t loc2, tree type, if (!gnu_vector_type_p (TREE_TYPE (expr)) || (!VECTOR_INTEGER_TYPE_P (TREE_TYPE (expr)) + && !VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (expr)) && !VECTOR_FLOAT_TYPE_P (TREE_TYPE (expr)))) { if (complain) @@ -1318,7 +1324,8 @@ c_build_vec_convert (location_t loc1, tree expr, location_t loc2, tree type, } if (!gnu_vector_type_p (type) - || (!VECTOR_INTEGER_TYPE_P (type) && !VECTOR_FLOAT_TYPE_P (type))) + || (!VECTOR_INTEGER_TYPE_P (type) && !VECTOR_FLOAT_TYPE_P (type) + && !VECTOR_BOOLEAN_TYPE_P (type))) { if (complain) error_at (loc2, "%<__builtin_convertvector%> second argument must " @@ -3437,20 +3444,41 @@ pointer_int_sum (location_t loc, enum tree_code resultcode, an overflow error if the constant is negative but INTOP is not. */ && (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (intop)) || (TYPE_PRECISION (TREE_TYPE (intop)) - == TYPE_PRECISION (TREE_TYPE (ptrop))))) - { - enum tree_code subcode = resultcode; - tree int_type = TREE_TYPE (intop); - if (TREE_CODE (intop) == MINUS_EXPR) - subcode = (subcode == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR); - /* Convert both subexpression types to the type of intop, - because weird cases involving pointer arithmetic - can result in a sum or difference with different type args. */ - ptrop = build_binary_op (EXPR_LOCATION (TREE_OPERAND (intop, 1)), - subcode, ptrop, - convert (int_type, TREE_OPERAND (intop, 1)), - true); - intop = convert (int_type, TREE_OPERAND (intop, 0)); + == TYPE_PRECISION (TREE_TYPE (ptrop)))) + && TYPE_PRECISION (TREE_TYPE (intop)) <= TYPE_PRECISION (sizetype)) + { + tree intop0 = TREE_OPERAND (intop, 0); + tree intop1 = TREE_OPERAND (intop, 1); + if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype) + || TYPE_UNSIGNED (TREE_TYPE (intop)) != TYPE_UNSIGNED (sizetype)) + { + tree optype = c_common_type_for_size (TYPE_PRECISION (sizetype), + TYPE_UNSIGNED (sizetype)); + intop0 = convert (optype, intop0); + intop1 = convert (optype, intop1); + } + tree t = fold_build2_loc (loc, MULT_EXPR, TREE_TYPE (intop0), intop0, + convert (TREE_TYPE (intop0), size_exp)); + intop0 = convert (sizetype, t); + if (TREE_OVERFLOW_P (intop0) && !TREE_OVERFLOW (t)) + intop0 = wide_int_to_tree (TREE_TYPE (intop0), wi::to_wide (intop0)); + t = fold_build2_loc (loc, MULT_EXPR, TREE_TYPE (intop1), intop1, + convert (TREE_TYPE (intop1), size_exp)); + intop1 = convert (sizetype, t); + if (TREE_OVERFLOW_P (intop1) && !TREE_OVERFLOW (t)) + intop1 = wide_int_to_tree (TREE_TYPE (intop1), wi::to_wide (intop1)); + intop = build_binary_op (EXPR_LOCATION (intop), TREE_CODE (intop), + intop0, intop1, true); + + /* Create the sum or difference. */ + if (resultcode == MINUS_EXPR) + intop = fold_build1_loc (loc, NEGATE_EXPR, sizetype, intop); + + ret = fold_build_pointer_plus_loc (loc, ptrop, intop); + + fold_undefer_and_ignore_overflow_warnings (); + + return ret; } /* Convert the integer argument to a type the same size as sizetype @@ -3917,14 +3945,40 @@ c_common_get_alias_set (tree t) /* The C standard specifically allows aliasing between signed and unsigned variants of the same type. We treat the signed variant as canonical. */ - if ((TREE_CODE (t) == INTEGER_TYPE || TREE_CODE (t) == BITINT_TYPE) - && TYPE_UNSIGNED (t)) - { - tree t1 = c_common_signed_type (t); - - /* t1 == t can happen for boolean nodes which are always unsigned. */ - if (t1 != t) - return get_alias_set (t1); + if (TREE_CODE (t) == INTEGER_TYPE || TREE_CODE (t) == BITINT_TYPE) + { + /* For normal INTEGER_TYPEs (except ones built by + build_nonstandard_integer_type), both signed and unsigned variants + of the type are always reachable from GTY roots, so just calling + get_alias_set on the signed type is ok. For BITINT_TYPE and + non-standard INTEGER_TYPEs, only unsigned could be used and the + corresponding signed type could be created on demand and garbage + collected as unused, so the alias set of unsigned type could keep + changing. + Avoid that by remembering the signed type alias set in + TYPE_ALIAS_SET and also when being asked about !TYPE_UNSIGNED + check if there isn't a corresponding unsigned type with + TYPE_ALIAS_SET_KNOWN_P. */ + if (TYPE_UNSIGNED (t)) + { + /* There is no signed _BitInt(1). */ + if (TREE_CODE (t) == BITINT_TYPE && TYPE_PRECISION (t) == 1) + return -1; + tree t1 = c_common_signed_type (t); + gcc_checking_assert (t != t1); + TYPE_ALIAS_SET (t) = get_alias_set (t1); + return TYPE_ALIAS_SET (t); + } + else + { + tree t1 = c_common_unsigned_type (t); + gcc_checking_assert (t != t1); + if (TYPE_ALIAS_SET_KNOWN_P (t1)) + { + TYPE_ALIAS_SET (t) = TYPE_ALIAS_SET (t1); + return TYPE_ALIAS_SET (t); + } + } } return -1; @@ -4080,6 +4134,79 @@ c_alignof_expr (location_t loc, tree expr) return fold_convert_loc (loc, size_type_node, t); } + +/* Implement the _Countof keyword: + Return the number of elements of an array. */ + +tree +c_countof_type (location_t loc, tree type) +{ + enum tree_code type_code; + tree value; + + type_code = TREE_CODE (type); + if (type_code != ARRAY_TYPE) + { + error_at (loc, "invalid application of %<_Countof%> to type %qT", type); + return error_mark_node; + } + if (!COMPLETE_TYPE_P (type)) + { + error_at (loc, + "invalid application of %<_Countof%> to incomplete type %qT", + type); + return error_mark_node; + } + + value = array_type_nelts_top (type); + /* VALUE will have the middle-end integer type sizetype. + However, we should really return a value of type `size_t', + which is just a typedef for an ordinary integer type. */ + value = fold_convert_loc (loc, size_type_node, value); + return value; +} + +/* Implement the _Maxof operator: + Return the maximum representable value of an integer type. */ + +tree +c_maxof_type (location_t loc, tree type) +{ + if (!INTEGRAL_TYPE_P (type)) + { + error_at (loc, "invalid application of %<_Maxof%> to type %qT", type); + return error_mark_node; + } + if (!COMPLETE_TYPE_P (type)) + { + error_at (loc, "invalid application of %<_Maxof%> to incomplete type %qT", + type); + return error_mark_node; + } + + return TYPE_MAX_VALUE (type); +} + +/* Implement the _Minof operator: + Return the minimum representable value of an integer type. */ + +tree +c_minof_type (location_t loc, tree type) +{ + if (!INTEGRAL_TYPE_P (type)) + { + error_at (loc, "invalid application of %<_Minof%> to type %qT", type); + return error_mark_node; + } + if (!COMPLETE_TYPE_P (type)) + { + error_at (loc, "invalid application of %<_Minof%> to incomplete type %qT", + type); + return error_mark_node; + } + + return TYPE_MIN_VALUE (type); +} /* Handle C and C++ default attributes. */ @@ -5723,8 +5850,8 @@ struct nonnull_arg_ctx /* The function whose arguments are being checked and its type (used for calls through function pointers). */ const_tree fndecl, fntype; - /* For nonnull_if_nonzero, index of the other argument. */ - unsigned HOST_WIDE_INT other; + /* For nonnull_if_nonzero, index of the other arguments. */ + unsigned HOST_WIDE_INT other1, other2; /* True if a warning has been issued. */ bool warned_p; }; @@ -5792,6 +5919,7 @@ check_function_nonnull (nonnull_arg_ctx &ctx, int nargs, tree *argarray) check_function_arguments_recurse (check_nonnull_arg, &ctx, argarray[i], i + 1, OPT_Wnonnull); + a = NULL_TREE; } } if (a == NULL_TREE) @@ -5803,17 +5931,25 @@ check_function_nonnull (nonnull_arg_ctx &ctx, int nargs, tree *argarray) unsigned int idx = TREE_INT_CST_LOW (TREE_VALUE (args)) - 1; unsigned int idx2 = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (args))) - 1; + unsigned int idx3 = idx2; + if (tree chain2 = TREE_CHAIN (TREE_CHAIN (args))) + idx3 = TREE_INT_CST_LOW (TREE_VALUE (chain2)) - 1; if (idx < (unsigned) nargs - firstarg && idx2 < (unsigned) nargs - firstarg + && idx3 < (unsigned) nargs - firstarg && INTEGRAL_TYPE_P (TREE_TYPE (argarray[firstarg + idx2])) - && integer_nonzerop (argarray[firstarg + idx2])) + && integer_nonzerop (argarray[firstarg + idx2]) + && INTEGRAL_TYPE_P (TREE_TYPE (argarray[firstarg + idx3])) + && integer_nonzerop (argarray[firstarg + idx3])) { - ctx.other = firstarg + idx2 + 1; + ctx.other1 = firstarg + idx2 + 1; + ctx.other2 = firstarg + idx3 + 1; check_function_arguments_recurse (check_nonnull_arg, &ctx, argarray[firstarg + idx], firstarg + idx + 1, OPT_Wnonnull); - ctx.other = 0; + ctx.other1 = 0; + ctx.other2 = 0; } } return ctx.warned_p; @@ -5997,14 +6133,25 @@ check_nonnull_arg (void *ctx, tree param, unsigned HOST_WIDE_INT param_num) } else { - if (pctx->other) + if (pctx->other1 && pctx->other2 != pctx->other1) + warned = warning_at (loc, OPT_Wnonnull, + "argument %u null where non-null expected " + "because arguments %u and %u are nonzero", + (unsigned) param_num, + TREE_CODE (pctx->fntype) == METHOD_TYPE + ? (unsigned) pctx->other1 - 1 + : (unsigned) pctx->other1, + TREE_CODE (pctx->fntype) == METHOD_TYPE + ? (unsigned) pctx->other2 - 1 + : (unsigned) pctx->other2); + else if (pctx->other1) warned = warning_at (loc, OPT_Wnonnull, "argument %u null where non-null expected " "because argument %u is nonzero", (unsigned) param_num, TREE_CODE (pctx->fntype) == METHOD_TYPE - ? (unsigned) pctx->other - 1 - : (unsigned) pctx->other); + ? (unsigned) pctx->other1 - 1 + : (unsigned) pctx->other1); else warned = warning_at (loc, OPT_Wnonnull, "argument %u null where non-null expected", @@ -6013,7 +6160,7 @@ check_nonnull_arg (void *ctx, tree param, unsigned HOST_WIDE_INT param_num) inform (DECL_SOURCE_LOCATION (pctx->fndecl), "in a call to function %qD declared %qs", pctx->fndecl, - pctx->other ? "nonnull_if_nonzero" : "nonnull"); + pctx->other1 ? "nonnull_if_nonzero" : "nonnull"); } if (warned) @@ -6269,7 +6416,7 @@ check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype, to do this if format checking is enabled. */ if (warn_nonnull) { - nonnull_arg_ctx ctx = { loc, fndecl, fntype, 0, false }; + nonnull_arg_ctx ctx = { loc, fndecl, fntype, 0, 0, false }; warned_p = check_function_nonnull (ctx, nargs, argarray); } @@ -6958,7 +7105,7 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token_type, /* Return the gcc option code associated with the reason for a cpp message, or 0 if none. */ -static diagnostic_option_id +static diagnostics::option_id c_option_controlling_cpp_diagnostic (enum cpp_warning_reason reason) { const struct cpp_reason_option_codes_t *entry; @@ -7000,8 +7147,8 @@ c_cpp_diagnostic (cpp_reader *pfile ATTRIBUTE_UNUSED, rich_location *richloc, const char *msg, va_list *ap) { - diagnostic_info diagnostic; - diagnostic_t dlevel; + diagnostics::diagnostic_info diagnostic; + enum diagnostics::kind dlevel; bool save_warn_system_headers = global_dc->m_warn_system_headers; bool ret; @@ -7015,24 +7162,24 @@ c_cpp_diagnostic (cpp_reader *pfile ATTRIBUTE_UNUSED, case CPP_DL_WARNING: if (flag_no_output) return false; - dlevel = DK_WARNING; + dlevel = diagnostics::kind::warning; break; case CPP_DL_PEDWARN: if (flag_no_output && !flag_pedantic_errors) return false; - dlevel = DK_PEDWARN; + dlevel = diagnostics::kind::pedwarn; break; case CPP_DL_ERROR: - dlevel = DK_ERROR; + dlevel = diagnostics::kind::error; break; case CPP_DL_ICE: - dlevel = DK_ICE; + dlevel = diagnostics::kind::ice; break; case CPP_DL_NOTE: - dlevel = DK_NOTE; + dlevel = diagnostics::kind::note; break; case CPP_DL_FATAL: - dlevel = DK_FATAL; + dlevel = diagnostics::kind::fatal; break; default: gcc_unreachable (); @@ -9896,8 +10043,11 @@ c_family_tests (void) c_indentation_cc_tests (); c_pretty_print_cc_tests (); c_spellcheck_cc_tests (); - c_diagnostic_cc_tests (); c_opt_problem_cc_tests (); + + /* According to https://gcc.gnu.org/pipermail/gcc/2021-November/237703.html + this has some language-specific assumptions, so we run it here. */ + diagnostics::selftest::context_cc_tests (); } } // namespace selftest @@ -9979,7 +10129,7 @@ try_to_locate_new_include_insertion_point (const char *file, location_t loc) return UNKNOWN_LOCATION; /* The "start_location" is column 0, meaning "the whole line". - rich_location and edit_context can't cope with this, so use + rich_location and diagnostics::changes can't cope with this, so use column 1 instead. */ location_t col_0 = ord_map_for_insertion->start_location; return linemap_position_for_loc_and_offset (line_table, col_0, 1); @@ -10043,7 +10193,7 @@ maybe_add_include_fixit (rich_location *richloc, const char *header, richloc->add_fixit_insert_before (include_insert_loc, text); free (text); - if (override_location && global_dc->m_source_printing.enabled) + if (override_location && global_dc->get_source_printing_options ().enabled) { /* Replace the primary location with that of the insertion point for the fix-it hint. @@ -10224,6 +10374,7 @@ braced_list_to_string (tree type, tree ctor, bool member) j = i - start; else j -= start; + value = copy_node (value); RAW_DATA_POINTER (value) -= start; RAW_DATA_LENGTH (value) += start + end; i += end; diff --git a/gcc/c-family/c-common.def b/gcc/c-family/c-common.def index cf22282..9b1f034 100644 --- a/gcc/c-family/c-common.def +++ b/gcc/c-family/c-common.def @@ -50,6 +50,15 @@ DEFTREECODE (EXCESS_PRECISION_EXPR, "excess_precision_expr", tcc_expression, 1) number. */ DEFTREECODE (USERDEF_LITERAL, "userdef_literal", tcc_exceptional, 3) +/* Represents a 'countof' expression. */ +DEFTREECODE (COUNTOF_EXPR, "countof_expr", tcc_expression, 1) + +/* Represents a 'maxof' expression. */ +DEFTREECODE (MAXOF_EXPR, "maxof_expr", tcc_expression, 1) + +/* Represents a 'minof' expression. */ +DEFTREECODE (MINOF_EXPR, "minof_expr", tcc_expression, 1) + /* Represents a 'sizeof' expression during C++ template expansion, or for the purpose of -Wsizeof-pointer-memaccess warning. */ DEFTREECODE (SIZEOF_EXPR, "sizeof_expr", tcc_expression, 1) diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index ea6c297..6a92bd6 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -105,6 +105,7 @@ enum rid /* C extensions */ RID_ASM, RID_TYPEOF, RID_TYPEOF_UNQUAL, RID_ALIGNOF, RID_ATTRIBUTE, + RID_COUNTOF, RID_MAXOF, RID_MINOF, RID_C23_VA_START, RID_VA_ARG, RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_CHOOSE_EXPR, RID_TYPES_COMPATIBLE_P, RID_BUILTIN_COMPLEX, RID_BUILTIN_SHUFFLE, @@ -447,6 +448,7 @@ extern machine_mode c_default_pointer_mode; #define D_CXX20 0x8000 /* In C++, C++20 only. */ #define D_CXX_COROUTINES 0x10000 /* In C++, only with coroutines. */ #define D_CXX_MODULES 0x20000 /* In C++, only with modules. */ +#define D_CXX26 0x40000 /* In C++, C++26 only. */ #define D_CXX_CONCEPTS_FLAGS D_CXXONLY | D_CXX_CONCEPTS #define D_CXX_CHAR8_T_FLAGS D_CXXONLY | D_CXX_CHAR8_T @@ -746,7 +748,7 @@ enum cxx_dialect { cxx26 }; -/* The C++ dialect being used. C++98 is the default. */ +/* The C++ dialect being used. C++17 is the default. */ extern enum cxx_dialect cxx_dialect; /* Maximum template instantiation depth. This limit is rather @@ -890,6 +892,9 @@ extern tree c_common_truthvalue_conversion (location_t, tree); extern void c_apply_type_quals_to_decl (int, tree); extern tree c_sizeof_or_alignof_type (location_t, tree, bool, bool, int); extern tree c_alignof_expr (location_t, tree); +extern tree c_countof_type (location_t, tree); +extern tree c_maxof_type (location_t, tree); +extern tree c_minof_type (location_t, tree); /* Print an error message for invalid operands to arith operation CODE. NOP_EXPR is used as a special case (see truthvalue_conversion). */ extern void binary_op_error (rich_location *, enum tree_code, tree, tree); @@ -977,7 +982,7 @@ extern tree build_va_arg (location_t, tree, tree); extern const unsigned int c_family_lang_mask; extern unsigned int c_common_option_lang_mask (void); -extern void c_common_diagnostics_set_defaults (diagnostic_context *); +extern void c_common_diagnostics_set_defaults (diagnostics::context *); extern bool c_common_complain_wrong_lang_p (const struct cl_option *); extern void c_common_init_options_struct (struct gcc_options *); extern void c_common_init_options (unsigned int, struct cl_decoded_option *); @@ -1263,7 +1268,7 @@ extern void c_stddef_cpp_builtins (void); extern void fe_file_change (const line_map_ordinary *); extern void c_parse_error (const char *, enum cpp_ttype, tree, unsigned char, rich_location *richloc); -extern diagnostic_option_id get_option_for_builtin_define (const char *macro_name); +extern diagnostics::option_id get_option_for_builtin_define (const char *macro_name); /* In c-ppoutput.cc */ extern void init_pp_output (FILE *); @@ -1301,10 +1306,12 @@ enum c_omp_region_type C_ORT_TARGET = 1 << 3, C_ORT_EXIT_DATA = 1 << 4, C_ORT_INTEROP = 1 << 5, + C_ORT_DECLARE_MAPPER = 1 << 6, C_ORT_OMP_DECLARE_SIMD = C_ORT_OMP | C_ORT_DECLARE_SIMD, C_ORT_OMP_TARGET = C_ORT_OMP | C_ORT_TARGET, C_ORT_OMP_EXIT_DATA = C_ORT_OMP | C_ORT_EXIT_DATA, C_ORT_OMP_INTEROP = C_ORT_OMP | C_ORT_INTEROP, + C_ORT_OMP_DECLARE_MAPPER = C_ORT_OMP | C_ORT_DECLARE_MAPPER, C_ORT_ACC_TARGET = C_ORT_ACC | C_ORT_TARGET }; @@ -1343,6 +1350,9 @@ extern enum omp_clause_defaultmap_kind c_omp_predetermined_mapping (tree); extern tree c_omp_check_context_selector (location_t, tree); extern void c_omp_mark_declare_variant (location_t, tree, tree); extern void c_omp_adjust_map_clauses (tree, bool); +template<typename T> struct omp_mapper_list; +extern void c_omp_find_nested_mappers (struct omp_mapper_list<tree> *, tree); +extern tree c_omp_instantiate_mappers (tree); namespace omp_addr_tokenizer { struct omp_addr_token; } typedef omp_addr_tokenizer::omp_addr_token omp_addr_token; @@ -1616,7 +1626,7 @@ extern void c_do_switch_warnings (splay_tree, location_t, tree, tree, bool); extern void warn_for_omitted_condop (location_t, tree); extern bool warn_for_restrict (unsigned, tree *, unsigned); extern void warn_for_address_of_packed_member (tree, tree); -extern void warn_parm_array_mismatch (location_t, tree, tree); +extern void warn_parms_array_mismatch (location_t, tree, tree); extern void maybe_warn_sizeof_array_div (location_t, tree, tree, tree, tree); extern void do_warn_array_compare (location_t, tree_code, tree, tree); @@ -1706,7 +1716,7 @@ extern enum flt_eval_method excess_precision_mode_join (enum flt_eval_method, enum flt_eval_method); extern int c_flt_eval_method (bool ts18661_p); -extern void add_no_sanitize_value (tree node, unsigned int flags); +extern void add_no_sanitize_value (tree node, sanitize_code_type flags); extern void maybe_add_include_fixit (rich_location *, const char *, bool); extern void maybe_suggest_missing_token_insertion (rich_location *richloc, @@ -1722,7 +1732,6 @@ extern tree braced_lists_to_strings (tree, tree); namespace selftest { /* Declarations for specific families of tests within c-family, by source file, in alphabetical order. */ - extern void c_diagnostic_cc_tests (void); extern void c_format_cc_tests (void); extern void c_indentation_cc_tests (void); extern void c_opt_problem_cc_tests (void); diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc index 4589ee4..eac6969 100644 --- a/gcc/c-family/c-cppbuiltin.cc +++ b/gcc/c-family/c-cppbuiltin.cc @@ -913,23 +913,42 @@ c_cpp_builtins (cpp_reader *pfile) /* encoding definitions used by users and libraries */ builtin_define_with_value ("__GNUC_EXECUTION_CHARSET_NAME", - cpp_get_narrow_charset_name (pfile), 1); + cpp_get_narrow_charset_name (pfile), 1); builtin_define_with_value ("__GNUC_WIDE_EXECUTION_CHARSET_NAME", - cpp_get_wide_charset_name (pfile), 1); - + cpp_get_wide_charset_name (pfile), 1); if (c_dialect_cxx ()) - { - int major; - parse_basever (&major, NULL, NULL); - cpp_define_formatted (pfile, "__GNUG__=%d", major); - } + { + int major; + parse_basever (&major, NULL, NULL); + cpp_define_formatted (pfile, "__GNUG__=%d", major); + } /* For stddef.h. They require macros defined in c-common.cc. */ c_stddef_cpp_builtins (); + /* Variant of cpp_define which arranges for diagnostics on user #define + or #undef of the macros. */ + auto cpp_define_warn = [] (cpp_reader *pfile, const char *def) + { + const char *end = strchr (def, '='); + cpp_define (pfile, def); + cpp_warn (pfile, def, end ? end - def : strlen (def)); + }; + if (c_dialect_cxx ()) { + /* Treat all cpp_define calls in this block for macros starting + with __cpp_ (for C++20 and later) or __STDCPP_ as cpp_define_warn. */ + auto cpp_define = [=] (cpp_reader *pfile, const char *def) + { + if ((cxx_dialect >= cxx20 && startswith (def, "__cpp_")) + || startswith (def, "__STDCPP_")) + cpp_define_warn (pfile, def); + else + ::cpp_define (pfile, def); + }; + if (flag_weak && SUPPORTS_ONE_ONLY) cpp_define (pfile, "__GXX_WEAK__=1"); else @@ -1087,52 +1106,78 @@ c_cpp_builtins (cpp_reader *pfile) { /* Set feature test macros for C++26. */ cpp_define (pfile, "__cpp_constexpr=202406L"); + cpp_define (pfile, "__cpp_constexpr_exceptions=202411L"); cpp_define (pfile, "__cpp_static_assert=202306L"); cpp_define (pfile, "__cpp_placeholder_variables=202306L"); - cpp_define (pfile, "__cpp_structured_bindings=202403L"); + cpp_define (pfile, "__cpp_structured_bindings=202411L"); cpp_define (pfile, "__cpp_deleted_function=202403L"); cpp_define (pfile, "__cpp_variadic_friend=202403L"); cpp_define (pfile, "__cpp_pack_indexing=202311L"); cpp_define (pfile, "__cpp_pp_embed=202502L"); + cpp_define (pfile, "__cpp_constexpr_virtual_inheritance=202506L"); + cpp_define (pfile, "__cpp_expansion_statements=202506L"); } if (flag_concepts && cxx_dialect > cxx14) cpp_define (pfile, "__cpp_concepts=202002L"); + else if (cxx_dialect >= cxx20) + cpp_warn (pfile, "__cpp_concepts"); if (flag_contracts) { cpp_define (pfile, "__cpp_contracts=201906L"); cpp_define (pfile, "__cpp_contracts_literal_semantics=201906L"); cpp_define (pfile, "__cpp_contracts_roles=201906L"); } + else if (cxx_dialect >= cxx26) + cpp_warn (pfile, "__cpp_contracts"); if (flag_modules) /* The std-defined value is 201907L, but I don't think we can claim victory yet. 201810 is the p1103 date. */ cpp_define (pfile, "__cpp_modules=201810L"); + else if (cxx_dialect >= cxx20) + cpp_warn (pfile, "__cpp_modules"); if (flag_coroutines) cpp_define (pfile, "__cpp_impl_coroutine=201902L"); /* n4861, DIS */ + else if (cxx_dialect >= cxx20) + cpp_warn (pfile, "__cpp_impl_coroutine"); if (flag_tm) /* Use a value smaller than the 201505 specified in the TS, since we don't yet support atomic_cancel. */ cpp_define (pfile, "__cpp_transactional_memory=201500L"); if (flag_sized_deallocation) cpp_define (pfile, "__cpp_sized_deallocation=201309L"); + else if (cxx_dialect >= cxx20) + cpp_warn (pfile, "__cpp_sized_deallocation"); if (aligned_new_threshold) { cpp_define (pfile, "__cpp_aligned_new=201606L"); cpp_define_formatted (pfile, "__STDCPP_DEFAULT_NEW_ALIGNMENT__=%d", aligned_new_threshold); } + else if (cxx_dialect >= cxx20) + cpp_warn (pfile, "__cpp_aligned_new"); + if (cxx_dialect >= cxx17) + cpp_warn (pfile, "__STDCPP_DEFAULT_NEW_ALIGNMENT__"); if (flag_new_ttp) cpp_define (pfile, "__cpp_template_template_args=201611L"); + else if (cxx_dialect >= cxx20) + cpp_warn (pfile, "__cpp_template_template_args"); if (flag_threadsafe_statics) cpp_define (pfile, "__cpp_threadsafe_static_init=200806L"); + else if (cxx_dialect >= cxx20) + cpp_warn (pfile, "__cpp_threadsafe_static_init"); if (flag_char8_t) cpp_define (pfile, "__cpp_char8_t=202207L"); + else if (cxx_dialect >= cxx20) + cpp_warn (pfile, "__cpp_char8_t"); #ifndef THREAD_MODEL_SPEC /* Targets that define THREAD_MODEL_SPEC need to define __STDCPP_THREADS__ in their config/XXX/XXX-c.c themselves. */ if (cxx_dialect >= cxx11 && strcmp (thread_model, "single") != 0) cpp_define (pfile, "__STDCPP_THREADS__=1"); + else #endif + if (cxx_dialect >= cxx11) + cpp_warn (pfile, "__STDCPP_THREADS__"); if (flag_implicit_constexpr) cpp_define (pfile, "__cpp_implicit_constexpr=20211111L"); } @@ -1281,16 +1326,22 @@ c_cpp_builtins (cpp_reader *pfile) for (int i = 0; i < NUM_FLOATN_NX_TYPES; i++) { - if (FLOATN_NX_TYPE_NODE (i) == NULL_TREE) - continue; if (c_dialect_cxx () && cxx_dialect > cxx20 && !floatn_nx_types[i].extended) { char name[sizeof ("__STDCPP_FLOAT128_T__=1")]; + if (FLOATN_NX_TYPE_NODE (i) == NULL_TREE) + { + sprintf (name, "__STDCPP_FLOAT%d_T__", floatn_nx_types[i].n); + cpp_warn (pfile, name); + continue; + } sprintf (name, "__STDCPP_FLOAT%d_T__=1", floatn_nx_types[i].n); - cpp_define (pfile, name); + cpp_define_warn (pfile, name); } + else if (FLOATN_NX_TYPE_NODE (i) == NULL_TREE) + continue; char prefix[20], csuffix[20]; sprintf (prefix, "FLT%d%s", floatn_nx_types[i].n, floatn_nx_types[i].extended ? "X" : ""); @@ -1302,10 +1353,12 @@ c_cpp_builtins (cpp_reader *pfile) if (bfloat16_type_node) { if (c_dialect_cxx () && cxx_dialect > cxx20) - cpp_define (pfile, "__STDCPP_BFLOAT16_T__=1"); + cpp_define_warn (pfile, "__STDCPP_BFLOAT16_T__=1"); builtin_define_float_constants ("BFLT16", "BF16", "%s", "BF16", bfloat16_type_node); } + else if (cxx_dialect >= cxx23) + cpp_warn (pfile, "__STDCPP_BFLOAT16_T__"); /* For float.h. */ if (targetm.decimal_float_supported_p ()) @@ -1678,7 +1731,7 @@ c_cpp_builtins (cpp_reader *pfile) /* Given NAME, return the command-line option that would make it be a builtin define, or 0 if unrecognized. */ -diagnostic_option_id +diagnostics::option_id get_option_for_builtin_define (const char *name) { if (!strcmp (name, "_OPENACC")) diff --git a/gcc/c-family/c-format.cc b/gcc/c-family/c-format.cc index 211d20d..bf144d0 100644 --- a/gcc/c-family/c-format.cc +++ b/gcc/c-family/c-format.cc @@ -32,7 +32,8 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic.h" #include "substring-locations.h" #include "selftest.h" -#include "selftest-diagnostic.h" +#include "diagnostics/selftest-context.h" +#include "diagnostics/file-cache.h" #include "builtins.h" #include "attribs.h" #include "c-family/c-type-mismatch.h" @@ -70,6 +71,7 @@ static GTY(()) tree local_event_ptr_node; static GTY(()) tree local_pp_element_ptr_node; static GTY(()) tree local_gimple_ptr_node; static GTY(()) tree local_cgraph_node_ptr_node; +static GTY(()) tree local_string_slice_node; static GTY(()) tree locus; static bool decode_format_attr (const_tree, tree, tree, function_format_info *, @@ -770,6 +772,7 @@ static const format_char_info asm_fprintf_char_table[] = { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "c", NULL }, \ { "r", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "//cR", NULL }, \ { "@", 1, STD_C89, { T_EVENT_PTR, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, \ + { "B", 1, STD_C89, { T_STRING_SLICE, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q", "", NULL }, \ { "e", 1, STD_C89, { T_PP_ELEMENT_PTR, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "\"", NULL }, \ { "<", 0, STD_C89, NOARGUMENTS, "", "<", NULL }, \ { ">", 0, STD_C89, NOARGUMENTS, "", ">", NULL }, \ @@ -2124,7 +2127,7 @@ flag_chars_t::validate (const format_kind_info *fki, { format_warning_at_char (format_string_loc, format_string_cst, format_chars - orig_format_chars - 1, - OPT_Wformat_, + OPT_Wformat_diag, "%s used within a quoted sequence", _(s->name)); } @@ -2137,7 +2140,7 @@ flag_chars_t::validate (const format_kind_info *fki, { format_warning_at_char (format_string_loc, format_string_cst, format_chars - orig_format_chars, - OPT_Wformat_, + OPT_Wformat_diag, "%qc conversion used unquoted", format_char); } @@ -4632,7 +4635,7 @@ get_corrected_substring (const substring_loc &fmt_loc, if (caret.column > finish.column) return NULL; - char_span line + diagnostics::char_span line = global_dc->get_file_cache ().get_source_line (start.file, start.line); if (!line) return NULL; @@ -4644,7 +4647,8 @@ get_corrected_substring (const substring_loc &fmt_loc, specification, up to the (but not including) the length modifier. In the above example, this would be "%-+*.*". */ int length_up_to_type = caret.column - start.column; - char_span prefix_span = line.subspan (start.column - 1, length_up_to_type); + diagnostics::char_span prefix_span + = line.subspan (start.column - 1, length_up_to_type); char *prefix = prefix_span.xstrdup (); /* Now attempt to generate a suggestion for the rest of the specification @@ -5211,6 +5215,11 @@ init_dynamic_diag_info (void) || local_cgraph_node_ptr_node == void_type_node) local_cgraph_node_ptr_node = get_named_type ("cgraph_node"); + /* Similar to the above but for string_slice*. */ + if (!local_string_slice_node + || local_string_slice_node == void_type_node) + local_string_slice_node = get_named_type ("string_slice"); + /* Similar to the above but for diagnostic_event_id_t*. */ if (!local_event_ptr_node || local_event_ptr_node == void_type_node) @@ -5577,10 +5586,12 @@ test_type_mismatch_range_labels () gcc_rich_location richloc (fmt, &fmt_label, nullptr); richloc.add_range (param, SHOW_RANGE_WITHOUT_CARET, ¶m_label); - test_diagnostic_context dc; + diagnostics::selftest::test_context dc; diagnostic_show_locus (&dc, - dc.m_source_printing, - &richloc, DK_ERROR, dc.get_reference_printer ()); + dc.get_source_printing_options (), + &richloc, + diagnostics::kind::error, + dc.get_reference_printer ()); if (c_dialect_cxx ()) /* "char*", without a space. */ ASSERT_STREQ (" printf (\"msg: %i\\n\", msg);\n" diff --git a/gcc/c-family/c-format.h b/gcc/c-family/c-format.h index 323338c..d44d386 100644 --- a/gcc/c-family/c-format.h +++ b/gcc/c-family/c-format.h @@ -317,6 +317,7 @@ struct format_kind_info #define T89_G { STD_C89, NULL, &local_gimple_ptr_node } #define T_CGRAPH_NODE { STD_C89, NULL, &local_cgraph_node_ptr_node } #define T_EVENT_PTR { STD_C89, NULL, &local_event_ptr_node } +#define T_STRING_SLICE { STD_C89, NULL, &local_string_slice_node } #define T_PP_ELEMENT_PTR { STD_C89, NULL, &local_pp_element_ptr_node } #define T89_T { STD_C89, NULL, &local_tree_type_node } #define T89_V { STD_C89, NULL, T_V } diff --git a/gcc/c-family/c-gimplify.cc b/gcc/c-family/c-gimplify.cc index c6fb764..2249c10 100644 --- a/gcc/c-family/c-gimplify.cc +++ b/gcc/c-family/c-gimplify.cc @@ -66,6 +66,19 @@ along with GCC; see the file COPYING3. If not see walk back up, we check that they fit our constraints, and copy them into temporaries if not. */ + +/* Check whether TP is an address computation whose base is a call to + .ACCESS_WITH_SIZE. */ + +static bool +is_address_with_access_with_size (tree tp) +{ + if (TREE_CODE (tp) == POINTER_PLUS_EXPR + && is_access_with_size_p (TREE_OPERAND (tp, 0))) + return true; + return false; +} + /* Callback for c_genericize. */ static tree @@ -121,6 +134,20 @@ ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data) walk_tree (&TREE_OPERAND (*tp, 1), ubsan_walk_array_refs_r, pset, pset); walk_tree (&TREE_OPERAND (*tp, 0), ubsan_walk_array_refs_r, pset, pset); } + else if (TREE_CODE (*tp) == INDIRECT_REF + && is_address_with_access_with_size (TREE_OPERAND (*tp, 0))) + { + ubsan_maybe_instrument_array_ref (&TREE_OPERAND (*tp, 0), false); + /* Make sure ubsan_maybe_instrument_array_ref is not called again on + the POINTER_PLUS_EXPR, so ensure it is not walked again and walk + its subtrees manually. */ + tree aref = TREE_OPERAND (*tp, 0); + pset->add (aref); + *walk_subtrees = 0; + walk_tree (&TREE_OPERAND (aref, 0), ubsan_walk_array_refs_r, pset, pset); + } + else if (is_address_with_access_with_size (*tp)) + ubsan_maybe_instrument_array_ref (tp, true); return NULL_TREE; } @@ -1009,7 +1036,14 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED, && call_expr_nargs (*expr_p) == 2 && TREE_CODE (CALL_EXPR_ARG (*expr_p, 1)) != INTEGER_CST) { - tree a = save_expr (CALL_EXPR_ARG (*expr_p, 0)); + tree a = CALL_EXPR_ARG (*expr_p, 0); + if (gimplify_expr (&a, pre_p, post_p, is_gimple_val, fb_rvalue) + == GS_ERROR) + return GS_ERROR; + tree b = CALL_EXPR_ARG (*expr_p, 1); + if (gimplify_expr (&b, pre_p, post_p, is_gimple_val, fb_rvalue) + == GS_ERROR) + return GS_ERROR; tree c = build_call_expr_loc (EXPR_LOCATION (*expr_p), fndecl, 1, a); *expr_p = build3_loc (EXPR_LOCATION (*expr_p), COND_EXPR, @@ -1017,7 +1051,7 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED, build2_loc (EXPR_LOCATION (*expr_p), NE_EXPR, boolean_type_node, a, build_zero_cst (TREE_TYPE (a))), - c, CALL_EXPR_ARG (*expr_p, 1)); + c, b); return GS_OK; } break; diff --git a/gcc/c-family/c-indentation.cc b/gcc/c-family/c-indentation.cc index 2e8261d..d378464 100644 --- a/gcc/c-family/c-indentation.cc +++ b/gcc/c-family/c-indentation.cc @@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see #include "c-indentation.h" #include "selftest.h" #include "diagnostic.h" +#include "diagnostics/file-cache.h" /* Round up VIS_COLUMN to nearest tab stop. */ @@ -45,13 +46,13 @@ next_tab_stop (unsigned int vis_column, unsigned int tab_width) on the line (up to or before EXPLOC). */ static bool -get_visual_column (file_cache &fc, +get_visual_column (diagnostics::file_cache &fc, expanded_location exploc, unsigned int *out, unsigned int *first_nws, unsigned int tab_width) { - char_span line = fc.get_source_line (exploc.file, exploc.line); + diagnostics::char_span line = fc.get_source_line (exploc.file, exploc.line); if (!line) return false; if ((size_t)exploc.column > line.length ()) @@ -88,14 +89,14 @@ get_visual_column (file_cache &fc, Otherwise, return false, leaving *FIRST_NWS untouched. */ static bool -get_first_nws_vis_column (file_cache &fc, +get_first_nws_vis_column (diagnostics::file_cache &fc, const char *file, int line_num, unsigned int *first_nws, unsigned int tab_width) { gcc_assert (first_nws); - char_span line = fc.get_source_line (file, line_num); + diagnostics::char_span line = fc.get_source_line (file, line_num); if (!line) return false; unsigned int vis_column = 0; @@ -160,7 +161,7 @@ get_first_nws_vis_column (file_cache &fc, Return true if such an unindent/outdent is detected. */ static bool -detect_intervening_unindent (file_cache &fc, +detect_intervening_unindent (diagnostics::file_cache &fc, const char *file, int body_line, int next_stmt_line, @@ -329,13 +330,13 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo, if (guard_loc == body_loc || body_loc == next_stmt_loc) return false; - const unsigned int tab_width = global_dc->m_tabstop; + const unsigned int tab_width = global_dc->get_column_options ().m_tabstop; /* They must be in the same file. */ if (next_stmt_exploc.file != body_exploc.file) return false; - file_cache &fc = global_dc->get_file_cache (); + diagnostics::file_cache &fc = global_dc->get_file_cache (); /* If NEXT_STMT_LOC and BODY_LOC are on the same line, consider the location of the guard. @@ -691,7 +692,7 @@ test_next_tab_stop () static void assert_get_visual_column_succeeds (const location &loc, - file_cache &fc, + diagnostics::file_cache &fc, const char *file, int line, int column, const unsigned int tab_width, unsigned int expected_visual_column, @@ -735,7 +736,7 @@ assert_get_visual_column_succeeds (const location &loc, static void assert_get_visual_column_fails (const location &loc, - file_cache &fc, + diagnostics::file_cache &fc, const char *file, int line, int column, const unsigned int tab_width) { @@ -783,7 +784,7 @@ test_get_visual_column () "\t line 2\n"); line_table_test ltt; temp_source_file tmp (SELFTEST_LOCATION, ".txt", content); - file_cache fc; + diagnostics::file_cache fc; const unsigned int tab_width = 8; const char *file = tmp.get_filename (); diff --git a/gcc/c-family/c-lex.cc b/gcc/c-family/c-lex.cc index fef6ae6..b45d722 100644 --- a/gcc/c-family/c-lex.cc +++ b/gcc/c-family/c-lex.cc @@ -1176,7 +1176,7 @@ interpret_integer (const cpp_token *token, unsigned int flags, && (flags & CPP_N_WIDTH) != CPP_N_LARGE) emit_diagnostic ((c_dialect_cxx () ? cxx_dialect == cxx98 : !flag_isoc99) - ? DK_PEDWARN : DK_WARNING, + ? diagnostics::kind::pedwarn : diagnostics::kind::warning, input_location, OPT_Wlong_long, (flags & CPP_N_UNSIGNED) ? "integer constant is too large for %<unsigned long%> type" diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc index a92c6e3..e183c40 100644 --- a/gcc/c-family/c-omp.cc +++ b/gcc/c-family/c-omp.cc @@ -52,8 +52,8 @@ c_finish_oacc_wait (location_t loc, tree parms, tree clauses) vec_alloc (args, nparms + 2); stmt = builtin_decl_explicit (BUILT_IN_GOACC_WAIT); - if (omp_find_clause (clauses, OMP_CLAUSE_ASYNC)) - t = OMP_CLAUSE_ASYNC_EXPR (clauses); + if ((t = omp_find_clause (clauses, OMP_CLAUSE_ASYNC))) + t = OMP_CLAUSE_ASYNC_EXPR (t); else t = build_int_cst (integer_type_node, GOMP_ASYNC_SYNC); @@ -71,6 +71,11 @@ c_finish_oacc_wait (location_t loc, tree parms, tree clauses) stmt = build_call_expr_loc_vec (loc, stmt, args); + t = omp_find_clause (clauses, OMP_CLAUSE_IF); + if (t) + stmt = build3_loc (input_location, COND_EXPR, void_type_node, + OMP_CLAUSE_IF_EXPR (t), stmt, NULL_TREE); + vec_free (args); return stmt; @@ -764,9 +769,7 @@ c_finish_omp_depobj (location_t loc, tree depobj, kind = OMP_CLAUSE_DEPEND_KIND (clause); t = OMP_CLAUSE_DECL (clause); gcc_assert (t); - if (TREE_CODE (t) == TREE_LIST - && TREE_PURPOSE (t) - && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC) + if (OMP_ITERATOR_DECL_P (t)) { error_at (OMP_CLAUSE_LOCATION (clause), "%<iterator%> modifier may not be specified on " @@ -2173,11 +2176,12 @@ c_omp_split_clauses (location_t loc, enum tree_code code, { /* First the clauses that are unique to some constructs. */ case OMP_CLAUSE_DEVICE: - case OMP_CLAUSE_MAP: - case OMP_CLAUSE_IS_DEVICE_PTR: - case OMP_CLAUSE_HAS_DEVICE_ADDR: case OMP_CLAUSE_DEFAULTMAP: case OMP_CLAUSE_DEPEND: + case OMP_CLAUSE_DYN_GROUPPRIVATE: + case OMP_CLAUSE_IS_DEVICE_PTR: + case OMP_CLAUSE_HAS_DEVICE_ADDR: + case OMP_CLAUSE_MAP: s = C_OMP_CLAUSE_SPLIT_TARGET; break; case OMP_CLAUSE_DOACROSS: @@ -4282,6 +4286,306 @@ c_omp_address_inspector::expand_map_clause (tree c, tree expr, return error_mark_node; } +/* Given a mapper function MAPPER_FN, recursively scan through the map clauses + for that mapper, and if any of those should use a (named or unnamed) mapper + themselves, add it to MLIST. */ + +void +c_omp_find_nested_mappers (omp_mapper_list<tree> *mlist, tree mapper_fn) +{ + tree mapper = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn); + tree mapper_name = NULL_TREE; + + if (mapper == error_mark_node) + return; + + gcc_assert (TREE_CODE (mapper) == OMP_DECLARE_MAPPER); + + for (tree clause = OMP_DECLARE_MAPPER_CLAUSES (mapper); + clause; + clause = OMP_CLAUSE_CHAIN (clause)) + { + tree expr = OMP_CLAUSE_DECL (clause); + enum gomp_map_kind clause_kind = OMP_CLAUSE_MAP_KIND (clause); + tree elem_type; + + if (clause_kind == GOMP_MAP_PUSH_MAPPER_NAME) + { + mapper_name = expr; + continue; + } + else if (clause_kind == GOMP_MAP_POP_MAPPER_NAME) + { + mapper_name = NULL_TREE; + continue; + } + + gcc_assert (TREE_CODE (expr) != TREE_LIST); + if (TREE_CODE (expr) == OMP_ARRAY_SECTION) + { + while (TREE_CODE (expr) == OMP_ARRAY_SECTION) + expr = TREE_OPERAND (expr, 0); + + elem_type = TREE_TYPE (expr); + } + else + elem_type = TREE_TYPE (expr); + + /* This might be too much... or not enough? */ + while (TREE_CODE (elem_type) == ARRAY_TYPE + || TREE_CODE (elem_type) == POINTER_TYPE + || TREE_CODE (elem_type) == REFERENCE_TYPE) + elem_type = TREE_TYPE (elem_type); + + elem_type = TYPE_MAIN_VARIANT (elem_type); + + if (RECORD_OR_UNION_TYPE_P (elem_type) + && !mlist->contains (mapper_name, elem_type)) + { + tree nested_mapper_fn + = lang_hooks.decls.omp_mapper_lookup (mapper_name, elem_type); + + if (nested_mapper_fn) + { + mlist->add_mapper (mapper_name, elem_type, nested_mapper_fn); + c_omp_find_nested_mappers (mlist, nested_mapper_fn); + } + else if (mapper_name) + { + error ("mapper %qE not found for type %qT", mapper_name, + elem_type); + continue; + } + } + } +} + +struct remap_mapper_decl_info +{ + tree dummy_var; + tree expr; +}; + +/* Helper for rewriting DUMMY_VAR into EXPR in a map clause decl. */ + +static tree +remap_mapper_decl_1 (tree *tp, int *walk_subtrees, void *data) +{ + remap_mapper_decl_info *map_info = (remap_mapper_decl_info *) data; + + if (operand_equal_p (*tp, map_info->dummy_var)) + { + *tp = map_info->expr; + *walk_subtrees = 0; + } + + return NULL_TREE; +} + +/* Instantiate a mapper MAPPER for expression EXPR, adding new clauses to + OUTLIST. OUTER_KIND is the mapping kind to use if not already specified in + the mapper declaration. */ + +static tree * +omp_instantiate_mapper (tree *outlist, tree mapper, tree expr, + enum gomp_map_kind outer_kind) +{ + tree clauses = OMP_DECLARE_MAPPER_CLAUSES (mapper); + tree dummy_var = OMP_DECLARE_MAPPER_DECL (mapper); + tree mapper_name = NULL_TREE; + + remap_mapper_decl_info map_info; + map_info.dummy_var = dummy_var; + map_info.expr = expr; + + for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) + { + tree unshared = unshare_expr (c); + enum gomp_map_kind clause_kind = OMP_CLAUSE_MAP_KIND (c); + tree t = OMP_CLAUSE_DECL (unshared); + tree type = NULL_TREE; + bool nonunit_array_with_mapper = false; + + if (clause_kind == GOMP_MAP_PUSH_MAPPER_NAME) + { + mapper_name = t; + continue; + } + else if (clause_kind == GOMP_MAP_POP_MAPPER_NAME) + { + mapper_name = NULL_TREE; + continue; + } + + if (TREE_CODE (t) == OMP_ARRAY_SECTION) + { + location_t loc = OMP_CLAUSE_LOCATION (c); + tree t2 = lang_hooks.decls.omp_map_array_section (loc, t); + + if (t2 == t) + { + nonunit_array_with_mapper = true; + /* We'd want use the mapper for the element type if this worked: + look that one up. */ + type = TREE_TYPE (TREE_TYPE (t)); + } + else + { + t = t2; + type = TREE_TYPE (t); + } + } + else + type = TREE_TYPE (t); + + gcc_assert (type); + + if (type == error_mark_node) + continue; + + walk_tree (&unshared, remap_mapper_decl_1, &map_info, NULL); + + if (OMP_CLAUSE_MAP_KIND (unshared) == GOMP_MAP_UNSET) + OMP_CLAUSE_SET_MAP_KIND (unshared, outer_kind); + + type = TYPE_MAIN_VARIANT (type); + + tree mapper_fn = lang_hooks.decls.omp_mapper_lookup (mapper_name, type); + + if (mapper_fn && nonunit_array_with_mapper) + { + sorry ("user-defined mapper with non-unit length array section"); + continue; + } + else if (mapper_fn) + { + tree nested_mapper + = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn); + if (nested_mapper != mapper) + { + if (clause_kind == GOMP_MAP_UNSET) + clause_kind = outer_kind; + + outlist = omp_instantiate_mapper (outlist, nested_mapper, + t, clause_kind); + continue; + } + } + else if (mapper_name) + { + error ("mapper %qE not found for type %qT", mapper_name, type); + continue; + } + + *outlist = unshared; + outlist = &OMP_CLAUSE_CHAIN (unshared); + } + + return outlist; +} + +/* Given a list of CLAUSES, scan each clause and invoke a user-defined mapper + appropriate to the type of the data in that clause, if such a mapper is + visible in the current parsing context. */ + +tree +c_omp_instantiate_mappers (tree clauses) +{ + tree c, *pc, mapper_name = NULL_TREE; + + for (pc = &clauses, c = clauses; c; c = *pc) + { + bool using_mapper = false; + + switch (OMP_CLAUSE_CODE (c)) + { + case OMP_CLAUSE_MAP: + { + tree t = OMP_CLAUSE_DECL (c); + tree type = NULL_TREE; + bool nonunit_array_with_mapper = false; + + if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME + || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POP_MAPPER_NAME) + { + if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_PUSH_MAPPER_NAME) + mapper_name = OMP_CLAUSE_DECL (c); + else + mapper_name = NULL_TREE; + pc = &OMP_CLAUSE_CHAIN (c); + continue; + } + + if (TREE_CODE (t) == OMP_ARRAY_SECTION) + { + location_t loc = OMP_CLAUSE_LOCATION (c); + tree t2 = lang_hooks.decls.omp_map_array_section (loc, t); + + if (t2 == t) + { + /* !!! Array sections of size >1 with mappers for elements + are hard to support. Do something here. */ + nonunit_array_with_mapper = true; + type = TREE_TYPE (TREE_TYPE (t)); + } + else + { + t = t2; + type = TREE_TYPE (t); + } + } + else + type = TREE_TYPE (t); + + if (type == NULL_TREE || type == error_mark_node) + { + pc = &OMP_CLAUSE_CHAIN (c); + continue; + } + + enum gomp_map_kind kind = OMP_CLAUSE_MAP_KIND (c); + if (kind == GOMP_MAP_UNSET) + kind = GOMP_MAP_TOFROM; + + type = TYPE_MAIN_VARIANT (type); + + tree mapper_fn + = lang_hooks.decls.omp_mapper_lookup (mapper_name, type); + + if (mapper_fn && nonunit_array_with_mapper) + { + sorry ("user-defined mapper with non-unit length " + "array section"); + using_mapper = true; + } + else if (mapper_fn) + { + tree mapper + = lang_hooks.decls.omp_extract_mapper_directive (mapper_fn); + pc = omp_instantiate_mapper (pc, mapper, t, kind); + using_mapper = true; + } + else if (mapper_name) + { + error ("mapper %qE not found for type %qT", mapper_name, type); + using_mapper = true; + } + } + break; + + default: + ; + } + + if (using_mapper) + *pc = OMP_CLAUSE_CHAIN (c); + else + pc = &OMP_CLAUSE_CHAIN (c); + } + + return clauses; +} + const struct c_omp_directive c_omp_directives[] = { /* Keep this alphabetically sorted by the first word. Non-null second/third if any should precede null ones. */ @@ -4299,8 +4603,11 @@ const struct c_omp_directive c_omp_directives[] = { 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", "declare", "variant", PRAGMA_OMP_BEGIN, + C_OMP_DIR_DECLARATIVE, false }, + /* 'begin metadirective' is not yet implemented; however, + it is only applicable if an end-directive exists, but + metadirectives are of limited use for declarative directives. */ /* { "begin", "metadirective", nullptr, PRAGMA_OMP_BEGIN, C_OMP_DIR_META, false }, */ { "cancel", nullptr, nullptr, PRAGMA_OMP_CANCEL, @@ -4309,8 +4616,10 @@ const struct c_omp_directive c_omp_directives[] = { 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", "induction", nullptr, PRAGMA_OMP_DECLARE, + C_OMP_DIR_DECLARATIVE, true }, */ + { "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, @@ -4329,19 +4638,25 @@ const struct c_omp_directive c_omp_directives[] = { C_OMP_DIR_INFORMATIONAL, false }, { "end", "declare", "target", PRAGMA_OMP_END, C_OMP_DIR_DECLARATIVE, false }, - /* { "end", "declare", "variant", PRAGMA_OMP_END, - 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_META, false }, */ /* error with at(execution) is C_OMP_DIR_STANDALONE. */ { "error", nullptr, nullptr, PRAGMA_OMP_ERROR, C_OMP_DIR_UTILITY, false }, + /* { "flatten", nullptr, nullptr, PRAGMA_OMP_FLATTEN, + C_OMP_DIR_CONSTRUCT, true }, */ { "flush", nullptr, nullptr, PRAGMA_OMP_FLUSH, C_OMP_DIR_STANDALONE, false }, { "for", nullptr, nullptr, PRAGMA_OMP_FOR, C_OMP_DIR_CONSTRUCT, true }, + /* { "fuse", nullptr, nullptr, PRAGMA_OMP_FUSE, + C_OMP_DIR_CONSTRUCT, true }, */ /* { "groupprivate", nullptr, nullptr, PRAGMA_OMP_GROUPPRIVATE, C_OMP_DIR_DECLARATIVE, false }, */ + /* { "interchange", nullptr, nullptr, PRAGMA_OMP_INTERCHANGE, + C_OMP_DIR_CONSTRUCT, true }, */ { "interop", nullptr, nullptr, PRAGMA_OMP_INTEROP, C_OMP_DIR_STANDALONE, false }, { "loop", nullptr, nullptr, PRAGMA_OMP_LOOP, @@ -4373,6 +4688,10 @@ const struct c_omp_directive c_omp_directives[] = { C_OMP_DIR_CONSTRUCT, true }, { "single", nullptr, nullptr, PRAGMA_OMP_SINGLE, C_OMP_DIR_CONSTRUCT, false }, + /* { "split", nullptr, nullptr, PRAGMA_OMP_SPLIT, + C_OMP_DIR_CONSTRUCT, true }, */ + /* { "stripe", nullptr, nullptr, PRAGMA_OMP_STRIPE, + C_OMP_DIR_CONSTRUCT, true }, */ { "target", "data", nullptr, PRAGMA_OMP_TARGET, C_OMP_DIR_CONSTRUCT, false }, { "target", "enter", "data", PRAGMA_OMP_TARGET, @@ -4385,6 +4704,10 @@ const struct c_omp_directive c_omp_directives[] = { C_OMP_DIR_CONSTRUCT, true }, { "task", nullptr, nullptr, PRAGMA_OMP_TASK, C_OMP_DIR_CONSTRUCT, false }, + /* { "task", "iteration", nullptr, PRAGMA_OMP_TASK_ITERATION, + C_OMP_DIR_STANDALONE, false }, */ + /* { "taskgraph", nullptr, nullptr, PRAGMA_OMP_TASKGRAPH, + C_OMP_DIR_CONSTRUCT, false }, */ { "taskgroup", nullptr, nullptr, PRAGMA_OMP_TASKGROUP, C_OMP_DIR_CONSTRUCT, false }, { "taskloop", nullptr, nullptr, PRAGMA_OMP_TASKLOOP, diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc index 4016382..8da5175 100644 --- a/gcc/c-family/c-opts.cc +++ b/gcc/c-family/c-opts.cc @@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ +#define INCLUDE_VECTOR #include "config.h" #include "system.h" #include "coretypes.h" @@ -32,7 +33,7 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "toplev.h" #include "langhooks.h" -#include "diagnostic-macro-unwinding.h" /* for virt_loc_aware_diagnostic_finalizer */ +#include "diagnostics/macro-unwinding.h" /* for virt_loc_aware_diagnostic_finalizer */ #include "intl.h" #include "cppdefault.h" #include "incpath.h" @@ -43,7 +44,7 @@ along with GCC; see the file COPYING3. If not see #include "dumpfile.h" #include "file-prefix-map.h" /* add_*_prefix_map() */ #include "context.h" -#include "diagnostic-format-text.h" +#include "diagnostics/text-sink.h" #ifndef DOLLARS_IN_IDENTIFIERS # define DOLLARS_IN_IDENTIFIERS true @@ -169,9 +170,9 @@ c_common_option_lang_mask (void) /* Diagnostic finalizer for C/C++/Objective-C/Objective-C++. */ static void -c_diagnostic_text_finalizer (diagnostic_text_output_format &text_output, - const diagnostic_info *diagnostic, - diagnostic_t) +c_diagnostic_text_finalizer (diagnostics::text_sink &text_output, + const diagnostics::diagnostic_info *diagnostic, + enum diagnostics::kind) { pretty_printer *const pp = text_output.get_printer (); char *saved_prefix = pp_take_prefix (pp); @@ -179,20 +180,20 @@ c_diagnostic_text_finalizer (diagnostic_text_output_format &text_output, pp_newline (pp); diagnostic_show_locus (&text_output.get_context (), text_output.get_source_printing_options (), - diagnostic->richloc, diagnostic->kind, pp); + diagnostic->m_richloc, diagnostic->m_kind, pp); /* By default print macro expansion contexts in the diagnostic finalizer -- for tokens resulting from macro expansion. */ - virt_loc_aware_diagnostic_finalizer (text_output, diagnostic); + diagnostics::virt_loc_aware_text_finalizer (text_output, diagnostic); pp_set_prefix (pp, saved_prefix); pp_flush (pp); } /* Common default settings for diagnostics. */ void -c_common_diagnostics_set_defaults (diagnostic_context *context) +c_common_diagnostics_set_defaults (diagnostics::context *context) { - diagnostic_text_finalizer (context) = c_diagnostic_text_finalizer; - context->m_opt_permissive = OPT_fpermissive; + diagnostics::text_finalizer (context) = c_diagnostic_text_finalizer; + context->set_permissive_option (OPT_fpermissive); } /* Input charset configuration for diagnostics. */ @@ -229,7 +230,6 @@ c_common_init_options_struct (struct gcc_options *opts) /* By default, C99-like requirements for complex multiply and divide. */ opts->x_flag_complex_method = 2; - opts->x_flag_default_complex_method = opts->x_flag_complex_method; } /* Common initialization before calling option handlers. */ @@ -274,11 +274,11 @@ c_common_init_options (unsigned int decoded_options_count, } } - /* Set C++ standard to C++17 if not specified on the command line. */ + /* Set C++ standard to C++20 if not specified on the command line. */ if (c_dialect_cxx ()) - set_std_cxx17 (/*ISO*/false); + set_std_cxx20 (/*ISO*/false); - global_dc->m_source_printing.colorize_source_p = true; + global_dc->get_source_printing_options ().colorize_source_p = true; } /* Handle switch SCODE with argument ARG. VALUE is true, unless no- @@ -864,8 +864,12 @@ c_common_post_options (const char **pfilename) sanitize_cpp_opts (); - register_include_chains (parse_in, sysroot, iprefix, imultilib, - std_inc, std_cxx_inc && c_dialect_cxx (), verbose); + /* Don't register include chains if under -fpreprocessed since we might not + have correct sysroot this mode, and this may cause file permssion + issue. */ + if (!cpp_opts->preprocessed) + register_include_chains (parse_in, sysroot, iprefix, imultilib, + std_inc, std_cxx_inc && c_dialect_cxx (), verbose); #ifdef C_COMMON_OVERRIDE_OPTIONS /* Some machines may reject certain combinations of C @@ -913,6 +917,16 @@ c_common_post_options (const char **pfilename) else flag_permitted_flt_eval_methods = PERMITTED_FLT_EVAL_METHODS_C11; + if (cxx_dialect >= cxx26) + SET_OPTION_IF_UNSET (&global_options, &global_options_set, + flag_auto_var_init, AUTO_INIT_CXX26); + + /* The -Wtrivial-auto-var-init warning is useless for C++, where we always + add .DEFERRED_INIT calls when some (vacuous) initializers are bypassed + through jumps from switch condition to case/default label. */ + if (c_dialect_cxx ()) + warn_trivial_auto_var_init = 0; + /* C23 Annex F does not permit certain built-in functions to raise "inexact". */ if (flag_isoc23) @@ -959,6 +973,15 @@ c_common_post_options (const char **pfilename) if (warn_enum_compare == -1) warn_enum_compare = c_dialect_cxx () ? 1 : 0; + /* For C++26 default to -Wkeyword-macro if -Wpedantic. */ + if (cxx_dialect >= cxx26 && pedantic) + { + SET_OPTION_IF_UNSET (&global_options, &global_options_set, + warn_keyword_macro, 1); + if (warn_keyword_macro) + cpp_opts->cpp_warn_keyword_macro = warn_keyword_macro; + } + /* -Wpacked-bitfield-compat is on by default for the C languages. The warning is issued in stor-layout.cc which is not part of the front-end so we need to selectively turn it on here. */ @@ -1085,12 +1108,21 @@ 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 = 21; + /* Possibly different for non-default ABI fixes within a release. */ + const int default_abi_version = latest_abi_version; /* Generate compatibility aliases for ABI v18 (GCC 13) by default. */ const int abi_compat_default = 18; + if (flag_abi_version > latest_abi_version) + warning (0, "%<-fabi-version=%d%> is not supported, using =%d", + flag_abi_version, latest_abi_version); + + SET_OPTION_IF_UNSET (&global_options, &global_options_set, + flag_abi_version, default_abi_version); + #define clamp(X) if (X == 0 || X > latest_abi_version) X = latest_abi_version clamp (flag_abi_version); - clamp (warn_abi_version); + /* Don't clamp warn_abi_version, let it be 0 or out of bounds. */ clamp (flag_abi_compat_version); #undef clamp @@ -1101,24 +1133,17 @@ c_common_post_options (const char **pfilename) flag_abi_compat_version = warn_abi_version; else if (warn_abi_version == -1 && flag_abi_compat_version == -1) { - warn_abi_version = latest_abi_version; - if (flag_abi_version == latest_abi_version) - { - auto_diagnostic_group d; - if (warning (OPT_Wabi, "%<-Wabi%> won%'t warn about anything")) - { - inform (input_location, "%<-Wabi%> warns about differences " - "from the most up-to-date ABI, which is also used " - "by default"); - inform (input_location, "use e.g. %<-Wabi=11%> to warn about " - "changes from GCC 7"); - } - flag_abi_compat_version = abi_compat_default; - } + warn_abi_version = 0; + if (flag_abi_version == default_abi_version) + flag_abi_compat_version = abi_compat_default; else flag_abi_compat_version = latest_abi_version; } + /* Allow warnings vs ABI versions beyond what we currently support. */ + if (warn_abi_version == 0) + warn_abi_version = 1000; + /* By default, enable the new inheriting constructor semantics along with ABI 11. New and old should coexist fine, but it is a change in what artificial symbols are generated. */ @@ -1163,6 +1188,9 @@ c_common_post_options (const char **pfilename) warn_cxx20_compat = 0; cpp_opts->cpp_warn_cxx20_compat = 0; } + if (cxx_dialect >= cxx26) + /* Don't warn about C++26 compatibility changes in C++26 or later. */ + warn_cxx26_compat = 0; /* C++17 has stricter evaluation order requirements; let's use some of them for earlier C++ as well, so chaining works as expected. */ @@ -1186,7 +1214,7 @@ c_common_post_options (const char **pfilename) flag_char8_t = (cxx_dialect >= cxx20) || flag_isoc23; cpp_opts->unsigned_utf8char = flag_char8_t ? 1 : cpp_opts->unsigned_char; - cpp_opts->cpp_tabstop = global_dc->m_tabstop; + cpp_opts->cpp_tabstop = global_dc->get_column_options ().m_tabstop; if (flag_extern_tls_init) { @@ -1213,10 +1241,25 @@ c_common_post_options (const char **pfilename) if (cxx_dialect >= cxx20) flag_concepts = 1; + /* Coroutines are also a C++20 feature. */ + SET_OPTION_IF_UNSET (&global_options, &global_options_set, + flag_coroutines, cxx_dialect >= cxx20); + /* Enable lifetime extension of range based for temporaries for C++23. */ SET_OPTION_IF_UNSET (&global_options, &global_options_set, flag_range_for_ext_temps, cxx_dialect >= cxx23); + /* EnabledBy unfortunately can't specify value to use if set and + LangEnabledBy can't specify multiple options with &&. For -Wunused + or -Wunused -Wextra we want these to default to 3 unless user specified + some other level explicitly. */ + if (warn_unused_but_set_parameter == 1) + SET_OPTION_IF_UNSET (&global_options, &global_options_set, + warn_unused_but_set_parameter, 3); + if (warn_unused_but_set_variable == 1) + SET_OPTION_IF_UNSET (&global_options, &global_options_set, + warn_unused_but_set_variable, 3); + /* -fimmediate-escalation has no effect when immediate functions are not supported. */ if (flag_immediate_escalation && cxx_dialect < cxx20) @@ -1661,6 +1704,7 @@ c_finish_options (void) bool cxx_assert_seen_p = false; /* All command line defines must have the same location. */ + line_table->cmdline_location = line_table->highest_line; cpp_force_token_locations (parse_in, line_table->highest_line); for (size_t i = 0; i < deferred_count; i++) { @@ -2007,8 +2051,6 @@ set_std_cxx20 (int iso) flag_isoc94 = 1; flag_isoc99 = 1; flag_isoc11 = 1; - /* C++20 includes coroutines. */ - flag_coroutines = true; cxx_dialect = cxx20; lang_hooks.name = "GNU C++20"; } @@ -2025,8 +2067,6 @@ set_std_cxx23 (int iso) flag_isoc94 = 1; flag_isoc99 = 1; flag_isoc11 = 1; - /* C++23 includes coroutines. */ - flag_coroutines = true; cxx_dialect = cxx23; lang_hooks.name = "GNU C++23"; } @@ -2043,8 +2083,6 @@ set_std_cxx26 (int iso) flag_isoc94 = 1; flag_isoc99 = 1; flag_isoc11 = 1; - /* C++26 includes coroutines. */ - flag_coroutines = true; cxx_dialect = cxx26; lang_hooks.name = "GNU C++26"; } diff --git a/gcc/c-family/c-pch.cc b/gcc/c-family/c-pch.cc index b8f075e..8f0fea8 100644 --- a/gcc/c-family/c-pch.cc +++ b/gcc/c-family/c-pch.cc @@ -347,18 +347,18 @@ c_common_read_pch (cpp_reader *pfile, const char *name, rebuild_location_adhoc_htab (line_table); line_table->trace_includes = saved_trace_includes; - /* Set the current location to the line containing the #include (or the - #pragma GCC pch_preprocess) for the purpose of assigning locations to any - macros that are about to be restored. */ - linemap_add (line_table, LC_ENTER, 0, saved_loc.file, - saved_loc.line > 1 ? saved_loc.line - 1 : saved_loc.line); + /* Set the line_map current location to the start of the file, so that things + remain in order after cpp_read_state() re-adds any macros that were defined + prior to calling gt_pch_restore(). */ + linemap_add (line_table, LC_ENTER, saved_loc.sysp, saved_loc.file, 0); timevar_push (TV_PCH_CPP_RESTORE); cpp_result = cpp_read_state (pfile, name, f, smd); /* Set the current location to the line following the #include, where we were prior to processing the PCH. */ - linemap_line_start (line_table, saved_loc.line, 0); + linemap_add (line_table, LC_RENAME, saved_loc.sysp, saved_loc.file, + saved_loc.line); timevar_pop (TV_PCH_CPP_RESTORE); diff --git a/gcc/c-family/c-pragma.cc b/gcc/c-family/c-pragma.cc index 8b5cdcc..8a1218b 100644 --- a/gcc/c-family/c-pragma.cc +++ b/gcc/c-family/c-pragma.cc @@ -781,7 +781,7 @@ public: PK_IGNORED_ATTRIBUTES, PK_DIAGNOSTIC, } pd_kind; - diagnostic_t diagnostic_kind; + enum diagnostics::kind diagnostic_kind; const char *kind_str; const char *option_str; bool own_option_str; @@ -792,7 +792,7 @@ public: valid = false; loc_kind = loc_option = UNKNOWN_LOCATION; pd_kind = PK_INVALID; - diagnostic_kind = DK_UNSPECIFIED; + diagnostic_kind = diagnostics::kind::unspecified; kind_str = option_str = nullptr; own_option_str = false; } @@ -808,7 +808,7 @@ public: kind_str = kind_string; pd_kind = PK_INVALID; - diagnostic_kind = DK_UNSPECIFIED; + diagnostic_kind = diagnostics::kind::unspecified; if (strcmp (kind_str, "push") == 0) pd_kind = PK_PUSH; else if (strcmp (kind_str, "pop") == 0) @@ -818,17 +818,17 @@ public: else if (strcmp (kind_str, "error") == 0) { pd_kind = PK_DIAGNOSTIC; - diagnostic_kind = DK_ERROR; + diagnostic_kind = diagnostics::kind::error; } else if (strcmp (kind_str, "warning") == 0) { pd_kind = PK_DIAGNOSTIC; - diagnostic_kind = DK_WARNING; + diagnostic_kind = diagnostics::kind::warning; } else if (strcmp (kind_str, "ignored") == 0) { pd_kind = PK_DIAGNOSTIC; - diagnostic_kind = DK_IGNORED; + diagnostic_kind = diagnostics::kind::ignored; } } @@ -1016,7 +1016,8 @@ handle_pragma_diagnostic_impl () what we used to do here before and changing it breaks e.g. PR69543 and PR69558. */ control_warning_option (option_index, (int) data.diagnostic_kind, - arg, data.diagnostic_kind != DK_IGNORED, + arg, + data.diagnostic_kind != diagnostics::kind::ignored, input_location, lang_mask, &handlers, &global_options, &global_options_set, global_dc); @@ -1847,7 +1848,9 @@ init_pragma (void) c_register_pragma_with_early_handler ("GCC", "target", handle_pragma_target, handle_pragma_target); - c_register_pragma ("GCC", "optimize", handle_pragma_optimize); + c_register_pragma_with_early_handler ("GCC", "optimize", + handle_pragma_optimize, + handle_pragma_optimize); c_register_pragma_with_early_handler ("GCC", "push_options", handle_pragma_push_options, handle_pragma_push_options); diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index 13df9ea..a61a2c7 100644 --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -119,6 +119,7 @@ enum pragma_omp_clause { PRAGMA_OMP_CLAUSE_DEVICE_TYPE, PRAGMA_OMP_CLAUSE_DIST_SCHEDULE, PRAGMA_OMP_CLAUSE_DOACROSS, + PRAGMA_OMP_CLAUSE_DYN_GROUPPRIVATE, PRAGMA_OMP_CLAUSE_ENTER, PRAGMA_OMP_CLAUSE_FILTER, PRAGMA_OMP_CLAUSE_FINAL, diff --git a/gcc/c-family/c-pretty-print.cc b/gcc/c-family/c-pretty-print.cc index fad6b5e..5adb13b 100644 --- a/gcc/c-family/c-pretty-print.cc +++ b/gcc/c-family/c-pretty-print.cc @@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "basic-block.h" #include "gimple.h" +#include "tm.h" /* The pretty-printer code is primarily designed to closely follow (GNU) C and C++ grammars. That is to be contrasted with spaghetti @@ -45,12 +46,6 @@ along with GCC; see the file COPYING3. If not see takes expression or declaration contexts into account. */ -#define pp_c_maybe_whitespace(PP) \ - do { \ - if ((PP)->get_padding () == pp_before) \ - pp_c_whitespace (PP); \ - } while (0) - /* literal */ static void pp_c_char (c_pretty_printer *, int); @@ -3054,6 +3049,76 @@ pp_c_tree_decl_identifier (c_pretty_printer *pp, tree t) pp_c_identifier (pp, name); } +/* Prints "[version: VERSION]" for a versioned function decl. + This will only print for targets with target_version semantics. */ +void +pp_c_function_target_version (c_pretty_printer *pp, tree t) +{ + if (TARGET_HAS_FMV_TARGET_ATTRIBUTE) + return; + + string_slice version = get_target_version (t); + if (!version.is_valid ()) + return; + + pp_c_whitespace (pp); + + pp_c_left_bracket (pp); + pp_c_left_bracket (pp); + pp_string (pp, "target_version"); + pp_c_left_paren (pp); + pp_doublequote (pp); + pp_string_n (pp, version.begin (), version.size ()); + pp_doublequote (pp); + pp_c_right_paren (pp); + pp_c_right_bracket (pp); + pp_c_right_bracket (pp); + + pp->set_padding (pp_before); +} + +/* Prints "[clones: VERSION, +]" for a versioned function decl. + This only works for targets with target_version semantics. */ +void +pp_c_function_target_clones (c_pretty_printer *pp, tree t) +{ + /* Only print for target_version semantics. + This is because for target FMV semantics a target_clone always defines + the entire FMV set. target_version semantics can mix target_clone and + target_version decls in the definition of a FMV set and so the + target_clone becomes a part of the identity of the declaration. */ + if (TARGET_HAS_FMV_TARGET_ATTRIBUTE) + return; + + auto_vec<string_slice> versions = get_clone_versions (t, NULL, false); + if (versions.is_empty ()) + return; + + pp_c_whitespace (pp); + + string_slice final_version = versions.pop (); + pp_c_left_bracket (pp); + pp_c_left_bracket (pp); + pp_string (pp, "target_clones"); + pp_c_left_paren (pp); + for (string_slice version : versions) + { + pp_doublequote (pp); + pp_string_n (pp, version.begin (), version.size ()); + pp_doublequote (pp); + pp_string (pp, ","); + pp_c_whitespace (pp); + } + pp_doublequote (pp); + pp_string_n (pp, final_version.begin (), final_version.size ()); + pp_doublequote (pp); + pp_c_right_paren (pp); + pp_c_right_bracket (pp); + pp_c_right_bracket (pp); + + pp->set_padding (pp_before); +} + #if CHECKING_P namespace selftest { diff --git a/gcc/c-family/c-pretty-print.h b/gcc/c-family/c-pretty-print.h index c8fb678..5e00b95 100644 --- a/gcc/c-family/c-pretty-print.h +++ b/gcc/c-family/c-pretty-print.h @@ -102,6 +102,12 @@ public: #define pp_ptr_operator(PP, D) (PP)->ptr_operator (PP, D) #define pp_parameter_list(PP, T) (PP)->parameter_list (PP, T) +#define pp_c_maybe_whitespace(PP) \ + do { \ + if ((PP)->get_padding () == pp_before) \ + pp_c_whitespace (PP); \ + } while (0) + void pp_c_whitespace (c_pretty_printer *); void pp_c_left_paren (c_pretty_printer *); void pp_c_right_paren (c_pretty_printer *); @@ -138,6 +144,8 @@ void pp_c_ws_string (c_pretty_printer *, const char *); void pp_c_identifier (c_pretty_printer *, const char *); void pp_c_string_literal (c_pretty_printer *, tree); void pp_c_integer_constant (c_pretty_printer *, tree); +void pp_c_function_target_version (c_pretty_printer *, tree); +void pp_c_function_target_clones (c_pretty_printer *, tree); void print_c_tree (FILE *file, tree t, dump_flags_t); diff --git a/gcc/c-family/c-ubsan.cc b/gcc/c-family/c-ubsan.cc index 78b7868..29534d7 100644 --- a/gcc/c-family/c-ubsan.cc +++ b/gcc/c-family/c-ubsan.cc @@ -397,8 +397,7 @@ get_bound_from_access_with_size (tree call) return NULL_TREE; tree ref_to_size = CALL_EXPR_ARG (call, 1); - unsigned int class_of_size = TREE_INT_CST_LOW (CALL_EXPR_ARG (call, 2)); - tree type = TREE_TYPE (CALL_EXPR_ARG (call, 3)); + tree type = TREE_TYPE (TREE_TYPE (CALL_EXPR_ARG (call, 2))); tree size = fold_build2 (MEM_REF, type, unshare_expr (ref_to_size), build_int_cst (ptr_type_node, 0)); /* If size is negative value, treat it as zero. */ @@ -410,12 +409,7 @@ get_bound_from_access_with_size (tree call) build_zero_cst (type), size); } - /* Only when class_of_size is 1, i.e, the number of the elements of - the object type, return the size. */ - if (class_of_size != 1) - return NULL_TREE; - else - size = fold_convert (sizetype, size); + size = fold_convert (sizetype, size); return size; } @@ -460,7 +454,7 @@ ubsan_instrument_bounds (location_t loc, tree array, tree *index, bound = fold_build2 (PLUS_EXPR, TREE_TYPE (bound), bound, build_int_cst (TREE_TYPE (bound), - 1 + ignore_off_by_one)); + 1 + ignore_off_by_one)); /* Detect flexible array members and suchlike, unless -fsanitize=bounds-strict. */ @@ -547,45 +541,332 @@ ubsan_instrument_bounds (location_t loc, tree array, tree *index, return NULL_TREE; *index = save_expr (*index); + /* If TYPE is a VLA, use 1 instead of 0 as the first argument and + use just the addend to TYPE_MAX_VALUE (domain) as the third argument + temporarily, so that gimplification can use TYPE_MAX_VALUE (domain) + after gimplify_type_sizes. See PR120052. */ + bool is_vla = (TYPE_MAX_VALUE (domain) + && TREE_CODE (TYPE_MAX_VALUE (domain)) != INTEGER_CST); + if (is_vla) + bound = build_int_cst (TREE_TYPE (bound), 1 + ignore_off_by_one); + /* Create a "(T *) 0" (or 1) tree node to describe the array type. */ + tree zero_with_type = build_int_cst (build_pointer_type (type), is_vla); + return build_call_expr_internal_loc (loc, IFN_UBSAN_BOUNDS, + void_type_node, 3, zero_with_type, + *index, bound); +} + + +/* Instrument array bounds for the pointer array address which is + a call to .ACCESS_WITH_SIZE. We create special + builtin, that gets expanded in the sanopt pass, and make an array + dimention of it. POINTER_ADDR is the pointer array's base address. + *INDEX is an index to the array. + IGNORE_OFF_BY_ONE is true if the POINTER_ADDR is not inside an + INDIRECT_REF. + Return NULL_TREE if no instrumentation is emitted. */ + +tree +ubsan_instrument_bounds_pointer_address (location_t loc, tree pointer_addr, + tree *index, + bool ignore_off_by_one) +{ + tree call = pointer_addr; + if (!is_access_with_size_p (call)) + return NULL_TREE; + tree bound = get_bound_from_access_with_size (call); + + if (ignore_off_by_one) + bound = fold_build2 (PLUS_EXPR, TREE_TYPE (bound), bound, + build_int_cst (TREE_TYPE (bound), + 1)); + + /* Don't emit instrumentation in the most common cases. */ + tree idx = NULL_TREE; + if (TREE_CODE (*index) == INTEGER_CST) + idx = *index; + else if (TREE_CODE (*index) == BIT_AND_EXPR + && TREE_CODE (TREE_OPERAND (*index, 1)) == INTEGER_CST) + idx = TREE_OPERAND (*index, 1); + if (idx + && TREE_CODE (bound) == INTEGER_CST + && tree_int_cst_sgn (idx) >= 0 + && tree_int_cst_lt (idx, bound)) + return NULL_TREE; + + *index = save_expr (*index); + + /* Create an array_type for the corresponding pointer array. */ + tree itype = build_range_type (sizetype, size_zero_node, NULL_TREE); + /* The array's element type can be get from the return type of the call to + .ACCESS_WITH_SIZE. */ + tree element_type = TREE_TYPE (TREE_TYPE (call)); + tree array_type = build_array_type (element_type, itype); /* Create a "(T *) 0" tree node to describe the array type. */ - tree zero_with_type = build_int_cst (build_pointer_type (type), 0); + tree zero_with_type = build_int_cst (build_pointer_type (array_type), 0); return build_call_expr_internal_loc (loc, IFN_UBSAN_BOUNDS, void_type_node, 3, zero_with_type, *index, bound); } -/* Return true iff T is an array that was instrumented by SANITIZE_BOUNDS. */ +/* This structure is to combine a factor with its parent and its position + * in its parent tree. */ +struct factor_t +{ + tree factor; + tree parent; /* the parent tree of this factor. */ + int pos; /* the position of this factor in its parent tree. */ +}; + +/* for a multiply expression like: + ((long unsigned int) m * (long unsigned int) SAVE_EXPR <n>) * 4 + + locate all the factors, the parents of the factor and the position of + the factor in its parent, and put them to VEC_FACTORS. */ + +static void +get_factors_from_mul_expr (tree mult_expr, tree parent, + int pos, auto_vec<factor_t> *vec_factors) +{ + struct factor_t mult_factor = {0, 0, -1}; + mult_factor.factor = mult_expr; + mult_factor.parent = parent; + mult_factor.pos = pos; + + while (CONVERT_EXPR_CODE_P (TREE_CODE (mult_expr))) + { + mult_factor.parent = mult_expr; + mult_factor.pos = 0; + mult_expr = TREE_OPERAND (mult_expr, 0); + mult_factor.factor = mult_expr; + } + if (TREE_CODE (mult_expr) != MULT_EXPR) + vec_factors->safe_push (mult_factor); + else + { + get_factors_from_mul_expr (TREE_OPERAND (mult_expr, 0), mult_expr, + 0, vec_factors); + get_factors_from_mul_expr (TREE_OPERAND (mult_expr, 1), mult_expr, + 1, vec_factors); + } +} + +/* Given an OFFSET expression, and the ELEMENT_SIZE, + get the index expression from OFFSET and return it. + For example: + OFFSET: + ((long unsigned int) m * (long unsigned int) SAVE_EXPR <n>) * 4 + ELEMENT_SIZE: + (sizetype) SAVE_EXPR <n> * 4 + get the index as (long unsigned int) m, and return it. + The INDEX_P holds the pointer to the parent tree of the index, + INDEX_N holds the position of the index in its parent. */ + +static tree +get_index_from_offset (tree offset, tree *index_p, + int *index_n, tree element_size) +{ + if (TREE_CODE (offset) != MULT_EXPR) + return NULL_TREE; + + auto_vec<factor_t> e_factors, o_factors; + get_factors_from_mul_expr (element_size, NULL, -1, &e_factors); + get_factors_from_mul_expr (offset, *index_p, *index_n, &o_factors); + + if (e_factors.is_empty () || o_factors.is_empty ()) + return NULL_TREE; + + bool all_found = true; + for (unsigned i = 0; i < e_factors.length (); i++) + { + factor_t e_size_factor = e_factors[i]; + bool found = false; + for (unsigned j = 0; j < o_factors.length ();) + { + factor_t o_exp_factor = o_factors[j]; + if (operand_equal_p (e_size_factor.factor, o_exp_factor.factor)) + { + o_factors.unordered_remove (j); + found = true; + break; + } + else + j++; + } + if (!found) + all_found = false; + } + + if (!all_found) + return NULL_TREE; + + if (o_factors.length () != 1) + return NULL_TREE; + + *index_p = o_factors[0].parent; + *index_n = o_factors[0].pos; + return o_factors[0].factor; +} + +/* For an pointer + offset computation expression, such as, + .ACCESS_WITH_SIZE (p->c, &p->b, 1, 0, -1, 0B) + + (sizetype) ((long unsigned int) index * 4 + Return the index of this pointer array reference, + set the parent tree of INDEX to *INDEX_P. + set the operand position of the INDEX in the parent tree to *INDEX_N. + If failed, return NULL_TREE. */ + +static tree +get_index_from_pointer_addr_expr (tree pointer, tree *index_p, int *index_n) +{ + *index_p = NULL_TREE; + *index_n = -1; + tree call = TREE_OPERAND (pointer, 0); + if (!is_access_with_size_p (call)) + return NULL_TREE; + + /* Get the pointee type of the call to .ACCESS_WITH_SIZE. + This should be the element type of the pointer array. */ + tree pointee_type = TREE_TYPE (TREE_TYPE (call)); + tree pointee_size = TYPE_SIZE_UNIT (pointee_type); + + tree index_exp = TREE_OPERAND (pointer, 1); + *index_p = pointer; + *index_n = 1; + + if (!(TREE_CODE (index_exp) != MULT_EXPR + && tree_int_cst_equal (pointee_size, integer_one_node))) + { + while (CONVERT_EXPR_CODE_P (TREE_CODE (index_exp))) + { + *index_p = index_exp; + *index_n = 0; + index_exp = TREE_OPERAND (index_exp, 0); + } + index_exp = get_index_from_offset (index_exp, index_p, + index_n, pointee_size); + + if (!index_exp) + return NULL_TREE; + } + + while (CONVERT_EXPR_CODE_P (TREE_CODE (index_exp))) + { + *index_p = index_exp; + *index_n = 0; + index_exp = TREE_OPERAND (index_exp, 0); + } + + return index_exp; +} + +/* Return TRUE when the EXPR is a pointer array address that could be + instrumented. + We only instrument an address computation similar as the following: + .ACCESS_WITH_SIZE (p->c, &p->b, 1, 0, -1, 0B) + + (sizetype) ((long unsigned int) index * 4) + if the EXPR is instrumentable, return TRUE and + set the index to *INDEX. + set the .ACCESS_WITH_SIZE to *BASE. + set the parent tree of INDEX to *INDEX_P. + set the operand position of the INDEX in the parent tree to INDEX_N. */ + +static bool +is_instrumentable_pointer_array_address (tree expr, tree *base, + tree *index, tree *index_p, + int *index_n) +{ + /* For a pointer array address as: + .ACCESS_WITH_SIZE (p->c, &p->b, 1, 0, -1, 0B) + + (sizetype) ((long unsigned int) index * 4) + op0 is the call to .ACCESS_WITH_SIZE; + op1 is the index. */ + if (TREE_CODE (expr) != POINTER_PLUS_EXPR) + return false; + + tree op0 = TREE_OPERAND (expr, 0); + if (!is_access_with_size_p (op0)) + return false; + tree op1 = get_index_from_pointer_addr_expr (expr, index_p, index_n); + if (op1 != NULL_TREE) + { + *base = op0; + *index = op1; + return true; + } + return false; +} + +/* Return true iff T is an array or an indirect reference that was + instrumented by SANITIZE_BOUNDS. */ bool -ubsan_array_ref_instrumented_p (const_tree t) +ubsan_array_ref_instrumented_p (tree t) { - if (TREE_CODE (t) != ARRAY_REF) + if (TREE_CODE (t) != ARRAY_REF + && TREE_CODE (t) != MEM_REF) return false; - tree op1 = TREE_OPERAND (t, 1); - return TREE_CODE (op1) == COMPOUND_EXPR - && TREE_CODE (TREE_OPERAND (op1, 0)) == CALL_EXPR - && CALL_EXPR_FN (TREE_OPERAND (op1, 0)) == NULL_TREE - && CALL_EXPR_IFN (TREE_OPERAND (op1, 0)) == IFN_UBSAN_BOUNDS; + bool is_array = (TREE_CODE (t) == ARRAY_REF); + tree op0 = NULL_TREE; + tree op1 = NULL_TREE; + tree index_p = NULL_TREE; + int index_n = 0; + if (is_array) + { + op1 = TREE_OPERAND (t, 1); + return TREE_CODE (op1) == COMPOUND_EXPR + && TREE_CODE (TREE_OPERAND (op1, 0)) == CALL_EXPR + && CALL_EXPR_FN (TREE_OPERAND (op1, 0)) == NULL_TREE + && CALL_EXPR_IFN (TREE_OPERAND (op1, 0)) == IFN_UBSAN_BOUNDS; + } + else if (is_instrumentable_pointer_array_address (t, &op0, &op1, + &index_p, &index_n)) + return TREE_CODE (op1) == COMPOUND_EXPR + && TREE_CODE (TREE_OPERAND (op1, 0)) == CALL_EXPR + && CALL_EXPR_FN (TREE_OPERAND (op1, 0)) == NULL_TREE + && CALL_EXPR_IFN (TREE_OPERAND (op1, 0)) == IFN_UBSAN_BOUNDS; + + return false; } -/* Instrument an ARRAY_REF, if it hasn't already been instrumented. - IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR. */ +/* Instrument an ARRAY_REF or an address computation whose base address is + a call to .ACCESS_WITH_SIZE, if it hasn't already been instrumented. + IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR, or the + address computation is not inside a INDIRECT_REF. */ void ubsan_maybe_instrument_array_ref (tree *expr_p, bool ignore_off_by_one) { + tree e = NULL_TREE; + tree op0 = NULL_TREE; + tree op1 = NULL_TREE; + tree index_p = NULL_TREE; /* the parent tree of INDEX. */ + int index_n = 0; /* the operand position of INDEX in the parent tree. */ + if (!ubsan_array_ref_instrumented_p (*expr_p) && sanitize_flags_p (SANITIZE_BOUNDS | SANITIZE_BOUNDS_STRICT) && current_function_decl != NULL_TREE) { - tree op0 = TREE_OPERAND (*expr_p, 0); - tree op1 = TREE_OPERAND (*expr_p, 1); - tree e = ubsan_instrument_bounds (EXPR_LOCATION (*expr_p), op0, &op1, - ignore_off_by_one); + if (TREE_CODE (*expr_p) == ARRAY_REF) + { + op0 = TREE_OPERAND (*expr_p, 0); + op1 = TREE_OPERAND (*expr_p, 1); + index_p = *expr_p; + index_n = 1; + e = ubsan_instrument_bounds (EXPR_LOCATION (*expr_p), op0, + &op1, ignore_off_by_one); + } + else if (is_instrumentable_pointer_array_address (*expr_p, &op0, &op1, + &index_p, &index_n)) + e = ubsan_instrument_bounds_pointer_address (EXPR_LOCATION (*expr_p), + op0, &op1, + ignore_off_by_one); + + /* Replace the original INDEX with the instrumented INDEX. */ if (e != NULL_TREE) - TREE_OPERAND (*expr_p, 1) = build2 (COMPOUND_EXPR, TREE_TYPE (op1), - e, op1); + TREE_OPERAND (index_p, index_n) + = build2 (COMPOUND_EXPR, TREE_TYPE (op1), e, op1); } } diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc index d547b08..5eb735e 100644 --- a/gcc/c-family/c-warn.cc +++ b/gcc/c-family/c-warn.cc @@ -3425,349 +3425,363 @@ expr_to_str (pretty_printer &pp, tree expr, const char *dflt) return pp_formatted_text (&pp); } -/* Detect and diagnose a mismatch between an attribute access specification - on the original declaration of FNDECL and that on the parameters NEWPARMS - from its redeclaration. ORIGLOC is the location of the first declaration - (FNDECL's is set to the location of the redeclaration). */ +/* Helper for warn_parms_array_mismatch. Compare the mappings of + two function parameters and diagnose mismatches. ORIGLOC is the + location of the first function declaration. CURP and NEWP are the + parameters in the first and second function declarators, + respectively. PARMPOS is the position of the parameters within the + list of parameter declarations. BUILTIN is true if the function is + a builtin. */ -void -warn_parm_array_mismatch (location_t origloc, tree fndecl, tree newparms) +static void +warn_parm_array_mismatch (location_t origloc, rdwr_map *cur_idx, + rdwr_map *new_idx, tree curp, tree newp, + unsigned parmpos, bool builtin) { - /* 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) + /* Create an empty access specification and use it for pointers with + no spec of their own. */ + attr_access ptr_spec = { }; + + /* Only check pointers and C++ references. */ + tree curptype = TREE_TYPE (curp); + tree newptype = TREE_TYPE (newp); + if (!POINTER_TYPE_P (curptype) || !POINTER_TYPE_P (newptype)) return; - if (TREE_CODE (curparms) != PARM_DECL - || TREE_CODE (newparms) != PARM_DECL) + /* Skip mismatches in __builtin_va_list that is commonly + an array but that in declarations of built-ins decays + to a pointer. */ + if (builtin && TREE_TYPE (newptype) == TREE_TYPE (va_list_type_node)) return; - /* Extract the (possibly empty) attribute access specification from - the declaration and its type (it doesn't yet reflect those created - in response to NEWPARMS). */ - rdwr_map cur_idx; - tree fntype = TREE_TYPE (fndecl); - init_attr_rdwr_indices (&cur_idx, TYPE_ATTRIBUTES (fntype)); - /* Build a (possibly null) chain of access attributes corresponding - to NEWPARMS. */ - const bool builtin = fndecl_built_in_p (fndecl); - tree newattrs = build_attr_access_from_parms (newparms, builtin); + /* Access specs for the argument on the current (previous) and + new (to replace the current) declarations. Either may be null, + indicating the parameter is an ordinary pointer with no size + associated with it. */ + attr_access *cura = cur_idx->get (parmpos); + attr_access *newa = new_idx->get (parmpos); - /* Extract the (possibly empty) attribute access specification from - NEWATTRS. */ - rdwr_map new_idx; - init_attr_rdwr_indices (&new_idx, newattrs); + if (!newa) + { + /* Continue if both parameters are pointers with no size + associated with them. */ + if (!cura) + return; - if (cur_idx.is_empty () && new_idx.is_empty ()) + /* Otherwise point at PTR_SPEC and set its parameter pointer + and number. */ + newa = &ptr_spec; + newa->ptr = newp; + newa->ptrarg = parmpos; + } + else if (!cura) { - /* If both specs are empty check pointers to VLAs for mismatches. */ - warn_parm_ptrarray_mismatch (origloc, curparms, newparms); - return; + cura = &ptr_spec; + cura->ptr = curp; + cura->ptrarg = parmpos; } - /* ...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 would be - empty. */ - - /* Create an empty access specification and use it for pointers with - no spec of their own. */ - attr_access ptr_spec = { }; - /* Iterate over the two lists of function parameters, comparing their - respective mappings and diagnosing mismatches. */ - unsigned parmpos = 0; - for (tree curp = curparms, newp = newparms; curp; - curp = TREE_CHAIN (curp), newp = TREE_CHAIN (newp), ++parmpos) - { - if (!newp) - /* Bail on invalid redeclarations with fewer arguments. */ - return; + /* Set if the parameter is [re]declared as a VLA. */ + const bool cur_vla_p = cura->size || cura->minsize == HOST_WIDE_INT_M1U; + const bool new_vla_p = newa->size || newa->minsize == HOST_WIDE_INT_M1U; - /* Only check pointers and C++ references. */ - tree curptype = TREE_TYPE (curp); - tree newptype = TREE_TYPE (newp); - if (!POINTER_TYPE_P (curptype) || !POINTER_TYPE_P (newptype)) - continue; + if (DECL_P (curp)) + origloc = DECL_SOURCE_LOCATION (curp); + else if (EXPR_P (curp) && EXPR_HAS_LOCATION (curp)) + origloc = EXPR_LOCATION (curp); - /* Skip mismatches in __builtin_va_list that is commonly - an array but that in declarations of built-ins decays - to a pointer. */ - if (builtin && TREE_TYPE (newptype) == TREE_TYPE (va_list_type_node)) - continue; + /* The location of the parameter in the current redeclaration. */ + location_t newloc = DECL_SOURCE_LOCATION (newp); + if (origloc == UNKNOWN_LOCATION) + origloc = newloc; - /* Access specs for the argument on the current (previous) and - new (to replace the current) declarations. Either may be null, - indicating the parameter is an ordinary pointer with no size - associated with it. */ - attr_access *cura = cur_idx.get (parmpos); - attr_access *newa = new_idx.get (parmpos); + const std::string newparmstr = newa->array_as_string (newptype); + const std::string curparmstr = cura->array_as_string (curptype); + if (new_vla_p && !cur_vla_p) + { + if (warning_at (newloc, OPT_Wvla_parameter, + "argument %u of type %s " + "declared as a variable length array", + parmpos + 1, newparmstr.c_str ())) + inform (origloc, + (cura == &ptr_spec + ? G_("previously declared as a pointer %s") + : G_("previously declared as an ordinary array %s")), + curparmstr.c_str ()); + return; + } - if (!newa) + if (newa == &ptr_spec) + { + /* The new declaration uses the pointer form. Detect mismatches + between the pointer and a previous array or VLA forms. */ + if (cura->minsize == HOST_WIDE_INT_M1U) { - /* Continue of both parameters are pointers with no size - associated with it. */ - if (!cura) - continue; - - /* Otherwise point at PTR_SPEC and set its parameter pointer - and number. */ - newa = &ptr_spec; - newa->ptr = newp; - newa->ptrarg = parmpos; + /* Diagnose a pointer/VLA mismatch. */ + if (warning_at (newloc, OPT_Wvla_parameter, + "argument %u of type %s declared as a pointer", + parmpos + 1, newparmstr.c_str ())) + inform (origloc, + "previously declared as a variable length array %s", + curparmstr.c_str ()); + return; } - else if (!cura) + + if (cura->minsize && cura->minsize != HOST_WIDE_INT_M1U) { - cura = &ptr_spec; - cura->ptr = curp; - cura->ptrarg = parmpos; + /* Diagnose mismatches between arrays with a constant + bound and pointers. */ + if (warning_at (newloc, OPT_Warray_parameter_, + "argument %u of type %s declared as a pointer", + parmpos + 1, newparmstr.c_str ())) + inform (origloc, "previously declared as an array %s", + curparmstr.c_str ()); + return; } + } - /* Set if the parameter is [re]declared as a VLA. */ - const bool cur_vla_p = cura->size || cura->minsize == HOST_WIDE_INT_M1U; - const bool new_vla_p = newa->size || newa->minsize == HOST_WIDE_INT_M1U; + if (!new_vla_p && cur_vla_p) + { + if (warning_at (newloc, OPT_Wvla_parameter, + "argument %u of type %s declared as an ordinary array", + parmpos + 1, newparmstr.c_str ())) + inform (origloc, "previously declared as a variable length array %s", + curparmstr.c_str ()); + return; + } - if (DECL_P (curp)) - origloc = DECL_SOURCE_LOCATION (curp); - else if (EXPR_P (curp) && EXPR_HAS_LOCATION (curp)) - origloc = EXPR_LOCATION (curp); + /* Move on to the next pair of parameters if both of the current + pair are VLAs with a single variable bound that refers to + a parameter at the same position. */ + if (newa->size && cura->size + && newa->sizarg != UINT_MAX + && newa->sizarg == cura->sizarg + && newa->minsize == cura->minsize + && !TREE_PURPOSE (newa->size) && !TREE_PURPOSE (cura->size)) + return; - /* The location of the parameter in the current redeclaration. */ - location_t newloc = DECL_SOURCE_LOCATION (newp); - if (origloc == UNKNOWN_LOCATION) - origloc = newloc; + if (newa->size || cura->size) + { + unsigned newunspec, curunspec; + unsigned newbnds = newa->vla_bounds (&newunspec) + newunspec; + unsigned curbnds = cura->vla_bounds (&curunspec) + curunspec; - const std::string newparmstr = newa->array_as_string (newptype); - const std::string curparmstr = cura->array_as_string (curptype); - if (new_vla_p && !cur_vla_p) + if (newbnds != curbnds) { - if (warning_at (newloc, OPT_Wvla_parameter, - "argument %u of type %s declared as " - "a variable length array", - parmpos + 1, newparmstr.c_str ())) - inform (origloc, - (cura == &ptr_spec - ? G_("previously declared as a pointer %s") - : G_("previously declared as an ordinary array %s")), - curparmstr.c_str ()); - continue; + if (warning_n (newloc, OPT_Wvla_parameter, newbnds, + "argument %u of type %s declared with " + "%u variable bound", + "argument %u of type %s declared with " + "%u variable bounds", + parmpos + 1, newparmstr.c_str (), + newbnds)) + inform_n (origloc, curbnds, + "previously declared as %s with %u variable bound", + "previously declared as %s with %u variable bounds", + curparmstr.c_str (), curbnds); + return; } - if (newa == &ptr_spec) + if (newunspec > curunspec) { - /* The new declaration uses the pointer form. Detect mismatches - between the pointer and a previous array or VLA forms. */ - if (cura->minsize == HOST_WIDE_INT_M1U) - { - /* Diagnose a pointer/VLA mismatch. */ - if (warning_at (newloc, OPT_Wvla_parameter, - "argument %u of type %s declared " - "as a pointer", - parmpos + 1, newparmstr.c_str ())) - inform (origloc, - "previously declared as a variable length array %s", - curparmstr.c_str ()); - continue; - } - - if (cura->minsize && cura->minsize != HOST_WIDE_INT_M1U) + location_t warnloc = newloc, noteloc = origloc; + const char *warnparmstr = newparmstr.c_str (); + const char *noteparmstr = curparmstr.c_str (); + unsigned warnunspec = newunspec, noteunspec = curunspec; + + if (warning_n (warnloc, OPT_Wvla_parameter, warnunspec, + "argument %u of type %s declared with " + "%u unspecified variable bound", + "argument %u of type %s declared with " + "%u unspecified variable bounds", + parmpos + 1, warnparmstr, warnunspec)) { - /* Diagnose mismatches between arrays with a constant - bound and pointers. */ - if (warning_at (newloc, OPT_Warray_parameter_, - "argument %u of type %s declared " - "as a pointer", - parmpos + 1, newparmstr.c_str ())) - inform (origloc, "previously declared as an array %s", - curparmstr.c_str ()); - continue; + if (warnloc == newloc) + inform_n (noteloc, noteunspec, + "previously declared as %s with " + "%u unspecified variable bound", + "previously declared as %s with " + "%u unspecified variable bounds", + noteparmstr, noteunspec); + else + inform_n (noteloc, noteunspec, + "subsequently declared as %s with " + "%u unspecified variable bound", + "subsequently declared as %s with " + "%u unspecified variable bounds", + noteparmstr, noteunspec); } + return; } + } - if (!new_vla_p && cur_vla_p) - { - if (warning_at (newloc, OPT_Wvla_parameter, - "argument %u of type %s declared " - "as an ordinary array", - parmpos + 1, newparmstr.c_str ())) - inform (origloc, - "previously declared as a variable length array %s", - curparmstr.c_str ()); - continue; - } + /* Iterate over the lists of VLA variable bounds, comparing each + pair for equality, and diagnosing mismatches. */ + for (tree newvbl = newa->size, curvbl = cura->size; newvbl && curvbl; + newvbl = TREE_CHAIN (newvbl), curvbl = TREE_CHAIN (curvbl)) + { + tree newpos = TREE_PURPOSE (newvbl); + tree curpos = TREE_PURPOSE (curvbl); - /* Move on to the next pair of parameters if both of the current - pair are VLAs with a single variable bound that refers to - a parameter at the same position. */ - if (newa->size && cura->size - && newa->sizarg != UINT_MAX - && newa->sizarg == cura->sizarg - && newa->minsize == cura->minsize - && !TREE_PURPOSE (newa->size) && !TREE_PURPOSE (cura->size)) + tree newbnd = vla_bound_parm_decl (TREE_VALUE (newvbl)); + tree curbnd = vla_bound_parm_decl (TREE_VALUE (curvbl)); + + if (newpos == curpos && newbnd == curbnd) + /* In the expected case when both bounds either refer to + the same positional parameter or when neither does, + and both are the same expression they are necessarily + the same. */ continue; - if (newa->size || cura->size) - { - unsigned newunspec, curunspec; - unsigned newbnds = newa->vla_bounds (&newunspec) + newunspec; - unsigned curbnds = cura->vla_bounds (&curunspec) + curunspec; + pretty_printer pp1, pp2; + const char* const newbndstr = expr_to_str (pp1, newbnd, "*"); + const char* const curbndstr = expr_to_str (pp2, curbnd, "*"); - if (newbnds != curbnds) + if (!newpos != !curpos + || (newpos && !tree_int_cst_equal (newpos, curpos))) + { + /* Diagnose a mismatch between a specified VLA bound and + an unspecified one. This can only happen in the most + significant bound. + + Distinguish between the common case of bounds that are + other function parameters such as in + f (int n, int[n]); + and others. */ + + gcc_rich_location richloc (newloc); + bool warned; + if (newpos) { - if (warning_n (newloc, OPT_Wvla_parameter, newbnds, - "argument %u of type %s declared with " - "%u variable bound", - "argument %u of type %s declared with " - "%u variable bounds", - parmpos + 1, newparmstr.c_str (), - newbnds)) - inform_n (origloc, curbnds, - "previously declared as %s with %u variable bound", - "previously declared as %s with %u variable bounds", - curparmstr.c_str (), curbnds); - continue; + /* Also underline the VLA bound argument. */ + richloc.add_range (DECL_SOURCE_LOCATION (newbnd)); + warned = warning_at (&richloc, OPT_Wvla_parameter, + "argument %u of type %s " + "declared with mismatched bound argument %E", + parmpos + 1, newparmstr.c_str (), + plus_one (newpos)); } + else + warned = warning_at (&richloc, OPT_Wvla_parameter, + "argument %u of type %s " + "declared with mismatched bound %qs", + parmpos + 1, newparmstr.c_str (), + newbndstr); - if (newunspec > curunspec) + if (warned) { - location_t warnloc = newloc, noteloc = origloc; - const char *warnparmstr = newparmstr.c_str (); - const char *noteparmstr = curparmstr.c_str (); - unsigned warnunspec = newunspec, noteunspec = curunspec; - - if (warning_n (warnloc, OPT_Wvla_parameter, warnunspec, - "argument %u of type %s declared with " - "%u unspecified variable bound", - "argument %u of type %s declared with " - "%u unspecified variable bounds", - parmpos + 1, warnparmstr, warnunspec)) + gcc_rich_location richloc (origloc); + if (curpos) { - if (warnloc == newloc) - inform_n (noteloc, noteunspec, - "previously declared as %s with %u unspecified " - "variable bound", - "previously declared as %s with %u unspecified " - "variable bounds", - noteparmstr, noteunspec); - else - inform_n (noteloc, noteunspec, - "subsequently declared as %s with %u unspecified " - "variable bound", - "subsequently declared as %s with %u unspecified " - "variable bounds", - noteparmstr, noteunspec); + /* Also underline the VLA bound argument. */ + richloc.add_range (DECL_SOURCE_LOCATION (curbnd)); + inform (&richloc, + "previously declared as %s with bound argument %E", + curparmstr.c_str (), plus_one (curpos)); } + else + inform (&richloc, + "previously declared as %s with bound %qs", + curparmstr.c_str (), curbndstr); + continue; } } - /* Iterate over the lists of VLA variable bounds, comparing each - pair for equality, and diagnosing mismatches. */ - for (tree newvbl = newa->size, curvbl = cura->size; newvbl && curvbl; - newvbl = TREE_CHAIN (newvbl), curvbl = TREE_CHAIN (curvbl)) + if (!newpos && newbnd && curbnd) { - tree newpos = TREE_PURPOSE (newvbl); - tree curpos = TREE_PURPOSE (curvbl); + /* 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_DECL_NAME | OEP_LEXICOGRAPHIC)) + continue; - tree newbnd = vla_bound_parm_decl (TREE_VALUE (newvbl)); - tree curbnd = vla_bound_parm_decl (TREE_VALUE (curvbl)); + if (warning_at (newloc, OPT_Wvla_parameter, + "argument %u of type %s " + "declared with mismatched bound %qs", + parmpos + 1, newparmstr.c_str (), newbndstr)) + inform (origloc, "previously declared as %s with bound %qs", + curparmstr.c_str (), curbndstr); + continue; + } + } - if (newpos == curpos && newbnd == curbnd) - /* In the expected case when both bounds either refer to - the same positional parameter or when neither does, - and both are the same expression they are necessarily - the same. */ - continue; + if (newa->minsize == cura->minsize + || (((newa->minsize == 0 && newa->mode != access_deferred) + || (cura->minsize == 0 && cura->mode != access_deferred)) + && newa != &ptr_spec + && cura != &ptr_spec)) + return; - pretty_printer pp1, pp2; - const char* const newbndstr = expr_to_str (pp1, newbnd, "*"); - const char* const curbndstr = expr_to_str (pp2, curbnd, "*"); + if (!newa->static_p && !cura->static_p && warn_array_parameter < 2) + /* Avoid warning about mismatches in ordinary (non-static) arrays + at levels below 2. */ + return; - if (!newpos != !curpos - || (newpos && !tree_int_cst_equal (newpos, curpos))) - { - /* Diagnose a mismatch between a specified VLA bound and - an unspecified one. This can only happen in the most - significant bound. - - Distinguish between the common case of bounds that are - other function parameters such as in - f (int n, int[n]); - and others. */ - - gcc_rich_location richloc (newloc); - bool warned; - if (newpos) - { - /* Also underline the VLA bound argument. */ - richloc.add_range (DECL_SOURCE_LOCATION (newbnd)); - warned = warning_at (&richloc, OPT_Wvla_parameter, - "argument %u of type %s declared " - "with mismatched bound argument %E", - parmpos + 1, newparmstr.c_str (), - plus_one (newpos)); - } - else - warned = warning_at (&richloc, OPT_Wvla_parameter, - "argument %u of type %s declared " - "with mismatched bound %qs", - parmpos + 1, newparmstr.c_str (), - newbndstr); + if (warning_at (newloc, OPT_Warray_parameter_, + "argument %u of type %s with mismatched bound", + parmpos + 1, newparmstr.c_str ())) + inform (origloc, "previously declared as %s", curparmstr.c_str ()); +} - if (warned) - { - gcc_rich_location richloc (origloc); - if (curpos) - { - /* Also underline the VLA bound argument. */ - richloc.add_range (DECL_SOURCE_LOCATION (curbnd)); - inform (&richloc, "previously declared as %s with " - "bound argument %E", - curparmstr.c_str (), plus_one (curpos)); - } - else - inform (&richloc, "previously declared as %s with bound " - "%qs", curparmstr.c_str (), curbndstr); +/* Detect and diagnose a mismatch between an attribute access specification + on the original declaration of FNDECL and that on the parameters NEWPARMS + from its redeclaration. ORIGLOC is the location of the first declaration + (FNDECL's is set to the location of the redeclaration). */ - continue; - } - } +void +warn_parms_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 declaration. */ + tree curparms = DECL_ARGUMENTS (fndecl); + if (!curparms || !newparms || curparms == newparms) + return; - if (!newpos && newbnd && curbnd) - { - /* 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_DECL_NAME | OEP_LEXICOGRAPHIC)) - continue; - - if (warning_at (newloc, OPT_Wvla_parameter, - "argument %u of type %s declared with " - "mismatched bound %qs", - parmpos + 1, newparmstr.c_str (), newbndstr)) - inform (origloc, "previously declared as %s with bound %qs", - curparmstr.c_str (), curbndstr); - continue; - } - } + if (TREE_CODE (curparms) != PARM_DECL + || TREE_CODE (newparms) != PARM_DECL) + return; + /* Extract the (possibly empty) attribute access specification from + the declaration and its type (it doesn't yet reflect those created + in response to NEWPARMS). */ + rdwr_map cur_idx; + tree fntype = TREE_TYPE (fndecl); + init_attr_rdwr_indices (&cur_idx, TYPE_ATTRIBUTES (fntype)); - if (newa->minsize == cura->minsize - || (((newa->minsize == 0 && newa->mode != access_deferred) - || (cura->minsize == 0 && cura->mode != access_deferred)) - && newa != &ptr_spec - && cura != &ptr_spec)) - continue; + /* Build a (possibly null) chain of access attributes corresponding + to NEWPARMS. */ + const bool builtin = fndecl_built_in_p (fndecl); + tree newattrs = build_attr_access_from_parms (newparms, builtin); - if (!newa->static_p && !cura->static_p && warn_array_parameter < 2) - /* Avoid warning about mismatches in ordinary (non-static) arrays - at levels below 2. */ - continue; + /* Extract the (possibly empty) attribute access specification from + NEWATTRS. */ + rdwr_map new_idx; + init_attr_rdwr_indices (&new_idx, newattrs); - if (warning_at (newloc, OPT_Warray_parameter_, - "argument %u of type %s with mismatched bound", - parmpos + 1, newparmstr.c_str ())) - inform (origloc, "previously declared as %s", curparmstr.c_str ()); + if (cur_idx.is_empty () && new_idx.is_empty ()) + { + /* If both specs are empty check pointers to VLAs for mismatches. */ + warn_parm_ptrarray_mismatch (origloc, curparms, 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 would be + empty. */ + + /* Iterate over the two lists of function parameters, comparing their + respective mappings and diagnosing mismatches. */ + unsigned parmpos = 0; + for (tree curp = curparms, newp = newparms; curp; + curp = TREE_CHAIN (curp), newp = TREE_CHAIN (newp), ++parmpos) + { + if (!newp) + /* Bail on invalid redeclarations with fewer arguments. */ + return; + + warn_parm_array_mismatch (origloc, &cur_idx, &new_idx, curp, newp, parmpos, + builtin); } } @@ -3835,7 +3849,7 @@ do_warn_array_compare (location_t location, tree_code code, tree op0, tree op1) op1 = TREE_OPERAND (op1, 0); auto_diagnostic_group d; - diagnostic_t kind = DK_WARNING; + enum diagnostics::kind kind = diagnostics::kind::warning; const char *msg; if (c_dialect_cxx () && cxx_dialect >= cxx20) { @@ -3843,7 +3857,7 @@ do_warn_array_compare (location_t location, tree_code code, tree op0, tree op1) if (cxx_dialect >= cxx26) { msg = G_("comparison between two arrays is not allowed in C++26"); - kind = DK_PERMERROR; + kind = diagnostics::kind::permerror; } else msg = G_("comparison between two arrays is deprecated in C++20"); diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 75b6531..e1576c9 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -45,6 +45,10 @@ C ObjC C++ ObjC++ Separate Alias(A) MissingArgError(assertion missing after %qs) -assert= C ObjC C++ ObjC++ Joined Alias(A) MissingArgError(assertion missing after %qs) +-compile-std-module +C++ ObjC++ Driver +--compile-std-module Compile module units for <bits/stdc++.h>, std, and std.compat. + -comments C ObjC C++ ObjC++ Alias(C) @@ -267,15 +271,15 @@ C ObjC C++ ObjC++ Joined Separate MissingArgError(missing makefile target after -MT <target> Add a target that does not require quoting. fdeps-format= -C ObjC C++ ObjC++ NoDriverArg Joined MissingArgError(missing format after %qs) +C ObjC C++ ObjC++ RejectNegative Joined MissingArgError(missing format after %qs) Structured format for output dependency information. Supported (\"p1689r5\"). fdeps-file= -C ObjC C++ ObjC++ NoDriverArg Joined MissingArgError(missing output path after %qs) +C ObjC C++ ObjC++ RejectNegative Joined MissingArgError(missing output path after %qs) File for output dependency information. fdeps-target= -C ObjC C++ ObjC++ NoDriverArg Joined MissingArgError(missing path after %qs) +C ObjC C++ ObjC++ RejectNegative Joined MissingArgError(missing path after %qs) -fdeps-target=obj.o Output file for the compile step. P @@ -351,12 +355,12 @@ C ObjC C++ ObjC++ Var(warn_alloc_size) Warning LangEnabledBy(C ObjC C++ ObjC++, Warn when allocating insufficient storage for the target type of the assigned pointer. Walloc-size-larger-than= -C ObjC C++ LTO ObjC++ Var(warn_alloc_size_limit) Joined Host_Wide_Int ByteSize Warning Init(HOST_WIDE_INT_MAX) +C ObjC C++ LTO ObjC++ Var(warn_alloc_size_limit) Joined RejectNegative Host_Wide_Int ByteSize Warning Init(HOST_WIDE_INT_MAX) -Walloc-size-larger-than=<bytes> Warn for calls to allocation functions that attempt to allocate objects larger than the specified number of bytes. Wno-alloc-size-larger-than -C ObjC C++ LTO ObjC++ Alias(Walloc-size-larger-than=,18446744073709551615EiB,none) Warning +C ObjC C++ LTO ObjC++ RejectNegative Alias(Walloc-size-larger-than=,18446744073709551615EiB,none) Warning Disable Walloc-size-larger-than= warning. Equivalent to Walloc-size-larger-than=<SIZE_MAX> or larger. Walloc-zero @@ -364,13 +368,13 @@ C ObjC C++ ObjC++ Var(warn_alloc_zero) Warning Warn for calls to allocation functions that specify zero bytes. Walloca-larger-than= -C ObjC C++ LTO ObjC++ Var(warn_alloca_limit) Warning Joined Host_Wide_Int ByteSize Init(HOST_WIDE_INT_MAX) +C ObjC C++ LTO ObjC++ Var(warn_alloca_limit) Warning Joined RejectNegative Host_Wide_Int ByteSize Init(HOST_WIDE_INT_MAX) -Walloca-larger-than=<number> Warn on unbounded uses of alloca, and on bounded uses of alloca whose bound can be larger than <number> bytes. Wno-alloca-larger-than -C ObjC C++ LTO ObjC++ Alias(Walloca-larger-than=,18446744073709551615EiB,none) Warning +C ObjC C++ LTO ObjC++ RejectNegative Alias(Walloca-larger-than=,18446744073709551615EiB,none) Warning Disable Walloca-larger-than= warning. Equivalent to Walloca-larger-than=<SIZE_MAX> or larger. Warith-conversion @@ -397,6 +401,10 @@ Wassign-intercept ObjC ObjC++ Var(warn_assign_intercept) Warning Warn whenever an Objective-C assignment is being intercepted by the garbage collector. +Wabbreviated-auto-in-template-arg +C++ ObjC++ Warning Var(warn_abbev_auto_targ) Init(1) +Diagnose a placeholder type in a template argument in a function parameter type. + Wbad-function-cast C ObjC Var(warn_bad_function_cast) Warning Warn about casting functions to incompatible types. @@ -493,6 +501,10 @@ Wc++20-compat C++ ObjC++ Var(warn_cxx20_compat) Warning LangEnabledBy(C++ ObjC++,Wall) Init(0) CPP(cpp_warn_cxx20_compat) CppReason(CPP_W_CXX20_COMPAT) Warn about C++ constructs whose meaning differs between ISO C++ 2017 and ISO C++ 2020. +Wc++26-compat +C++ ObjC++ Var(warn_cxx26_compat) Warning LangEnabledBy(C++ ObjC++,Wall) Init(0) +Warn about C++ constructs whose meaning differs between ISO C++ 2023 and ISO C++ 2026. + Wc++11-extensions C++ ObjC++ Var(warn_cxx11_extensions) Warning Init(1) Warn about C++11 constructs in code compiled with an older standard. @@ -753,6 +765,14 @@ Wexpansion-to-defined C ObjC C++ ObjC++ CPP(warn_expansion_to_defined) CppReason(CPP_W_EXPANSION_TO_DEFINED) Var(cpp_warn_expansion_to_defined) Init(0) Warning EnabledBy(Wextra || Wpedantic) Warn if \"defined\" is used outside #if. +Wexternal-tu-local +C++ ObjC++ Var(warn_tu_local) Warning Init(1) +Warn about naming a TU-local entity declared in another translation unit. + +Wexpose-global-module-tu-local +C++ ObjC++ Var(warn_expose_global_module_tu_local) Init(1) Warning +Warn when a module exposes a TU-local entity from the global module fragment. + Wextra C ObjC C++ ObjC++ Warning ; in common.opt @@ -762,7 +782,7 @@ C++ ObjC++ Var(warn_extra_semi) Init(-1) Warning Warn about semicolon after in-class function definition. Wflex-array-member-not-at-end -C C++ Var(warn_flex_array_member_not_at_end) Warning +C ObjC C++ ObjC++ Var(warn_flex_array_member_not_at_end) Warning Warn when a structure containing a C99 flexible array member as the last field is not at the end of another structure. @@ -854,11 +874,11 @@ C ObjC C++ ObjC++ Var(warn_if_not_aligned) Init(1) Warning Warn when the field in a struct is not aligned. Wignored-qualifiers -C C++ Var(warn_ignored_qualifiers) Warning EnabledBy(Wextra) +C ObjC C++ ObjC++ Var(warn_ignored_qualifiers) Warning EnabledBy(Wextra) Warn whenever type qualifiers are ignored. Wignored-attributes -C C++ Var(warn_ignored_attributes) Init(1) Warning +C ObjC C++ ObjC++ Var(warn_ignored_attributes) Init(1) Warning Warn whenever attributes are ignored. Wimplicit @@ -938,7 +958,7 @@ C ObjC C++ ObjC++ CPP(cpp_warn_invalid_utf8) CppReason(CPP_W_INVALID_UTF8) Var(w Warn about invalid UTF-8 characters. Wjump-misses-init -C ObjC Var(warn_jump_misses_init) Warning LangEnabledby(C ObjC,Wc++-compat) +C ObjC Var(warn_jump_misses_init) Warning LangEnabledBy(C ObjC,Wc++-compat) Warn when a jump misses a variable initialization. Enum @@ -956,6 +976,10 @@ Enum(warn_leading_whitespace_kind) String(tabs) Value(2) EnumValue Enum(warn_leading_whitespace_kind) String(blanks) Value(3) +Wkeyword-macro +C ObjC C++ ObjC++ CPP(cpp_warn_keyword_macro) CppReason(CPP_W_KEYWORD_MACRO) Var(warn_keyword_macro) Init(0) Warning +Warn about defining or undefining macros with identifiers equal to keywords (or for C++ conditional keywords or standard attribute names). + Wleading-whitespace= C ObjC C++ ObjC++ CPP(cpp_warn_leading_whitespace) CppReason(CPP_W_LEADING_WHITESPACE) Enum(warn_leading_whitespace_kind) Joined RejectNegative Var(warn_leading_whitespace) Init(0) Warning Warn about leading whitespace style issues on lines except when in raw string literals. @@ -997,7 +1021,7 @@ C ObjC C++ ObjC++ Var(warn_memset_transposed_args) Warning LangEnabledBy(C ObjC Warn about suspicious calls to memset where the third argument is constant literal zero and the second is not. Wmisleading-indentation -C C++ Common Var(warn_misleading_indentation) Warning LangEnabledBy(C C++,Wall) +C ObjC C++ ObjC++ Common Var(warn_misleading_indentation) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) Warn when the indentation of the code does not reflect the block structure. Wmismatched-dealloc @@ -1074,6 +1098,10 @@ Wmultiple-inheritance C++ ObjC++ Var(warn_multiple_inheritance) Warning Warn on direct multiple inheritance. +Wmultiple-parameter-fwd-decl-lists +C ObjC Var(warn_multiple_parameter_fwd_decl_lists) Warning EnabledBy(Wextra) +Warn for multiple lists of forward declarations of function parameters. + 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. @@ -1098,6 +1126,10 @@ Wnoexcept-type C++ ObjC++ Warning Var(warn_noexcept_type) LangEnabledBy(C++ ObjC++,Wabi || Wc++17-compat) Warn if C++17 noexcept function type will change the mangled name of a symbol. +Wnon-c-typedef-for-linkage +C++ ObjC++ Var(warn_non_c_typedef_for_linkage) Init(1) Warning +Warn for non-C compatible unnamed classes with a typedef name for linkage purposes. + Wnon-template-friend C++ ObjC++ Var(warn_nontemplate_friend) Init(1) Warning Warn when non-templatized friend functions are declared within a template. @@ -1163,7 +1195,7 @@ 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 +C ObjC C++ ObjC++ Var(warn_openacc_parallelism) Warning Warn about potentially suboptimal choices related to OpenACC parallelism. Wopenmp @@ -1171,7 +1203,7 @@ C ObjC C++ ObjC++ Warning Var(warn_openmp) Init(1) Warn about suspicious OpenMP code. Wopenmp-simd -C C++ Var(warn_openmp_simd) Warning LangEnabledBy(C C++,Wall) +C ObjC C++ ObjC++ Var(warn_openmp_simd) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) Warn if a simd directive is overridden by the vectorizer cost model. Woverlength-strings @@ -1183,7 +1215,7 @@ C++ ObjC++ Warning Alias(Woverloaded-virtual=,2,0) Warn about overloaded virtual function names. Woverloaded-virtual= -C++ ObjC++ Joined UInteger IntegerRange(0,2) Var(warn_overloaded_virtual) Warning LangEnabledBy(C++ ObjC++,Wall,1,0) +C++ ObjC++ Joined RejectNegative UInteger IntegerRange(0,2) Var(warn_overloaded_virtual) Warning LangEnabledBy(C++ ObjC++,Wall,1,0) Warn about overloaded virtual function names. Woverride-init @@ -1219,11 +1251,11 @@ C++ ObjC++ Var(warn_pessimizing_move) Warning LangEnabledBy(C++ ObjC++, Wall) Warn about calling std::move on a local object in a return statement preventing copy elision. Wplacement-new -C++ Warning Alias(Wplacement-new=, 1, 0) +C++ ObjC++ Warning Alias(Wplacement-new=, 1, 0) Warn for placement new expressions with undefined behavior. Wplacement-new= -C++ Joined RejectNegative UInteger Var(warn_placement_new) Init(-1) Warning IntegerRange(0, 2) +C++ ObjC++ Joined RejectNegative UInteger Var(warn_placement_new) Init(-1) Warning IntegerRange(0, 2) Warn for placement new expressions with undefined behavior. Wpmf-conversions @@ -1319,6 +1351,14 @@ Wsequence-point C ObjC C++ ObjC++ Var(warn_sequence_point) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) Warn about possible violations of sequence point rules. +Wsfinae-incomplete= +C++ ObjC++ Var(warn_sfinae_incomplete) Warning Init(1) Joined RejectNegative UInteger IntegerRange(0, 2) +Warn about an incomplete type affecting semantics in a non-error context. + +Wsfinae-incomplete +C++ ObjC++ Warning Alias(Wsfinae-incomplete=, 1, 0) +Warn about an incomplete type affecting semantics in a non-error context. + Wshadow-ivar ObjC ObjC++ Var(warn_shadow_ivar) EnabledBy(Wshadow) Init(1) Warning Warn if a local declaration hides an instance variable. @@ -1385,7 +1425,7 @@ C ObjC C++ ObjC++ LangEnabledBy(C ObjC C++ ObjC++,Wall, 3, 0) IntegerRange(0, 3) ; Wstrict-flex-arrays -C C++ Var(warn_strict_flex_arrays) Warning +C ObjC C++ ObjC++ Var(warn_strict_flex_arrays) Warning Warn about improper usages of flexible array members according to the level of -fstrict-flex-arrays. @@ -1463,12 +1503,12 @@ C ObjC C++ ObjC++ Var(warn_switch_outside_range) Warning Init(1) Warn about switch values that are outside of the switch's type range. Wsync-nand -C C++ Var(warn_sync_nand) Init(1) Warning +C ObjC C++ ObjC++ Var(warn_sync_nand) Init(1) Warning Warn when __sync_fetch_and_nand and __sync_nand_and_fetch built-in functions are used. Wsynth -C++ ObjC++ Var(warn_synth) Warning -Deprecated. This switch has no effect. +C++ ObjC++ Warning Ignore +Does nothing. Preserved for backward compatibility. Wsystem-headers C ObjC C++ ObjC++ Warning @@ -1615,13 +1655,13 @@ C ObjC C++ ObjC++ Var(warn_vla) Init(-1) Warning Warn if a variable length array is used. Wvla-larger-than= -C ObjC C++ LTO ObjC++ Var(warn_vla_limit) Warning Joined Host_Wide_Int ByteSize Init(HOST_WIDE_INT_MAX) +C ObjC C++ LTO ObjC++ Var(warn_vla_limit) Warning Joined RejectNegative Host_Wide_Int ByteSize Init(HOST_WIDE_INT_MAX) -Wvla-larger-than=<number> Warn on unbounded uses of variable-length arrays, and on bounded uses of variable-length arrays whose bound can be larger than <number> bytes. Wno-vla-larger-than -C ObjC C++ LTO ObjC++ Alias(Wvla-larger-than=,18446744073709551615EiB,none) Warning +C ObjC C++ LTO ObjC++ RejectNegative Alias(Wvla-larger-than=,18446744073709551615EiB,none) Warning Disable Wvla-larger-than= warning. Equivalent to Wvla-larger-than=<SIZE_MAX> or larger. Wvla-parameter @@ -1868,35 +1908,35 @@ EnumValue Enum(on_off) String(on) Value(1) fcontract-assumption-mode= -C++ Joined RejectNegative +C++ ObjC++ Joined RejectNegative -fcontract-assumption-mode=[on|off] Enable or disable treating axiom level contracts as assumptions (default on). fcontract-build-level= -C++ Joined RejectNegative +C++ ObjC++ Joined RejectNegative -fcontract-build-level=[off|default|audit] Specify max contract level to generate runtime checks for. fcontract-strict-declarations= -C++ Var(flag_contract_strict_declarations) Enum(on_off) Joined Init(0) RejectNegative +C++ ObjC++ Var(flag_contract_strict_declarations) Enum(on_off) Joined Init(0) RejectNegative -fcontract-strict-declarations=[on|off] Enable or disable warnings on generalized redeclaration of functions with contracts (default off). fcontract-mode= -C++ Var(flag_contract_mode) Enum(on_off) Joined Init(1) RejectNegative +C++ ObjC++ Var(flag_contract_mode) Enum(on_off) Joined Init(1) RejectNegative -fcontract-mode=[on|off] Enable or disable all contract facilities (default on). fcontract-continuation-mode= -C++ Joined RejectNegative +C++ ObjC++ Joined RejectNegative -fcontract-continuation-mode=[on|off] Enable or disable contract continuation mode (default off). fcontract-role= -C++ Joined RejectNegative +C++ ObjC++ Joined RejectNegative -fcontract-role=<name>:<semantics> Specify the semantics for all levels in a role (default, review), or a custom contract role with given semantics (ex: opt:assume,assume,assume). fcontract-semantic= -C++ Joined RejectNegative +C++ ObjC++ Joined RejectNegative -fcontract-semantic=<level>:<semantic> Specify the concrete semantics for level. fcoroutines -C++ LTO Var(flag_coroutines) +C++ ObjC++ LTO Var(flag_coroutines) Enable C++ coroutines (experimental). fdebug-cpp @@ -2086,7 +2126,7 @@ C++ ObjC++ Var(flag_module_lazy) Init(1) Enable lazy module importing. fmodule-version-ignore -C++ ObjC Var(flag_module_version_ignore) Integer +C++ ObjC Var(flag_module_version_ignore) Integer Undocumented ; undocumented, Very dangerous, but occasionally useful Winvalid-imported-macros @@ -2098,23 +2138,23 @@ C ObjC Var(warn_compare_distinct_pointer_types) Warning Init(1) Warn if pointers of distinct types are compared without a cast. flang-info-include-translate -C++ Var(note_include_translate_yes) +C++ ObjC++ Var(note_include_translate_yes) Note #include directives translated to import declarations. flang-info-include-translate-not -C++ Var(note_include_translate_no) +C++ ObjC++ Var(note_include_translate_no) Note #include directives not translated to import declarations, and not known to be textual. flang-info-include-translate= -C++ Joined RejectNegative MissingArgError(missing header name) +C++ ObjC++ Joined RejectNegative MissingArgError(missing header name) Note a #include translation of a specific header. flang-info-module-cmi -C++ Var(note_module_cmi_yes) +C++ ObjC++ Var(note_module_cmi_yes) Note Compiled Module Interface pathnames. flang-info-module-cmi= -C++ Joined RejectNegative MissingArgError(missing module name) +C++ ObjC++ Joined RejectNegative MissingArgError(missing module name) Note Compiled Module Interface pathname of a specific module or header-unit. fmax-include-depth= @@ -2227,7 +2267,7 @@ C ObjC C++ ObjC++ LTO Var(flag_openacc) Enable OpenACC. fopenacc-dim= -C ObjC C++ ObjC++ LTO Joined Var(flag_openacc_dims) +C ObjC C++ ObjC++ LTO Joined RejectNegative Var(flag_openacc_dims) Specify default OpenACC compute dimensions. fopenmp @@ -2325,10 +2365,10 @@ C++ ObjC++ Var(flag_sized_deallocation) Init(-1) Enable C++14 sized deallocation support. fstrict-flex-arrays -C C++ Common Alias(fstrict-flex-arrays=,3,0) +C ObjC C++ ObjC++ Common Alias(fstrict-flex-arrays=,3,0) fstrict-flex-arrays= -C C++ Common Joined RejectNegative UInteger Var(flag_strict_flex_arrays) Init(0) IntegerRange(0,3) +C ObjC C++ ObjC++ Common Joined RejectNegative UInteger Var(flag_strict_flex_arrays) Init(0) IntegerRange(0,3) -fstrict-flex-arrays=<level> Control when to treat the trailing array of a structure as a flexible array member for the purposes of accessing the elements of such an array. The default is treating all trailing arrays of structures as flexible array members. fsquangle @@ -2458,15 +2498,15 @@ ObjC ObjC++ Driver Var(flag_gen_declaration) RejectNegative Dump declarations to a .decl file. femit-struct-debug-baseonly -C ObjC C++ ObjC++ +C ObjC C++ ObjC++ RejectNegative -femit-struct-debug-baseonly Aggressive reduced debug info for structs. femit-struct-debug-reduced -C ObjC C++ ObjC++ +C ObjC C++ ObjC++ RejectNegative -femit-struct-debug-reduced Conservative reduced debug info for structs. femit-struct-debug-detailed= -C ObjC C++ ObjC++ Joined +C ObjC C++ ObjC++ Joined RejectNegative -femit-struct-debug-detailed=<spec-list> Detailed reduced debug info for structs. fext-numeric-literals @@ -2578,15 +2618,15 @@ Conform to the ISO 2017 C++ standard. std=c++2a C++ ObjC++ Alias(std=c++20) Undocumented -Conform to the ISO 2020 C++ standard (experimental and incomplete support). +Deprecated in favor of -std=c++20. std=c++20 C++ ObjC++ -Conform to the ISO 2020 C++ standard (experimental and incomplete support). +Conform to the ISO 2020 C++ standard. std=c++2b C++ ObjC++ Alias(std=c++23) Undocumented -Conform to the ISO 2023 C++ standard (published in 2024; experimental and incomplete support). +Deprecated in favor of -std=c++23. std=c++23 C++ ObjC++ @@ -2680,15 +2720,15 @@ Conform to the ISO 2017 C++ standard with GNU extensions. std=gnu++2a C++ ObjC++ Alias(std=gnu++20) Undocumented -Conform to the ISO 2020 C++ standard with GNU extensions (experimental and incomplete support). +Deprecated in favor of -std=gnu++20. std=gnu++20 C++ ObjC++ -Conform to the ISO 2020 C++ standard with GNU extensions (experimental and incomplete support). +Conform to the ISO 2020 C++ standard with GNU extensions. std=gnu++2b C++ ObjC++ Alias(std=gnu++23) Undocumented -Conform to the ISO 2023 C++ standard with GNU extensions (published in 2024; experimental and incomplete support). +Deprecated in favor of -std=gnu++23. std=gnu++23 C++ ObjC++ diff --git a/gcc/c-family/c.opt.urls b/gcc/c-family/c.opt.urls index ad6d8a0..9430f4b 100644 --- a/gcc/c-family/c.opt.urls +++ b/gcc/c-family/c.opt.urls @@ -1,8 +1,5 @@ ; Autogenerated by regenerate-opt-urls.py from gcc/c-family/c.opt and generated HTML -A -UrlSuffix(gcc/Preprocessor-Options.html#index-A) - C UrlSuffix(gcc/Preprocessor-Options.html#index-C) LangUrlSuffix_Fortran(gfortran/Preprocessing-Options.html#index-C) @@ -26,7 +23,7 @@ H UrlSuffix(gcc/Preprocessor-Options.html#index-H) LangUrlSuffix_D(gdc/Code-Generation.html#index-H) LangUrlSuffix_Fortran(gfortran/Preprocessing-Options.html#index-H) I -UrlSuffix(gcc/Directory-Options.html#index-I) LangUrlSuffix_D(gdc/Directory-Options.html#index-I) +UrlSuffix(gcc/Directory-Options.html#index-I) LangUrlSuffix_D(gdc/Directory-Options.html#index-I) LangUrlSuffix_Algol68(ga68/Directory-options.html#index-I) M UrlSuffix(gcc/Preprocessor-Options.html#index-M) LangUrlSuffix_D(gdc/Code-Generation.html#index-M) @@ -139,6 +136,9 @@ UrlSuffix(gcc/Warning-Options.html#index-Warray-parameter) Wassign-intercept UrlSuffix(gcc/Objective-C-and-Objective-C_002b_002b-Dialect-Options.html#index-Wassign-intercept) +Wabbreviated-auto-in-template-arg +UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wabbreviated-auto-in-template-arg) + Wbad-function-cast UrlSuffix(gcc/Warning-Options.html#index-Wbad-function-cast) @@ -163,6 +163,9 @@ UrlSuffix(gcc/Warning-Options.html#index-Wbuiltin-macro-redefined) Wc11-c23-compat UrlSuffix(gcc/Warning-Options.html#index-Wc11-c23-compat) +Wc11-c2x-compat +UrlSuffix(gcc/Warning-Options.html#index-Wc11-c2x-compat) + Wc23-c2y-compat UrlSuffix(gcc/Warning-Options.html#index-Wc23-c2y-compat) @@ -187,6 +190,9 @@ UrlSuffix(gcc/Warning-Options.html#index-Wc_002b_002b17-compat) Wc++20-compat UrlSuffix(gcc/Warning-Options.html#index-Wc_002b_002b20-compat) +Wc++26-compat +UrlSuffix(gcc/Warning-Options.html#index-Wc_002b_002b26-compat) + Wc++11-extensions UrlSuffix(gcc/Warning-Options.html#index-Wc_002b_002b11-extensions) @@ -301,6 +307,9 @@ UrlSuffix(gcc/Warning-Options.html#index-Wdeprecated) LangUrlSuffix_D(gdc/Warnin Wdeprecated-copy UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wdeprecated-copy) +Wdeprecated-copy-dtor +UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wdeprecated-copy-dtor) + Wdeprecated-enum-enum-conversion UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wdeprecated-enum-enum-conversion) @@ -370,6 +379,12 @@ UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wexceptions) Wexpansion-to-defined UrlSuffix(gcc/Warning-Options.html#index-Wexpansion-to-defined) +Wexternal-tu-local +UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wexternal-tu-local) + +Wexpose-global-module-tu-local +UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wexpose-global-module-tu-local) + Wextra UrlSuffix(gcc/Warning-Options.html#index-Wextra) LangUrlSuffix_D(gdc/Warnings.html#index-Wextra) LangUrlSuffix_Fortran(gfortran/Error-and-Warning-Options.html#index-Wextra) @@ -391,6 +406,9 @@ UrlSuffix(gcc/Warning-Options.html#index-Wformat) Wformat-contains-nul UrlSuffix(gcc/Warning-Options.html#index-Wformat-contains-nul) +Wformat-diag +UrlSuffix(gcc/Warning-Options.html#index-Wformat-diag) + Wformat-extra-args UrlSuffix(gcc/Warning-Options.html#index-Wformat-extra-args) @@ -502,6 +520,9 @@ UrlSuffix(gcc/Warning-Options.html#index-Winvalid-utf8) Wjump-misses-init UrlSuffix(gcc/Warning-Options.html#index-Wjump-misses-init) +Wkeyword-macro +UrlSuffix(gcc/Warning-Options.html#index-Wkeyword-macro) + Wleading-whitespace= UrlSuffix(gcc/Warning-Options.html#index-Wleading-whitespace_003d) @@ -586,6 +607,9 @@ UrlSuffix(gcc/Warning-Options.html#index-Wmultichar) Wmultiple-inheritance UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wmultiple-inheritance) +Wmultiple-parameter-fwd-decl-lists +UrlSuffix(gcc/Warning-Options.html#index-Wmultiple-parameter-fwd-decl-lists) + Wmultistatement-macros UrlSuffix(gcc/Warning-Options.html#index-Wmultistatement-macros) @@ -604,6 +628,9 @@ UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wno-noexcept) Wnoexcept-type UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wno-noexcept-type) +Wnon-c-typedef-for-linkage +UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wno-non-c-typedef-for-linkage) + Wnon-template-friend UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wno-non-template-friend) @@ -756,6 +783,12 @@ UrlSuffix(gcc/Warning-Options.html#index-Wno-self-move) Wsequence-point UrlSuffix(gcc/Warning-Options.html#index-Wno-sequence-point) +Wsfinae-incomplete= +UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wno-sfinae-incomplete) + +Wsfinae-incomplete +UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wno-sfinae-incomplete) + Wshadow-ivar UrlSuffix(gcc/Warning-Options.html#index-Wno-shadow-ivar) @@ -1024,7 +1057,7 @@ UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-fassume-sane-operators-new- ; duplicate: 'gdc/Runtime-Options.html#index-fbuiltin' fcanonical-system-headers -UrlSuffix(gcc/Preprocessor-Options.html#index-fno-canonical-system-headers) +UrlSuffix(gcc/Preprocessor-Options.html#index-fcanonical-system-headers) fchar8_t UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-fchar8_005ft) @@ -1032,6 +1065,9 @@ UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-fchar8_005ft) fconcepts UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-fconcepts) +fconcepts-diagnostics-depth= +UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-fconcepts-diagnostics-depth) + fcond-mismatch UrlSuffix(gcc/C-Dialect-Options.html#index-fcond-mismatch) @@ -1074,6 +1110,9 @@ UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-fcontract-continuation-mode fcontract-role= UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-fcontract-role) +fcontract-semantic= +UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-fcontract-semantic) + fcoroutines UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-fcoroutines) @@ -1105,6 +1144,9 @@ UrlSuffix(gcc/Preprocessor-Options.html#index-fmacro-prefix-map) fdump-ada-spec UrlSuffix(gcc/Overall-Options.html#index-fdump-ada-spec) +fdump-ada-spec-slim +UrlSuffix(gcc/Overall-Options.html#index-fdump-ada-spec-slim) + felide-constructors UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-felide-constructors) diff --git a/gcc/c-family/known-headers.cc b/gcc/c-family/known-headers.cc index 7e0fa95..e3c0113 100644 --- a/gcc/c-family/known-headers.cc +++ b/gcc/c-family/known-headers.cc @@ -329,9 +329,10 @@ suggest_missing_header::~suggest_missing_header () /* suggest_missing_option's ctor. */ -suggest_missing_option::suggest_missing_option (location_t loc, - const char *macro_name, - diagnostic_option_id option_id) +suggest_missing_option:: +suggest_missing_option (location_t loc, + const char *macro_name, + diagnostics::option_id option_id) : deferred_diagnostic (loc), m_name_str (macro_name), m_option_id (option_id) { gcc_assert (macro_name); diff --git a/gcc/c-family/known-headers.h b/gcc/c-family/known-headers.h index b1da757..3ffe5f3 100644 --- a/gcc/c-family/known-headers.h +++ b/gcc/c-family/known-headers.h @@ -48,12 +48,12 @@ class suggest_missing_option : public deferred_diagnostic { public: suggest_missing_option (location_t loc, const char *name, - diagnostic_option_id option_id); + diagnostics::option_id option_id); ~suggest_missing_option (); private: const char *m_name_str; - diagnostic_option_id m_option_id; + diagnostics::option_id m_option_id; }; #endif /* GCC_KNOWN_HEADERS_H */ |
