diff options
author | David Malcolm <dmalcolm@redhat.com> | 2018-08-20 21:06:46 +0000 |
---|---|---|
committer | David Malcolm <dmalcolm@gcc.gnu.org> | 2018-08-20 21:06:46 +0000 |
commit | 097f82ec9d19ccb5420c8df98cf35e1898b4fdab (patch) | |
tree | 083d8bf17b0bcd664af40648942c7c901ba1ed58 /gcc/cp | |
parent | a31505a339c847f0073c0ce9223a2b3c9bec6cef (diff) | |
download | gcc-097f82ec9d19ccb5420c8df98cf35e1898b4fdab.zip gcc-097f82ec9d19ccb5420c8df98cf35e1898b4fdab.tar.gz gcc-097f82ec9d19ccb5420c8df98cf35e1898b4fdab.tar.bz2 |
Add support for grouping of related diagnostics (PR other/84889)
We often emit logically-related groups of diagnostics.
A relatively simple case is this:
if (warning_at (body_loc, OPT_Wmultistatement_macros,
"macro expands to multiple statements"))
inform (guard_loc, "some parts of macro expansion are not guarded by "
"this %qs clause", guard_tinfo_to_string (keyword));
where the "note" diagnostic issued by the "inform" call
is guarded by the -Wmultistatement_macros warning.
More complicated examples can be seen in the C++ frontend,
where e.g. print_z_candidates can lead to numerous "note"
diagnostics being emitted.
I'm looking at various ways to improve how we handle such related
diagnostics, but, prior to this patch, there was no explicit
relationship between these diagnostics: the diagnostics subsystem
had no way of "knowing" that these were related.
This patch introduces a simple way to group the diagnostics:
an auto_diagnostic_group class: all diagnostics emitted within
the lifetime of an auto_diagnostic_group instance are logically
grouped.
Hence in the above example, the two diagnostics can be grouped
by simply adding an auto_diagnostic_group instance:
auto_diagnostic_group d;
if (warning_at (body_loc, OPT_Wmultistatement_macros,
"macro expands to multiple statements"))
inform (guard_loc, "some parts of macro expansion are not guarded by "
"this %qs clause", guard_tinfo_to_string (keyword));
Some more awkard cases are of the form:
if (some_condition
&& warning_at (...)
&& more_conditions)
inform (...);
which thus need restructuring to:
if (some_condition)
{
auto_diagnostic_group d;
warning_at (...);
if (more_conditions)
inform (...);
}
so that the lifetime of the auto_diagnostic_group groups the
warning_at and the inform call.
Nesting is handled by simply tracking a nesting depth within the
diagnostic_context.: all diagnostics are treated as grouped until the
final auto_diagnostic_group is popped.
diagnostic.c uses this internally, so that all diagnostics are part of
a group - those that are "by themselves" are treated as being part of
a group with one element.
The diagnostic_context gains optional callbacks for displaying the
start of a group (when the first diagnostic is emitted within it), and
the end of a group (for when the group was non-empty); these callbacks
are unused by default, but a test plugin demonstrates them (and verifies
that the machinery is working).
As noted above, I'm looking at various ways to use the grouping to
improve how we output the diagnostics.
FWIW, I experimented with a more involved implementation, of the form:
diagnostic_group d;
if (d.warning_at (body_loc, OPT_Wmultistatement_macros,
"macro expands to multiple statements"))
d.inform (guard_loc, "some parts of macro expansion are not guarded by "
"this %qs clause", guard_tinfo_to_string (keyword));
which had the advantage of allowing auto-detection of the places where
groups were needed (by converting ::warning_at's return type to bool),
but it was a much more invasive patch, especially when dealing with
the places in the C++ frontend that can emit numerous notes after
an error or warning (and thus having to pass the group around)
Hence I went with this simpler approach.
gcc/c-family/ChangeLog:
PR other/84889
* c-attribs.c (common_handle_aligned_attribute): Add
auto_diagnostic_group instance.
* c-indentation.c (warn_for_misleading_indentation): Likewise.
* c-opts.c (c_common_post_options): Likewise.
* c-warn.c (warn_logical_not_parentheses): Likewise.
(warn_duplicated_cond_add_or_warn): Likewise.
(warn_for_multistatement_macros): Likewise.
gcc/c/ChangeLog:
PR other/84889
* c-decl.c (pushtag): Add auto_diagnostic_group instance.
(diagnose_mismatched_decls): Likewise, in various places.
(warn_if_shadowing): Likewise.
(implicit_decl_warning): Likewise.
(implicitly_declare): Likewise.
(undeclared_variable): Likewise.
(declare_label): Likewise.
(grokdeclarator): Likewise.
(start_function): Likewise.
* c-parser.c (c_parser_declaration_or_fndef): Likewise.
(c_parser_parameter_declaration): Likewise.
(c_parser_binary_expression): Likewise.
* c-typeck.c (c_expr_sizeof_expr): Likewise.
(parser_build_binary_op): Likewise.
(build_unary_op): Likewise.
(error_init): Likewise.
(pedwarn_init): Likewise.
(warning_init): Likewise.
(convert_for_assignment): Likewise.
gcc/cp/ChangeLog:
PR other/84889
* call.c (build_user_type_conversion_1): Add auto_diagnostic_group
instance(s).
(print_error_for_call_failure): Likewise.
(build_op_call_1): Likewise.
(build_conditional_expr_1): Likewise.
(build_new_op_1): Likewise.
(build_op_delete_call): Likewise.
(convert_like_real): Likewise.
(build_over_call): Likewise.
(build_new_method_call_1): Likewise.
(joust): Likewise.
* class.c (check_tag): Likewise.
(finish_struct_anon_r): Likewise.
(one_inherited_ctor): Likewise.
(finalize_literal_type_property): Likewise.
(explain_non_literal_class): Likewise.
(find_flexarrays): Likewise.
(resolve_address_of_overloaded_function): Likewise.
* constexpr.c (ensure_literal_type_for_constexpr_object): Likewise.
(is_valid_constexpr_fn): Likewise.
(cx_check_missing_mem_inits): Likewise.
* cp-gimplify.c (cp_genericize_r): Likewise.
* cvt.c (maybe_warn_nodiscard): Likewise.
* decl.c (warn_extern_redeclared_static): Likewise.
(check_redeclaration_exception_specification): Likewise.
(check_no_redeclaration_friend_default_args): Likewise.
(duplicate_decls): Likewise.
(redeclaration_error_message): Likewise.
(warn_misplaced_attr_for_class_type): Likewise.
* decl2.c (finish_static_data_member_decl): Likewise.
(no_linkage_error): Likewise.
(cp_warn_deprecated_use): Likewise.
* error.c (qualified_name_lookup_error): Likewise.
* friend.c (make_friend_class): Likewise.
(do_friend): Likewise.
* init.c (perform_member_init): Likewise.
(build_new_1): Likewise.
(build_vec_delete_1): Likewise.
(build_delete): Likewise.
* lex.c (unqualified_name_lookup_error): Likewise.
* name-lookup.c (check_extern_c_conflict): Likewise.
(inform_shadowed): New function.
(check_local_shadow): Add auto_diagnostic_group instances,
replacing goto "inform_shadowed" label with call to subroutine.
(set_local_extern_decl_linkage): Add auto_diagnostic_group
instance(s).
* parser.c (cp_parser_diagnose_invalid_type_name): Likewise.
(cp_parser_namespace_name): Likewise.
* pt.c (check_specialization_namespace): Likewise.
(check_template_variable): Likewise.
(warn_spec_missing_attributes): Likewise.
(check_explicit_specialization): Likewise.
(process_partial_specialization): Likewise.
(lookup_template_class_1): Likewise.
(finish_template_variable): Likewise.
(do_auto_deduction): Likewise.
* search.c (check_final_overrider): Likewise.
(look_for_overrides_r): Likewise.
* tree.c (maybe_warn_parm_abi): Likewise.
* typeck.c (cxx_sizeof_expr): Likewise.
(cp_build_function_call_vec): Likewise.
(cp_build_binary_op): Likewise.
(convert_for_assignment): Likewise.
(maybe_warn_about_returning_address_of_local): Likewise.
* typeck2.c (abstract_virtuals_error_sfinae): Likewise.
(check_narrowing): Likewise.
gcc/ChangeLog:
PR other/84889
* attribs.c (diag_attr_exclusions): Add auto_diagnostic_group instance.
(decl_attributes): Likewise.
* calls.c (maybe_warn_nonstring_arg): Add auto_diagnostic_group
instance.
* cgraphunit.c (maybe_diag_incompatible_alias): Likewise.
* diagnostic-core.h (class auto_diagnostic_group): New class.
* diagnostic.c (diagnostic_initialize): Initialize the new fields.
(diagnostic_report_diagnostic): Handle the first diagnostics within
a group.
(emit_diagnostic): Add auto_diagnostic_group instance.
(inform): Likewise.
(inform_n): Likewise.
(warning): Likewise.
(warning_at): Likewise.
(warning_n): Likewise.
(pedwarn): Likewise.
(permerror): Likewise.
(error): Likewise.
(error_n): Likewise.
(error_at): Likewise.
(sorry): Likewise.
(fatal_error): Likewise.
(internal_error): Likewise.
(internal_error_no_backtrace): Likewise.
(auto_diagnostic_group::auto_diagnostic_group): New ctor.
(auto_diagnostic_group::~auto_diagnostic_group): New dtor.
* diagnostic.h (struct diagnostic_context): Add fields
"diagnostic_group_nesting_depth",
"diagnostic_group_emission_count", "begin_group_cb",
"end_group_cb".
* gimple-ssa-isolate-paths.c (find_implicit_erroneous_behavior):
Add auto_diagnostic_group instance(s).
(find_explicit_erroneous_behavior): Likewise.
* gimple-ssa-warn-alloca.c (pass_walloca::execute): Likewise.
* gimple-ssa-warn-restrict.c (maybe_diag_offset_bounds): Likewise.
* gimplify.c (warn_implicit_fallthrough_r): Likewise.
(gimplify_va_arg_expr): Likewise.
* hsa-gen.c (HSA_SORRY_ATV): Likewise.
(HSA_SORRY_AT): Likewise.
* ipa-devirt.c (compare_virtual_tables): Likewise.
(warn_odr): Likewise.
* multiple_target.c (expand_target_clones): Likewise.
* opts-common.c (cmdline_handle_error): Likewise.
* reginfo.c (globalize_reg): Likewise.
* substring-locations.c (format_warning_n_va): Likewise.
* tree-inline.c (expand_call_inline): Likewise.
* tree-ssa-ccp.c (pass_post_ipa_warn::execute): Likewise.
* tree-ssa-loop-niter.c
(do_warn_aggressive_loop_optimizations): Likewise.
* tree-ssa-uninit.c (warn_uninit): Likewise.
* tree.c (warn_deprecated_use): Likewise.
gcc/testsuite/ChangeLog:
PR other/84889
* gcc.dg/plugin/diagnostic-group-test-1.c: New test.
* gcc.dg/plugin/diagnostic_group_plugin.c: New test.
* gcc.dg/plugin/plugin.exp (plugin_test_list): Add the new tests.
From-SVN: r263675
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 70 | ||||
-rw-r--r-- | gcc/cp/call.c | 29 | ||||
-rw-r--r-- | gcc/cp/class.c | 75 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 21 | ||||
-rw-r--r-- | gcc/cp/cp-gimplify.c | 15 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 3 | ||||
-rw-r--r-- | gcc/cp/decl.c | 28 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 3 | ||||
-rw-r--r-- | gcc/cp/error.c | 2 | ||||
-rw-r--r-- | gcc/cp/friend.c | 4 | ||||
-rw-r--r-- | gcc/cp/init.c | 48 | ||||
-rw-r--r-- | gcc/cp/lex.c | 1 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 35 | ||||
-rw-r--r-- | gcc/cp/parser.c | 6 | ||||
-rw-r--r-- | gcc/cp/pt.c | 8 | ||||
-rw-r--r-- | gcc/cp/search.c | 10 | ||||
-rw-r--r-- | gcc/cp/tree.c | 2 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 49 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 2 |
19 files changed, 310 insertions, 101 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d8be9308..28c0974 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,73 @@ +2018-08-20 David Malcolm <dmalcolm@redhat.com> + + PR other/84889 + * call.c (build_user_type_conversion_1): Add auto_diagnostic_group + instance(s). + (print_error_for_call_failure): Likewise. + (build_op_call_1): Likewise. + (build_conditional_expr_1): Likewise. + (build_new_op_1): Likewise. + (build_op_delete_call): Likewise. + (convert_like_real): Likewise. + (build_over_call): Likewise. + (build_new_method_call_1): Likewise. + (joust): Likewise. + * class.c (check_tag): Likewise. + (finish_struct_anon_r): Likewise. + (one_inherited_ctor): Likewise. + (finalize_literal_type_property): Likewise. + (explain_non_literal_class): Likewise. + (find_flexarrays): Likewise. + (resolve_address_of_overloaded_function): Likewise. + * constexpr.c (ensure_literal_type_for_constexpr_object): Likewise. + (is_valid_constexpr_fn): Likewise. + (cx_check_missing_mem_inits): Likewise. + * cp-gimplify.c (cp_genericize_r): Likewise. + * cvt.c (maybe_warn_nodiscard): Likewise. + * decl.c (warn_extern_redeclared_static): Likewise. + (check_redeclaration_exception_specification): Likewise. + (check_no_redeclaration_friend_default_args): Likewise. + (duplicate_decls): Likewise. + (redeclaration_error_message): Likewise. + (warn_misplaced_attr_for_class_type): Likewise. + * decl2.c (finish_static_data_member_decl): Likewise. + (no_linkage_error): Likewise. + (cp_warn_deprecated_use): Likewise. + * error.c (qualified_name_lookup_error): Likewise. + * friend.c (make_friend_class): Likewise. + (do_friend): Likewise. + * init.c (perform_member_init): Likewise. + (build_new_1): Likewise. + (build_vec_delete_1): Likewise. + (build_delete): Likewise. + * lex.c (unqualified_name_lookup_error): Likewise. + * name-lookup.c (check_extern_c_conflict): Likewise. + (inform_shadowed): New function. + (check_local_shadow): Add auto_diagnostic_group instances, + replacing goto "inform_shadowed" label with call to subroutine. + (set_local_extern_decl_linkage): Add auto_diagnostic_group + instance(s). + * parser.c (cp_parser_diagnose_invalid_type_name): Likewise. + (cp_parser_namespace_name): Likewise. + * pt.c (check_specialization_namespace): Likewise. + (check_template_variable): Likewise. + (warn_spec_missing_attributes): Likewise. + (check_explicit_specialization): Likewise. + (process_partial_specialization): Likewise. + (lookup_template_class_1): Likewise. + (finish_template_variable): Likewise. + (do_auto_deduction): Likewise. + * search.c (check_final_overrider): Likewise. + (look_for_overrides_r): Likewise. + * tree.c (maybe_warn_parm_abi): Likewise. + * typeck.c (cxx_sizeof_expr): Likewise. + (cp_build_function_call_vec): Likewise. + (cp_build_binary_op): Likewise. + (convert_for_assignment): Likewise. + (maybe_warn_about_returning_address_of_local): Likewise. + * typeck2.c (abstract_virtuals_error_sfinae): Likewise. + (check_narrowing): Likewise. + 2018-08-17 David Malcolm <dmalcolm@redhat.com> * typeck.c (string_conv_p): Extract location from EXP and use it diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 16bb6bf..1f72ac8 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -3968,6 +3968,7 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags, { if (complain & tf_error) { + auto_diagnostic_group d; error ("conversion from %qH to %qI is ambiguous", fromtype, totype); print_z_candidates (location_of (expr), candidates); @@ -4280,6 +4281,7 @@ print_error_for_call_failure (tree fn, vec<tree, va_gc> *args, if (targs) name = lookup_template_function (name, targs); + auto_diagnostic_group d; if (!any_strictly_viable (candidates)) error_at (loc, "no matching function for call to %<%D(%A)%>", name, build_tree_list_vec (args)); @@ -4590,6 +4592,7 @@ build_op_call_1 (tree obj, vec<tree, va_gc> **args, tsubst_flags_t complain) { if (complain & tf_error) { + auto_diagnostic_group d; error ("no match for call to %<(%T) (%A)%>", TREE_TYPE (obj), build_tree_list_vec (*args)); print_z_candidates (location_of (TREE_TYPE (obj)), candidates); @@ -4603,6 +4606,7 @@ build_op_call_1 (tree obj, vec<tree, va_gc> **args, tsubst_flags_t complain) { if (complain & tf_error) { + auto_diagnostic_group d; error ("call of %<(%T) (%A)%> is ambiguous", TREE_TYPE (obj), build_tree_list_vec (*args)); print_z_candidates (location_of (TREE_TYPE (obj)), candidates); @@ -5229,6 +5233,7 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3, { if (complain & tf_error) { + auto_diagnostic_group d; op_error (loc, COND_EXPR, NOP_EXPR, arg1, arg2, arg3, FALSE); print_z_candidates (loc, candidates); } @@ -5860,6 +5865,7 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1, { /* ... Otherwise, report the more generic "no matching operator found" error */ + auto_diagnostic_group d; op_error (loc, code, code2, arg1, arg2, arg3, FALSE); print_z_candidates (loc, candidates); } @@ -5875,6 +5881,7 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1, { if (complain & tf_error) { + auto_diagnostic_group d; op_error (loc, code, code2, arg1, arg2, arg3, TRUE); print_z_candidates (loc, candidates); } @@ -6311,14 +6318,18 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, -Wc++14-compat. */ else if (!flag_sized_deallocation) { - if ((complain & tf_warning) - && warning (OPT_Wc__14_compat, msg1)) - inform (DECL_SOURCE_LOCATION (fn), msg2, fn); + if (complain & tf_warning) + { + auto_diagnostic_group d; + if (warning (OPT_Wc__14_compat, msg1)) + inform (DECL_SOURCE_LOCATION (fn), msg2, fn); + } goto ok; } if (complain & tf_warning_or_error) { + auto_diagnostic_group d; if (permerror (input_location, msg1)) { /* Only mention C++14 for namespace-scope delete. */ @@ -6712,6 +6723,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, { if (t->kind == ck_user && t->cand->reason) { + auto_diagnostic_group d; complained = permerror (loc, "invalid user-defined conversion " "from %qH to %qI", TREE_TYPE (expr), totype); @@ -6795,6 +6807,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, if (CONSTRUCTOR_NELTS (expr) == 0 && FUNCTION_FIRST_USER_PARMTYPE (convfn) != void_list_node) { + auto_diagnostic_group d; if (pedwarn (loc, 0, "converting to %qT from initializer list " "would use explicit constructor %qD", totype, convfn)) @@ -6973,6 +6986,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, { if (complain & tf_error) { + auto_diagnostic_group d; maybe_print_user_conv_context (convs); if (fn) inform (DECL_SOURCE_LOCATION (fn), @@ -7025,6 +7039,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, expr = build_temp (expr, totype, flags, &diag_kind, complain); if (diag_kind && complain) { + auto_diagnostic_group d; maybe_print_user_conv_context (convs); if (fn) inform (DECL_SOURCE_LOCATION (fn), @@ -7040,6 +7055,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, if (convs->bad_p && !next_conversion (convs)->bad_p) { tree extype = TREE_TYPE (expr); + auto_diagnostic_group d; if (TYPE_REF_IS_RVALUE (ref_type) && lvalue_p (expr)) error_at (loc, "cannot bind rvalue reference of type %qH to " @@ -7931,6 +7947,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) { if (complain & tf_error) { + auto_diagnostic_group d; if (permerror (input_location, "passing %qT as %<this%> " "argument discards qualifiers", TREE_TYPE (argtype))) @@ -9212,6 +9229,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, basetype = DECL_CONTEXT (fn); name = constructor_name (basetype); + auto_diagnostic_group d; if (permerror (input_location, "cannot call constructor %<%T::%D%> directly", basetype, name)) @@ -9350,6 +9368,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, { if (complain & tf_error) { + auto_diagnostic_group d; if (!COMPLETE_OR_OPEN_TYPE_P (basetype)) cxx_incomplete_type_error (instance, basetype); else if (optype) @@ -9393,6 +9412,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, arglist = build_tree_list_vec (user_args); if (skip_first_for_error) arglist = TREE_CHAIN (arglist); + auto_diagnostic_group d; if (!any_strictly_viable (candidates)) error ("no matching function for call to %<%s(%A)%>", pretty_name, arglist); @@ -10299,6 +10319,7 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn, tree source = source_type (w->convs[0]); if (INDIRECT_TYPE_P (source)) source = TREE_TYPE (source); + auto_diagnostic_group d; if (warning (OPT_Wconversion, "choosing %qD over %qD", w->fn, l->fn) && warning (OPT_Wconversion, " for conversion from %qH to %qI", source, w->second_conv->type)) @@ -10526,6 +10547,7 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn, { if (complain & tf_error) { + auto_diagnostic_group d; if (permerror (input_location, "default argument mismatch in " "overload resolution")) @@ -10577,6 +10599,7 @@ tweak: return 0; if (warn) { + auto_diagnostic_group d; pedwarn (input_location, 0, "ISO C++ says that these are ambiguous, even " "though the worst conversion for the first is better than " diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 7b10b20..e11173d 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1331,6 +1331,7 @@ check_tag (tree tag, tree id, tree *tp, abi_tag_data *p) /* Otherwise we're diagnosing missing tags. */ if (TREE_CODE (p->t) == FUNCTION_DECL) { + auto_diagnostic_group d; if (warning (OPT_Wabi_tag, "%qD inherits the %E ABI tag " "that %qT (used in its return type) has", p->t, tag, *tp)) @@ -1338,12 +1339,14 @@ check_tag (tree tag, tree id, tree *tp, abi_tag_data *p) } else if (VAR_P (p->t)) { + auto_diagnostic_group d; if (warning (OPT_Wabi_tag, "%qD inherits the %E ABI tag " "that %qT (used in its type) has", p->t, tag, *tp)) inform (location_of (*tp), "%qT declared here", *tp); } else if (TYPE_P (p->subob)) { + auto_diagnostic_group d; if (warning (OPT_Wabi_tag, "%qT does not have the %E ABI tag " "that base %qT has", p->t, tag, p->subob)) inform (location_of (p->subob), "%qT declared here", @@ -1351,6 +1354,7 @@ check_tag (tree tag, tree id, tree *tp, abi_tag_data *p) } else { + auto_diagnostic_group d; if (warning (OPT_Wabi_tag, "%qT does not have the %E ABI tag " "that %qT (used in the type of %qD) has", p->t, tag, *tp, p->subob)) @@ -2904,20 +2908,24 @@ finish_struct_anon_r (tree field, bool complain) { /* We already complained about static data members in finish_static_data_member_decl. */ - if (!VAR_P (elt) - && permerror (DECL_SOURCE_LOCATION (elt), - TREE_CODE (TREE_TYPE (field)) == UNION_TYPE - ? "%q#D invalid; an anonymous union may " - "only have public non-static data members" - : "%q#D invalid; an anonymous struct may " - "only have public non-static data members", elt)) + if (!VAR_P (elt)) { - static bool hint; - if (flag_permissive && !hint) + auto_diagnostic_group d; + if (permerror (DECL_SOURCE_LOCATION (elt), + TREE_CODE (TREE_TYPE (field)) == UNION_TYPE + ? "%q#D invalid; an anonymous union may " + "only have public non-static data members" + : "%q#D invalid; an anonymous struct may " + "only have public non-static data members", elt)) { - hint = true; - inform (DECL_SOURCE_LOCATION (elt), - "this flexibility is deprecated and will be removed"); + static bool hint; + if (flag_permissive && !hint) + { + hint = true; + inform (DECL_SOURCE_LOCATION (elt), + "this flexibility is deprecated and will be " + "removed"); + } } } } @@ -3107,6 +3115,7 @@ one_inherited_ctor (tree ctor, tree t, tree using_decl) one_inheriting_sig (t, ctor, new_parms, i); if (parms == NULL_TREE) { + auto_diagnostic_group d; if (warning (OPT_Winherited_variadic_ctor, "the ellipsis in %qD is not inherited", ctor)) inform (DECL_SOURCE_LOCATION (ctor), "%qD declared here", ctor); @@ -5399,11 +5408,14 @@ finalize_literal_type_property (tree t) && !DECL_CONSTRUCTOR_P (fn)) { DECL_DECLARED_CONSTEXPR_P (fn) = false; - if (!DECL_GENERATED_P (fn) - && pedwarn (DECL_SOURCE_LOCATION (fn), OPT_Wpedantic, - "enclosing class of %<constexpr%> non-static member " - "function %q+#D is not a literal type", fn)) - explain_non_literal_class (t); + if (!DECL_GENERATED_P (fn)) + { + auto_diagnostic_group d; + if (pedwarn (DECL_SOURCE_LOCATION (fn), OPT_Wpedantic, + "enclosing class of %<constexpr%> non-static " + "member function %q+#D is not a literal type", fn)) + explain_non_literal_class (t); + } } } @@ -5425,6 +5437,7 @@ explain_non_literal_class (tree t) /* Already explained. */ return; + auto_diagnostic_group d; inform (UNKNOWN_LOCATION, "%q+T is not literal because:", t); if (cxx_dialect < cxx17 && LAMBDA_TYPE_P (t)) inform (UNKNOWN_LOCATION, @@ -6626,17 +6639,20 @@ find_flexarrays (tree t, flexmems_t *fmem, bool base_p, static void diagnose_invalid_flexarray (const flexmems_t *fmem) { - if (fmem->array && fmem->enclosing - && pedwarn (location_of (fmem->enclosing), OPT_Wpedantic, - TYPE_DOMAIN (TREE_TYPE (fmem->array)) - ? G_("invalid use of %q#T with a zero-size array " - "in %q#D") - : G_("invalid use of %q#T with a flexible array member " - "in %q#T"), - DECL_CONTEXT (fmem->array), - DECL_CONTEXT (fmem->enclosing))) - inform (DECL_SOURCE_LOCATION (fmem->array), - "array member %q#D declared here", fmem->array); + if (fmem->array && fmem->enclosing) + { + auto_diagnostic_group d; + if (pedwarn (location_of (fmem->enclosing), OPT_Wpedantic, + TYPE_DOMAIN (TREE_TYPE (fmem->array)) + ? G_("invalid use of %q#T with a zero-size array " + "in %q#D") + : G_("invalid use of %q#T with a flexible array member " + "in %q#T"), + DECL_CONTEXT (fmem->array), + DECL_CONTEXT (fmem->enclosing))) + inform (DECL_SOURCE_LOCATION (fmem->array), + "array member %q#D declared here", fmem->array); + } } /* Issue diagnostics for invalid flexible array members or zero-length @@ -6671,6 +6687,7 @@ diagnose_flexarrays (tree t, const flexmems_t *fmem) { location_t loc = DECL_SOURCE_LOCATION (fmem->array); + auto_diagnostic_group d; if (pedwarn (loc, OPT_Wpedantic, msg, fmem->array, t)) { inform (location_of (t), "in the definition of %q#T", t); @@ -6690,6 +6707,7 @@ diagnose_flexarrays (tree t, const flexmems_t *fmem) location_t loc = DECL_SOURCE_LOCATION (fmem->array); diagd = true; + auto_diagnostic_group d; error_at (loc, msg, fmem->array, t); /* In the unlikely event that the member following the flexible @@ -7923,6 +7941,7 @@ resolve_address_of_overloaded_function (tree target_type, if (!(complain & tf_error)) return error_mark_node; + auto_diagnostic_group d; if (permerror (input_location, "assuming pointer to member %qD", fn) && !explained) { diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index ece2c8a..54c8b5e 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -97,6 +97,7 @@ ensure_literal_type_for_constexpr_object (tree decl) { if (DECL_DECLARED_CONSTEXPR_P (decl)) { + auto_diagnostic_group d; error ("the type %qT of %<constexpr%> variable %qD " "is not literal", type, decl); explain_non_literal_class (type); @@ -106,6 +107,7 @@ ensure_literal_type_for_constexpr_object (tree decl) { if (!is_instantiation_of_constexpr (current_function_decl)) { + auto_diagnostic_group d; error ("variable %qD of non-literal type %qT in %<constexpr%> " "function", decl, type); explain_non_literal_class (type); @@ -200,6 +202,7 @@ is_valid_constexpr_fn (tree fun, bool complain) ret = false; if (complain) { + auto_diagnostic_group d; error ("invalid type for parameter %d of %<constexpr%> " "function %q+#D", DECL_PARM_INDEX (parm), fun); explain_non_literal_class (TREE_TYPE (parm)); @@ -222,6 +225,7 @@ is_valid_constexpr_fn (tree fun, bool complain) ret = false; if (complain) { + auto_diagnostic_group d; error ("invalid return type %qT of %<constexpr%> function %q+D", rettype, fun); explain_non_literal_class (rettype); @@ -234,11 +238,15 @@ is_valid_constexpr_fn (tree fun, bool complain) && !CLASSTYPE_LITERAL_P (DECL_CONTEXT (fun))) { ret = false; - if (complain - && pedwarn (DECL_SOURCE_LOCATION (fun), OPT_Wpedantic, - "enclosing class of %<constexpr%> non-static member " - "function %q+#D is not a literal type", fun)) - explain_non_literal_class (DECL_CONTEXT (fun)); + if (complain) + { + auto_diagnostic_group d; + if (pedwarn (DECL_SOURCE_LOCATION (fun), OPT_Wpedantic, + "enclosing class of %<constexpr%> non-static" + " member function %q+#D is not a literal type", + fun)) + explain_non_literal_class (DECL_CONTEXT (fun)); + } } } else if (CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fun))) @@ -818,6 +826,7 @@ cx_check_missing_mem_inits (tree ctype, tree body, bool complain) } if (!complain) return true; + auto_diagnostic_group d; error ("member %qD must be initialized by mem-initializer " "in %<constexpr%> constructor", field); inform (DECL_SOURCE_LOCATION (field), "declared here"); @@ -4303,6 +4312,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, { if (!ctx->quiet) { + auto_diagnostic_group d; error ("temporary of non-literal type %qT in a " "constant expression", TREE_TYPE (t)); explain_non_literal_class (TREE_TYPE (t)); @@ -5995,6 +6005,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, { if (flags & tf_error) { + auto_diagnostic_group d; error_at (loc, "temporary of non-literal type %qT in a " "constant expression", TREE_TYPE (t)); explain_non_literal_class (TREE_TYPE (t)); diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 7db4acc..f610991 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -1420,12 +1420,15 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) /* Never mind. */; else if (wtd->try_block) { - if (TREE_CODE (wtd->try_block) == MUST_NOT_THROW_EXPR - && warning_at (loc, OPT_Wterminate, - "throw will always call terminate()") - && cxx_dialect >= cxx11 - && DECL_DESTRUCTOR_P (current_function_decl)) - inform (loc, "in C++11 destructors default to noexcept"); + if (TREE_CODE (wtd->try_block) == MUST_NOT_THROW_EXPR) + { + auto_diagnostic_group d; + if (warning_at (loc, OPT_Wterminate, + "throw will always call terminate()") + && cxx_dialect >= cxx11 + && DECL_DESTRUCTOR_P (current_function_decl)) + inform (loc, "in C++11 destructors default to noexcept"); + } } else { diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index da98414..315b0d6 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -1017,6 +1017,7 @@ maybe_warn_nodiscard (tree expr, impl_conv_void implicit) if (implicit != ICV_CAST && fn && lookup_attribute ("nodiscard", DECL_ATTRIBUTES (fn))) { + auto_diagnostic_group d; if (warning_at (loc, OPT_Wunused_result, "ignoring return value of %qD, " "declared with attribute nodiscard", fn)) @@ -1025,6 +1026,7 @@ maybe_warn_nodiscard (tree expr, impl_conv_void implicit) else if (implicit != ICV_CAST && lookup_attribute ("nodiscard", TYPE_ATTRIBUTES (rettype))) { + auto_diagnostic_group d; if (warning_at (loc, OPT_Wunused_result, "ignoring returned value of type %qT, " "declared with attribute nodiscard", rettype)) @@ -1043,6 +1045,7 @@ maybe_warn_nodiscard (tree expr, impl_conv_void implicit) result is used, so handle that case here. */ if (fn) { + auto_diagnostic_group d; if (warning_at (loc, OPT_Wunused_result, "ignoring return value of %qD, " "declared with attribute warn_unused_result", diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index fa58bc4..f6dbd6b 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -1133,6 +1133,7 @@ warn_extern_redeclared_static (tree newdecl, tree olddecl) && DECL_ARTIFICIAL (olddecl)) return; + auto_diagnostic_group d; if (permerror (DECL_SOURCE_LOCATION (newdecl), "%qD was declared %<extern%> and later %<static%>", newdecl)) inform (DECL_SOURCE_LOCATION (olddecl), @@ -1176,6 +1177,7 @@ check_redeclaration_exception_specification (tree new_decl, = G_("declaration of %qF has a different exception specifier"); bool complained = true; location_t new_loc = DECL_SOURCE_LOCATION (new_decl); + auto_diagnostic_group d; if (DECL_IN_SYSTEM_HEADER (old_decl)) complained = pedwarn (new_loc, OPT_Wsystem_headers, msg, new_decl); else if (!flag_exceptions) @@ -1304,6 +1306,7 @@ check_no_redeclaration_friend_default_args (tree olddecl, tree newdecl, if ((olddecl_hidden_friend_p && TREE_PURPOSE (t1)) || (DECL_FRIEND_P (newdecl) && TREE_PURPOSE (t2))) { + auto_diagnostic_group d; if (permerror (DECL_SOURCE_LOCATION (newdecl), "friend declaration of %q#D specifies default " "arguments and isn't the only declaration", newdecl)) @@ -1555,6 +1558,7 @@ next_arg:; "declaration %q#D", newdecl, olddecl); return error_mark_node; } + auto_diagnostic_group d; if (permerror (newdecl_loc, "new declaration %q#D ambiguates built-in" " declaration %q#D", newdecl, olddecl) @@ -1801,6 +1805,7 @@ next_arg:; const char *errmsg = redeclaration_error_message (newdecl, olddecl); if (errmsg) { + auto_diagnostic_group d; error_at (newdecl_loc, errmsg, newdecl); if (DECL_NAME (olddecl) != NULL_TREE) inform (olddecl_loc, @@ -1815,6 +1820,7 @@ next_arg:; && prototype_p (TREE_TYPE (newdecl))) { /* Prototype decl follows defn w/o prototype. */ + auto_diagnostic_group d; if (warning_at (newdecl_loc, 0, "prototype specified for %q#D", newdecl)) inform (olddecl_loc, @@ -1856,6 +1862,7 @@ next_arg:; } else { + auto_diagnostic_group d; error_at (newdecl_loc, "conflicting declaration of %q#D with %qL linkage", newdecl, DECL_LANGUAGE (newdecl)); @@ -1893,6 +1900,7 @@ next_arg:; if (simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2)) == 1) { + auto_diagnostic_group d; if (permerror (newdecl_loc, "default argument given for parameter " "%d of %q#D", i, newdecl)) @@ -1902,6 +1910,7 @@ next_arg:; } else { + auto_diagnostic_group d; error_at (newdecl_loc, "default argument given for parameter %d " "of %q#D", i, newdecl); @@ -1977,6 +1986,7 @@ next_arg:; && (! DECL_TEMPLATE_SPECIALIZATION (newdecl) || DECL_TEMPLATE_SPECIALIZATION (olddecl))) { + auto_diagnostic_group d; if (warning_at (newdecl_loc, OPT_Wredundant_decls, "redundant redeclaration of %qD in same scope", @@ -1990,6 +2000,7 @@ next_arg:; { if (DECL_DELETED_FN (newdecl)) { + auto_diagnostic_group d; error_at (newdecl_loc, "deleted definition of %qD", newdecl); inform (olddecl_loc, "previous declaration of %qD", olddecl); @@ -2567,6 +2578,7 @@ next_arg:; && DECL_VISIBILITY_SPECIFIED (newdecl) && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl)) { + auto_diagnostic_group d; if (warning_at (newdecl_loc, OPT_Wattributes, "%qD: visibility attribute ignored because it " "conflicts with previous declaration", newdecl)) @@ -2986,12 +2998,15 @@ redeclaration_error_message (tree newdecl, tree olddecl) { DECL_EXTERNAL (newdecl) = 1; /* For now, only warn with explicit -Wdeprecated. */ - if (global_options_set.x_warn_deprecated - && warning_at (DECL_SOURCE_LOCATION (newdecl), OPT_Wdeprecated, - "redundant redeclaration of %<constexpr%> static " - "data member %qD", newdecl)) - inform (DECL_SOURCE_LOCATION (olddecl), - "previous declaration of %qD", olddecl); + if (global_options_set.x_warn_deprecated) + { + auto_diagnostic_group d; + if (warning_at (DECL_SOURCE_LOCATION (newdecl), OPT_Wdeprecated, + "redundant redeclaration of %<constexpr%> " + "static data member %qD", newdecl)) + inform (DECL_SOURCE_LOCATION (olddecl), + "previous declaration of %qD", olddecl); + } return NULL; } @@ -4753,6 +4768,7 @@ warn_misplaced_attr_for_class_type (source_location location, { gcc_assert (OVERLOAD_TYPE_P (class_type)); + auto_diagnostic_group d; if (warning_at (location, OPT_Wattributes, "attribute ignored in declaration " "of %q#T", class_type)) diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index d67ced0..a5ad0ee 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -764,6 +764,7 @@ finish_static_data_member_decl (tree decl, t = CP_TYPE_CONTEXT (t)) if (TYPE_UNNAMED_P (t)) { + auto_diagnostic_group d; if (permerror (DECL_SOURCE_LOCATION (decl), "static data member %qD in unnamed class", decl)) inform (DECL_SOURCE_LOCATION (TYPE_NAME (t)), @@ -4287,6 +4288,7 @@ no_linkage_error (tree decl) else if (TYPE_UNNAMED_P (t)) { bool d = false; + auto_diagnostic_group grp; if (cxx_dialect >= cxx11) d = permerror (DECL_SOURCE_LOCATION (decl), "%q#D, declared using " "unnamed type, is used but never defined", decl); @@ -5208,6 +5210,7 @@ cp_warn_deprecated_use (tree decl, tsubst_flags_t complain) && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl) && copy_fn_p (decl)) { + auto_diagnostic_group d; /* Don't warn about system library classes (c++/86342). */ if (!DECL_IN_SYSTEM_HEADER (decl)) warned = warning (OPT_Wdeprecated_copy, diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 355a5e8..452ecb9 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -4270,12 +4270,14 @@ qualified_name_lookup_error (tree scope, tree name, } else if (scope != global_namespace) { + auto_diagnostic_group d; error_at (location, "%qD is not a member of %qD", name, scope); if (!suggest_alternative_in_explicit_scope (location, name, scope)) suggest_alternatives_for (location, name, false); } else { + auto_diagnostic_group d; error_at (location, "%<::%D%> has not been declared", name); suggest_alternatives_for (location, name, true); } diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index 2c9c12f..ce85a80 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -304,6 +304,7 @@ make_friend_class (tree type, tree friend_type, bool complain) if (TYPE_TEMPLATE_INFO (friend_type) && !PRIMARY_TEMPLATE_P (TYPE_TI_TEMPLATE (friend_type))) { + auto_diagnostic_group d; error ("%qT is not a template", friend_type); inform (location_of (friend_type), "previous declaration here"); if (TYPE_CLASS_SCOPE_P (friend_type) @@ -384,6 +385,7 @@ make_friend_class (tree type, tree friend_type, bool complain) } if (template_member_p && !DECL_CLASS_TEMPLATE_P (decl)) { + auto_diagnostic_group d; error ("%qT is not a member class template of %qT", name, ctype); inform (DECL_SOURCE_LOCATION (decl), @@ -393,6 +395,7 @@ make_friend_class (tree type, tree friend_type, bool complain) if (!template_member_p && (TREE_CODE (decl) != TYPE_DECL || !CLASS_TYPE_P (TREE_TYPE (decl)))) { + auto_diagnostic_group d; error ("%qT is not a nested class of %qT", name, ctype); inform (DECL_SOURCE_LOCATION (decl), @@ -636,6 +639,7 @@ do_friend (tree ctype, tree declarator, tree decl, static int explained; bool warned; + auto_diagnostic_group d; warned = warning (OPT_Wnon_template_friend, "friend declaration " "%q#D declares a non-template function", decl); if (! explained && warned) diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 94f8fdd..15046b4 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -915,6 +915,7 @@ perform_member_init (tree member, tree init) { /* TYPE_NEEDS_CONSTRUCTING can be set just because we have a vtable; still give this diagnostic. */ + auto_diagnostic_group d; if (permerror (DECL_SOURCE_LOCATION (current_function_decl), "uninitialized const member in %q#T", type)) inform (DECL_SOURCE_LOCATION (member), @@ -932,6 +933,7 @@ perform_member_init (tree member, tree init) /* member traversal: note it leaves init NULL */ if (TYPE_REF_P (type)) { + auto_diagnostic_group d; if (permerror (DECL_SOURCE_LOCATION (current_function_decl), "uninitialized reference member in %q#T", type)) inform (DECL_SOURCE_LOCATION (member), @@ -939,6 +941,7 @@ perform_member_init (tree member, tree init) } else if (CP_TYPE_CONST_P (type)) { + auto_diagnostic_group d; if (permerror (DECL_SOURCE_LOCATION (current_function_decl), "uninitialized const member in %q#T", type)) inform (DECL_SOURCE_LOCATION (member), @@ -3255,6 +3258,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, || CP_DECL_CONTEXT (alloc_fn) == global_namespace) && !aligned_allocation_fn_p (alloc_fn)) { + auto_diagnostic_group d; if (warning (OPT_Waligned_new_, "%<new%> of type %qT with extended " "alignment %d", elt_type, TYPE_ALIGN_UNIT (elt_type))) { @@ -3831,16 +3835,19 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, if (!COMPLETE_TYPE_P (type)) { - if ((complain & tf_warning) - && warning (OPT_Wdelete_incomplete, - "possible problem detected in invocation of " - "delete [] operator:")) - { - cxx_incomplete_type_diagnostic (base, type, DK_WARNING); - inform (input_location, "neither the destructor nor the " - "class-specific operator delete [] will be called, " - "even if they are declared when the class is defined"); - } + if (complain & tf_warning) + { + auto_diagnostic_group d; + if (warning (OPT_Wdelete_incomplete, + "possible problem detected in invocation of " + "delete [] operator:")) + { + cxx_incomplete_type_diagnostic (base, type, DK_WARNING); + inform (input_location, "neither the destructor nor the " + "class-specific operator delete [] will be called, " + "even if they are declared when the class is defined"); + } + } /* This size won't actually be used. */ size_exp = size_one_node; goto no_destructor; @@ -4712,16 +4719,19 @@ build_delete (tree otype, tree addr, special_function_kind auto_delete, complete_type (type); if (!COMPLETE_TYPE_P (type)) { - if ((complain & tf_warning) - && warning (OPT_Wdelete_incomplete, - "possible problem detected in invocation of " - "delete operator:")) + if (complain & tf_warning) { - cxx_incomplete_type_diagnostic (addr, type, DK_WARNING); - inform (input_location, - "neither the destructor nor the class-specific " - "operator delete will be called, even if they are " - "declared when the class is defined"); + auto_diagnostic_group d; + if (warning (OPT_Wdelete_incomplete, + "possible problem detected in invocation of " + "delete operator:")) + { + cxx_incomplete_type_diagnostic (addr, type, DK_WARNING); + inform (input_location, + "neither the destructor nor the class-specific " + "operator delete will be called, even if they " + "are declared when the class is defined"); + } } } else if (deleting && warn_delnonvdtor diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index bd5d507..47b99c3 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -499,6 +499,7 @@ unqualified_name_lookup_error (tree name, location_t loc) { if (!objc_diagnose_private_ivar (name)) { + auto_diagnostic_group d; error_at (loc, "%qD was not declared in this scope", name); suggest_alternatives_for (loc, name, true); } diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 3ba7644..8c7f685 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -2556,6 +2556,7 @@ check_extern_c_conflict (tree decl) if (mismatch) { + auto_diagnostic_group d; pedwarn (input_location, 0, "conflicting C language linkage declaration %q#D", decl); inform (DECL_SOURCE_LOCATION (old), @@ -2604,6 +2605,15 @@ c_linkage_bindings (tree name) return NULL_TREE; } +/* Subroutine of check_local_shadow. */ + +static void +inform_shadowed (tree shadowed) +{ + inform (DECL_SOURCE_LOCATION (shadowed), + "shadowed declaration is here"); +} + /* DECL is being declared at a local scope. Emit suitable shadow warnings. */ @@ -2631,7 +2641,6 @@ check_local_shadow (tree decl) old_scope = binding->scope; } - tree shadowed = NULL_TREE; if (old && (TREE_CODE (old) == PARM_DECL || VAR_P (old) @@ -2702,6 +2711,7 @@ check_local_shadow (tree decl) && old_scope == current_binding_level->level_chain && (old_scope->kind == sk_cond || old_scope->kind == sk_for)) { + auto_diagnostic_group d; error ("redeclaration of %q#D", decl); inform (DECL_SOURCE_LOCATION (old), "%q#D previously declared here", old); @@ -2724,6 +2734,7 @@ check_local_shadow (tree decl) || current_binding_level->level_chain->kind == sk_catch) && in_function_try_handler)) { + auto_diagnostic_group d; if (permerror (input_location, "redeclaration of %q#D", decl)) inform (DECL_SOURCE_LOCATION (old), "%q#D previously declared here", old); @@ -2764,11 +2775,9 @@ check_local_shadow (tree decl) else msg = "declaration of %qD shadows a previous local"; + auto_diagnostic_group d; if (warning_at (input_location, warning_code, msg, decl)) - { - shadowed = old; - goto inform_shadowed; - } + inform_shadowed (old); return; } @@ -2793,14 +2802,12 @@ check_local_shadow (tree decl) || TYPE_PTRFN_P (TREE_TYPE (decl)) || TYPE_PTRMEMFUNC_P (TREE_TYPE (decl))) { + auto_diagnostic_group d; if (warning_at (input_location, OPT_Wshadow, "declaration of %qD shadows a member of %qT", decl, current_nonlambda_class_type ()) && DECL_P (member)) - { - shadowed = member; - goto inform_shadowed; - } + inform_shadowed (member); } return; } @@ -2815,20 +2822,15 @@ check_local_shadow (tree decl) && !instantiating_current_function_p ()) /* XXX shadow warnings in outer-more namespaces */ { + auto_diagnostic_group d; if (warning_at (input_location, OPT_Wshadow, "declaration of %qD shadows a global declaration", decl)) - { - shadowed = old; - goto inform_shadowed; - } + inform_shadowed (old); return; } return; - - inform_shadowed: - inform (DECL_SOURCE_LOCATION (shadowed), "shadowed declaration is here"); } /* DECL is being pushed inside function CTX. Set its context, if @@ -2954,6 +2956,7 @@ set_local_extern_decl_linkage (tree decl, bool shadowed) && !comptypes (TREE_TYPE (decl), TREE_TYPE (other), COMPARE_REDECLARATION))) { + auto_diagnostic_group d; if (permerror (DECL_SOURCE_LOCATION (decl), "local external declaration %q#D", decl)) inform (DECL_SOURCE_LOCATION (other), diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 8cfcd15..aa5286b 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -3280,6 +3280,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id, to specify an argument list. Emit a useful error message. */ if (DECL_TYPE_TEMPLATE_P (decl)) { + auto_diagnostic_group d; error_at (location, "invalid use of template-name %qE without an argument list", decl); @@ -3296,6 +3297,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id, else if (!parser->scope) { /* Issue an error message. */ + auto_diagnostic_group d; name_hint hint; if (TREE_CODE (id) == IDENTIFIER_NODE) hint = lookup_name_fuzzy (id, FUZZY_LOOKUP_TYPENAME, location); @@ -3370,6 +3372,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id, { if (TREE_CODE (parser->scope) == NAMESPACE_DECL) { + auto_diagnostic_group d; if (cp_lexer_next_token_is (parser->lexer, CPP_LESS)) error_at (location_of (id), "%qE in namespace %qE does not name a template type", @@ -3392,6 +3395,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id, && constructor_name_p (id, parser->scope)) { /* A<T>::A<T>() */ + auto_diagnostic_group d; error_at (location, "%<%T::%E%> names the constructor, not" " the type", parser->scope, id); if (cp_lexer_next_token_is (parser->lexer, CPP_LESS)) @@ -3417,6 +3421,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id, } else if (TYPE_P (parser->scope)) { + auto_diagnostic_group d; if (!COMPLETE_TYPE_P (parser->scope)) cxx_incomplete_type_error (location_of (id), NULL_TREE, parser->scope); @@ -18615,6 +18620,7 @@ cp_parser_namespace_name (cp_parser* parser) { if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) { + auto_diagnostic_group d; error_at (token->location, "%qD is not a namespace-name", identifier); if (namespace_decl == error_mark_node && parser->scope && TREE_CODE (parser->scope) == NAMESPACE_DECL) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index cbb7b8e..efed9a1 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -800,6 +800,7 @@ check_specialization_namespace (tree tmpl) return true; else { + auto_diagnostic_group d; if (permerror (input_location, "specialization of %qD in different namespace", tmpl)) inform (DECL_SOURCE_LOCATION (tmpl), @@ -2592,6 +2593,7 @@ check_template_variable (tree decl) } if (template_header_count > wanted) { + auto_diagnostic_group d; bool warned = pedwarn (DECL_SOURCE_LOCATION (decl), 0, "too many template headers for %qD " "(should be %d)", @@ -2724,6 +2726,7 @@ warn_spec_missing_attributes (tree tmpl, tree spec, tree attrlist) if (!nattrs) return; + auto_diagnostic_group d; if (warning_at (DECL_SOURCE_LOCATION (spec), OPT_Wmissing_attributes, "explicit specialization %q#D may be missing attributes", spec)) @@ -3070,6 +3073,7 @@ check_explicit_specialization (tree declarator, if (TREE_CODE (decl) == FUNCTION_DECL && DECL_HIDDEN_FRIEND_P (tmpl)) { + auto_diagnostic_group d; if (pedwarn (DECL_SOURCE_LOCATION (decl), 0, "friend declaration %qD is not visible to " "explicit specialization", tmpl)) @@ -4891,6 +4895,7 @@ process_partial_specialization (tree decl) && TMPL_ARGS_DEPTH (specargs) == 1 && !get_partial_spec_bindings (maintmpl, maintmpl, specargs)) { + auto_diagnostic_group d; if (permerror (input_location, "partial specialization %qD is not " "more specialized than", decl)) inform (DECL_SOURCE_LOCATION (maintmpl), "primary template %qD", @@ -9354,6 +9359,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, { if (complain & tf_error) { + auto_diagnostic_group d; error ("template constraint failure"); diagnose_constraints (input_location, gen_tmpl, arglist); } @@ -9712,6 +9718,7 @@ finish_template_variable (tree var, tsubst_flags_t complain) { if (complain & tf_error) { + auto_diagnostic_group d; error ("use of invalid variable template %qE", var); diagnose_constraints (location_of (var), templ, arglist); } @@ -26888,6 +26895,7 @@ do_auto_deduction (tree type, tree init, tree auto_node, { if (complain & tf_warning_or_error) { + auto_diagnostic_group d; switch (context) { case adc_unspecified: diff --git a/gcc/cp/search.c b/gcc/cp/search.c index c2860b0..d700fe3 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -1911,6 +1911,7 @@ check_final_overrider (tree overrider, tree basefn) /* GNU extension, allow trivial pointer conversions such as converting to void *, or qualification conversion. */ { + auto_diagnostic_group d; if (pedwarn (DECL_SOURCE_LOCATION (overrider), 0, "invalid covariant return type for %q#D", overrider)) inform (DECL_SOURCE_LOCATION (basefn), @@ -1927,12 +1928,14 @@ check_final_overrider (tree overrider, tree basefn) { if (fail == 1) { + auto_diagnostic_group d; error ("invalid covariant return type for %q+#D", overrider); inform (DECL_SOURCE_LOCATION (basefn), "overridden function is %q#D", basefn); } else { + auto_diagnostic_group d; error ("conflicting return type specified for %q+#D", overrider); inform (DECL_SOURCE_LOCATION (basefn), "overridden function is %q#D", basefn); @@ -1949,6 +1952,7 @@ check_final_overrider (tree overrider, tree basefn) if (!comp_except_specs (base_throw, over_throw, ce_derived)) { + auto_diagnostic_group d; error ("looser throw specifier for %q+#F", overrider); inform (DECL_SOURCE_LOCATION (basefn), "overridden function is %q#F", basefn); @@ -1962,6 +1966,7 @@ check_final_overrider (tree overrider, tree basefn) && !tx_safe_fn_type_p (base_type) && !tx_safe_fn_type_p (over_type)) { + auto_diagnostic_group d; error ("conflicting type attributes specified for %q+#D", overrider); inform (DECL_SOURCE_LOCATION (basefn), "overridden function is %q#D", basefn); @@ -1978,6 +1983,7 @@ check_final_overrider (tree overrider, tree basefn) && !lookup_attribute ("transaction_safe_dynamic", DECL_ATTRIBUTES (basefn))) { + auto_diagnostic_group d; error_at (DECL_SOURCE_LOCATION (overrider), "%qD declared %<transaction_safe_dynamic%>", overrider); inform (DECL_SOURCE_LOCATION (basefn), @@ -1988,6 +1994,7 @@ check_final_overrider (tree overrider, tree basefn) { if (DECL_DELETED_FN (overrider)) { + auto_diagnostic_group d; error ("deleted function %q+D overriding non-deleted function", overrider); inform (DECL_SOURCE_LOCATION (basefn), @@ -1996,6 +2003,7 @@ check_final_overrider (tree overrider, tree basefn) } else { + auto_diagnostic_group d; error ("non-deleted function %q+D overriding deleted function", overrider); inform (DECL_SOURCE_LOCATION (basefn), @@ -2005,6 +2013,7 @@ check_final_overrider (tree overrider, tree basefn) } if (DECL_FINAL_P (basefn)) { + auto_diagnostic_group d; error ("virtual function %q+D overriding final function", overrider); inform (DECL_SOURCE_LOCATION (basefn), "overridden function is %qD", basefn); @@ -2089,6 +2098,7 @@ look_for_overrides_r (tree type, tree fndecl) { /* A static member function cannot match an inherited virtual member function. */ + auto_diagnostic_group d; error ("%q+#D cannot be declared", fndecl); error (" since %q+#D declared in base class", fn); } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 1cf3269..8a1d299 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -4031,6 +4031,7 @@ maybe_warn_parm_abi (tree t, location_t loc) && classtype_has_non_deleted_move_ctor (t)) { bool w; + auto_diagnostic_group d; if (flag_abi_version > 12) w = warning_at (loc, OPT_Wabi, "-fabi-version=13 (GCC 8.2) fixes the " "calling convention for %qT, which was accidentally " @@ -4043,6 +4044,7 @@ maybe_warn_parm_abi (tree t, location_t loc) return; } + auto_diagnostic_group d; if (warning_at (loc, OPT_Wabi, "the calling convention for %qT changes in " "-fabi-version=13 (GCC 8.2)", t)) inform (location_of (t), " because all of its copy and move " diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 8c13ae9..99be38ed 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1691,6 +1691,7 @@ cxx_sizeof_expr (tree e, tsubst_flags_t complain) && DECL_ARRAY_PARAMETER_P (e) && (complain & tf_warning)) { + auto_diagnostic_group d; if (warning (OPT_Wsizeof_array_argument, "%<sizeof%> on array function " "parameter %qE will return size of %qT", e, TREE_TYPE (e))) inform (DECL_SOURCE_LOCATION (e), "declared here"); @@ -3699,6 +3700,7 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params, && (complain & tf_error) && !constraints_satisfied_p (function)) { + auto_diagnostic_group d; error ("cannot call function %qD", function); location_t loc = DECL_SOURCE_LOCATION (function); diagnose_constraints (loc, function, NULL_TREE); @@ -4467,13 +4469,16 @@ cp_build_binary_op (location_t location, && DECL_ARRAY_PARAMETER_P (first_arg) && warn_sizeof_array_argument) && (complain & tf_warning)) - if (warning_at (location, OPT_Wsizeof_pointer_div, - "division %<sizeof (%T) / sizeof (%T)%> does " - "not compute the number of array elements", + { + auto_diagnostic_group d; + if (warning_at (location, OPT_Wsizeof_pointer_div, + "division %<sizeof (%T) / sizeof (%T)%> does " + "not compute the number of array elements", type0, type1)) - if (DECL_P (first_arg)) - inform (DECL_SOURCE_LOCATION (first_arg), - "first %<sizeof%> operand was declared here"); + if (DECL_P (first_arg)) + inform (DECL_SOURCE_LOCATION (first_arg), + "first %<sizeof%> operand was declared here"); + } } if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE @@ -4766,12 +4771,15 @@ cp_build_binary_op (location_t location, else result_type = type0; - if (char_type_p (TREE_TYPE (orig_op1)) - && warning (OPT_Wpointer_compare, - "comparison between pointer and zero character " - "constant")) - inform (input_location, - "did you mean to dereference the pointer?"); + if (char_type_p (TREE_TYPE (orig_op1))) + { + auto_diagnostic_group d; + if (warning (OPT_Wpointer_compare, + "comparison between pointer and zero character " + "constant")) + inform (input_location, + "did you mean to dereference the pointer?"); + } warn_for_null_address (location, op0, complain); } else if (((code1 == POINTER_TYPE || TYPE_PTRDATAMEM_P (type1)) @@ -4786,12 +4794,15 @@ cp_build_binary_op (location_t location, else result_type = type1; - if (char_type_p (TREE_TYPE (orig_op0)) - && warning (OPT_Wpointer_compare, - "comparison between pointer and zero character " - "constant")) - inform (input_location, - "did you mean to dereference the pointer?"); + if (char_type_p (TREE_TYPE (orig_op0))) + { + auto_diagnostic_group d; + if (warning (OPT_Wpointer_compare, + "comparison between pointer and zero character " + "constant")) + inform (input_location, + "did you mean to dereference the pointer?"); + } warn_for_null_address (location, op1, complain); } else if ((code0 == POINTER_TYPE && code1 == POINTER_TYPE) @@ -8807,6 +8818,7 @@ convert_for_assignment (tree type, tree rhs, } else if (fndecl) { + auto_diagnostic_group d; location_t loc = cp_expr_location (rhs); range_label_for_type_mismatch rhs_label (rhstype, type); range_label *label = &rhs_label; @@ -9087,6 +9099,7 @@ maybe_warn_about_returning_address_of_local (tree retval) || TREE_PUBLIC (whats_returned))) { bool w = false; + auto_diagnostic_group d; if (TYPE_REF_P (valtype)) w = warning_at (loc, OPT_Wreturn_local_addr, "reference to local variable %qD returned", diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 674d087..f42f0c2 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -315,6 +315,7 @@ abstract_virtuals_error_sfinae (tree decl, tree type, abstract_class_use use, if (!(complain & tf_error)) return 1; + auto_diagnostic_group d; if (decl) { if (VAR_P (decl)) @@ -983,6 +984,7 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain, bool const_only) { if (complain & tf_warning_or_error) { + auto_diagnostic_group d; if ((!almost_ok || pedantic) && pedwarn (loc, OPT_Wnarrowing, "narrowing conversion of %qE from %qH to %qI", |