Message ID | 20210310032211.1265956-1-polacek@redhat.com |
---|---|
State | New |
Headers | show |
Series | c++: Fix bogus warning in deprecated namespace [PR99318] | expand |
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 >
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 --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" } +}