c++: Fix bogus warning in deprecated namespace [PR99318]

In GCC 10, I introduced cp_warn_deprecated_use_scopes so that we can
handle attribute deprecated on a namespace declaration.  This
function walks the decl's contexts so that we warn for code like

  namespace [[deprecated]] N { struct S { }; }
  N::S s;

We call cp_warn_deprecated_use_scopes when we encounter a TYPE_DECL.
But in the following testcase we have a TYPE_DECL whose context is
a deprecated function; that itself is not a reason to warn.  This
patch limits for which entities we call cp_warn_deprecated_use;
essentially it's what can follow ::.

I noticed that we didn't test that

  struct [[deprecated]] S { static void fn(); };
  S::fn();

produces the expected warning, so I've added gen-attrs-73.C.

gcc/cp/ChangeLog:

	PR c++/99318
	* decl2.c (cp_warn_deprecated_use_scopes): Only call
	cp_warn_deprecated_use when decl is a namespace, class, or enum.

gcc/testsuite/ChangeLog:

	PR c++/99318
	* g++.dg/cpp0x/attributes-namespace6.C: New test.
	* g++.dg/cpp0x/gen-attrs-73.C: New test.
This commit is contained in:
Marek Polacek 2021-03-09 19:23:48 -05:00
parent 212f4988f3
commit 831f9f768e
3 changed files with 43 additions and 1 deletions

View File

@ -5529,7 +5529,8 @@ cp_warn_deprecated_use_scopes (tree scope)
&& scope != error_mark_node
&& scope != global_namespace)
{
if (cp_warn_deprecated_use (scope))
if ((TREE_CODE (scope) == NAMESPACE_DECL || OVERLOAD_TYPE_P (scope))
&& cp_warn_deprecated_use (scope))
return;
if (TYPE_P (scope))
scope = CP_TYPE_CONTEXT (scope);

View File

@ -0,0 +1,21 @@
// PR c++/99318
// { dg-do compile { target c++11 } }
template <typename T>
struct S {
[[deprecated("foo")]] unsigned m_fn (char const chr)
{
using index_t = unsigned;
return T::arr[static_cast<index_t>(chr)]; // { dg-bogus "deprecated" }
}
};
extern unsigned int arr[];
struct R {
[[deprecated("foo")]] unsigned m_fn (char const chr)
{
using index_t = unsigned;
return arr[static_cast<index_t>(chr)]; // { dg-bogus "deprecated" }
}
};

View File

@ -0,0 +1,20 @@
// { dg-do compile { target c++11 } }
// Test attribute deprecated on :: with class, enum, and namespace.
struct [[deprecated]] S { static void fn(); static const int s = 0; };
union [[deprecated]] U { static void fn(); static const int u = 0; };
enum [[deprecated]] E { X };
enum class [[deprecated]] SE { Y };
namespace [[deprecated]] N { struct S { }; }
void
g ()
{
S::fn(); // { dg-warning "deprecated" }
(void) S::s; // { dg-warning "deprecated" }
U::fn(); // { dg-warning "deprecated" }
(void) U::u; // { dg-warning "deprecated" }
(void) E::X; // { dg-warning "deprecated" }
(void) SE::Y; // { dg-warning "deprecated" }
N::S s; // { dg-warning "deprecated" }
}