aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-family
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2022-07-27 10:15:41 -0700
committerIan Lance Taylor <iant@golang.org>2022-07-27 10:15:41 -0700
commit9f62ed218fa656607740b386c0caa03e65dcd283 (patch)
tree6bde49bc5e4c4241266b108e4277baef4b85535d /gcc/c-family
parent71e955da39cea0ebffcfee3432effa622d14ca99 (diff)
parent5eb9f117a361538834b9740d59219911680717d1 (diff)
downloadgcc-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/ChangeLog345
-rw-r--r--gcc/c-family/c-ada-spec.cc123
-rw-r--r--gcc/c-family/c-attribs.cc87
-rw-r--r--gcc/c-family/c-common.cc42
-rw-r--r--gcc/c-family/c-common.h16
-rw-r--r--gcc/c-family/c-format.cc99
-rw-r--r--gcc/c-family/c-gimplify.cc6
-rw-r--r--gcc/c-family/c-omp.cc40
-rw-r--r--gcc/c-family/c-opts.cc39
-rw-r--r--gcc/c-family/c-ppoutput.cc78
-rw-r--r--gcc/c-family/c-pragma.cc458
-rw-r--r--gcc/c-family/c-pragma.h16
-rw-r--r--gcc/c-family/c-pretty-print.cc6
-rw-r--r--gcc/c-family/c-pretty-print.h2
-rw-r--r--gcc/c-family/c-target.def2
-rw-r--r--gcc/c-family/c-ubsan.cc118
-rw-r--r--gcc/c-family/c-warn.cc31
-rw-r--r--gcc/c-family/c.opt42
-rw-r--r--gcc/c-family/known-headers.cc19
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 = &registered_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 = &registered_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];