diff mbox series

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

Message ID 20210310032211.1265956-1-polacek@redhat.com
State New
Headers show
Series c++: Fix bogus warning in deprecated namespace [PR99318] | expand

Commit Message

Marek Polacek March 10, 2021, 3:22 a.m. UTC
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.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/10?

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.
---
 gcc/cp/decl2.c                                |  3 ++-
 .../g++.dg/cpp0x/attributes-namespace6.C      | 21 +++++++++++++++++++
 gcc/testsuite/g++.dg/cpp0x/gen-attrs-73.C     | 20 ++++++++++++++++++
 3 files changed, 43 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/attributes-namespace6.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-73.C


base-commit: 63d74fed4566f1de583c368ecb9e2fc423fb1c87

Comments

Jason Merrill March 23, 2021, 1:05 p.m. UTC | #1
On 3/9/21 10:22 PM, Marek Polacek wrote:
> 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.

Hmm, I'd think we should warn about N as a consequence of seeing N::, 
not because we are using S.  For instance, in

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

we should warn about the using-directive, but not also the declaration 
of 's'.

But the patch is OK, that's just a possible future direction.

> 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.
> 
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/10?
> 
> 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.
> ---
>   gcc/cp/decl2.c                                |  3 ++-
>   .../g++.dg/cpp0x/attributes-namespace6.C      | 21 +++++++++++++++++++
>   gcc/testsuite/g++.dg/cpp0x/gen-attrs-73.C     | 20 ++++++++++++++++++
>   3 files changed, 43 insertions(+), 1 deletion(-)
>   create mode 100644 gcc/testsuite/g++.dg/cpp0x/attributes-namespace6.C
>   create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-73.C
> 
> diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
> index c46100de89a..ef79f6cc6d1 100644
> --- a/gcc/cp/decl2.c
> +++ b/gcc/cp/decl2.c
> @@ -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);
> diff --git a/gcc/testsuite/g++.dg/cpp0x/attributes-namespace6.C b/gcc/testsuite/g++.dg/cpp0x/attributes-namespace6.C
> new file mode 100644
> index 00000000000..2fbc8e1158f
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/attributes-namespace6.C
> @@ -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" }
> +    }
> +};
> diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-73.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-73.C
> new file mode 100644
> index 00000000000..75f4077af7b
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-73.C
> @@ -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" }
> +}
> 
> base-commit: 63d74fed4566f1de583c368ecb9e2fc423fb1c87
>
Marek Polacek March 23, 2021, 3:03 p.m. UTC | #2
On Tue, Mar 23, 2021 at 09:05:42AM -0400, Jason Merrill via Gcc-patches wrote:
> On 3/9/21 10:22 PM, Marek Polacek wrote:
> > 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.
> 
> Hmm, I'd think we should warn about N as a consequence of seeing N::, not
> because we are using S.  For instance, in
> 
> namespace [[deprecated]] N { struct S { }; }
> using namespace N;
> S s;
> 
> we should warn about the using-directive, but not also the declaration of
> 's'.

I agree, opened 99729.

> But the patch is OK, that's just a possible future direction.

Thanks, pushed.

Marek
diff mbox series

Patch

diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index c46100de89a..ef79f6cc6d1 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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);
diff --git a/gcc/testsuite/g++.dg/cpp0x/attributes-namespace6.C b/gcc/testsuite/g++.dg/cpp0x/attributes-namespace6.C
new file mode 100644
index 00000000000..2fbc8e1158f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/attributes-namespace6.C
@@ -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" }
+    }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-73.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-73.C
new file mode 100644
index 00000000000..75f4077af7b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-73.C
@@ -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" }
+}