diff options
author | Ian Lance Taylor <iant@golang.org> | 2022-07-27 10:15:41 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2022-07-27 10:15:41 -0700 |
commit | 9f62ed218fa656607740b386c0caa03e65dcd283 (patch) | |
tree | 6bde49bc5e4c4241266b108e4277baef4b85535d /gcc/c-family | |
parent | 71e955da39cea0ebffcfee3432effa622d14ca99 (diff) | |
parent | 5eb9f117a361538834b9740d59219911680717d1 (diff) | |
download | gcc-9f62ed218fa656607740b386c0caa03e65dcd283.zip gcc-9f62ed218fa656607740b386c0caa03e65dcd283.tar.gz gcc-9f62ed218fa656607740b386c0caa03e65dcd283.tar.bz2 |
Merge from trunk revision 5eb9f117a361538834b9740d59219911680717d1.
Diffstat (limited to 'gcc/c-family')
-rw-r--r-- | gcc/c-family/ChangeLog | 345 | ||||
-rw-r--r-- | gcc/c-family/c-ada-spec.cc | 123 | ||||
-rw-r--r-- | gcc/c-family/c-attribs.cc | 87 | ||||
-rw-r--r-- | gcc/c-family/c-common.cc | 42 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 16 | ||||
-rw-r--r-- | gcc/c-family/c-format.cc | 99 | ||||
-rw-r--r-- | gcc/c-family/c-gimplify.cc | 6 | ||||
-rw-r--r-- | gcc/c-family/c-omp.cc | 40 | ||||
-rw-r--r-- | gcc/c-family/c-opts.cc | 39 | ||||
-rw-r--r-- | gcc/c-family/c-ppoutput.cc | 78 | ||||
-rw-r--r-- | gcc/c-family/c-pragma.cc | 458 | ||||
-rw-r--r-- | gcc/c-family/c-pragma.h | 16 | ||||
-rw-r--r-- | gcc/c-family/c-pretty-print.cc | 6 | ||||
-rw-r--r-- | gcc/c-family/c-pretty-print.h | 2 | ||||
-rw-r--r-- | gcc/c-family/c-target.def | 2 | ||||
-rw-r--r-- | gcc/c-family/c-ubsan.cc | 118 | ||||
-rw-r--r-- | gcc/c-family/c-warn.cc | 31 | ||||
-rw-r--r-- | gcc/c-family/c.opt | 42 | ||||
-rw-r--r-- | gcc/c-family/known-headers.cc | 19 |
19 files changed, 1172 insertions, 397 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 77950b4..9e5f83c 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,348 @@ +2022-07-23 Immad Mir <mirimmad@outlook.com> + + * c-attribs.cc: (c_common_attribute_table): add three new attributes + namely: fd_arg, fd_arg_read and fd_arg_write. + (handle_fd_arg_attribute): New. + +2022-07-15 Marek Polacek <polacek@redhat.com> + + PR c++/104477 + * c-common.cc (c_common_reswords): Add + __reference_constructs_from_temporary and + __reference_converts_from_temporary. + * c-common.h (enum rid): Add RID_REF_CONSTRUCTS_FROM_TEMPORARY and + RID_REF_CONVERTS_FROM_TEMPORARY. + +2022-07-15 Jonathan Wakely <jwakely@redhat.com> + + * c-format.cc (class range_label_for_format_type_mismatch): + Adjust to new label_text API. + +2022-07-11 Lewis Hyatt <lhyatt@gmail.com> + + PR preprocessor/106252 + * c-pragma.cc (handle_pragma_diagnostic_impl): Don't look up the + option argument prior to verifying the option was found. + +2022-07-07 David Malcolm <dmalcolm@redhat.com> + + * c-format.cc (range_label_for_format_type_mismatch::get_text): + Update for removal of label_text::maybe_free in favor of automatic + memory management. + +2022-07-06 Lewis Hyatt <lhyatt@gmail.com> + + PR preprocessor/53920 + PR c++/53431 + * c-common.cc (c_option_is_from_cpp_diagnostics): New function. + * c-common.h (c_option_is_from_cpp_diagnostics): Declare. + (c_pp_stream_token): Declare. + * c-ppoutput.cc (init_pp_output): Refactor logic about skipping + pragmas to... + (should_output_pragmas): ...here. New function. + (token_streamer::stream): Support handling early pragmas. + (do_line_change): Likewise. + (c_pp_stream_token): New function. + * c-pragma.cc (struct pragma_diagnostic_data): New helper class. + (pragma_diagnostic_lex_normal): New function. Moved logic for + interpreting GCC diagnostic pragmas here. + (pragma_diagnostic_lex_pp): New function for parsing diagnostic pragmas + directly from libcpp. + (handle_pragma_diagnostic): Refactor into helper function... + (handle_pragma_diagnostic_impl): ...here. New function. + (handle_pragma_diagnostic_early): New function. + (handle_pragma_diagnostic_early_pp): New function. + (struct pragma_ns_name): Renamed to... + (struct pragma_pp_data): ...this. Add new "early_handler" member. + (c_register_pragma_1): Support early pragmas in the preprocessor. + (c_register_pragma_with_early_handler): New function. + (c_register_pragma): Support the new early handlers in struct + internal_pragma_handler. + (c_register_pragma_with_data): Likewise. + (c_register_pragma_with_expansion): Likewise. + (c_register_pragma_with_expansion_and_data): Likewise. + (c_invoke_early_pragma_handler): New function. + (c_pp_invoke_early_pragma_handler): New function. + (init_pragma): Add early pragma support for diagnostic pragmas. + * c-pragma.h (struct internal_pragma_handler): Add new early handler + members. + (c_register_pragma_with_early_handler): Declare. + (c_invoke_early_pragma_handler): Declare. + (c_pp_invoke_early_pragma_handler): Declare. + +2022-07-05 Marek Polacek <polacek@redhat.com> + + PR c++/105626 + * c-format.cc (check_format_arg): Don't emit -Wformat warnings with + u8 strings. + +2022-07-01 Marek Polacek <polacek@redhat.com> + + PR c++/106111 + * c-common.h (enum rid): Update RID_LAST_CXX20. + +2022-06-30 Jonathan Wakely <jwakely@redhat.com> + + * known-headers.cc (get_stdlib_header_for_name): Add <time.h> + names. + +2022-06-24 Jason Merrill <jason@redhat.com> + + PR c++/87729 + PR c++/20423 + * c.opt (Woverloaded-virtual): Add levels, include in -Wall. + +2022-06-18 Jakub Jelinek <jakub@redhat.com> + + * c-ubsan.cc (ubsan_instrument_division, ubsan_instrument_shift): + Use flag_sanitize_trap & SANITIZE_??? instead of + flag_sanitize_undefined_trap_on_error. If 2 sanitizers are involved + and flag_sanitize_trap differs for them, emit __builtin_trap only + for the comparison where trap is requested. + (ubsan_instrument_vla, ubsan_instrument_return): Use + lag_sanitize_trap & SANITIZE_??? instead of + flag_sanitize_undefined_trap_on_error. + +2022-06-13 Jason Merrill <jason@redhat.com> + + * c-ubsan.cc (ubsan_instrument_return): Use BUILTINS_LOCATION. + +2022-05-27 Marek Polacek <polacek@redhat.com> + + PR c/90658 + * c-attribs.cc (get_priority): Check FUNCTION_DECL. + +2022-05-27 Jakub Jelinek <jakub@redhat.com> + + * c-pragma.h (enum pragma_omp_clause): Add PRAGMA_OMP_CLAUSE_ENTER. + +2022-05-20 David Malcolm <dmalcolm@redhat.com> + + * c-format.cc: Replace uses of "FINAL" and "OVERRIDE" with "final" + and "override". + * c-pretty-print.h: Likewise. + +2022-05-18 Marek Polacek <polacek@redhat.com> + + PR c/105131 + * c.opt (Wenum-int-mismatch): New. + +2022-05-18 Marek Polacek <polacek@redhat.com> + + PR c++/105497 + * c-warn.cc (c_do_switch_warnings): Don't warn about unhandled + enumerator when it was marked with attribute unused. + +2022-05-18 Eric Botcazou <ebotcazou@adacore.com> + + * c-ada-spec.cc (dump_ada_node) <COMPLEX_TYPE>: Deal with usual + floating-point complex types. + <POINTER_TYPE>: Do not use limited_with clause if the designated + type is a scalar type. + +2022-05-17 Jakub Jelinek <jakub@redhat.com> + + * c-omp.cc (c_finish_omp_depobj): Handle + OMP_CLAUSE_DEPEND_INOUTSET. + +2022-05-16 Jason Merrill <jason@redhat.com> + + PR c/105492 + * c-attribs.cc (handle_mode_attribute): Don't fix broken typedefs + here. + +2022-05-16 Martin Liska <mliska@suse.cz> + + * c-common.cc (ARRAY_SIZE): Use ARRAY_SIZE. + (c_common_nodes_and_builtins): Likewise. + * c-format.cc (check_tokens): Likewise. + (check_plain): Likewise. + * c-pragma.cc (c_pp_lookup_pragma): Likewise. + (init_pragma): Likewise. + * known-headers.cc (get_string_macro_hint): Likewise. + (get_stdlib_header_for_name): Likewise. + * c-attribs.cc: Likewise. + +2022-05-13 Richard Biener <rguenther@suse.de> + + * c-omp.cc: Remove gimple-fold.h include. + +2022-05-12 Jakub Jelinek <jakub@redhat.com> + + * c-common.h (enum rid): Add RID_OMP_ALL_MEMORY. + * c-omp.cc (c_finish_omp_depobj): Don't build_fold_addr_expr + if null_pointer_node. + +2022-05-11 Martin Liska <mliska@suse.cz> + + PR target/105355 + * c-opts.cc (c_common_handle_option): Change option name. + * c.opt: Remove Joined and use Separate option. + +2022-05-09 Alex Coplan <alex.coplan@arm.com> + + * c-common.h (get_dump_info): Delete. + * c-gimplify.cc (c_genericize): Get TDI_original dump file info + from the global dump_manager instead of the (now obsolete) + get_dump_info. + * c-opts.cc (original_dump_file): Delete. + (original_dump_flags): Delete. + (c_common_parse_file): Switch to using global dump_manager to + manage the original dump file; fix leak of dump file. + (get_dump_info): Delete. + +2022-05-07 Marek Polacek <polacek@redhat.com> + + PR c++/101833 + PR c++/47634 + * c-attribs.cc (positional_argument): Pass POS by reference. Deal + with FN being either a function declaration or function type. Use + maybe_adjust_arg_pos_for_attribute. + * c-common.cc (check_function_arguments): Maybe pass FNDECL down to + check_function_format. + * c-common.h (maybe_adjust_arg_pos_for_attribute): Declare. + (positional_argument): Adjust. + * c-format.cc (get_constant): Rename to ... + (validate_constant): ... this. Take EXPR by reference. Return bool + instead of tree. + (handle_format_arg_attribute): Don't overwrite FORMAT_NUM_EXPR by the + return value of validate_constant. + (decode_format_attr): Don't overwrite FORMAT_NUM_EXPR and + FIRST_ARG_NUM_EXPR by the return value of validate_constant. + (check_function_format): Adjust a parameter name. + (handle_format_attribute): Maybe pass FNDECL down to decode_format_attr. + +2022-05-04 Marek Polacek <polacek@redhat.com> + + * c-warn.cc (warnings_for_convert_and_check): Convert constants of type + char to int. + +2022-04-30 Jason Merrill <jason@redhat.com> + + PR c/100545 + * c-attribs.cc (handle_mode_attribute): Copy attributes, aligned, + and typedef. + * c-common.cc (set_underlying_type): Add assert. + +2022-04-26 Patrick Palka <ppalka@redhat.com> + + PR c++/105304 + * c-common.cc (verify_tree) [restart]: Move up to before the + NULL test. + +2022-04-11 Jakub Jelinek <jakub@redhat.com> + + PR c++/105186 + * c-common.cc (c_common_nodes_and_builtins): After registering __int%d + and __int%d__ builtin types, initialize corresponding ridpointers + entry. + +2022-03-30 Marek Polacek <polacek@redhat.com> + + PR c++/101030 + * c-warn.cc (conversion_warning) <case COND_EXPR>: Don't call + conversion_warning when OP1 is null. + +2022-03-30 Thomas Schwinge <thomas@codesourcery.com> + + * c.opt (Wc++11-extensions, Wc++14-extensions, Wc++17-extensions) + (Wc++20-extensions, Wc++23-extensions): Remove 'LangEnabledBy' + option properties. + +2022-03-30 Thomas Schwinge <thomas@codesourcery.com> + + * c.opt (Wuse-after-free): Remove. + +2022-03-30 Thomas Schwinge <thomas@codesourcery.com> + + * c.opt (Warray-bounds): Remove. + +2022-03-26 Thomas Schwinge <thomas@codesourcery.com> + + * c.opt: Properly quote comment. + +2022-03-25 Eric Botcazou <ebotcazou@adacore.com> + + * c-ada-spec.cc (dump_ada_import): Deal with the "section" attribute + (dump_ada_node) <POINTER_TYPE>: Do not modify and pass the name, but + the referenced type instead. Deal with the anonymous original type + of a typedef'ed type. In the actual access case, follow the chain + of external subtypes. + <TYPE_DECL>: Tidy up control flow. + +2022-03-21 Qian Jianhua <qianjh@cn.fujitsu.com> + + * c-ada-spec.cc: Change array length + +2022-03-19 Arthur Cohen <arthur.cohen@embecosm.com> + + * c-common.cc (c_family_tests): Call the new tests. + * c-common.h (c_diagnostic_tests): Declare. + (c_opt_problem_cc_tests): Likewise. + +2022-03-19 Jakub Jelinek <jakub@redhat.com> + + PR c++/101515 + * c-pretty-print.cc (c_fold_indirect_ref_for_warn): For C++ don't + return COMPONENT_REFs with FIELD_DECLs whose containing scope can't + be printed. + +2022-03-16 Christophe Lyon <christophe.lyon@arm.com> + Roger Sayle <roger@nextmovesoftware.com> + + PR c/98198 + * c-attribs.cc (decl_or_type_attrs): Add error_mark_node check. + +2022-03-16 Patrick Palka <ppalka@redhat.com> + + PR c++/96780 + * c.opt: Add -ffold-simple-inlines. + +2022-03-13 Tobias Burnus <tobias@codesourcery.com> + + * c-target.def (check_string_object_format_arg): Fix description typo. + +2022-03-12 Thomas Schwinge <thomas@codesourcery.com> + + PR other/65095 + * c-common.h (c_omp_map_clause_name): Remove. + * c-omp.cc (c_omp_map_clause_name): Remove. + +2022-03-09 Jakub Jelinek <jakub@redhat.com> + + PR c/104711 + * c-opts.cc (c_common_post_options): Don't enable + -Wshift-negative-value from -Wextra for C++20 or later. + * c-ubsan.cc (ubsan_instrument_shift): Adjust comments. + * c-warn.cc (maybe_warn_shift_overflow): Use TYPE_OVERFLOW_WRAPS + instead of TYPE_UNSIGNED. + +2022-03-07 Jakub Jelinek <jakub@redhat.com> + + * c-attribs.cc: Fix up duplicated word issue in a comment. + +2022-03-01 Martin Liska <mliska@suse.cz> + + PR ipa/104533 + * c-attribs.cc (handle_target_clones_attribute): Use + get_target_clone_attr_len and report warning soon. + +2022-02-17 Jonathan Wakely <jwakely@redhat.com> + + * c-pragma.cc (handle_pragma_pack): Remove parameter name. + (handle_pragma_weak): Likewise. + (handle_pragma_scalar_storage_order): Likewise. + (handle_pragma_redefine_extname): Likewise. + (handle_pragma_visibility): Likewise. + (handle_pragma_diagnostic): Likewise. + (handle_pragma_target): Likewise. + (handle_pragma_optimize): Likewise. + (handle_pragma_push_options): Likewise. + (handle_pragma_pop_options): Likewise. + (handle_pragma_reset_options): Likewise. + (handle_pragma_message): Likewise. + (handle_pragma_float_const_decimal64): Likewise. + 2022-02-16 Jakub Jelinek <jakub@redhat.com> PR c/104531 diff --git a/gcc/c-family/c-ada-spec.cc b/gcc/c-family/c-ada-spec.cc index 149d336..faf7174 100644 --- a/gcc/c-family/c-ada-spec.cc +++ b/gcc/c-family/c-ada-spec.cc @@ -1526,6 +1526,15 @@ dump_ada_import (pretty_printer *buffer, tree t, int spc) newline_and_indent (buffer, spc + 5); + tree sec = lookup_attribute ("section", DECL_ATTRIBUTES (t)); + if (sec) + { + pp_string (buffer, "Linker_Section => \""); + pp_string (buffer, TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (sec)))); + pp_string (buffer, "\", "); + newline_and_indent (buffer, spc + 5); + } + pp_string (buffer, "External_Name => \""); if (is_stdcall) @@ -1579,7 +1588,7 @@ dump_ada_function_declaration (pretty_printer *buffer, tree func, tree type = TREE_TYPE (func); tree arg = TYPE_ARG_TYPES (type); tree t; - char buf[17]; + char buf[18]; int num, num_args = 0, have_args = true, have_ellipsis = false; /* Compute number of arguments. */ @@ -2096,6 +2105,21 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc, append_withs ("Interfaces.C.Extensions", false); pp_string (buffer, "Extensions.CFloat_128"); } + else if (TREE_TYPE (node) == float_type_node) + { + append_withs ("Ada.Numerics.Complex_Types", false); + pp_string (buffer, "Ada.Numerics.Complex_Types.Complex"); + } + else if (TREE_TYPE (node) == double_type_node) + { + append_withs ("Ada.Numerics.Long_Complex_Types", false); + pp_string (buffer, "Ada.Numerics.Long_Complex_Types.Complex"); + } + else if (TREE_TYPE (node) == long_double_type_node) + { + append_withs ("Ada.Numerics.Long_Long_Complex_Types", false); + pp_string (buffer, "Ada.Numerics.Long_Long_Complex_Types.Complex"); + } else pp_string (buffer, "<complex>"); break; @@ -2179,10 +2203,11 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc, } else { - const unsigned int quals = TYPE_QUALS (TREE_TYPE (node)); - bool is_access = false; + tree ref_type = TREE_TYPE (node); + const unsigned int quals = TYPE_QUALS (ref_type); + bool is_access; - if (VOID_TYPE_P (TREE_TYPE (node))) + if (VOID_TYPE_P (ref_type)) { if (!name_only) pp_string (buffer, "new "); @@ -2197,9 +2222,8 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc, else { if (TREE_CODE (node) == POINTER_TYPE - && TREE_CODE (TREE_TYPE (node)) == INTEGER_TYPE - && id_equal (DECL_NAME (TYPE_NAME (TREE_TYPE (node))), - "char")) + && TREE_CODE (ref_type) == INTEGER_TYPE + && id_equal (DECL_NAME (TYPE_NAME (ref_type)), "char")) { if (!name_only) pp_string (buffer, "new "); @@ -2214,28 +2238,11 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc, } else { - tree type_name = TYPE_NAME (TREE_TYPE (node)); - - /* Generate "access <type>" instead of "access <subtype>" - if the subtype comes from another file, because subtype - declarations do not contribute to the limited view of a - package and thus subtypes cannot be referenced through - a limited_with clause. */ - if (type_name - && TREE_CODE (type_name) == TYPE_DECL - && DECL_ORIGINAL_TYPE (type_name) - && TYPE_NAME (DECL_ORIGINAL_TYPE (type_name))) - { - const expanded_location xloc - = expand_location (decl_sloc (type_name, false)); - if (xloc.line - && xloc.file - && xloc.file != current_source_file) - type_name = DECL_ORIGINAL_TYPE (type_name); - } + tree stub = TYPE_STUB_DECL (ref_type); + tree type_name = TYPE_NAME (ref_type); /* For now, handle access-to-access as System.Address. */ - if (TREE_CODE (TREE_TYPE (node)) == POINTER_TYPE) + if (TREE_CODE (ref_type) == POINTER_TYPE) { if (package_prefix) { @@ -2250,8 +2257,11 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc, } if (!package_prefix) - pp_string (buffer, "access"); - else if (AGGREGATE_TYPE_P (TREE_TYPE (node))) + { + is_access = false; + pp_string (buffer, "access"); + } + else if (AGGREGATE_TYPE_P (ref_type)) { if (!type || TREE_CODE (type) != FUNCTION_DECL) { @@ -2264,29 +2274,62 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc, pp_string (buffer, "all "); } else if (quals & TYPE_QUAL_CONST) - pp_string (buffer, "in "); + { + is_access = false; + pp_string (buffer, "in "); + } else { is_access = true; pp_string (buffer, "access "); - /* ??? should be configurable: access or in out. */ } } else { - is_access = true; + /* We want to use regular with clauses for scalar types, + as they are not involved in circular declarations. */ + is_access = false; pp_string (buffer, "access "); if (!name_only) pp_string (buffer, "all "); } - if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node)) && type_name) - dump_ada_node (buffer, type_name, TREE_TYPE (node), spc, - is_access, true); - else - dump_ada_node (buffer, TREE_TYPE (node), TREE_TYPE (node), - spc, false, true); + /* If this is the anonymous original type of a typedef'ed + type, then use the name of the latter. */ + if (!type_name + && stub + && DECL_CHAIN (stub) + && TREE_CODE (DECL_CHAIN (stub)) == TYPE_DECL + && DECL_ORIGINAL_TYPE (DECL_CHAIN (stub)) == ref_type) + ref_type = TREE_TYPE (DECL_CHAIN (stub)); + + /* Generate "access <type>" instead of "access <subtype>" + if the subtype comes from another file, because subtype + declarations do not contribute to the limited view of a + package and thus subtypes cannot be referenced through + a limited_with clause. */ + else if (is_access) + while (type_name + && TREE_CODE (type_name) == TYPE_DECL + && DECL_ORIGINAL_TYPE (type_name) + && TYPE_NAME (DECL_ORIGINAL_TYPE (type_name))) + { + const expanded_location xloc + = expand_location (decl_sloc (type_name, false)); + if (xloc.line + && xloc.file + && xloc.file != current_source_file) + { + ref_type = DECL_ORIGINAL_TYPE (type_name); + type_name = TYPE_NAME (ref_type); + } + else + break; + } + + dump_ada_node (buffer, ref_type, ref_type, spc, is_access, + true); } } } @@ -2361,10 +2404,8 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc, else pp_string (buffer, "address"); } - break; } - - if (name_only) + else if (name_only) dump_ada_decl_name (buffer, node, limited_access); else { diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc index 3849dba..e4f1d35 100644 --- a/gcc/c-family/c-attribs.cc +++ b/gcc/c-family/c-attribs.cc @@ -173,6 +173,7 @@ static tree handle_objc_nullability_attribute (tree *, tree, tree, int, bool *); static tree handle_signed_bool_precision_attribute (tree *, tree, tree, int, bool *); static tree handle_retain_attribute (tree *, tree, tree, int, bool *); +static tree handle_fd_arg_attribute (tree *, tree, tree, int, bool *); /* Helper to define attribute exclusions. */ #define ATTR_EXCL(name, function, type, variable) \ @@ -555,6 +556,12 @@ const struct attribute_spec c_common_attribute_table[] = handle_dealloc_attribute, NULL }, { "tainted_args", 0, 0, true, false, false, false, handle_tainted_args_attribute, NULL }, + { "fd_arg", 1, 1, false, true, true, false, + handle_fd_arg_attribute, NULL}, + { "fd_arg_read", 1, 1, false, true, true, false, + handle_fd_arg_attribute, NULL}, + { "fd_arg_write", 1, 1, false, true, true, false, + handle_fd_arg_attribute, NULL}, { NULL, 0, 0, false, false, false, false, NULL, NULL } }; @@ -594,18 +601,23 @@ attribute_takes_identifier_p (const_tree attr_id) } /* Verify that argument value POS at position ARGNO to attribute NAME - applied to function TYPE refers to a function parameter at position - POS and the expected type CODE. Treat CODE == INTEGER_TYPE as - matching all C integral types except bool. If successful, return - POS after default conversions, if any. Otherwise, issue appropriate - warnings and return null. A non-zero 1-based ARGNO should be passed - in by callers only for attributes with more than one argument. */ + applied to function FN (which is either a function declaration or function + type) refers to a function parameter at position POS and the expected type + CODE. Treat CODE == INTEGER_TYPE as matching all C integral types except + bool. If successful, return POS after default conversions (and possibly + adjusted by ADJUST_POS). Otherwise, issue appropriate warnings and return + null. A non-zero 1-based ARGNO should be passed in by callers only for + attributes with more than one argument. + + N.B. This function modifies POS. */ tree -positional_argument (const_tree fntype, const_tree atname, tree pos, +positional_argument (const_tree fn, const_tree atname, tree &pos, tree_code code, int argno /* = 0 */, int flags /* = posargflags () */) { + const_tree fndecl = TYPE_P (fn) ? NULL_TREE : fn; + const_tree fntype = TYPE_P (fn) ? fn : TREE_TYPE (fn); if (pos && TREE_CODE (pos) != IDENTIFIER_NODE && TREE_CODE (pos) != FUNCTION_DECL) pos = default_conversion (pos); @@ -682,6 +694,11 @@ positional_argument (const_tree fntype, const_tree atname, tree pos, if (!prototype_p (fntype)) return pos; + /* ADJUST_POS is non-zero in C++ when the function type has invisible + parameters generated by the compiler, such as the in-charge or VTT + parameters. */ + const int adjust_pos = maybe_adjust_arg_pos_for_attribute (fndecl); + /* Verify that the argument position does not exceed the number of formal arguments to the function. When POSARG_ELLIPSIS is set, ARGNO may be beyond the last argument of a vararg @@ -690,7 +707,7 @@ positional_argument (const_tree fntype, const_tree atname, tree pos, if (!nargs || !tree_fits_uhwi_p (pos) || ((flags & POSARG_ELLIPSIS) == 0 - && !IN_RANGE (tree_to_uhwi (pos), 1, nargs))) + && !IN_RANGE (tree_to_uhwi (pos) + adjust_pos, 1, nargs))) { if (argno < 1) @@ -707,8 +724,9 @@ positional_argument (const_tree fntype, const_tree atname, tree pos, } /* Verify that the type of the referenced formal argument matches - the expected type. */ - unsigned HOST_WIDE_INT ipos = tree_to_uhwi (pos); + the expected type. Invisible parameters may have been added by + the compiler, so adjust the position accordingly. */ + unsigned HOST_WIDE_INT ipos = tree_to_uhwi (pos) + adjust_pos; /* Zero was handled above. */ gcc_assert (ipos != 0); @@ -791,7 +809,7 @@ positional_argument (const_tree fntype, const_tree atname, tree pos, return NULL_TREE; } - return pos; + return build_int_cst (TREE_TYPE (pos), ipos); } /* Return the first of DECL or TYPE attributes installed in NODE if it's @@ -806,6 +824,8 @@ decl_or_type_attrs (tree node) return attrs; tree type = TREE_TYPE (node); + if (type == error_mark_node) + return NULL_TREE; return TYPE_ATTRIBUTES (type); } @@ -1882,7 +1902,7 @@ get_priority (tree args, bool is_destructor) } arg = TREE_VALUE (args); - if (TREE_CODE (arg) == IDENTIFIER_NODE) + if (TREE_CODE (arg) == IDENTIFIER_NODE || TREE_CODE (arg) == FUNCTION_DECL) goto invalid; if (arg == error_mark_node) return DEFAULT_INIT_PRIORITY; @@ -2197,7 +2217,11 @@ handle_mode_attribute (tree *node, tree name, tree args, return NULL_TREE; } - *node = build_qualified_type (typefm, TYPE_QUALS (type)); + /* Copy any quals and attributes to the new type. */ + *node = build_type_attribute_qual_variant (typefm, TYPE_ATTRIBUTES (type), + TYPE_QUALS (type)); + if (TYPE_USER_ALIGN (type)) + *node = build_aligned_type (*node, TYPE_ALIGN (type)); } return NULL_TREE; @@ -3421,7 +3445,7 @@ handle_malloc_attribute (tree *node, tree name, tree args, int flags, it with this one. Ideally, the attribute would reference the DECL of the deallocator but since that changes for each redeclaration, use DECL_NAME instead. (DECL_ASSEMBLER_NAME - need not be set set this point and setting it here is too early. */ + need not be set at this point and setting it here is too early. */ tree attrs = build_tree_list (NULL_TREE, DECL_NAME (fndecl)); attrs = tree_cons (get_identifier ("*dealloc"), attrs, at_noinline); decl_attributes (&dealloc, attrs, 0); @@ -4504,6 +4528,30 @@ handle_nonnull_attribute (tree *node, tree name, return NULL_TREE; } +/* Handle the "fd_arg", "fd_arg_read" and "fd_arg_write" attributes */ + +static tree +handle_fd_arg_attribute (tree *node, tree name, tree args, + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + tree type = *node; + if (!args) + { + if (!prototype_p (type)) + { + error ("%qE attribute without arguments on a non-prototype", name); + *no_add_attrs = true; + } + return NULL_TREE; + } + + if (positional_argument (*node, name, TREE_VALUE (args), INTEGER_TYPE)) + return NULL_TREE; + + *no_add_attrs = true; + return NULL_TREE; +} + /* Handle the "nonstring" variable attribute. */ static tree @@ -4925,8 +4973,7 @@ handle_access_attribute (tree node[3], tree name, tree args, int flags, int imode; { - const int nmodes = - sizeof attr_access::mode_names / sizeof *attr_access::mode_names; + const int nmodes = ARRAY_SIZE (attr_access::mode_names); for (imode = 0; imode != nmodes; ++imode) if (!strncmp (ps, attr_access::mode_names[imode], @@ -5142,7 +5189,7 @@ handle_access_attribute (tree node[3], tree name, tree args, int flags, value: "+^2[*],$0$1^3[*],$1$1" list: < <0, x> <1, y> > - where the list has a single value which itself is is a list each + where the list has a single value which itself is a list, each of whose <node>s corresponds to one VLA bound for each of the two parameters. */ @@ -5486,6 +5533,12 @@ handle_target_clones_attribute (tree *node, tree name, tree ARG_UNUSED (args), "with %qs attribute", name, "target"); *no_add_attrs = true; } + else if (get_target_clone_attr_len (args) == -1) + { + warning (OPT_Wattributes, + "single %<target_clones%> attribute is ignored"); + *no_add_attrs = true; + } else /* Do not inline functions with multiple clone targets. */ DECL_UNINLINABLE (*node) = 1; diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc index 7203d76..655c3ae 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -537,6 +537,10 @@ const struct c_common_resword c_common_reswords[] = { "__is_constructible", RID_IS_CONSTRUCTIBLE, D_CXXONLY }, { "__is_nothrow_assignable", RID_IS_NOTHROW_ASSIGNABLE, D_CXXONLY }, { "__is_nothrow_constructible", RID_IS_NOTHROW_CONSTRUCTIBLE, D_CXXONLY }, + { "__reference_constructs_from_temporary", RID_REF_CONSTRUCTS_FROM_TEMPORARY, + D_CXXONLY }, + { "__reference_converts_from_temporary", RID_REF_CONVERTS_FROM_TEMPORARY, + D_CXXONLY }, /* C++ transactional memory. */ { "synchronized", RID_SYNCHRONIZED, D_CXX_OBJC | D_TRANSMEM }, @@ -602,8 +606,7 @@ const struct c_common_resword c_common_reswords[] = { "null_resettable", RID_NULL_RESETTABLE, D_OBJC }, }; -const unsigned int num_c_common_reswords = - sizeof c_common_reswords / sizeof (struct c_common_resword); +const unsigned int num_c_common_reswords = ARRAY_SIZE (c_common_reswords); /* Return identifier for address space AS. */ @@ -2009,12 +2012,12 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp, enum tree_code code; enum tree_code_class cl; + restart: /* X may be NULL if it is the operand of an empty statement expression ({ }). */ if (x == NULL) return; - restart: code = TREE_CODE (x); cl = TREE_CODE_CLASS (code); @@ -4278,6 +4281,8 @@ c_common_nodes_and_builtins (void) sprintf (name, "__int%d__", int_n_data[i].bitsize); record_builtin_type ((enum rid)(RID_FIRST_INT_N + i), name, int_n_trees[i].signed_type); + ridpointers[RID_FIRST_INT_N + i] + = DECL_NAME (TYPE_NAME (int_n_trees[i].signed_type)); sprintf (name, "__int%d unsigned", int_n_data[i].bitsize); record_builtin_type (RID_MAX, name, int_n_trees[i].unsigned_type); @@ -4480,9 +4485,7 @@ c_common_nodes_and_builtins (void) /* Make fileptr_type_node a distinct void * type until FILE type is defined. Likewise for const struct tm*. */ - for (unsigned i = 0; - i < sizeof (builtin_structptr_types) / sizeof (builtin_structptr_type); - ++i) + for (unsigned i = 0; i < ARRAY_SIZE (builtin_structptr_types); ++i) builtin_structptr_types[i].node = build_variant_type_copy (builtin_structptr_types[i].base); @@ -6069,8 +6072,8 @@ check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype, /* Check for errors in format strings. */ if (warn_format || warn_suggest_attribute_format) - check_function_format (fntype, TYPE_ATTRIBUTES (fntype), nargs, argarray, - arglocs); + check_function_format (fndecl ? fndecl : fntype, TYPE_ATTRIBUTES (fntype), nargs, + argarray, arglocs); if (warn_format) check_function_sentinel (fntype, nargs, argarray); @@ -6612,6 +6615,20 @@ c_option_controlling_cpp_diagnostic (enum cpp_warning_reason reason) return 0; } +/* Return TRUE if the given option index corresponds to a diagnostic + issued by libcpp. Linear search seems fine for now. */ +bool +c_option_is_from_cpp_diagnostics (int option_index) +{ + for (auto entry = cpp_reason_option_codes; entry->reason != CPP_W_NONE; + ++entry) + { + if (entry->option_code == option_index) + return true; + } + return false; +} + /* Callback from cpp_diagnostic for PFILE to print diagnostics from the preprocessor. The diagnostic is of type LEVEL, with REASON set to the reason code if LEVEL is represents a warning, at location @@ -8151,15 +8168,16 @@ check_missing_format_attribute (tree ltype, tree rtype) void set_underlying_type (tree x) { - if (x == error_mark_node) + if (x == error_mark_node || TREE_TYPE (x) == error_mark_node) return; if (DECL_IS_UNDECLARED_BUILTIN (x) && TREE_CODE (TREE_TYPE (x)) != ARRAY_TYPE) { if (TYPE_NAME (TREE_TYPE (x)) == 0) TYPE_NAME (TREE_TYPE (x)) = x; } - else if (TREE_TYPE (x) != error_mark_node - && DECL_ORIGINAL_TYPE (x) == NULL_TREE) + else if (DECL_ORIGINAL_TYPE (x)) + gcc_checking_assert (TYPE_NAME (TREE_TYPE (x)) == x); + else { tree tt = TREE_TYPE (x); DECL_ORIGINAL_TYPE (x) = tt; @@ -9120,6 +9138,8 @@ 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 (); } } // namespace selftest diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index a8d6f82..f906439 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -184,6 +184,8 @@ enum rid RID_IS_UNION, RID_UNDERLYING_TYPE, RID_IS_ASSIGNABLE, RID_IS_CONSTRUCTIBLE, RID_IS_NOTHROW_ASSIGNABLE, RID_IS_NOTHROW_CONSTRUCTIBLE, + RID_REF_CONSTRUCTS_FROM_TEMPORARY, + RID_REF_CONVERTS_FROM_TEMPORARY, /* C++11 */ RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT, @@ -219,6 +221,9 @@ enum rid RID_AT_INTERFACE, RID_AT_IMPLEMENTATION, + /* OpenMP */ + RID_OMP_ALL_MEMORY, + /* Named address support, mapping the keyword to a particular named address number. Named address space 0 is reserved for the generic address. If there are more than 254 named addresses, the addr_space_t type will need @@ -268,7 +273,7 @@ enum rid RID_FIRST_CXX11 = RID_CONSTEXPR, RID_LAST_CXX11 = RID_STATIC_ASSERT, RID_FIRST_CXX20 = RID_CONSTINIT, - RID_LAST_CXX20 = RID_CONSTINIT, + RID_LAST_CXX20 = RID_CO_RETURN, RID_FIRST_AT = RID_AT_ENCODE, RID_LAST_AT = RID_AT_IMPLEMENTATION, RID_FIRST_PQ = RID_IN, @@ -908,6 +913,7 @@ extern tree fold_for_warn (tree); extern tree c_common_get_narrower (tree, int *); extern bool get_attribute_operand (tree, unsigned HOST_WIDE_INT *); extern void c_common_finalize_early_debug (void); +extern bool c_option_is_from_cpp_diagnostics (int); /* Used by convert_and_check; in front ends. */ extern tree convert_init (tree, tree); @@ -950,7 +956,6 @@ extern bool c_common_post_options (const char **); extern bool c_common_init (void); extern void c_common_finish (void); extern void c_common_parse_file (void); -extern FILE *get_dump_info (int, dump_flags_t *); extern alias_set_type c_common_get_alias_set (tree); extern void c_register_builtin_type (tree, const char*); extern bool c_promoting_integer_type_p (const_tree); @@ -1049,6 +1054,7 @@ extern tree finish_label_address_expr (tree, location_t); extern tree lookup_label (tree); extern tree lookup_name (tree); extern bool lvalue_p (const_tree); +extern int maybe_adjust_arg_pos_for_attribute (const_tree); extern bool vector_targets_convertible_p (const_tree t1, const_tree t2); extern bool vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note); @@ -1188,6 +1194,7 @@ extern void preprocess_file (cpp_reader *); extern void pp_file_change (const line_map_ordinary *); extern void pp_dir_change (cpp_reader *, const char *); extern bool check_missing_format_attribute (tree, tree); +extern void c_pp_stream_token (cpp_reader *, const cpp_token *, location_t loc); /* In c-omp.cc */ typedef wide_int_bitmask omp_clause_mask; @@ -1250,7 +1257,6 @@ extern enum omp_clause_default_kind c_omp_predetermined_sharing (tree); 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 const char *c_omp_map_clause_name (tree, bool); extern void c_omp_adjust_map_clauses (tree, bool); enum c_omp_directive_kind { @@ -1494,7 +1500,7 @@ enum posargflags { POSARG_ELLIPSIS = 2 }; -extern tree positional_argument (const_tree, const_tree, tree, tree_code, +extern tree positional_argument (const_tree, const_tree, tree &, tree_code, int = 0, int = posargflags ()); extern enum flt_eval_method @@ -1513,8 +1519,10 @@ 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); extern void c_pretty_print_cc_tests (void); extern void c_spellcheck_cc_tests (void); diff --git a/gcc/c-family/c-format.cc b/gcc/c-family/c-format.cc index 98f28c0..68b94da 100644 --- a/gcc/c-family/c-format.cc +++ b/gcc/c-family/c-format.cc @@ -78,9 +78,9 @@ static bool check_format_string (const_tree argument, unsigned HOST_WIDE_INT format_num, int flags, bool *no_add_attrs, int expected_format_type); -static tree get_constant (const_tree fntype, const_tree atname, tree expr, - int argno, unsigned HOST_WIDE_INT *value, - int flags, bool validated_p); +static bool validate_constant (const_tree fn, const_tree atname, tree &expr, + int argno, unsigned HOST_WIDE_INT *value, + int flags, bool validated_p); static const char *convert_format_name_to_system_name (const char *attr_name); static int first_target_format_type; @@ -172,14 +172,12 @@ handle_format_arg_attribute (tree *node, tree atname, tree args, int flags, bool *no_add_attrs) { tree type = *node; - /* Note that TREE_VALUE (args) is changed in place below. */ + /* Note that TREE_VALUE (args) is changed in the validate_constant call. */ tree *format_num_expr = &TREE_VALUE (args); unsigned HOST_WIDE_INT format_num = 0; - if (tree val = get_constant (type, atname, *format_num_expr, 0, &format_num, - 0, false)) - *format_num_expr = val; - else + if (!validate_constant (type, atname, *format_num_expr, 0, &format_num, 0, + false)) { *no_add_attrs = true; return NULL_TREE; @@ -301,38 +299,39 @@ check_format_string (const_tree fntype, unsigned HOST_WIDE_INT format_num, /* Under the control of FLAGS, verify EXPR is a valid constant that refers to a positional argument ARGNO having a string type (char* or, for targets like Darwin, a pointer to struct CFString) to - a function type FNTYPE declared with attribute ATNAME. - If valid, store the constant's integer value in *VALUE and return - the value. - If VALIDATED_P is true assert the validation is successful. - Returns the converted constant value on success, null otherwise. */ + a function FN declared with attribute ATNAME. If valid, store the + constant's integer value in *VALUE and return true. If VALIDATED_P + is true assert the validation is successful. -static tree -get_constant (const_tree fntype, const_tree atname, tree expr, int argno, - unsigned HOST_WIDE_INT *value, int flags, bool validated_p) + N.B. This function modifies EXPR. */ + +static bool +validate_constant (const_tree fn, const_tree atname, tree &expr, int argno, + unsigned HOST_WIDE_INT *value, int flags, bool validated_p) { /* Require the referenced argument to have a string type. For targets like Darwin, also accept pointers to struct CFString. */ - if (tree val = positional_argument (fntype, atname, expr, STRING_CST, + if (tree val = positional_argument (fn, atname, expr, STRING_CST, argno, flags)) { *value = TREE_INT_CST_LOW (val); - return val; + return true; } gcc_assert (!validated_p); - return NULL_TREE; + return false; } /* Decode the arguments to a "format" attribute into a function_format_info structure. It is already known that the list is of the right length. If VALIDATED_P is true, then these attributes have already been validated and must not be erroneous; - if false, it will give an error message. Returns true if the - attributes are successfully decoded, false otherwise. */ + if false, it will give an error message. FN is either a function + declaration or function type. Returns true if the attributes are + successfully decoded, false otherwise. */ static bool -decode_format_attr (const_tree fntype, tree atname, tree args, +decode_format_attr (const_tree fn, tree atname, tree args, function_format_info *info, bool validated_p) { tree format_type_id = TREE_VALUE (args); @@ -372,17 +371,13 @@ decode_format_attr (const_tree fntype, tree atname, tree args, } } - if (tree val = get_constant (fntype, atname, *format_num_expr, - 2, &info->format_num, 0, validated_p)) - *format_num_expr = val; - else + if (!validate_constant (fn, atname, *format_num_expr, 2, &info->format_num, + 0, validated_p)) return false; - if (tree val = get_constant (fntype, atname, *first_arg_num_expr, - 3, &info->first_arg_num, - (POSARG_ZERO | POSARG_ELLIPSIS), validated_p)) - *first_arg_num_expr = val; - else + if (!validate_constant (fn, atname, *first_arg_num_expr, 3, + &info->first_arg_num, + (POSARG_ZERO | POSARG_ELLIPSIS), validated_p)) return false; if (info->first_arg_num != 0 && info->first_arg_num <= info->format_num) @@ -1154,13 +1149,12 @@ decode_format_type (const char *s, bool *is_raw /* = NULL */) /* Check the argument list of a call to printf, scanf, etc. ATTRS are the attributes on the function type. There are NARGS argument - values in the array ARGARRAY. - Also, if -Wsuggest-attribute=format, - warn for calls to vprintf or vscanf in functions with no such format - attribute themselves. */ + values in the array ARGARRAY. FN is either a function declaration or + function type. Also, if -Wsuggest-attribute=format, warn for calls to + vprintf or vscanf in functions with no such format attribute themselves. */ void -check_function_format (const_tree fntype, tree attrs, int nargs, +check_function_format (const_tree fn, tree attrs, int nargs, tree *argarray, vec<location_t> *arglocs) { tree a; @@ -1174,7 +1168,7 @@ check_function_format (const_tree fntype, tree attrs, int nargs, { /* Yup; check it. */ function_format_info info; - decode_format_attr (fntype, atname, TREE_VALUE (a), &info, + decode_format_attr (fn, atname, TREE_VALUE (a), &info, /*validated=*/true); if (warn_format) { @@ -1748,7 +1742,8 @@ check_format_arg (void *ctx, tree format_tree, } tree underlying_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (format_tree))); - if (underlying_type != char_type_node) + if (underlying_type != char_type_node + && !(flag_char8_t && underlying_type == char8_type_node)) { if (underlying_type == char16_type_node || underlying_type == char32_type_node @@ -3195,7 +3190,7 @@ check_tokens (const token_t *tokens, unsigned ntoks, else { /* Diagnose some common misspellings. */ - for (unsigned i = 0; i != sizeof badwords / sizeof *badwords; ++i) + for (unsigned i = 0; i != ARRAY_SIZE (badwords); ++i) { unsigned badwlen = strspn (badwords[i].name, " -"); if (wlen >= badwlen @@ -3390,14 +3385,14 @@ check_plain (location_t format_string_loc, tree format_string_cst, if (ISPUNCT (format_chars[0])) { - size_t nelts = sizeof c_opers / sizeof *c_opers; + size_t nelts = ARRAY_SIZE (c_opers); if (const char *ret = check_tokens (c_opers, nelts, format_string_loc, format_string_cst, orig_format_chars, format_chars, baltoks)) return ret; - nelts = c_dialect_cxx () ? sizeof cxx_opers / sizeof *cxx_opers : 0; + nelts = c_dialect_cxx () ? ARRAY_SIZE (cxx_opers) : 0; if (const char *ret = check_tokens (cxx_opers, nelts, format_string_loc, format_string_cst, orig_format_chars, format_chars, @@ -3407,14 +3402,14 @@ check_plain (location_t format_string_loc, tree format_string_cst, if (ISALPHA (format_chars[0])) { - size_t nelts = sizeof c_keywords / sizeof *c_keywords; + size_t nelts = ARRAY_SIZE (c_keywords); if (const char *ret = check_tokens (c_keywords, nelts, format_string_loc, format_string_cst, orig_format_chars, format_chars, baltoks)) return ret; - nelts = c_dialect_cxx () ? sizeof cxx_keywords / sizeof *cxx_keywords : 0; + nelts = c_dialect_cxx () ? ARRAY_SIZE (cxx_keywords) : 0; if (const char *ret = check_tokens (cxx_keywords, nelts, format_string_loc, format_string_cst, orig_format_chars, format_chars, @@ -3533,7 +3528,7 @@ check_plain (location_t format_string_loc, tree format_string_cst, && ISALPHA (format_chars[1])) { /* Diagnose a subset of contractions that are best avoided. */ - for (unsigned i = 0; i != sizeof contrs / sizeof *contrs; ++i) + for (unsigned i = 0; i != ARRAY_SIZE (contrs); ++i) { const char *apos = strchr (contrs[i].name, '\''); gcc_assert (apos != NULL); @@ -4619,18 +4614,17 @@ class range_label_for_format_type_mismatch { } - label_text get_text (unsigned range_idx) const FINAL OVERRIDE + label_text get_text (unsigned range_idx) const final override { label_text text = range_label_for_type_mismatch::get_text (range_idx); - if (text.m_buffer == NULL) + if (text.get () == NULL) return text; indirection_suffix suffix (m_pointer_count); char *p = (char *) alloca (suffix.get_buffer_size ()); suffix.fill_buffer (p); - char *result = concat (text.m_buffer, p, NULL); - text.maybe_free (); + char *result = concat (text.get (), p, NULL); return label_text::take (result); } @@ -5150,10 +5144,14 @@ convert_format_name_to_system_name (const char *attr_name) /* Handle a "format" attribute; arguments as in struct attribute_spec.handler. */ tree -handle_format_attribute (tree *node, tree atname, tree args, +handle_format_attribute (tree node[3], tree atname, tree args, int flags, bool *no_add_attrs) { const_tree type = *node; + /* NODE[2] may be NULL, and it also may be a PARM_DECL for function + pointers. */ + const_tree fndecl = ((node[2] && TREE_CODE (node[2]) == FUNCTION_DECL) + ? node[2] : NULL_TREE); function_format_info info; #ifdef TARGET_FORMAT_TYPES @@ -5179,7 +5177,8 @@ handle_format_attribute (tree *node, tree atname, tree args, if (TREE_CODE (TREE_VALUE (args)) == IDENTIFIER_NODE) TREE_VALUE (args) = canonicalize_attr_name (TREE_VALUE (args)); - if (!decode_format_attr (type, atname, args, &info, /* validated_p = */false)) + if (!decode_format_attr (fndecl ? fndecl : type, atname, args, &info, + /* validated_p = */false)) { *no_add_attrs = true; return NULL_TREE; diff --git a/gcc/c-family/c-gimplify.cc b/gcc/c-family/c-gimplify.cc index a00b0a0..a6f26c9 100644 --- a/gcc/c-family/c-gimplify.cc +++ b/gcc/c-family/c-gimplify.cc @@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see #include "dumpfile.h" #include "c-ubsan.h" #include "tree-nested.h" +#include "context.h" /* The gimplification pass converts the language-dependent trees (ld-trees) emitted by the parser into language-independent trees @@ -552,6 +553,7 @@ c_genericize_control_r (tree *stmt_p, int *walk_subtrees, void *data) void c_genericize (tree fndecl) { + dump_file_info *dfi; FILE *dump_orig; dump_flags_t local_dump_flags; struct cgraph_node *cgn; @@ -581,7 +583,9 @@ c_genericize (tree fndecl) do_warn_duplicated_branches_r, NULL); /* Dump the C-specific tree IR. */ - dump_orig = get_dump_info (TDI_original, &local_dump_flags); + dfi = g->get_dumps ()->get_dump_file_info (TDI_original); + dump_orig = dfi->pstream; + local_dump_flags = dfi->pflags; if (dump_orig) { fprintf (dump_orig, "\n;; Function %s", diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc index cd9d866..66d17a2 100644 --- a/gcc/c-family/c-omp.cc +++ b/gcc/c-family/c-omp.cc @@ -36,7 +36,6 @@ along with GCC; see the file COPYING3. If not see #include "gimplify.h" #include "langhooks.h" #include "bitmap.h" -#include "gimple-fold.h" /* Complete a #pragma oacc wait construct. LOC is the location of @@ -739,6 +738,7 @@ c_finish_omp_depobj (location_t loc, tree depobj, case OMP_CLAUSE_DEPEND_OUT: case OMP_CLAUSE_DEPEND_INOUT: case OMP_CLAUSE_DEPEND_MUTEXINOUTSET: + case OMP_CLAUSE_DEPEND_INOUTSET: kind = OMP_CLAUSE_DEPEND_KIND (clause); t = OMP_CLAUSE_DECL (clause); gcc_assert (t); @@ -757,7 +757,7 @@ c_finish_omp_depobj (location_t loc, tree depobj, t = build2 (COMPOUND_EXPR, TREE_TYPE (t1), TREE_OPERAND (t, 0), t1); } - else + else if (t != null_pointer_node) t = build_fold_addr_expr (t); break; default: @@ -797,6 +797,9 @@ c_finish_omp_depobj (location_t loc, tree depobj, case OMP_CLAUSE_DEPEND_MUTEXINOUTSET: k = GOMP_DEPEND_MUTEXINOUTSET; break; + case OMP_CLAUSE_DEPEND_INOUTSET: + k = GOMP_DEPEND_INOUTSET; + break; case OMP_CLAUSE_DEPEND_LAST: k = -1; break; @@ -2996,39 +2999,6 @@ c_omp_predetermined_mapping (tree decl) } -/* For OpenACC, the OMP_CLAUSE_MAP_KIND of an OMP_CLAUSE_MAP is used internally - to distinguish clauses as seen by the user. Return the "friendly" clause - name for error messages etc., where possible. See also - c/c-parser.cc:c_parser_oacc_data_clause and - cp/parser.cc:cp_parser_oacc_data_clause. */ - -const char * -c_omp_map_clause_name (tree clause, bool oacc) -{ - if (oacc && OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_MAP) - switch (OMP_CLAUSE_MAP_KIND (clause)) - { - case GOMP_MAP_FORCE_ALLOC: - case GOMP_MAP_ALLOC: return "create"; - case GOMP_MAP_FORCE_TO: - case GOMP_MAP_TO: return "copyin"; - case GOMP_MAP_FORCE_FROM: - case GOMP_MAP_FROM: return "copyout"; - case GOMP_MAP_FORCE_TOFROM: - case GOMP_MAP_TOFROM: return "copy"; - case GOMP_MAP_RELEASE: return "delete"; - case GOMP_MAP_FORCE_PRESENT: return "present"; - case GOMP_MAP_ATTACH: return "attach"; - case GOMP_MAP_FORCE_DETACH: - case GOMP_MAP_DETACH: return "detach"; - case GOMP_MAP_DEVICE_RESIDENT: return "device_resident"; - case GOMP_MAP_LINK: return "link"; - case GOMP_MAP_FORCE_DEVICEPTR: return "deviceptr"; - default: break; - } - return omp_clause_code_name[OMP_CLAUSE_CODE (clause)]; -} - /* Used to merge map clause information in c_omp_adjust_map_clauses. */ struct map_clause { diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc index 21ff22d..b9f01a6 100644 --- a/gcc/c-family/c-opts.cc +++ b/gcc/c-family/c-opts.cc @@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see #include "mkdeps.h" #include "dumpfile.h" #include "file-prefix-map.h" /* add_*_prefix_map() */ +#include "context.h" #ifndef DOLLARS_IN_IDENTIFIERS # define DOLLARS_IN_IDENTIFIERS true @@ -100,10 +101,6 @@ static size_t deferred_count; /* Number of deferred options scanned for -include. */ static size_t include_cursor; -/* Dump files/flags to use during parsing. */ -static FILE *original_dump_file = NULL; -static dump_flags_t original_dump_flags; - /* Whether any standard preincluded header has been preincluded. */ static bool done_preinclude; @@ -303,7 +300,7 @@ c_common_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value, result = false; break; - case OPT__output_pch_: + case OPT__output_pch: pch_file = arg; break; @@ -934,10 +931,12 @@ c_common_post_options (const char **pfilename) if (warn_shift_overflow == -1) warn_shift_overflow = cxx_dialect >= cxx11 || flag_isoc99; - /* -Wshift-negative-value is enabled by -Wextra in C99 and C++11 modes. */ + /* -Wshift-negative-value is enabled by -Wextra in C99 and C++11 to C++17 + modes. */ if (warn_shift_negative_value == -1) warn_shift_negative_value = (extra_warnings - && (cxx_dialect >= cxx11 || flag_isoc99)); + && (cxx_dialect >= cxx11 || flag_isoc99) + && cxx_dialect < cxx20); /* -Wregister is enabled by default in C++17. */ SET_OPTION_IF_UNSET (&global_options, &global_options_set, warn_register, @@ -1224,15 +1223,13 @@ c_common_init (void) void c_common_parse_file (void) { - unsigned int i; - - i = 0; - for (;;) + auto dumps = g->get_dumps (); + for (unsigned int i = 0;;) { c_finish_options (); /* Open the dump file to use for the original dump output here, to be used during parsing for the current file. */ - original_dump_file = dump_begin (TDI_original, &original_dump_flags); + dumps->dump_start (TDI_original, &dump_flags); pch_init (); push_file_scope (); c_parse_file (); @@ -1246,29 +1243,15 @@ c_common_parse_file (void) cpp_clear_file_cache (parse_in); this_input_filename = cpp_read_main_file (parse_in, in_fnames[i]); - if (original_dump_file) - { - dump_end (TDI_original, original_dump_file); - original_dump_file = NULL; - } /* If an input file is missing, abandon further compilation. cpplib has issued a diagnostic. */ if (!this_input_filename) break; + dumps->dump_finish (TDI_original); } c_parse_final_cleanups (); -} - -/* Returns the appropriate dump file for PHASE to dump with FLAGS. */ - -FILE * -get_dump_info (int phase, dump_flags_t *flags) -{ - gcc_assert (phase == TDI_original); - - *flags = original_dump_flags; - return original_dump_file; + dumps->dump_finish (TDI_original); } /* Common finish hook for the C, ObjC and C++ front ends. */ diff --git a/gcc/c-family/c-ppoutput.cc b/gcc/c-family/c-ppoutput.cc index 9de46a9..cd38c96 100644 --- a/gcc/c-family/c-ppoutput.cc +++ b/gcc/c-family/c-ppoutput.cc @@ -25,6 +25,8 @@ #include "c-pragma.h" /* For parse_in. */ #include "file-prefix-map.h" /* remap_macro_filename() */ +class token_streamer; + /* Encapsulates state used to convert a stream of tokens into a text file. */ static struct @@ -38,6 +40,8 @@ static struct bool prev_was_system_token; /* True if the previous token was a system token.*/ const char *src_file; /* Current source file. */ + token_streamer *streamer; /* Instance of class token_streamer using this + object. */ } print; /* Defined and undefined macros being queued for output with -dU at @@ -110,6 +114,14 @@ preprocess_file (cpp_reader *pfile) putc ('\n', print.outf); } +/* Don't emit #pragma or #ident directives if we are processing + assembly language; the assembler may choke on them. */ +static bool +should_output_pragmas () +{ + return cpp_get_options (parse_in)->lang != CLK_ASM; +} + /* Set up the callbacks as appropriate. */ void init_pp_output (FILE *out_stream) @@ -119,9 +131,7 @@ init_pp_output (FILE *out_stream) if (!flag_no_output) { cb->line_change = cb_line_change; - /* Don't emit #pragma or #ident directives if we are processing - assembly language; the assembler may choke on them. */ - if (cpp_get_options (parse_in)->lang != CLK_ASM) + if (should_output_pragmas ()) { cb->ident = cb_ident; cb->def_pragma = cb_def_pragma; @@ -163,6 +173,7 @@ init_pp_output (FILE *out_stream) print.first_time = 1; print.src_file = ""; print.prev_was_system_token = false; + print.streamer = nullptr; } // FIXME: Ideally we'd just turn the entirety of the print struct into @@ -183,6 +194,8 @@ class token_streamer in_pragma (false), line_marker_emitted (false) { + gcc_assert (!print.streamer); + print.streamer = this; } void begin_pragma () @@ -235,7 +248,7 @@ token_streamer::stream (cpp_reader *pfile, const cpp_token *token, print.printed = true; } } - else if (token->flags & PREV_WHITE) + else if (token->flags & PREV_WHITE && token->type != CPP_PRAGMA) { unsigned src_line = LOCATION_LINE (loc); @@ -252,22 +265,28 @@ token_streamer::stream (cpp_reader *pfile, const cpp_token *token, print.prev = token; if (token->type == CPP_PRAGMA) { - const char *space; - const char *name; - - line_marker_emitted = maybe_print_line (token->src_loc); - fputs ("#pragma ", print.outf); - c_pp_lookup_pragma (token->val.pragma, &space, &name); - if (space) - fprintf (print.outf, "%s %s", space, name); - else - fprintf (print.outf, "%s", name); - print.printed = true; in_pragma = true; + if (should_output_pragmas ()) + { + const char *space; + const char *name; + + line_marker_emitted = maybe_print_line (token->src_loc); + fputs ("#pragma ", print.outf); + c_pp_lookup_pragma (token->val.pragma, &space, &name); + if (space) + fprintf (print.outf, "%s %s", space, name); + else + fprintf (print.outf, "%s", name); + print.printed = true; + } + if (token->val.pragma >= PRAGMA_FIRST_EXTERNAL) + c_pp_invoke_early_pragma_handler (token->val.pragma); } else if (token->type == CPP_PRAGMA_EOL) { - maybe_print_line (UNKNOWN_LOCATION); + if (should_output_pragmas ()) + maybe_print_line (UNKNOWN_LOCATION); in_pragma = false; } else @@ -287,9 +306,12 @@ token_streamer::stream (cpp_reader *pfile, const cpp_token *token, do_line_change (pfile, token, loc, false); print.prev_was_system_token = !!in_system_header_at (loc); } - cpp_output_token (token, print.outf); - line_marker_emitted = false; - print.printed = true; + if (!in_pragma || should_output_pragmas ()) + { + cpp_output_token (token, print.outf); + line_marker_emitted = false; + print.printed = true; + } } /* CPP_COMMENT tokens and raw-string literal tokens can have @@ -561,8 +583,12 @@ do_line_change (cpp_reader *pfile, const cpp_token *token, one space per column greater than 2, since scan_translation_unit will provide a space if PREV_WHITE. Don't bother trying to reconstruct tabs; we can't get it right in general, and nothing - ought to care. Some things do care; the fault lies with them. */ - if (!CPP_OPTION (pfile, traditional)) + ought to care. Some things do care; the fault lies with them. + + Also do not output the spaces if this is a CPP_PRAGMA token. In this + case, libcpp has provided the location of the first token after #pragma, + so we would start at the wrong column. */ + if (!CPP_OPTION (pfile, traditional) && token->type != CPP_PRAGMA) { int spaces = LOCATION_COLUMN (src_loc) - 2; print.printed = true; @@ -782,6 +808,16 @@ cb_def_pragma (cpp_reader *pfile, location_t line) print.src_line++; } +/* Stream a token as if we had seen it directly ourselves; needed + in case a token was lexed externally, e.g. while processing a + pragma. */ +void +c_pp_stream_token (cpp_reader *pfile, const cpp_token *tok, location_t loc) +{ + gcc_assert (print.streamer); + print.streamer->stream (pfile, tok, loc); +} + /* Dump out the hash table. */ static int dump_macro (cpp_reader *pfile, cpp_hashnode *node, void *v ATTRIBUTE_UNUSED) diff --git a/gcc/c-family/c-pragma.cc b/gcc/c-family/c-pragma.cc index 9004b04..789719e 100644 --- a/gcc/c-family/c-pragma.cc +++ b/gcc/c-family/c-pragma.cc @@ -132,7 +132,7 @@ pop_alignment (tree id) #pragma pack (pop) #pragma pack (pop, ID) */ static void -handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy)) +handle_pragma_pack (cpp_reader *) { location_t loc; tree x, id = 0; @@ -355,7 +355,7 @@ maybe_apply_pending_pragma_weaks (void) /* #pragma weak name [= value] */ static void -handle_pragma_weak (cpp_reader * ARG_UNUSED (dummy)) +handle_pragma_weak (cpp_reader *) { tree name, value, x, decl; enum cpp_ttype t; @@ -418,7 +418,7 @@ maybe_apply_pragma_scalar_storage_order (tree type) } static void -handle_pragma_scalar_storage_order (cpp_reader *ARG_UNUSED(dummy)) +handle_pragma_scalar_storage_order (cpp_reader *) { const char *kind_string; enum cpp_ttype token; @@ -499,7 +499,7 @@ static void handle_pragma_redefine_extname (cpp_reader *); /* #pragma redefine_extname oldname newname */ static void -handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy)) +handle_pragma_redefine_extname (cpp_reader *) { tree oldname, newname, decls, x; enum cpp_ttype t; @@ -721,7 +721,7 @@ pop_visibility (int kind) specified on the command line. */ static void -handle_pragma_visibility (cpp_reader *dummy ATTRIBUTE_UNUSED) +handle_pragma_visibility (cpp_reader *) { /* Form is #pragma GCC visibility push(hidden)|pop */ tree x; @@ -764,142 +764,327 @@ handle_pragma_visibility (cpp_reader *dummy ATTRIBUTE_UNUSED) warning (OPT_Wpragmas, "junk at end of %<#pragma GCC visibility%>"); } +/* Helper routines for parsing #pragma GCC diagnostic. */ +class pragma_diagnostic_data +{ + pragma_diagnostic_data (const pragma_diagnostic_data &) = delete; + pragma_diagnostic_data& operator= (const pragma_diagnostic_data &) = delete; + +public: + bool valid; + location_t loc_kind, loc_option; + enum pd_kind_t + { + PK_INVALID, + PK_PUSH, + PK_POP, + PK_IGNORED_ATTRIBUTES, + PK_DIAGNOSTIC, + } pd_kind; + diagnostic_t diagnostic_kind; + const char *kind_str; + const char *option_str; + bool own_option_str; + + pragma_diagnostic_data () { clear (); } + void clear () + { + valid = false; + loc_kind = loc_option = UNKNOWN_LOCATION; + pd_kind = PK_INVALID; + diagnostic_kind = DK_UNSPECIFIED; + kind_str = option_str = nullptr; + own_option_str = false; + } + + ~pragma_diagnostic_data () + { + if (own_option_str && option_str) + XDELETEVEC (const_cast<char *> (option_str)); + } + + void set_kind (const char *kind_string) + { + kind_str = kind_string; + + pd_kind = PK_INVALID; + diagnostic_kind = DK_UNSPECIFIED; + if (strcmp (kind_str, "push") == 0) + pd_kind = PK_PUSH; + else if (strcmp (kind_str, "pop") == 0) + pd_kind = PK_POP; + else if (strcmp (kind_str, "ignored_attributes") == 0) + pd_kind = PK_IGNORED_ATTRIBUTES; + else if (strcmp (kind_str, "error") == 0) + { + pd_kind = PK_DIAGNOSTIC; + diagnostic_kind = DK_ERROR; + } + else if (strcmp (kind_str, "warning") == 0) + { + pd_kind = PK_DIAGNOSTIC; + diagnostic_kind = DK_WARNING; + } + else if (strcmp (kind_str, "ignored") == 0) + { + pd_kind = PK_DIAGNOSTIC; + diagnostic_kind = DK_IGNORED; + } + } + + bool needs_option () const + { + return pd_kind == PK_IGNORED_ATTRIBUTES + || pd_kind == PK_DIAGNOSTIC; + } + +}; + +/* When compiling normally, use pragma_lex () to obtain the needed tokens. + This will call into either the C or C++ frontends as appropriate. */ + static void -handle_pragma_diagnostic(cpp_reader *ARG_UNUSED(dummy)) +pragma_diagnostic_lex_normal (pragma_diagnostic_data *result) { + result->clear (); tree x; - location_t loc; - enum cpp_ttype token = pragma_lex (&x, &loc); - if (token != CPP_NAME) + auto ttype = pragma_lex (&x, &result->loc_kind); + if (ttype != CPP_NAME) + return; + result->set_kind (IDENTIFIER_POINTER (x)); + if (result->pd_kind == pragma_diagnostic_data::PK_INVALID) + return; + + if (result->needs_option ()) { - warning_at (loc, OPT_Wpragmas, - "missing %<error%>, %<warning%>, %<ignored%>, %<push%>, " - "%<pop%>, or %<ignored_attributes%> after " - "%<#pragma GCC diagnostic%>"); - return; + ttype = pragma_lex (&x, &result->loc_option); + if (ttype != CPP_STRING) + return; + result->option_str = TREE_STRING_POINTER (x); } - diagnostic_t kind; - const char *kind_string = IDENTIFIER_POINTER (x); - if (strcmp (kind_string, "error") == 0) - kind = DK_ERROR; - else if (strcmp (kind_string, "warning") == 0) - kind = DK_WARNING; - else if (strcmp (kind_string, "ignored") == 0) - kind = DK_IGNORED; - else if (strcmp (kind_string, "push") == 0) + result->valid = true; +} + +/* When preprocessing only, pragma_lex () is not available, so obtain the + tokens directly from libcpp. We also need to inform the token streamer + about all tokens we lex ourselves here, so it outputs them too; this is + done by calling c_pp_stream_token () for each. + + ??? If we need to support more pragmas in the future, maybe initialize + this_parser with the pragma tokens and call pragma_lex () instead? */ + +static void +pragma_diagnostic_lex_pp (pragma_diagnostic_data *result) +{ + result->clear (); + + auto tok = cpp_get_token_with_location (parse_in, &result->loc_kind); + c_pp_stream_token (parse_in, tok, result->loc_kind); + if (!(tok->type == CPP_NAME || tok->type == CPP_KEYWORD)) + return; + const unsigned char *const kind_u = cpp_token_as_text (parse_in, tok); + result->set_kind ((const char *)kind_u); + if (result->pd_kind == pragma_diagnostic_data::PK_INVALID) + return; + + if (result->needs_option ()) { - diagnostic_push_diagnostics (global_dc, input_location); - return; + tok = cpp_get_token_with_location (parse_in, &result->loc_option); + c_pp_stream_token (parse_in, tok, result->loc_option); + if (tok->type != CPP_STRING) + return; + cpp_string str; + if (!cpp_interpret_string_notranslate (parse_in, &tok->val.str, 1, &str, + CPP_STRING) + || !str.len) + return; + result->option_str = (const char *)str.text; + result->own_option_str = true; } - else if (strcmp (kind_string, "pop") == 0) + + result->valid = true; +} + +/* Handle #pragma GCC diagnostic. Early mode is used by frontends (such as C++) + that do not process the deferred pragma while they are consuming tokens; they + can use early mode to make sure diagnostics affecting the preprocessor itself + are correctly modified by the #pragma. */ +template<bool early, bool is_pp> static void +handle_pragma_diagnostic_impl () +{ + static const bool want_diagnostics = (is_pp || !early); + + pragma_diagnostic_data data; + if (is_pp) + pragma_diagnostic_lex_pp (&data); + else + pragma_diagnostic_lex_normal (&data); + + if (!data.kind_str) { - diagnostic_pop_diagnostics (global_dc, input_location); + if (want_diagnostics) + warning_at (data.loc_kind, OPT_Wpragmas, + "missing %<error%>, %<warning%>, %<ignored%>, %<push%>, " + "%<pop%>, or %<ignored_attributes%> after " + "%<#pragma GCC diagnostic%>"); return; } - else if (strcmp (kind_string, "ignored_attributes") == 0) + + switch (data.pd_kind) { - token = pragma_lex (&x, &loc); - if (token != CPP_STRING) - { - warning_at (loc, OPT_Wpragmas, - "missing attribute name after %<#pragma GCC diagnostic " - "ignored_attributes%>"); - return; - } - char *args = xstrdup (TREE_STRING_POINTER (x)); - const size_t l = strlen (args); - if (l == 0) - { - warning_at (loc, OPT_Wpragmas, "missing argument to %<#pragma GCC " - "diagnostic ignored_attributes%>"); - free (args); + + case pragma_diagnostic_data::PK_PUSH: + diagnostic_push_diagnostics (global_dc, input_location); + return; + + case pragma_diagnostic_data::PK_POP: + diagnostic_pop_diagnostics (global_dc, input_location); + return; + + case pragma_diagnostic_data::PK_IGNORED_ATTRIBUTES: + { + if (early) return; - } - else if (args[l - 1] == ',') + if (!data.option_str) + { + warning_at (data.loc_option, OPT_Wpragmas, + "missing attribute name after %<#pragma GCC diagnostic " + "ignored_attributes%>"); + return; + } + char *args = xstrdup (data.option_str); + const size_t l = strlen (args); + if (l == 0) + { + warning_at (data.loc_option, OPT_Wpragmas, + "missing argument to %<#pragma GCC " + "diagnostic ignored_attributes%>"); + free (args); + return; + } + else if (args[l - 1] == ',') + { + warning_at (data.loc_option, OPT_Wpragmas, + "trailing %<,%> in arguments for " + "%<#pragma GCC diagnostic ignored_attributes%>"); + free (args); + return; + } + auto_vec<char *> v; + for (char *p = strtok (args, ","); p; p = strtok (NULL, ",")) + v.safe_push (p); + handle_ignored_attributes_option (&v); + free (args); + return; + } + + case pragma_diagnostic_data::PK_DIAGNOSTIC: + if (!data.option_str) { - warning_at (loc, OPT_Wpragmas, "trailing %<,%> in arguments for " - "%<#pragma GCC diagnostic ignored_attributes%>"); - free (args); + if (want_diagnostics) + warning_at (data.loc_option, OPT_Wpragmas, + "missing option after %<#pragma GCC diagnostic%> kind"); return; } - auto_vec<char *> v; - for (char *p = strtok (args, ","); p; p = strtok (NULL, ",")) - v.safe_push (p); - handle_ignored_attributes_option (&v); - free (args); - return; - } - else - { - warning_at (loc, OPT_Wpragmas, - "expected %<error%>, %<warning%>, %<ignored%>, %<push%>, " - "%<pop%>, %<ignored_attributes%> after " - "%<#pragma GCC diagnostic%>"); - return; - } + break; - token = pragma_lex (&x, &loc); - if (token != CPP_STRING) - { - warning_at (loc, OPT_Wpragmas, - "missing option after %<#pragma GCC diagnostic%> kind"); + default: + if (want_diagnostics) + warning_at (data.loc_kind, OPT_Wpragmas, + "expected %<error%>, %<warning%>, %<ignored%>, %<push%>, " + "%<pop%>, %<ignored_attributes%> after " + "%<#pragma GCC diagnostic%>"); return; + } - const char *option_string = TREE_STRING_POINTER (x); + gcc_assert (data.pd_kind == pragma_diagnostic_data::PK_DIAGNOSTIC); + gcc_assert (data.valid); + unsigned int lang_mask = c_common_option_lang_mask () | CL_COMMON; /* option_string + 1 to skip the initial '-' */ - unsigned int option_index = find_opt (option_string + 1, lang_mask); + unsigned int option_index = find_opt (data.option_str + 1, lang_mask); + + if (early && !c_option_is_from_cpp_diagnostics (option_index)) + return; + if (option_index == OPT_SPECIAL_unknown) { - auto_diagnostic_group d; - if (warning_at (loc, OPT_Wpragmas, - "unknown option after %<#pragma GCC diagnostic%> kind")) + if (want_diagnostics) { - option_proposer op; - const char *hint = op.suggest_option (option_string + 1); - if (hint) - inform (loc, "did you mean %<-%s%>?", hint); + auto_diagnostic_group d; + if (warning_at (data.loc_option, OPT_Wpragmas, + "unknown option after %<#pragma GCC diagnostic%> kind")) + { + option_proposer op; + const char *hint = op.suggest_option (data.option_str + 1); + if (hint) + inform (data.loc_option, "did you mean %<-%s%>?", hint); + } } return; } else if (!(cl_options[option_index].flags & CL_WARNING)) { - warning_at (loc, OPT_Wpragmas, - "%qs is not an option that controls warnings", option_string); + if (want_diagnostics) + warning_at (data.loc_option, OPT_Wpragmas, + "%qs is not an option that controls warnings", + data.option_str); return; } else if (!(cl_options[option_index].flags & lang_mask)) { - char *ok_langs = write_langs (cl_options[option_index].flags); - char *bad_lang = write_langs (c_common_option_lang_mask ()); - warning_at (loc, OPT_Wpragmas, - "option %qs is valid for %s but not for %s", - option_string, ok_langs, bad_lang); - free (ok_langs); - free (bad_lang); + if (want_diagnostics) + { + char *ok_langs = write_langs (cl_options[option_index].flags); + char *bad_lang = write_langs (c_common_option_lang_mask ()); + warning_at (data.loc_option, OPT_Wpragmas, + "option %qs is valid for %s but not for %s", + data.option_str, ok_langs, bad_lang); + free (ok_langs); + free (bad_lang); + } return; } - struct cl_option_handlers handlers; - set_default_handlers (&handlers, NULL); const char *arg = NULL; if (cl_options[option_index].flags & CL_JOINED) - arg = option_string + 1 + cl_options[option_index].opt_len; + arg = data.option_str + 1 + cl_options[option_index].opt_len; + + struct cl_option_handlers handlers; + set_default_handlers (&handlers, NULL); /* FIXME: input_location isn't the best location here, but it is what we used to do here before and changing it breaks e.g. PR69543 and PR69558. */ - control_warning_option (option_index, (int) kind, - arg, kind != DK_IGNORED, + control_warning_option (option_index, (int) data.diagnostic_kind, + arg, data.diagnostic_kind != DK_IGNORED, input_location, lang_mask, &handlers, &global_options, &global_options_set, global_dc); } +static void +handle_pragma_diagnostic (cpp_reader *) +{ + handle_pragma_diagnostic_impl<false, false> (); +} + +static void +handle_pragma_diagnostic_early (cpp_reader *) +{ + handle_pragma_diagnostic_impl<true, false> (); +} + +static void +handle_pragma_diagnostic_early_pp (cpp_reader *) +{ + handle_pragma_diagnostic_impl<true, true> (); +} + /* Parse #pragma GCC target (xxx) to set target specific options. */ static void -handle_pragma_target(cpp_reader *ARG_UNUSED(dummy)) +handle_pragma_target(cpp_reader *) { location_t loc; enum cpp_ttype token; @@ -971,7 +1156,7 @@ handle_pragma_target(cpp_reader *ARG_UNUSED(dummy)) /* Handle #pragma GCC optimize to set optimization options. */ static void -handle_pragma_optimize (cpp_reader *ARG_UNUSED(dummy)) +handle_pragma_optimize (cpp_reader *) { enum cpp_ttype token; tree x; @@ -1057,7 +1242,7 @@ static GTY(()) struct opt_stack * options_stack; options. */ static void -handle_pragma_push_options (cpp_reader *ARG_UNUSED(dummy)) +handle_pragma_push_options (cpp_reader *) { enum cpp_ttype token; tree x = 0; @@ -1093,7 +1278,7 @@ handle_pragma_push_options (cpp_reader *ARG_UNUSED(dummy)) optimization options from a previous push_options. */ static void -handle_pragma_pop_options (cpp_reader *ARG_UNUSED(dummy)) +handle_pragma_pop_options (cpp_reader *) { enum cpp_ttype token; tree x = 0; @@ -1150,7 +1335,7 @@ handle_pragma_pop_options (cpp_reader *ARG_UNUSED(dummy)) optimization options to the original options used on the command line. */ static void -handle_pragma_reset_options (cpp_reader *ARG_UNUSED(dummy)) +handle_pragma_reset_options (cpp_reader *) { enum cpp_ttype token; tree x = 0; @@ -1186,7 +1371,7 @@ handle_pragma_reset_options (cpp_reader *ARG_UNUSED(dummy)) /* Print a plain user-specified message. */ static void -handle_pragma_message (cpp_reader *ARG_UNUSED(dummy)) +handle_pragma_message (cpp_reader *) { location_t loc; enum cpp_ttype token; @@ -1291,7 +1476,7 @@ handle_stdc_pragma (const char *pname) #pragma STDC FLOAT_CONST_DECIMAL64 DEFAULT */ static void -handle_pragma_float_const_decimal64 (cpp_reader *ARG_UNUSED (dummy)) +handle_pragma_float_const_decimal64 (cpp_reader *) { if (c_dialect_cxx ()) { @@ -1332,14 +1517,15 @@ handle_pragma_float_const_decimal64 (cpp_reader *ARG_UNUSED (dummy)) static vec<internal_pragma_handler> registered_pragmas; -struct pragma_ns_name +struct pragma_pp_data { const char *space; const char *name; + pragma_handler_1arg early_handler; }; -static vec<pragma_ns_name> registered_pp_pragmas; +static vec<pragma_pp_data> registered_pp_pragmas; struct omp_pragma_def { const char *name; unsigned int id; }; static const struct omp_pragma_def oacc_pragmas[] = { @@ -1400,8 +1586,8 @@ static const struct omp_pragma_def omp_pragmas_simd[] = { void c_pp_lookup_pragma (unsigned int id, const char **space, const char **name) { - const int n_oacc_pragmas = sizeof (oacc_pragmas) / sizeof (*oacc_pragmas); - const int n_omp_pragmas = sizeof (omp_pragmas) / sizeof (*omp_pragmas); + const int n_oacc_pragmas = ARRAY_SIZE (oacc_pragmas); + const int n_omp_pragmas = ARRAY_SIZE (omp_pragmas); const int n_omp_pragmas_simd = sizeof (omp_pragmas_simd) / sizeof (*omp_pragmas); int i; @@ -1452,14 +1638,14 @@ c_register_pragma_1 (const char *space, const char *name, if (flag_preprocess_only) { - pragma_ns_name ns_name; - - if (!allow_expansion) + if (!(allow_expansion || ihandler.early_handler.handler_1arg)) return; - ns_name.space = space; - ns_name.name = name; - registered_pp_pragmas.safe_push (ns_name); + pragma_pp_data pp_data; + pp_data.space = space; + pp_data.name = name; + pp_data.early_handler = ihandler.early_handler.handler_1arg; + registered_pp_pragmas.safe_push (pp_data); id = registered_pp_pragmas.length (); id += PRAGMA_FIRST_EXTERNAL - 1; } @@ -1485,9 +1671,16 @@ void c_register_pragma (const char *space, const char *name, pragma_handler_1arg handler) { + c_register_pragma_with_early_handler (space, name, handler, nullptr); +} +void c_register_pragma_with_early_handler (const char *space, const char *name, + pragma_handler_1arg handler, + pragma_handler_1arg early_handler) +{ internal_pragma_handler ihandler; ihandler.handler.handler_1arg = handler; + ihandler.early_handler.handler_1arg = early_handler; ihandler.extra_data = false; ihandler.data = NULL; c_register_pragma_1 (space, name, ihandler, false); @@ -1504,6 +1697,7 @@ c_register_pragma_with_data (const char *space, const char *name, internal_pragma_handler ihandler; ihandler.handler.handler_2arg = handler; + ihandler.early_handler.handler_2arg = nullptr; ihandler.extra_data = true; ihandler.data = data; c_register_pragma_1 (space, name, ihandler, false); @@ -1523,6 +1717,7 @@ c_register_pragma_with_expansion (const char *space, const char *name, internal_pragma_handler ihandler; ihandler.handler.handler_1arg = handler; + ihandler.early_handler.handler_1arg = nullptr; ihandler.extra_data = false; ihandler.data = NULL; c_register_pragma_1 (space, name, ihandler, true); @@ -1544,6 +1739,7 @@ c_register_pragma_with_expansion_and_data (const char *space, const char *name, internal_pragma_handler ihandler; ihandler.handler.handler_2arg = handler; + ihandler.early_handler.handler_2arg = nullptr; ihandler.extra_data = true; ihandler.data = data; c_register_pragma_1 (space, name, ihandler, true); @@ -1570,14 +1766,45 @@ c_invoke_pragma_handler (unsigned int id) } } +/* In contrast to the normal handler, the early handler is optional. */ +void +c_invoke_early_pragma_handler (unsigned int id) +{ + internal_pragma_handler *ihandler; + pragma_handler_1arg handler_1arg; + pragma_handler_2arg handler_2arg; + + id -= PRAGMA_FIRST_EXTERNAL; + ihandler = ®istered_pragmas[id]; + if (ihandler->extra_data) + { + handler_2arg = ihandler->early_handler.handler_2arg; + if (handler_2arg) + handler_2arg (parse_in, ihandler->data); + } + else + { + handler_1arg = ihandler->early_handler.handler_1arg; + if (handler_1arg) + handler_1arg (parse_in); + } +} + +void +c_pp_invoke_early_pragma_handler (unsigned int id) +{ + const auto data = ®istered_pp_pragmas[id - PRAGMA_FIRST_EXTERNAL]; + if (data->early_handler) + data->early_handler (parse_in); +} + /* Set up front-end pragmas. */ void init_pragma (void) { if (flag_openacc) { - const int n_oacc_pragmas - = sizeof (oacc_pragmas) / sizeof (*oacc_pragmas); + const int n_oacc_pragmas = ARRAY_SIZE (oacc_pragmas); int i; for (i = 0; i < n_oacc_pragmas; ++i) @@ -1587,7 +1814,7 @@ init_pragma (void) if (flag_openmp) { - const int n_omp_pragmas = sizeof (omp_pragmas) / sizeof (*omp_pragmas); + const int n_omp_pragmas = ARRAY_SIZE (omp_pragmas); int i; for (i = 0; i < n_omp_pragmas; ++i) @@ -1626,7 +1853,14 @@ init_pragma (void) c_register_pragma ("GCC", "visibility", handle_pragma_visibility); - c_register_pragma ("GCC", "diagnostic", handle_pragma_diagnostic); + if (flag_preprocess_only) + c_register_pragma_with_early_handler ("GCC", "diagnostic", + nullptr, + handle_pragma_diagnostic_early_pp); + else + c_register_pragma_with_early_handler ("GCC", "diagnostic", + handle_pragma_diagnostic, + handle_pragma_diagnostic_early); c_register_pragma ("GCC", "target", handle_pragma_target); c_register_pragma ("GCC", "optimize", handle_pragma_optimize); c_register_pragma ("GCC", "push_options", handle_pragma_push_options); diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index 54864c2..de806a6 100644 --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -90,7 +90,7 @@ enum pragma_kind { /* All clauses defined by OpenACC 2.0, and OpenMP 2.5, 3.0, 3.1, 4.0, 4.5, 5.0, - and 5.1. Used internally by both C and C++ parsers. */ + 5.1 and 5.2. Used internally by both C and C++ parsers. */ enum pragma_omp_clause { PRAGMA_OMP_CLAUSE_NONE = 0, @@ -108,6 +108,7 @@ enum pragma_omp_clause { PRAGMA_OMP_CLAUSE_DEVICE, PRAGMA_OMP_CLAUSE_DEVICE_TYPE, PRAGMA_OMP_CLAUSE_DIST_SCHEDULE, + PRAGMA_OMP_CLAUSE_ENTER, PRAGMA_OMP_CLAUSE_FILTER, PRAGMA_OMP_CLAUSE_FINAL, PRAGMA_OMP_CLAUSE_FIRSTPRIVATE, @@ -218,7 +219,7 @@ union gen_pragma_handler { }; /* Internally used to keep the data of the handler. */ struct internal_pragma_handler { - union gen_pragma_handler handler; + union gen_pragma_handler handler, early_handler; /* Permits to know if handler is a pragma_handler_1arg (extra_data is false) or a pragma_handler_2arg (extra_data is true). */ bool extra_data; @@ -241,6 +242,17 @@ extern void c_register_pragma_with_expansion_and_data (const char *space, void *data); extern void c_invoke_pragma_handler (unsigned int); +/* Early pragma handlers run in addition to the normal ones. They can be used + by frontends such as C++ that may want to process some pragmas during lexing + before they start processing them. */ +extern void +c_register_pragma_with_early_handler (const char *space, const char *name, + pragma_handler_1arg handler, + pragma_handler_1arg early_handler); +extern void c_invoke_early_pragma_handler (unsigned int); +extern void c_pp_invoke_early_pragma_handler (unsigned int); + + extern void maybe_apply_pragma_weak (tree); extern void maybe_apply_pending_pragma_weaks (void); extern tree maybe_apply_renaming_pragma (tree, tree); diff --git a/gcc/c-family/c-pretty-print.cc b/gcc/c-family/c-pretty-print.cc index dac1775..71a0cb5 100644 --- a/gcc/c-family/c-pretty-print.cc +++ b/gcc/c-family/c-pretty-print.cc @@ -1889,6 +1889,12 @@ c_fold_indirect_ref_for_warn (location_t loc, tree type, tree op, = wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (field))); if (upos <= off && off < upos + el_sz) { + /* The C++ pretty printers print scope of the FIELD_DECLs, + so punt if it is something that can't be printed. */ + if (c_dialect_cxx ()) + if (tree scope = get_containing_scope (field)) + if (TYPE_P (scope) && TYPE_NAME (scope) == NULL_TREE) + break; tree cop = build3_loc (loc, COMPONENT_REF, TREE_TYPE (field), op, field, NULL_TREE); off = off - upos; diff --git a/gcc/c-family/c-pretty-print.h b/gcc/c-family/c-pretty-print.h index ba7624d..be86bed 100644 --- a/gcc/c-family/c-pretty-print.h +++ b/gcc/c-family/c-pretty-print.h @@ -51,7 +51,7 @@ class c_pretty_printer : public pretty_printer { public: c_pretty_printer (); - pretty_printer *clone () const OVERRIDE; + pretty_printer *clone () const override; // Format string, possibly translated. void translate_string (const char *); diff --git a/gcc/c-family/c-target.def b/gcc/c-family/c-target.def index bd47db0..141dcf3 100644 --- a/gcc/c-family/c-target.def +++ b/gcc/c-family/c-target.def @@ -81,7 +81,7 @@ DEFHOOK DEFHOOK (check_string_object_format_arg, - "If a target implements string objects then this hook should should\n\ + "If a target implements string objects then this hook should\n\ provide a facility to check the function arguments in @var{args_list}\n\ against the format specifiers in @var{format_arg} where the type of\n\ @var{format_arg} is one recognized as a valid string reference type.", diff --git a/gcc/c-family/c-ubsan.cc b/gcc/c-family/c-ubsan.cc index 7fe4956..360ba82 100644 --- a/gcc/c-family/c-ubsan.cc +++ b/gcc/c-family/c-ubsan.cc @@ -83,8 +83,9 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1) x = NULL_TREE; flag = SANITIZE_SI_OVERFLOW; } - else if (flag_sanitize_undefined_trap_on_error - || (((flag_sanitize_recover & SANITIZE_DIVIDE) == 0) + else if ((((flag_sanitize_trap & SANITIZE_DIVIDE) == 0) + == ((flag_sanitize_trap & SANITIZE_SI_OVERFLOW) == 0)) + && (((flag_sanitize_recover & SANITIZE_DIVIDE) == 0) == ((flag_sanitize_recover & SANITIZE_SI_OVERFLOW) == 0))) { t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, x); @@ -105,7 +106,7 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1) make sure it gets evaluated before the condition. */ t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), unshare_expr (op0), t); t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), unshare_expr (op1), t); - if (flag_sanitize_undefined_trap_on_error) + if ((flag_sanitize_trap & flag) && x == NULL_TREE) tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0); else { @@ -113,25 +114,41 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1) ubsan_type_descriptor (type), NULL_TREE, NULL_TREE); data = build_fold_addr_expr_loc (loc, data); - enum built_in_function bcode - = (flag_sanitize_recover & flag) - ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW - : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT; - tt = builtin_decl_explicit (bcode); - op0 = unshare_expr (op0); - op1 = unshare_expr (op1); - tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0), - ubsan_encode_value (op1)); - if (x) + if (flag_sanitize_trap & flag) + tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), + 0); + else { - bcode = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW) - ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW - : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT; - tree xt = builtin_decl_explicit (bcode); + enum built_in_function bcode + = (flag_sanitize_recover & flag) + ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW + : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT; + tt = builtin_decl_explicit (bcode); op0 = unshare_expr (op0); op1 = unshare_expr (op1); - xt = build_call_expr_loc (loc, xt, 3, data, ubsan_encode_value (op0), + tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0), ubsan_encode_value (op1)); + } + if (x) + { + tree xt; + if (flag_sanitize_trap & SANITIZE_SI_OVERFLOW) + xt = build_call_expr_loc (loc, + builtin_decl_explicit (BUILT_IN_TRAP), + 0); + else + { + enum built_in_function bcode + = (flag_sanitize_recover & SANITIZE_SI_OVERFLOW) + ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW + : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT; + xt = builtin_decl_explicit (bcode); + op0 = unshare_expr (op0); + op1 = unshare_expr (op1); + xt = build_call_expr_loc (loc, xt, 3, data, + ubsan_encode_value (op0), + ubsan_encode_value (op1)); + } x = fold_build3 (COND_EXPR, void_type_node, x, xt, void_node); } } @@ -173,7 +190,7 @@ ubsan_instrument_shift (location_t loc, enum tree_code code, || cxx_dialect >= cxx20) ; - /* For signed x << y, in C99/C11, the following: + /* For signed x << y, in C99 and later, the following: (unsigned) x >> (uprecm1 - y) if non-zero, is undefined. */ else if (code == LSHIFT_EXPR && flag_isoc99 && cxx_dialect < cxx11) @@ -186,7 +203,7 @@ ubsan_instrument_shift (location_t loc, enum tree_code code, build_int_cst (TREE_TYPE (tt), 0)); } - /* For signed x << y, in C++11 and later, the following: + /* For signed x << y, in C++11 to C++17, the following: x < 0 || ((unsigned) x >> (uprecm1 - y)) if > 1, is undefined. */ else if (code == LSHIFT_EXPR && cxx_dialect >= cxx11) @@ -225,8 +242,9 @@ ubsan_instrument_shift (location_t loc, enum tree_code code, } else { - if (flag_sanitize_undefined_trap_on_error - || ((!(flag_sanitize_recover & SANITIZE_SHIFT_EXPONENT)) + if (((!(flag_sanitize_trap & SANITIZE_SHIFT_EXPONENT)) + == (!(flag_sanitize_trap & SANITIZE_SHIFT_BASE))) + && ((!(flag_sanitize_recover & SANITIZE_SHIFT_EXPONENT)) == (!(flag_sanitize_recover & SANITIZE_SHIFT_BASE)))) t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt); else @@ -234,7 +252,7 @@ ubsan_instrument_shift (location_t loc, enum tree_code code, } } - if (flag_sanitize_undefined_trap_on_error) + if ((flag_sanitize_trap & recover_kind) && else_t == void_node) tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0); else { @@ -244,26 +262,40 @@ ubsan_instrument_shift (location_t loc, enum tree_code code, NULL_TREE); data = build_fold_addr_expr_loc (loc, data); - enum built_in_function bcode - = (flag_sanitize_recover & recover_kind) - ? BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS - : BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS_ABORT; - tt = builtin_decl_explicit (bcode); - op0 = unshare_expr (op0); - op1 = unshare_expr (op1); - tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0), - ubsan_encode_value (op1)); + if (flag_sanitize_trap & recover_kind) + tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0); + else + { + enum built_in_function bcode + = (flag_sanitize_recover & recover_kind) + ? BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS + : BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS_ABORT; + tt = builtin_decl_explicit (bcode); + op0 = unshare_expr (op0); + op1 = unshare_expr (op1); + tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0), + ubsan_encode_value (op1)); + } if (else_t != void_node) { - bcode = (flag_sanitize_recover & SANITIZE_SHIFT_BASE) + tree else_tt; + if (flag_sanitize_trap & SANITIZE_SHIFT_BASE) + else_tt + = build_call_expr_loc (loc, + builtin_decl_explicit (BUILT_IN_TRAP), 0); + else + { + enum built_in_function bcode + = (flag_sanitize_recover & SANITIZE_SHIFT_BASE) ? BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS : BUILT_IN_UBSAN_HANDLE_SHIFT_OUT_OF_BOUNDS_ABORT; - tree else_tt = builtin_decl_explicit (bcode); - op0 = unshare_expr (op0); - op1 = unshare_expr (op1); - else_tt = build_call_expr_loc (loc, else_tt, 3, data, - ubsan_encode_value (op0), - ubsan_encode_value (op1)); + else_tt = builtin_decl_explicit (bcode); + op0 = unshare_expr (op0); + op1 = unshare_expr (op1); + else_tt = build_call_expr_loc (loc, else_tt, 3, data, + ubsan_encode_value (op0), + ubsan_encode_value (op1)); + } else_t = fold_build3 (COND_EXPR, void_type_node, else_t, else_tt, void_node); } @@ -282,7 +314,7 @@ ubsan_instrument_vla (location_t loc, tree size) tree t, tt; t = fold_build2 (LE_EXPR, boolean_type_node, size, build_int_cst (type, 0)); - if (flag_sanitize_undefined_trap_on_error) + if (flag_sanitize_trap & SANITIZE_VLA) tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0); else { @@ -307,8 +339,10 @@ ubsan_instrument_vla (location_t loc, tree size) tree ubsan_instrument_return (location_t loc) { - if (flag_sanitize_undefined_trap_on_error) - return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0); + if (flag_sanitize_trap & SANITIZE_RETURN) + /* pass_warn_function_return checks for BUILTINS_LOCATION. */ + return build_call_expr_loc (BUILTINS_LOCATION, + builtin_decl_explicit (BUILT_IN_TRAP), 0); tree data = ubsan_create_data ("__ubsan_missing_return_data", 1, &loc, NULL_TREE, NULL_TREE); diff --git a/gcc/c-family/c-warn.cc b/gcc/c-family/c-warn.cc index 1ce2202..ea7335f 100644 --- a/gcc/c-family/c-warn.cc +++ b/gcc/c-family/c-warn.cc @@ -1300,7 +1300,7 @@ conversion_warning (location_t loc, tree type, tree expr, tree result) tree op1 = TREE_OPERAND (expr, 1); tree op2 = TREE_OPERAND (expr, 2); - return (conversion_warning (loc, type, op1, result) + return ((op1 && conversion_warning (loc, type, op1, result)) || conversion_warning (loc, type, op2, result)); } @@ -1404,8 +1404,14 @@ warnings_for_convert_and_check (location_t loc, tree type, tree expr, result = TREE_OPERAND (result, 1); bool cst = TREE_CODE_CLASS (TREE_CODE (result)) == tcc_constant; - tree exprtype = TREE_TYPE (expr); + tree result_diag; + /* We're interested in the actual numerical value here, not its ASCII + representation. */ + if (cst && TYPE_MAIN_VARIANT (TREE_TYPE (result)) == char_type_node) + result_diag = fold_convert (integer_type_node, result); + else + result_diag = result; if (TREE_CODE (expr) == INTEGER_CST && (TREE_CODE (type) == INTEGER_TYPE @@ -1430,7 +1436,7 @@ warnings_for_convert_and_check (location_t loc, tree type, tree expr, "changes value from %qE to %qE") : G_("unsigned conversion from %qT to %qT " "changes value from %qE to %qE")), - exprtype, type, expr, result); + exprtype, type, expr, result_diag); else warning_at (loc, OPT_Woverflow, (TYPE_UNSIGNED (exprtype) @@ -1449,7 +1455,7 @@ warnings_for_convert_and_check (location_t loc, tree type, tree expr, warning_at (loc, OPT_Woverflow, "overflow in conversion from %qT to %qT " "changes value from %qE to %qE", - exprtype, type, expr, result); + exprtype, type, expr, result_diag); else warning_at (loc, OPT_Woverflow, "overflow in conversion from %qT to %qT " @@ -1466,7 +1472,7 @@ warnings_for_convert_and_check (location_t loc, tree type, tree expr, warning_at (loc, OPT_Woverflow, "overflow in conversion from %qT to %qT " "changes value from %qE to %qE", - exprtype, type, expr, result); + exprtype, type, expr, result_diag); else warning_at (loc, OPT_Woverflow, "overflow in conversion from %qT to %qT " @@ -1483,7 +1489,7 @@ warnings_for_convert_and_check (location_t loc, tree type, tree expr, warning_at (loc, OPT_Woverflow, "overflow in conversion from %qT to %qT " "changes value from %qE to %qE", - exprtype, type, expr, result); + exprtype, type, expr, result_diag); else warning_at (loc, OPT_Woverflow, "overflow in conversion from %qT to %qT " @@ -1732,8 +1738,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location, for (chain = TYPE_VALUES (type); chain; chain = TREE_CHAIN (chain)) { tree value = TREE_VALUE (chain); - if (TREE_CODE (value) == CONST_DECL) - value = DECL_INITIAL (value); + tree attrs = DECL_ATTRIBUTES (value); + value = DECL_INITIAL (value); node = splay_tree_lookup (cases, (splay_tree_key) value); if (node) { @@ -1763,6 +1769,13 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location, /* We've now determined that this enumerated literal isn't handled by the case labels of the switch statement. */ + /* Don't warn if the enumerator was marked as unused. We can't use + TREE_USED here: it could have been set on the enumerator if the + enumerator was used earlier. */ + if (lookup_attribute ("unused", attrs) + || lookup_attribute ("maybe_unused", attrs)) + continue; + /* If the switch expression is a constant, we only really care about whether that constant is handled by the switch. */ if (cond && tree_int_cst_compare (cond, value)) @@ -2605,7 +2618,7 @@ maybe_warn_shift_overflow (location_t loc, tree op0, tree op1) unsigned int prec0 = TYPE_PRECISION (type0); /* Left-hand operand must be signed. */ - if (TYPE_UNSIGNED (type0) || cxx_dialect >= cxx20) + if (TYPE_OVERFLOW_WRAPS (type0) || cxx_dialect >= cxx20) return false; unsigned int min_prec = (wi::min_precision (wi::to_wide (op0), SIGNED) diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 9cfd2a6..44e1a60 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -135,8 +135,8 @@ C ObjC C++ ObjC++ Separate Alias(o) -output= C ObjC C++ ObjC++ Joined Alias(o) --output-pch= -C ObjC C++ ObjC++ Joined Separate +-output-pch +C ObjC C++ ObjC++ Separate -pedantic C ObjC C++ ObjC++ Alias(pedantic) @@ -342,10 +342,6 @@ Wno-alloca-larger-than C ObjC C++ LTO ObjC++ Alias(Walloca-larger-than=,18446744073709551615EiB,none) Warning Disable Walloca-larger-than= warning. Equivalent to Walloca-larger-than=<SIZE_MAX> or larger. -Warray-bounds -LangEnabledBy(C ObjC C++ LTO ObjC++) -; in common.opt - Warray-bounds= LangEnabledBy(C ObjC C++ LTO ObjC++,Wall,1,0) ; in common.opt @@ -463,23 +459,23 @@ C++ ObjC++ Var(warn_cxx20_compat) Warning LangEnabledBy(C++ ObjC++,Wall) Warn about C++ constructs whose meaning differs between ISO C++ 2017 and ISO C++ 2020. Wc++11-extensions -C++ ObjC++ Var(warn_cxx11_extensions) Warning LangEnabledBy(C++ ObjC++) Init(1) +C++ ObjC++ Var(warn_cxx11_extensions) Warning Init(1) Warn about C++11 constructs in code compiled with an older standard. Wc++14-extensions -C++ ObjC++ Var(warn_cxx14_extensions) Warning LangEnabledBy(C++ ObjC++) Init(1) +C++ ObjC++ Var(warn_cxx14_extensions) Warning Init(1) Warn about C++14 constructs in code compiled with an older standard. Wc++17-extensions -C++ ObjC++ Var(warn_cxx17_extensions) Warning LangEnabledBy(C++ ObjC++) Init(1) +C++ ObjC++ Var(warn_cxx17_extensions) Warning Init(1) Warn about C++17 constructs in code compiled with an older standard. Wc++20-extensions -C++ ObjC++ Var(warn_cxx20_extensions) Warning LangEnabledBy(C++ ObjC++) Init(1) +C++ ObjC++ Var(warn_cxx20_extensions) Warning Init(1) Warn about C++20 constructs in code compiled with an older standard. Wc++23-extensions -C++ ObjC++ Var(warn_cxx23_extensions) Warning LangEnabledBy(C++ ObjC++) Init(1) +C++ ObjC++ Var(warn_cxx23_extensions) Warning Init(1) Warn about C++23 constructs in code compiled with an older standard. Wcast-function-type @@ -642,6 +638,10 @@ Wenum-conversion C ObjC C++ ObjC++ Var(warn_enum_conversion) Init(0) Warning LangEnabledBy(C ObjC,Wextra) Warn about implicit conversion of enum types. +Wenum-int-mismatch +C ObjC Var(warn_enum_int_mismatch) Warning LangEnabledBy(C ObjC,Wall || Wc++-compat) +Warn about enum/integer type mismatches. + Werror C ObjC C++ ObjC++ ; Documented in common.opt @@ -1126,7 +1126,11 @@ C ObjC C++ ObjC++ Var(warn_overlength_strings) Warning LangEnabledBy(C ObjC C++ Warn if a string is longer than the maximum portable length specified by the standard. Woverloaded-virtual -C++ ObjC++ Var(warn_overloaded_virtual) Warning +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) Warn about overloaded virtual function names. Woverride-init @@ -1377,13 +1381,9 @@ Wunused-const-variable= C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_unused_const_variable) Warning LangEnabledBy(C ObjC,Wunused-variable, 1, 0) IntegerRange(0, 2) Warn when a const variable is unused. -# Defining these options here in addition to common.opt is necessary -# in order for the default -Wall setting of -Wuse-after-free=2 to take -# effect. - -Wuse-after-free -LangEnabledBy(C ObjC C++ LTO ObjC++) -; in common.opt +; Defining this option here in addition to common.opt is necessary +; in order for the default -Wall setting of -Wuse-after-free=2 to take +; effect. Wuse-after-free= LangEnabledBy(C ObjC C++ LTO ObjC++, Wall,2,0) @@ -1731,6 +1731,10 @@ Support dynamic initialization of thread-local variables in a different translat fexternal-templates C++ ObjC++ WarnRemoved +ffold-simple-inlines +C++ ObjC++ Optimization Var(flag_fold_simple_inlines) +Fold calls to simple inline functions. + ffor-scope C++ ObjC++ WarnRemoved diff --git a/gcc/c-family/known-headers.cc b/gcc/c-family/known-headers.cc index 8ad3eb3f..9c25617 100644 --- a/gcc/c-family/known-headers.cc +++ b/gcc/c-family/known-headers.cc @@ -79,8 +79,7 @@ get_string_macro_hint (const char *name, enum stdlib lib) if ((lib == STDLIB_C && flag_isoc99) || (lib == STDLIB_CPLUSPLUS && cxx_dialect >= cxx11 )) { - const size_t num_c99_cxx11_macros - = sizeof (c99_cxx11_macros) / sizeof (c99_cxx11_macros[0]); + const size_t num_c99_cxx11_macros = ARRAY_SIZE (c99_cxx11_macros); for (size_t i = 0; i < num_c99_cxx11_macros; i++) if (strcmp (name, c99_cxx11_macros[i]) == 0) return lib == STDLIB_C ? "<inttypes.h>" : "<cinttypes>"; @@ -200,11 +199,25 @@ get_stdlib_header_for_name (const char *name, enum stdlib lib) {"WINT_MAX", {"<stdint.h>", "<cstdint>"} }, {"WINT_MIN", {"<stdint.h>", "<cstdint>"} }, + /* <time.h>. */ + {"asctime", {"<time.h>", "<ctime>"} }, + {"clock", {"<time.h>", "<ctime>"} }, + {"clock_t", {"<time.h>", "<ctime>"} }, + {"ctime", {"<time.h>", "<ctime>"} }, + {"difftime", {"<time.h>", "<ctime>"} }, + {"gmtime", {"<time.h>", "<ctime>"} }, + {"localtime", {"<time.h>", "<ctime>"} }, + {"mktime", {"<time.h>", "<ctime>"} }, + {"strftime", {"<time.h>", "<ctime>"} }, + {"time", {"<time.h>", "<ctime>"} }, + {"time_t", {"<time.h>", "<ctime>"} }, + {"tm", {"<time.h>", "<ctime>"} }, + /* <wchar.h>. */ {"WCHAR_MAX", {"<wchar.h>", "<cwchar>"} }, {"WCHAR_MIN", {"<wchar.h>", "<cwchar>"} } }; - const size_t num_hints = sizeof (hints) / sizeof (hints[0]); + const size_t num_hints = ARRAY_SIZE (hints); for (size_t i = 0; i < num_hints; i++) if (strcmp (name, hints[i].name) == 0) return hints[i].header[lib]; |