c++: reduce redundant deprecated warnings

If a template uses a deprecated function, we should warn there and not also
whenever the template is instantiated.  I implement this by suppressing
the warning at the location; then to make this also work with modules, I
need to make sure to set TREE_NO_WARNING so that the warning spec for this
location gets recorded.

And then I noticed that has_warning_spec was broken such that if it
returned true than get_nowarn_spec would always return null.

gcc/cp/ChangeLog:

	* decl2.cc (cp_handle_deprecated_or_unavailable): Avoid redundant
	warning.
	* call.cc (build_over_call): Set TREE_NO_WARNING for calls
	to deprecated functions.
	* semantics.cc (finish_call_expr): Propagate TREE_NO_WARNING.

gcc/ChangeLog:

	* warning-control.cc (has_warning_spec): Fix handling of
	get_no_warning_bit.

gcc/testsuite/ChangeLog:

	* g++.dg/warn/deprecated-21.C: New test.
	* g++.dg/modules/warn-spec-2_a.C: New test.
	* g++.dg/modules/warn-spec-2_b.C: New test.
This commit is contained in:
Jason Merrill 2024-11-18 15:00:32 +01:00
parent a4842917dc
commit 59fbdb3a87
7 changed files with 56 additions and 6 deletions

View File

@ -10004,6 +10004,11 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
SET_EXPR_LOCATION (expr, input_location);
if (TREE_THIS_VOLATILE (fn) && cfun)
current_function_returns_abnormally = 1;
if (TREE_DEPRECATED (fn)
&& warning_suppressed_at (input_location,
OPT_Wdeprecated_declarations))
/* Make the expr consistent with the location. */
TREE_NO_WARNING (expr) = true;
if (immediate_invocation_p (fn))
{
tree obj_arg = NULL_TREE, exprimm = expr;
@ -10704,6 +10709,14 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
if (TREE_CODE (c) == CALL_EXPR)
suppress_warning (c /* Suppress all warnings. */);
}
else if (TREE_DEPRECATED (fn)
&& warning_suppressed_at (input_location,
OPT_Wdeprecated_declarations))
{
tree c = extract_call_expr (call);
if (TREE_CODE (c) == CALL_EXPR)
TREE_NO_WARNING (c) = true;
}
return call;
}

View File

@ -5943,7 +5943,12 @@ cp_handle_deprecated_or_unavailable (tree decl, tsubst_flags_t complain)
}
}
else
warned = warn_deprecated_use (decl, NULL_TREE);
{
if (!warning_suppressed_at (input_location,
OPT_Wdeprecated_declarations))
warned = warn_deprecated_use (decl, NULL_TREE);
suppress_warning_at (input_location, OPT_Wdeprecated_declarations);
}
return warned;
}

View File

@ -3313,11 +3313,12 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
orig_fn = sel_fn;
}
result = build_call_vec (TREE_TYPE (result), orig_fn, orig_args);
SET_EXPR_LOCATION (result, input_location);
KOENIG_LOOKUP_P (result) = koenig_p;
tree r = build_call_vec (TREE_TYPE (result), orig_fn, orig_args);
SET_EXPR_LOCATION (r, input_location);
KOENIG_LOOKUP_P (r) = koenig_p;
TREE_NO_WARNING (r) = TREE_NO_WARNING (result);
release_tree_vector (orig_args);
result = convert_from_reference (result);
result = convert_from_reference (r);
}
return result;

View File

@ -0,0 +1,11 @@
// { dg-additional-options -fmodules }
export module M;
[[deprecated]] void depr_fn() {}
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
export {
template <class T> void f(T) { depr_fn(); }
}

View File

@ -0,0 +1,8 @@
// { dg-additional-options -fmodules }
import M;
int main()
{
f(42);
}

View File

@ -0,0 +1,12 @@
// { dg-do compile { target c++11 } }
[[deprecated]] void depr_fn() {}
template <class T> void f(T) {
depr_fn(); // { dg-warning "deprecated" }
}
int main()
{
f(42);
}

View File

@ -262,7 +262,7 @@ copy_warning (gimple *to, const gimple *from)
bool has_warning_spec (const_tree t)
{
const location_t loc = get_location (t);
return !RESERVED_LOCATION_P (loc) && !get_no_warning_bit (t);
return !RESERVED_LOCATION_P (loc) && get_no_warning_bit (t);
}
/* Retrieve warning dispostion bitmap for tree streaming. */