aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2018-08-20 21:06:46 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2018-08-20 21:06:46 +0000
commit097f82ec9d19ccb5420c8df98cf35e1898b4fdab (patch)
tree083d8bf17b0bcd664af40648942c7c901ba1ed58 /gcc/c
parenta31505a339c847f0073c0ce9223a2b3c9bec6cef (diff)
downloadgcc-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/c')
-rw-r--r--gcc/c/ChangeLog23
-rw-r--r--gcc/c/c-decl.c44
-rw-r--r--gcc/c/c-parser.c22
-rw-r--r--gcc/c/c-typeck.c78
4 files changed, 127 insertions, 40 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 7bde11c..e943f0a 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,26 @@
+2018-08-20 David Malcolm <dmalcolm@redhat.com>
+
+ 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.
+
2018-08-15 David Malcolm <dmalcolm@redhat.com>
* c-objc-common.c: Include "gcc-rich-location.h".
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 1bbccdd..9524977 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -1571,6 +1571,7 @@ pushtag (location_t loc, tree name, tree type)
&& (TYPE_MAIN_VARIANT (TREE_TYPE (b->decl))
!= TYPE_MAIN_VARIANT (type)))
{
+ auto_diagnostic_group d;
if (warning_at (loc, OPT_Wc___compat,
("using %qD as both a typedef and a tag is "
"invalid in C++"), b->decl)
@@ -1823,8 +1824,6 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
tree *newtypep, tree *oldtypep)
{
tree newtype, oldtype;
- bool pedwarned = false;
- bool warned = false;
bool retval = true;
#define DECL_EXTERN_INLINE(DECL) (DECL_DECLARED_INLINE_P (DECL) \
@@ -1847,6 +1846,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
&& DECL_BUILT_IN (olddecl)
&& !C_DECL_DECLARED_BUILTIN (olddecl)))
{
+ auto_diagnostic_group d;
error ("%q+D redeclared as different kind of symbol", newdecl);
locate_old_decl (olddecl);
}
@@ -1864,11 +1864,16 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
given scope. */
if (TREE_CODE (olddecl) == CONST_DECL)
{
+ auto_diagnostic_group d;
error ("redeclaration of enumerator %q+D", newdecl);
locate_old_decl (olddecl);
return false;
}
+ bool pedwarned = false;
+ bool warned = false;
+ auto_diagnostic_group d;
+
if (!comptypes (oldtype, newtype))
{
if (TREE_CODE (olddecl) == FUNCTION_DECL
@@ -2052,6 +2057,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
)
&& same_translation_unit_p (newdecl, olddecl))
{
+ auto_diagnostic_group d;
error ("redefinition of %q+D", newdecl);
locate_old_decl (olddecl);
return false;
@@ -2062,11 +2068,14 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
the argument types must be checked specially. */
else if (DECL_INITIAL (olddecl)
&& !prototype_p (oldtype) && prototype_p (newtype)
- && TYPE_ACTUAL_ARG_TYPES (oldtype)
- && !validate_proto_after_old_defn (newdecl, newtype, oldtype))
+ && TYPE_ACTUAL_ARG_TYPES (oldtype))
{
- locate_old_decl (olddecl);
- return false;
+ auto_diagnostic_group d;
+ if (!validate_proto_after_old_defn (newdecl, newtype, oldtype))
+ {
+ locate_old_decl (olddecl);
+ return false;
+ }
}
/* A non-static declaration (even an "extern") followed by a
static declaration is undefined behavior per C99 6.2.2p3-5,7.
@@ -2087,6 +2096,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
if (!DECL_IS_BUILTIN (olddecl)
&& !DECL_EXTERN_INLINE (olddecl))
{
+ auto_diagnostic_group d;
error ("static declaration of %q+D follows "
"non-static declaration", newdecl);
locate_old_decl (olddecl);
@@ -2097,6 +2107,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
{
if (DECL_CONTEXT (olddecl))
{
+ auto_diagnostic_group d;
error ("non-static declaration of %q+D follows "
"static declaration", newdecl);
locate_old_decl (olddecl);
@@ -2121,6 +2132,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
DECL_ATTRIBUTES (olddecl)) != NULL;
if (newa != olda)
{
+ auto_diagnostic_group d;
error_at (input_location, "%<gnu_inline%> attribute present on %q+D",
newa ? newdecl : olddecl);
error_at (DECL_SOURCE_LOCATION (newa ? olddecl : newdecl),
@@ -2141,6 +2153,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
}
else if (DECL_THREAD_LOCAL_P (newdecl) != DECL_THREAD_LOCAL_P (olddecl))
{
+ auto_diagnostic_group d;
if (DECL_THREAD_LOCAL_P (newdecl))
error ("thread-local declaration of %q+D follows "
"non-thread-local declaration", newdecl);
@@ -2155,6 +2168,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
/* Multiple initialized definitions are not allowed (6.9p3,5). */
if (DECL_INITIAL (newdecl) && DECL_INITIAL (olddecl))
{
+ auto_diagnostic_group d;
error ("redefinition of %q+D", newdecl);
locate_old_decl (olddecl);
return false;
@@ -2175,6 +2189,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
{
if (!DECL_FILE_SCOPE_P (olddecl))
{
+ auto_diagnostic_group d;
error ("extern declaration of %q+D follows "
"declaration with no linkage", newdecl);
locate_old_decl (olddecl);
@@ -2189,6 +2204,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
}
else
{
+ auto_diagnostic_group d;
if (TREE_PUBLIC (newdecl))
error ("non-static declaration of %q+D follows "
"static declaration", newdecl);
@@ -2211,12 +2227,14 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
}
else if (DECL_EXTERNAL (olddecl))
{
+ auto_diagnostic_group d;
error ("declaration of %q+D with no linkage follows "
"extern declaration", newdecl);
locate_old_decl (olddecl);
}
else
{
+ auto_diagnostic_group d;
error ("redeclaration of %q+D with no linkage", newdecl);
locate_old_decl (olddecl);
}
@@ -2263,6 +2281,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
if (TREE_CODE (newdecl) == PARM_DECL
&& (!TREE_ASM_WRITTEN (olddecl) || TREE_ASM_WRITTEN (newdecl)))
{
+ auto_diagnostic_group d;
error ("redefinition of parameter %q+D", newdecl);
locate_old_decl (olddecl);
return false;
@@ -2778,7 +2797,6 @@ warn_if_shadowing (tree new_decl)
DECL_SOURCE_LOCATION (b->decl))))
{
tree old_decl = b->decl;
- bool warned = false;
if (old_decl == error_mark_node)
{
@@ -2786,7 +2804,10 @@ warn_if_shadowing (tree new_decl)
"non-variable", new_decl);
break;
}
- else if (TREE_CODE (old_decl) == PARM_DECL)
+
+ bool warned = false;
+ auto_diagnostic_group d;
+ if (TREE_CODE (old_decl) == PARM_DECL)
{
enum opt_code warning_code;
@@ -3123,6 +3144,7 @@ implicit_decl_warning (location_t loc, tree id, tree olddecl)
return;
bool warned;
+ auto_diagnostic_group d;
name_hint hint;
if (!olddecl)
hint = lookup_name_fuzzy (id, FUZZY_LOOKUP_FUNCTION_NAME, loc);
@@ -3435,6 +3457,7 @@ implicitly_declare (location_t loc, tree functionid)
{
if (!comptypes (newtype, TREE_TYPE (decl)))
{
+ auto_diagnostic_group d;
error_at (loc, "incompatible implicit declaration of "
"function %qD", decl);
locate_old_decl (decl);
@@ -3487,6 +3510,7 @@ undeclared_variable (location_t loc, tree id)
static bool already = false;
struct c_scope *scope;
+ auto_diagnostic_group d;
if (current_function_decl == NULL_TREE)
{
name_hint guessed_id = lookup_name_fuzzy (id, FUZZY_LOOKUP_NAME, loc);
@@ -3686,6 +3710,7 @@ declare_label (tree name)
at this scope */
if (b && B_IN_CURRENT_SCOPE (b))
{
+ auto_diagnostic_group d;
error ("duplicate label declaration %qE", name);
locate_old_decl (b->decl);
@@ -3784,6 +3809,7 @@ define_label (location_t location, tree name)
|| (DECL_CONTEXT (label) != current_function_decl
&& C_DECLARED_LABEL_FLAG (label))))
{
+ auto_diagnostic_group d;
error_at (location, "duplicate label %qD", label);
locate_old_decl (label);
return NULL_TREE;
@@ -6720,6 +6746,7 @@ grokdeclarator (const struct c_declarator *declarator,
|| (current_scope == file_scope && B_IN_EXTERNAL_SCOPE (b)))
&& TYPE_MAIN_VARIANT (b->decl) != TYPE_MAIN_VARIANT (type))
{
+ auto_diagnostic_group d;
if (warning_at (declarator->id_loc, OPT_Wc___compat,
("using %qD as both a typedef and a tag is "
"invalid in C++"), decl)
@@ -8794,6 +8821,7 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
{
if (stdarg_p (TREE_TYPE (old_decl)))
{
+ auto_diagnostic_group d;
warning_at (loc, 0, "%q+D defined as variadic function "
"without prototype", decl1);
locate_old_decl (old_decl);
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 5ad4f57..0d5dbea 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1814,6 +1814,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
}
else
{
+ auto_diagnostic_group d;
name_hint hint = lookup_name_fuzzy (name, FUZZY_LOOKUP_TYPENAME,
here);
if (hint)
@@ -4058,6 +4059,7 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
c_parser_set_source_position_from_token (token);
if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
{
+ auto_diagnostic_group d;
name_hint hint = lookup_name_fuzzy (token->value,
FUZZY_LOOKUP_TYPENAME,
token->location);
@@ -6873,14 +6875,18 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
&& !(TREE_CODE (first_arg) == PARM_DECL \
&& C_ARRAY_PARAMETER (first_arg) \
&& warn_sizeof_array_argument)) \
- if (warning_at (stack[sp].loc, 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"); \
- } \
+ { \
+ auto_diagnostic_group d; \
+ if (warning_at (stack[sp].loc, 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"); \
+ } \
+ } \
break; \
default: \
break; \
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 726ea83..54c7967 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -2906,6 +2906,7 @@ c_expr_sizeof_expr (location_t loc, struct c_expr expr)
if (TREE_CODE (expr.value) == PARM_DECL
&& C_ARRAY_PARAMETER (expr.value))
{
+ auto_diagnostic_group d;
if (warning_at (loc, OPT_Wsizeof_array_argument,
"%<sizeof%> on array function parameter %qE will "
"return size of %qT", expr.value,
@@ -3735,19 +3736,27 @@ parser_build_binary_op (location_t location, enum tree_code code,
"comparison with string literal results in unspecified behavior");
/* Warn for ptr == '\0', it's likely that it should've been ptr[0]. */
if (POINTER_TYPE_P (type1)
- && null_pointer_constant_p (arg2.value)
- && char_type_p (type2)
- && warning_at (location, OPT_Wpointer_compare,
- "comparison between pointer and zero character "
- "constant"))
- inform (arg1.get_start (), "did you mean to dereference the pointer?");
+ && null_pointer_constant_p (arg2.value)
+ && char_type_p (type2))
+ {
+ auto_diagnostic_group d;
+ if (warning_at (location, OPT_Wpointer_compare,
+ "comparison between pointer and zero character "
+ "constant"))
+ inform (arg1.get_start (),
+ "did you mean to dereference the pointer?");
+ }
else if (POINTER_TYPE_P (type2)
&& null_pointer_constant_p (arg1.value)
- && char_type_p (type1)
- && warning_at (location, OPT_Wpointer_compare,
- "comparison between pointer and zero character "
- "constant"))
- inform (arg2.get_start (), "did you mean to dereference the pointer?");
+ && char_type_p (type1))
+ {
+ auto_diagnostic_group d;
+ if (warning_at (location, OPT_Wpointer_compare,
+ "comparison between pointer and zero character "
+ "constant"))
+ inform (arg2.get_start (),
+ "did you mean to dereference the pointer?");
+ }
}
else if (TREE_CODE_CLASS (code) == tcc_comparison
&& (code1 == STRING_CST || code2 == STRING_CST))
@@ -4288,13 +4297,16 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
e = TREE_OPERAND (e, 1);
if ((TREE_CODE (TREE_TYPE (arg)) == BOOLEAN_TYPE
- || truth_value_p (TREE_CODE (e)))
- && warning_at (location, OPT_Wbool_operation,
- "%<~%> on a boolean expression"))
+ || truth_value_p (TREE_CODE (e))))
{
- gcc_rich_location richloc (location);
- richloc.add_fixit_insert_before (location, "!");
- inform (&richloc, "did you mean to use logical not?");
+ auto_diagnostic_group d;
+ if (warning_at (location, OPT_Wbool_operation,
+ "%<~%> on a boolean expression"))
+ {
+ gcc_rich_location richloc (location);
+ richloc.add_fixit_insert_before (location, "!");
+ inform (&richloc, "did you mean to use logical not?");
+ }
}
if (!noconvert)
arg = default_conversion (arg);
@@ -6197,6 +6209,8 @@ error_init (location_t loc, const char *gmsgid)
{
char *ofwhat;
+ auto_diagnostic_group d;
+
/* The gmsgid may be a format string with %< and %>. */
error_at (loc, gmsgid);
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
@@ -6216,7 +6230,7 @@ pedwarn_init (location_t loc, int opt, const char *gmsgid, ...)
it was defined to make sure macros defined in system headers
but used incorrectly elsewhere are diagnosed. */
source_location exploc = expansion_point_location_if_in_system_header (loc);
-
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
bool warned = emit_diagnostic_valist (DK_PEDWARN, exploc, opt, gmsgid, &ap);
@@ -6238,6 +6252,8 @@ warning_init (location_t loc, int opt, const char *gmsgid)
char *ofwhat;
bool warned;
+ auto_diagnostic_group d;
+
/* Use the location where a macro was expanded rather than where
it was defined to make sure macros defined in system headers
but used incorrectly elsewhere are diagnosed. */
@@ -6379,8 +6395,11 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
switch (errtype) \
{ \
case ic_argpass: \
- if (pedwarn (PLOC, OPT, AR, parmnum, rname)) \
- inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \
+ { \
+ auto_diagnostic_group d; \
+ if (pedwarn (PLOC, OPT, AR, parmnum, rname)) \
+ inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \
+ } \
break; \
case ic_assign: \
pedwarn (LOCATION, OPT, AS); \
@@ -6405,8 +6424,11 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
switch (errtype) \
{ \
case ic_argpass: \
- if (pedwarn (PLOC, OPT, AR, parmnum, rname, QUALS)) \
- inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \
+ { \
+ auto_diagnostic_group d; \
+ if (pedwarn (PLOC, OPT, AR, parmnum, rname, QUALS)) \
+ inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \
+ } \
break; \
case ic_assign: \
pedwarn (LOCATION, OPT, AS, QUALS); \
@@ -6431,8 +6453,11 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
switch (errtype) \
{ \
case ic_argpass: \
- if (warning_at (PLOC, OPT, AR, parmnum, rname, QUALS)) \
- inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \
+ { \
+ auto_diagnostic_group d; \
+ if (warning_at (PLOC, OPT, AR, parmnum, rname, QUALS)) \
+ inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype); \
+ } \
break; \
case ic_assign: \
warning_at (LOCATION, OPT, AS, QUALS); \
@@ -6925,6 +6950,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
{
case ic_argpass:
{
+ auto_diagnostic_group d;
range_label_for_type_mismatch rhs_label (rhstype, type);
gcc_rich_location richloc (expr_loc, &rhs_label);
if (pedwarn (&richloc, OPT_Wpointer_sign,
@@ -6984,6 +7010,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
{
case ic_argpass:
{
+ auto_diagnostic_group d;
range_label_for_type_mismatch rhs_label (rhstype, type);
gcc_rich_location richloc (expr_loc, &rhs_label);
if (pedwarn (&richloc, OPT_Wincompatible_pointer_types,
@@ -7031,6 +7058,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
{
case ic_argpass:
{
+ auto_diagnostic_group d;
range_label_for_type_mismatch rhs_label (rhstype, type);
gcc_rich_location richloc (expr_loc, &rhs_label);
if (pedwarn (&richloc, OPT_Wint_conversion,
@@ -7066,6 +7094,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
{
case ic_argpass:
{
+ auto_diagnostic_group d;
range_label_for_type_mismatch rhs_label (rhstype, type);
gcc_rich_location richloc (expr_loc, &rhs_label);
if (pedwarn (&richloc, OPT_Wint_conversion,
@@ -7109,6 +7138,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
{
case ic_argpass:
{
+ auto_diagnostic_group d;
range_label_for_type_mismatch rhs_label (rhstype, type);
gcc_rich_location richloc (expr_loc, &rhs_label);
error_at (&richloc, "incompatible type for argument %d of %qE", parmnum,