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
+2018-08-20 David Malcolm <dmalcolm@redhat.com>
+
+ 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.
+
2018-08-20 H.J. Lu <hongjiu.lu@intel.com>
PR target/87014
/* Print a note? */
bool note = last_decl != NULL_TREE;
-
+ auto_diagnostic_group d;
if (TREE_CODE (node) == FUNCTION_DECL
&& DECL_BUILT_IN (node))
note &= warning (OPT_Wattributes,
/* This is a c++11 attribute that appertains to a
type-specifier, outside of the definition of, a class
type. Ignore it. */
+ auto_diagnostic_group d;
if (warning (OPT_Wattributes, "attribute ignored"))
inform (input_location,
"an attribute that appertains to a type-specifier "
+2018-08-20 David Malcolm <dmalcolm@redhat.com>
+
+ 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.
+
2018-08-20 Nathan Sidwell <nathan@acm.org>
* c-ada-spec.c (macro_length, dump_ada_macros): Adjust macro parm
bitalign /= BITS_PER_UNIT;
bool diagd = true;
+ auto_diagnostic_group d;
if (DECL_USER_ALIGN (decl) || DECL_USER_ALIGN (last_decl))
diagd = warning (OPT_Wattributes,
"ignoring attribute %<%E (%u)%> because it conflicts "
body_tinfo,
next_tinfo))
{
+ auto_diagnostic_group d;
if (warning_at (guard_tinfo.location, OPT_Wmisleading_indentation,
"this %qs clause does not guard...",
guard_tinfo_to_string (guard_tinfo.keyword)))
warn_abi_version = latest_abi_version;
if (flag_abi_version == latest_abi_version)
{
+ auto_diagnostic_group d;
if (warning (OPT_Wabi, "-Wabi won't warn about anything"))
{
inform (input_location, "-Wabi warns about differences "
&& integer_zerop (rhs))
return;
+ auto_diagnostic_group d;
if (warning_at (location, OPT_Wlogical_not_parentheses,
"logical not is only applied to the left hand side of "
"comparison")
FOR_EACH_VEC_ELT (**chain, ix, t)
if (operand_equal_p (cond, t, 0))
{
+ auto_diagnostic_group d;
if (warning_at (loc, OPT_Wduplicated_cond,
"duplicated %<if%> condition"))
inform (EXPR_LOCATION (t), "previously used here");
return;
}
+ 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 "
+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".
&& (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)
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) \
&& 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);
}
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
)
&& same_translation_unit_p (newdecl, olddecl))
{
+ auto_diagnostic_group d;
error ("redefinition of %q+D", newdecl);
locate_old_decl (olddecl);
return false;
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.
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);
{
if (DECL_CONTEXT (olddecl))
{
+ auto_diagnostic_group d;
error ("non-static declaration of %q+D follows "
"static declaration", newdecl);
locate_old_decl (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),
}
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);
/* 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;
{
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);
}
else
{
+ auto_diagnostic_group d;
if (TREE_PUBLIC (newdecl))
error ("non-static declaration of %q+D follows "
"static declaration", newdecl);
}
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);
}
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;
DECL_SOURCE_LOCATION (b->decl))))
{
tree old_decl = b->decl;
- bool warned = false;
if (old_decl == error_mark_node)
{
"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;
return;
bool warned;
+ auto_diagnostic_group d;
name_hint hint;
if (!olddecl)
hint = lookup_name_fuzzy (id, FUZZY_LOOKUP_FUNCTION_NAME, loc);
{
if (!comptypes (newtype, TREE_TYPE (decl)))
{
+ auto_diagnostic_group d;
error_at (loc, "incompatible implicit declaration of "
"function %qD", decl);
locate_old_decl (decl);
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);
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);
|| (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;
|| (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)
{
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);
}
else
{
+ auto_diagnostic_group d;
name_hint hint = lookup_name_fuzzy (name, FUZZY_LOOKUP_TYPENAME,
here);
if (hint)
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);
&& !(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; \
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,
"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))
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);
{
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));
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);
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. */
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); \
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); \
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); \
{
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,
{
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,
{
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,
{
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,
{
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,
bool warned = false;
+ auto_diagnostic_group d;
if (wi::ltu_p (asize, wibnd))
{
if (bndrng[0] == bndrng[1])
{
funcptr = build_pointer_type (funcptr);
+ auto_diagnostic_group d;
if (warning_at (DECL_SOURCE_LOCATION (target),
OPT_Wattribute_alias,
"%<ifunc%> resolver for %qD should return %qT",
inform (DECL_SOURCE_LOCATION (alias),
"resolver indirect function declared here");
}
- else if (warning_at (DECL_SOURCE_LOCATION (alias),
- OPT_Wattribute_alias,
- "%qD alias between functions of incompatible "
- "types %qT and %qT", alias, altype, targtype))
- inform (DECL_SOURCE_LOCATION (target),
- "aliased declaration here");
+ else
+ {
+ auto_diagnostic_group d;
+ if (warning_at (DECL_SOURCE_LOCATION (alias),
+ OPT_Wattribute_alias,
+ "%qD alias between functions of incompatible "
+ "types %qT and %qT", alias, altype, targtype))
+ inform (DECL_SOURCE_LOCATION (target),
+ "aliased declaration here");
+ }
}
}
+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
{
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);
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));
{
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);
{
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);
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
op_error (loc, COND_EXPR, NOP_EXPR, arg1, arg2, arg3, FALSE);
print_z_candidates (loc, candidates);
}
{
/* ... 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);
}
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
op_error (loc, code, code2, arg1, arg2, arg3, TRUE);
print_z_candidates (loc, candidates);
}
-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. */
{
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);
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))
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
maybe_print_user_conv_context (convs);
if (fn)
inform (DECL_SOURCE_LOCATION (fn),
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),
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 "
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
if (permerror (input_location, "passing %qT as %<this%> "
"argument discards qualifiers",
TREE_TYPE (argtype)))
basetype = DECL_CONTEXT (fn);
name = constructor_name (basetype);
+ auto_diagnostic_group d;
if (permerror (input_location,
"cannot call constructor %<%T::%D%> directly",
basetype, name))
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
if (!COMPLETE_OR_OPEN_TYPE_P (basetype))
cxx_incomplete_type_error (instance, basetype);
else if (optype)
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);
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))
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
if (permerror (input_location,
"default argument mismatch in "
"overload resolution"))
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 "
/* 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))
}
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",
}
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))
{
/* 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");
+ }
}
}
}
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);
&& !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);
+ }
}
}
/* 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,
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
{
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);
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
if (!(complain & tf_error))
return error_mark_node;
+ auto_diagnostic_group d;
if (permerror (input_location, "assuming pointer to member %qD", fn)
&& !explained)
{
{
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);
{
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);
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));
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);
&& !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)))
}
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");
{
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));
{
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));
/* 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
{
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))
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))
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",
&& 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),
= 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)
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))
"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)
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,
&& 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,
}
else
{
+ auto_diagnostic_group d;
error_at (newdecl_loc,
"conflicting declaration of %q#D with %qL linkage",
newdecl, DECL_LANGUAGE (newdecl));
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))
}
else
{
+ auto_diagnostic_group d;
error_at (newdecl_loc,
"default argument given for parameter %d "
"of %q#D", i, newdecl);
&& (! 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",
{
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);
&& 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))
{
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;
}
{
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))
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)),
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);
&& 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,
}
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);
}
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)
}
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),
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),
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)
{
/* 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),
/* 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),
}
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),
|| 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)))
{
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;
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
{
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);
}
if (mismatch)
{
+ auto_diagnostic_group d;
pedwarn (input_location, 0,
"conflicting C language linkage declaration %q#D", decl);
inform (DECL_SOURCE_LOCATION (old),
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. */
old_scope = binding->scope;
}
- tree shadowed = NULL_TREE;
if (old
&& (TREE_CODE (old) == PARM_DECL
|| VAR_P (old)
&& 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);
|| 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);
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;
}
|| 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;
}
&& !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
&& !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),
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);
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);
{
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",
&& 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))
}
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);
{
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)
return true;
else
{
+ auto_diagnostic_group d;
if (permerror (input_location,
"specialization of %qD in different namespace", tmpl))
inform (DECL_SOURCE_LOCATION (tmpl),
}
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)",
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))
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))
&& 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",
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
error ("template constraint failure");
diagnose_constraints (input_location, gen_tmpl, arglist);
}
{
if (complain & tf_error)
{
+ auto_diagnostic_group d;
error ("use of invalid variable template %qE", var);
diagnose_constraints (location_of (var), templ, arglist);
}
{
if (complain & tf_warning_or_error)
{
+ auto_diagnostic_group d;
switch (context)
{
case adc_unspecified:
/* 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),
{
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);
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);
&& !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);
&& !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),
{
if (DECL_DELETED_FN (overrider))
{
+ auto_diagnostic_group d;
error ("deleted function %q+D overriding non-deleted function",
overrider);
inform (DECL_SOURCE_LOCATION (basefn),
}
else
{
+ auto_diagnostic_group d;
error ("non-deleted function %q+D overriding deleted function",
overrider);
inform (DECL_SOURCE_LOCATION (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);
{
/* 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);
}
&& 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 "
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 "
&& 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");
&& (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);
&& 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
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))
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)
}
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;
|| 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",
if (!(complain & tf_error))
return 1;
+ auto_diagnostic_group d;
if (decl)
{
if (VAR_P (decl))
{
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",
DK_POP
} diagnostic_t;
+/* RAII-style class for grouping related diagnostics. */
+
+class auto_diagnostic_group
+{
+ public:
+ auto_diagnostic_group ();
+ ~auto_diagnostic_group ();
+};
+
extern const char *progname;
extern const char *trim_filename (const char *);
context->show_ruler_p = false;
context->parseable_fixits_p = false;
context->edit_context_ptr = NULL;
+ context->diagnostic_group_nesting_depth = 0;
+ context->diagnostic_group_emission_count = 0;
+ context->begin_group_cb = NULL;
+ context->end_group_cb = NULL;
}
/* Maybe initialize the color support. We require clients to do this
else
++diagnostic_kind_count (context, diagnostic->kind);
+ /* Is this the initial diagnostic within the stack of groups? */
+ if (context->diagnostic_group_emission_count == 0)
+ {
+ if (context->begin_group_cb)
+ context->begin_group_cb (context);
+ }
+ context->diagnostic_group_emission_count++;
+
diagnostic->message.x_data = &diagnostic->x_data;
diagnostic->x_data = NULL;
pp_format (context->printer, &diagnostic->message);
emit_diagnostic (diagnostic_t kind, location_t location, int opt,
const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, location);
void
inform (location_t location, const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, location);
{
gcc_assert (richloc);
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
diagnostic_impl (richloc, -1, gmsgid, &ap, DK_NOTE);
{
va_list ap;
va_start (ap, plural_gmsgid);
+ auto_diagnostic_group d;
rich_location richloc (line_table, location);
diagnostic_n_impl (&richloc, -1, n, singular_gmsgid, plural_gmsgid,
&ap, DK_NOTE);
bool
warning (int opt, const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, input_location);
bool
warning_at (location_t location, int opt, const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, location);
{
gcc_assert (richloc);
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
bool ret = diagnostic_impl (richloc, opt, gmsgid, &ap, DK_WARNING);
{
gcc_assert (richloc);
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, plural_gmsgid);
bool ret = diagnostic_n_impl (richloc, opt, n,
warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
const char *singular_gmsgid, const char *plural_gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, plural_gmsgid);
rich_location richloc (line_table, location);
bool
pedwarn (location_t location, int opt, const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, location);
{
gcc_assert (richloc);
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
bool ret = diagnostic_impl (richloc, opt, gmsgid, &ap, DK_PEDWARN);
bool
permerror (location_t location, const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, location);
{
gcc_assert (richloc);
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
bool ret = diagnostic_impl (richloc, -1, gmsgid, &ap, DK_PERMERROR);
void
error (const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, input_location);
error_n (location_t location, unsigned HOST_WIDE_INT n,
const char *singular_gmsgid, const char *plural_gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, plural_gmsgid);
rich_location richloc (line_table, location);
void
error_at (location_t loc, const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, loc);
{
gcc_assert (richloc);
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
diagnostic_impl (richloc, -1, gmsgid, &ap, DK_ERROR);
void
sorry (const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, input_location);
void
fatal_error (location_t loc, const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, loc);
void
internal_error (const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, input_location);
void
internal_error_no_backtrace (const char *gmsgid, ...)
{
+ auto_diagnostic_group d;
va_list ap;
va_start (ap, gmsgid);
rich_location richloc (line_table, input_location);
internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
}
+/* class auto_diagnostic_group. */
+
+/* Constructor: "push" this group into global_dc. */
+
+auto_diagnostic_group::auto_diagnostic_group ()
+{
+ global_dc->diagnostic_group_nesting_depth++;
+}
+
+/* Destructor: "pop" this group from global_dc. */
+
+auto_diagnostic_group::~auto_diagnostic_group ()
+{
+ if (--global_dc->diagnostic_group_nesting_depth == 0)
+ {
+ /* Handle the case where we've popped the final diagnostic group.
+ If any diagnostics were emitted, give the context a chance
+ to do something. */
+ if (global_dc->diagnostic_group_emission_count > 0)
+ {
+ if (global_dc->end_group_cb)
+ global_dc->end_group_cb (global_dc);
+ }
+ global_dc->diagnostic_group_emission_count = 0;
+ }
+}
+
/* Really call the system 'abort'. This has to go right at the end of
this file, so that there are no functions after it that call abort
and get the system abort instead of our macro. */
/* If non-NULL, an edit_context to which fix-it hints should be
applied, for generating patches. */
edit_context *edit_context_ptr;
+
+ /* How many diagnostic_group instances are currently alive. */
+ int diagnostic_group_nesting_depth;
+
+ /* How many diagnostics have been emitted since the bottommost
+ diagnostic_group was pushed. */
+ int diagnostic_group_emission_count;
+
+ /* Optional callbacks for handling diagnostic groups. */
+
+ /* If non-NULL, this will be called immediately before the first
+ time a diagnostic is emitted within a stack of groups. */
+ void (*begin_group_cb) (diagnostic_context * context);
+
+ /* If non-NULL, this will be called when a stack of groups is
+ popped if any diagnostics were emitted within that group. */
+ void (*end_group_cb) (diagnostic_context * context);
};
static inline void
if (gimple_return_retval (return_stmt) != lhs)
continue;
- if (warning_at (gimple_location (use_stmt),
- OPT_Wreturn_local_addr,
- "function may return address "
- "of local variable"))
- inform (DECL_SOURCE_LOCATION(valbase),
- "declared here");
+ {
+ auto_diagnostic_group d;
+ if (warning_at (gimple_location (use_stmt),
+ OPT_Wreturn_local_addr,
+ "function may return address "
+ "of local variable"))
+ inform (DECL_SOURCE_LOCATION(valbase),
+ "declared here");
+ }
if (gimple_bb (use_stmt) == bb)
{
else
msg = N_("function may return address of "
"local variable");
-
- if (warning_at (gimple_location (stmt),
- OPT_Wreturn_local_addr, msg))
- inform (DECL_SOURCE_LOCATION(valbase), "declared here");
+ {
+ auto_diagnostic_group d;
+ if (warning_at (gimple_location (stmt),
+ OPT_Wreturn_local_addr, msg))
+ inform (DECL_SOURCE_LOCATION(valbase),
+ "declared here");
+ }
tree zero = build_zero_cst (TREE_TYPE (val));
gimple_return_set_retval (return_stmt, zero);
update_stmt (stmt);
case ALLOCA_OK:
break;
case ALLOCA_BOUND_MAYBE_LARGE:
- if (warning_at (loc, wcode,
- is_vla ? G_("argument to variable-length array "
- "may be too large")
- : G_("argument to %<alloca%> may be too large"))
- && t.limit != 0)
- {
- print_decu (t.limit, buff);
- inform (loc, G_("limit is %wu bytes, but argument "
- "may be as large as %s"),
- is_vla ? warn_vla_limit : warn_alloca_limit, buff);
- }
+ {
+ auto_diagnostic_group d;
+ if (warning_at (loc, wcode,
+ is_vla ? G_("argument to variable-length "
+ "array may be too large")
+ : G_("argument to %<alloca%> may be too "
+ "large"))
+ && t.limit != 0)
+ {
+ print_decu (t.limit, buff);
+ inform (loc, G_("limit is %wu bytes, but argument "
+ "may be as large as %s"),
+ is_vla ? warn_vla_limit : warn_alloca_limit, buff);
+ }
+ }
break;
case ALLOCA_BOUND_DEFINITELY_LARGE:
- if (warning_at (loc, wcode,
- is_vla ? G_("argument to variable-length array "
- "is too large")
- : G_("argument to %<alloca%> is too large"))
- && t.limit != 0)
- {
- print_decu (t.limit, buff);
- inform (loc, G_("limit is %wu bytes, but argument is %s"),
- is_vla ? warn_vla_limit : warn_alloca_limit, buff);
- }
+ {
+ auto_diagnostic_group d;
+ if (warning_at (loc, wcode,
+ is_vla ? G_("argument to variable-length"
+ " array is too large")
+ : G_("argument to %<alloca%> is too large"))
+ && t.limit != 0)
+ {
+ print_decu (t.limit, buff);
+ inform (loc, G_("limit is %wu bytes, but argument is %s"),
+ is_vla ? warn_vla_limit : warn_alloca_limit,
+ buff);
+ }
+ }
break;
case ALLOCA_BOUND_UNKNOWN:
warning_at (loc, wcode,
if (DECL_P (ref.base)
&& TREE_CODE (type = TREE_TYPE (ref.base)) == ARRAY_TYPE)
{
+ auto_diagnostic_group d;
if (warning_at (loc, OPT_Warray_bounds,
"%G%qD pointer overflow between offset %s "
"and size %s accessing array %qD with type %qT",
if (DECL_P (ref.base))
{
+ auto_diagnostic_group d;
if ((ref.basesize < maxobjsize
&& warning_at (loc, OPT_Warray_bounds,
form
{
struct label_entry *l;
bool warned_p = false;
+ auto_diagnostic_group d;
if (!should_warn_for_implicit_fallthrough (gsi_p, label))
/* Quiet. */;
else if (gimple_code (prev) == GIMPLE_LABEL
/* Unfortunately, this is merely undefined, rather than a constraint
violation, so we cannot make this an error. If this call is never
executed, the program is still strictly conforming. */
+ auto_diagnostic_group d;
warned = warning_at (xloc, 0,
"%qT is promoted to %qT when passed through %<...%>",
type, promoted_type);
do \
{ \
hsa_fail_cfun (); \
+ auto_diagnostic_group d; \
if (warning_at (EXPR_LOCATION (hsa_cfun->m_decl), OPT_Whsa, \
HSA_SORRY_MSG)) \
inform (location, message, __VA_ARGS__); \
do \
{ \
hsa_fail_cfun (); \
+ auto_diagnostic_group d; \
if (warning_at (EXPR_LOCATION (hsa_cfun->m_decl), OPT_Whsa, \
HSA_SORRY_MSG)) \
inform (location, message); \
prevailing = vtable;
vtable = tmp;
}
+ auto_diagnostic_group d;
if (warning_at (DECL_SOURCE_LOCATION
(TYPE_NAME (DECL_CONTEXT (vtable->decl))),
OPT_Wodr,
&& TREE_CODE (ref1->referred->decl) == FUNCTION_DECL))
&& TREE_CODE (ref2->referred->decl) != FUNCTION_DECL)
{
- if (!class_type->rtti_broken
- && warning_at (DECL_SOURCE_LOCATION
- (TYPE_NAME (DECL_CONTEXT (vtable->decl))),
- OPT_Wodr,
- "virtual table of type %qD contains RTTI "
- "information",
- DECL_CONTEXT (vtable->decl)))
+ if (!class_type->rtti_broken)
{
- inform (DECL_SOURCE_LOCATION
- (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
- "but is prevailed by one without from other translation "
- "unit");
- inform (DECL_SOURCE_LOCATION
- (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
- "RTTI will not work on this type");
- class_type->rtti_broken = true;
+ auto_diagnostic_group d;
+ if (warning_at (DECL_SOURCE_LOCATION
+ (TYPE_NAME (DECL_CONTEXT (vtable->decl))),
+ OPT_Wodr,
+ "virtual table of type %qD contains RTTI "
+ "information",
+ DECL_CONTEXT (vtable->decl)))
+ {
+ inform (DECL_SOURCE_LOCATION
+ (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
+ "but is prevailed by one without from other"
+ " translation unit");
+ inform (DECL_SOURCE_LOCATION
+ (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
+ "RTTI will not work on this type");
+ class_type->rtti_broken = true;
+ }
}
n2++;
end2 = !vtable->iterate_reference (n2, ref2);
if (DECL_SIZE (prevailing->decl) != DECL_SIZE (vtable->decl))
{
class_type->odr_violated = true;
+ auto_diagnostic_group d;
if (warning_at (DECL_SOURCE_LOCATION
(TYPE_NAME (DECL_CONTEXT (vtable->decl))),
OPT_Wodr,
if (TREE_CODE (ref1->referred->decl) != FUNCTION_DECL
&& TREE_CODE (ref2->referred->decl) != FUNCTION_DECL)
{
+ auto_diagnostic_group d;
if (warning_at (DECL_SOURCE_LOCATION
(TYPE_NAME (DECL_CONTEXT (vtable->decl))),
OPT_Wodr,
vtable = tmp;
ref1 = ref2;
}
+ auto_diagnostic_group d;
if (warning_at (DECL_SOURCE_LOCATION
(TYPE_NAME (DECL_CONTEXT (vtable->decl))),
OPT_Wodr,
/* And in the last case we have either mistmatch in between two virtual
methods or two virtual table pointers. */
+ auto_diagnostic_group d;
if (warning_at (DECL_SOURCE_LOCATION
(TYPE_NAME (DECL_CONTEXT (vtable->decl))), OPT_Wodr,
"virtual table of type %qD violates "
if (lto_location_cache::current_cache)
lto_location_cache::current_cache->apply_location_cache ();
+ auto_diagnostic_group d;
if (!warning_at (DECL_SOURCE_LOCATION (TYPE_NAME (t1)), OPT_Wodr,
"type %qT violates the C++ One Definition Rule",
t1))
if (node->definition
&& !tree_versionable_function_p (node->decl))
{
+ auto_diagnostic_group d;
error_at (DECL_SOURCE_LOCATION (node->decl),
"clones for %<target_clones%> attribute cannot be created");
const char *reason = NULL;
unsigned int i;
char *s;
+ auto_diagnostic_group d;
if (e->unknown_error)
error_at (loc, e->unknown_error, arg);
else
if (global_regs[i])
{
+ auto_diagnostic_group d;
warning_at (loc, 0,
"register of %qD used for multiple global register variables",
decl);
if (substring_within_range)
primary_label = fmt_label;
+ auto_diagnostic_group d;
gcc_rich_location richloc (primary_loc, primary_label);
if (param_loc != UNKNOWN_LOCATION)
+2018-08-20 David Malcolm <dmalcolm@redhat.com>
+
+ 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.
+
2018-08-20 H.J. Lu <hongjiu.lu@intel.com>
PR target/87014
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-fdiagnostics-show-caret" } */
+
+extern void __emit_warning (const char *message);
+
+static void test_1 (void)
+{
+ __emit_warning ("warning 1");
+}
+
+/* { dg-begin-multiline-output "" }
+================================= BEGIN GROUP ==============================
+PREFIX
+ __emit_warning ("warning 1");
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
+PREFIX: message for note
+PREFIX: some more detail
+PREFIX: yet more detail
+---------------------------------- END GROUP -------------------------------
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+================================= BEGIN GROUP ==============================
+PREFIX: an unrelated message
+---------------------------------- END GROUP -------------------------------
+ { dg-end-multiline-output "" } */
--- /dev/null
+/* { dg-options "-O" } */
+
+#include "gcc-plugin.h"
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "stringpool.h"
+#include "toplev.h"
+#include "basic-block.h"
+#include "hash-table.h"
+#include "vec.h"
+#include "ggc.h"
+#include "basic-block.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-fold.h"
+#include "tree-eh.h"
+#include "gimple-expr.h"
+#include "is-a.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "tree.h"
+#include "tree-pass.h"
+#include "intl.h"
+#include "plugin-version.h"
+#include "c-family/c-common.h"
+#include "diagnostic.h"
+#include "context.h"
+
+int plugin_is_GPL_compatible;
+
+/* A custom pass for emitting dummy warnings from the middle-end. */
+
+const pass_data pass_data_test_groups =
+{
+ GIMPLE_PASS, /* type */
+ "test_groups", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_NONE, /* tv_id */
+ PROP_ssa, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_test_groups : public gimple_opt_pass
+{
+public:
+ pass_test_groups(gcc::context *ctxt)
+ : gimple_opt_pass(pass_data_test_groups, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ bool gate (function *) { return true; }
+ virtual unsigned int execute (function *);
+
+}; // class pass_test_groups
+
+/* Determine if STMT is a call with NUM_ARGS arguments to a function
+ named FUNCNAME.
+ If so, return STMT as a gcall *. Otherwise return NULL. */
+
+static gcall *
+check_for_named_call (gimple *stmt,
+ const char *funcname, unsigned int num_args)
+{
+ gcc_assert (funcname);
+
+ gcall *call = dyn_cast <gcall *> (stmt);
+ if (!call)
+ return NULL;
+
+ tree fndecl = gimple_call_fndecl (call);
+ if (!fndecl)
+ return NULL;
+
+ if (strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), funcname))
+ return NULL;
+
+ if (gimple_call_num_args (call) != num_args)
+ {
+ error_at (stmt->location, "expected number of args: %i (got %i)",
+ num_args, gimple_call_num_args (call));
+ return NULL;
+ }
+
+ return call;
+}
+
+/* Emit a warning at LOC. */
+
+static void
+emit_warning (location_t loc)
+{
+ source_range src_range = get_range_from_loc (line_table, loc);
+ warning_at (loc, 0, "range %i:%i-%i:%i",
+ LOCATION_LINE (src_range.m_start),
+ LOCATION_COLUMN (src_range.m_start),
+ LOCATION_LINE (src_range.m_finish),
+ LOCATION_COLUMN (src_range.m_finish));
+}
+
+/* Code for simulating the emission of a warning from the middle-end.
+ Emit a warning for each call to a function named "__emit_warning". */
+
+static void
+test_groups (gimple *stmt)
+{
+ gcall *call = check_for_named_call (stmt, "__emit_warning", 1);
+ if (!call)
+ return;
+
+ /* We expect an ADDR_EXPR with a STRING_CST inside it for the
+ initial arg. */
+ tree t_addr_string = gimple_call_arg (call, 0);
+ if (TREE_CODE (t_addr_string) != ADDR_EXPR)
+ {
+ error_at (call->location, "string literal required for arg 1");
+ return;
+ }
+
+ tree t_string = TREE_OPERAND (t_addr_string, 0);
+ if (TREE_CODE (t_string) != STRING_CST)
+ {
+ error_at (call->location, "string literal required for arg 1");
+ return;
+ }
+
+ {
+ auto_diagnostic_group d;
+ if (warning_at (call->location, 0, "%s", call,
+ TREE_STRING_POINTER (t_string)))
+ {
+ inform (call->location, "message for note");
+ inform (call->location, " some more detail");
+ inform (call->location, " yet more detail");
+ }
+ }
+ inform (call->location, "an unrelated message");
+}
+
+/* Call test_groups on every statement within FUN. */
+
+unsigned int
+pass_test_groups::execute (function *fun)
+{
+ gimple_stmt_iterator gsi;
+ basic_block bb;
+
+ FOR_EACH_BB_FN (bb, fun)
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ test_groups (stmt);
+ }
+
+ return 0;
+}
+
+/* Custom diagnostic callback, to avoid having the path in the
+ expected output. */
+
+void
+test_diagnostic_starter (diagnostic_context *context,
+ diagnostic_info *diagnostic)
+{
+ pp_set_prefix (context->printer, xstrdup ("PREFIX: "));
+}
+
+/* Custom diagnostic callback, to avoid having the path in the
+ expected output. */
+
+void
+test_diagnostic_start_span_fn (diagnostic_context *context,
+ expanded_location exploc)
+{
+ pp_string (context->printer, "START_SPAN_FN: ");
+ pp_newline (context->printer);
+}
+
+/* Custom diagnostic callback: loudly announce a new diagnostic group. */
+
+static void
+test_begin_group_cb (diagnostic_context * context)
+{
+ pp_string (context->printer,
+ "================================= BEGIN GROUP ==============================");
+ pp_newline (context->printer);
+}
+
+/* Custom diagnostic callback: loudly announce the end of a
+ diagnostic group. */
+
+static void
+test_end_group_cb (diagnostic_context * context)
+{
+ pp_string (context->printer,
+ "---------------------------------- END GROUP -------------------------------");
+ pp_newline_and_flush (context->printer);
+}
+
+/* Entrypoint for the plugin.
+ Install custom callbacks into the global_dc.
+ Create and register the custom pass. */
+
+int
+plugin_init (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version)
+{
+ struct register_pass_info pass_info;
+ const char *plugin_name = plugin_info->base_name;
+ int argc = plugin_info->argc;
+ struct plugin_argument *argv = plugin_info->argv;
+
+ if (!plugin_default_version_check (version, &gcc_version))
+ return 1;
+
+ diagnostic_starter (global_dc) = test_diagnostic_starter;
+ global_dc->start_span = test_diagnostic_start_span_fn;
+ global_dc->begin_group_cb = test_begin_group_cb;
+ global_dc->end_group_cb = test_end_group_cb;
+
+ pass_info.pass = new pass_test_groups (g);
+ pass_info.reference_pass_name = "*warn_function_noreturn";
+ pass_info.ref_pass_instance_number = 1;
+ pass_info.pos_op = PASS_POS_INSERT_AFTER;
+ register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL,
+ &pass_info);
+
+ return 0;
+}
{ poly-int-05_plugin.c poly-int-test-1.c } \
{ poly-int-06_plugin.c poly-int-test-1.c } \
{ poly-int-07_plugin.c poly-int-test-1.c } \
+ { diagnostic_group_plugin.c \
+ diagnostic-group-test-1.c } \
{ diagnostic_plugin_test_show_locus.c \
diagnostic-test-show-locus-bw.c \
diagnostic-test-show-locus-color.c \
/* Avoid warnings during early inline pass. */
&& symtab->global_info_ready)
{
+ auto_diagnostic_group d;
if (warning (OPT_Winline, "inlining failed in call to %q+F: %s",
fn, _(cgraph_inline_failed_string (reason))))
{
continue;
location_t loc = gimple_location (stmt);
+ auto_diagnostic_group d;
if (warning_at (loc, OPT_Wnonnull,
"%Gargument %u null where non-null "
"expected", stmt, i + 1))
char buf[WIDE_INT_PRINT_BUFFER_SIZE];
print_dec (i_bound, buf, TYPE_UNSIGNED (TREE_TYPE (loop->nb_iterations))
? UNSIGNED : SIGNED);
+ auto_diagnostic_group d;
if (warning_at (gimple_location (stmt), OPT_Waggressive_loop_optimizations,
"iteration %s invokes undefined behavior", buf))
inform (gimple_location (estmt), "within this loop");
cfun_loc = DECL_SOURCE_LOCATION (cfun->decl);
xloc = expand_location (location);
floc = expand_location (cfun_loc);
+ auto_diagnostic_group d;
if (warning_at (location, wc, gmsgid, expr))
{
TREE_NO_WARNING (expr) = 1;
bool w = false;
if (DECL_P (node))
{
+ auto_diagnostic_group d;
if (msg)
w = warning (OPT_Wdeprecated_declarations,
"%qD is deprecated: %s", node, (const char *) msg);
what = DECL_NAME (TYPE_NAME (node));
}
+ auto_diagnostic_group d;
if (what)
{
if (msg)