Hi! As the following testcase shows, if we have a deprecated class, we warn about any uses, including e.g. arguments of methods of that class (how can one e.g. declare or define a copy ctor without warnings?).
The following patch changes it, so that we don't warn about deprecated uses in methods of that deprecated class (warn about uses of other deprecated classes of course). There is still one xfailed case where we warn about template-id in the containing scope if the deprecated class is a template. clang++ warns about the bar (const C &, const C &) function, both about the parameters and about the use in the body (like g++) and doesn't warn inside of (perhaps uninstantiated only) templates at all (which I think is better that we do warn). Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2018-03-14 Jakub Jelinek <ja...@redhat.com> PR c++/84222 * cp-tree.h (cp_warn_deprecated_use): Declare. * tree.c (cp_warn_deprecated_use): New function. * typeck2.c (build_functional_cast): Use it. * decl.c (grokparms): Likewise. (grokdeclarator): Likewise. Temporarily push nested class scope around grokparms call for out of class member definitions. * g++.dg/warn/deprecated.C (T::member3): Change dg-warning to dg-bogus. * g++.dg/warn/deprecated-6.C (T::member3): Likewise. * g++.dg/warn/deprecated-13.C: New test. --- gcc/cp/cp-tree.h.jj 2018-03-11 17:48:36.360061435 +0100 +++ gcc/cp/cp-tree.h 2018-03-14 11:49:58.924816419 +0100 @@ -7064,6 +7064,7 @@ extern tree cxx_copy_lang_qualifiers (c extern void cxx_print_statistics (void); extern bool maybe_warn_zero_as_null_pointer_constant (tree, location_t); +extern void cp_warn_deprecated_use (tree); /* in ptree.c */ extern void cxx_print_xnode (FILE *, tree, int); --- gcc/cp/tree.c.jj 2018-03-07 22:51:58.671478659 +0100 +++ gcc/cp/tree.c 2018-03-14 11:49:58.926816421 +0100 @@ -5347,6 +5347,19 @@ cp_tree_code_length (enum tree_code code } } +/* Wrapper around warn_deprecated_use that doesn't warn for + current_class_type. */ + +void +cp_warn_deprecated_use (tree node) +{ + if (TYPE_P (node) + && current_class_type + && TYPE_MAIN_VARIANT (node) == current_class_type) + return; + warn_deprecated_use (node, NULL_TREE); +} + /* Implement -Wzero_as_null_pointer_constant. Return true if the conditions for the warning hold, false otherwise. */ bool --- gcc/cp/typeck2.c.jj 2018-03-02 00:15:54.096781050 +0100 +++ gcc/cp/typeck2.c 2018-03-14 11:49:58.931816424 +0100 @@ -2057,7 +2057,7 @@ build_functional_cast (tree exp, tree pa if (complain & tf_warning && TREE_DEPRECATED (type) && DECL_ARTIFICIAL (exp)) - warn_deprecated_use (type, NULL_TREE); + cp_warn_deprecated_use (type); } else type = exp; --- gcc/cp/decl.c.jj 2018-03-14 09:44:55.744974946 +0100 +++ gcc/cp/decl.c 2018-03-14 12:18:08.094012453 +0100 @@ -10448,7 +10448,7 @@ grokdeclarator (const cp_declarator *dec suppress reports of deprecated items. */ if (type && TREE_DEPRECATED (type) && deprecated_state != DEPRECATED_SUPPRESS) - warn_deprecated_use (type, NULL_TREE); + cp_warn_deprecated_use (type); if (type && TREE_CODE (type) == TYPE_DECL) { typedef_decl = type; @@ -10456,7 +10456,7 @@ grokdeclarator (const cp_declarator *dec if (TREE_DEPRECATED (type) && DECL_ARTIFICIAL (typedef_decl) && deprecated_state != DEPRECATED_SUPPRESS) - warn_deprecated_use (type, NULL_TREE); + cp_warn_deprecated_use (type); } /* No type at all: default to `int', and set DEFAULTED_INT because it was not a user-defined typedef. */ @@ -11271,8 +11271,18 @@ grokdeclarator (const cp_declarator *dec explicitp = 2; } - arg_types = grokparms (declarator->u.function.parameters, - &parms); + tree pushed_scope = NULL_TREE; + if (funcdecl_p + && decl_context != FIELD + && inner_declarator->u.id.qualifying_scope + && CLASS_TYPE_P (inner_declarator->u.id.qualifying_scope)) + pushed_scope + = push_scope (inner_declarator->u.id.qualifying_scope); + + arg_types = grokparms (declarator->u.function.parameters, &parms); + + if (pushed_scope) + pop_scope (pushed_scope); if (inner_declarator && inner_declarator->kind == cdk_id @@ -12799,7 +12809,7 @@ grokparms (tree parmlist, tree *parms) { tree deptype = type_is_deprecated (type); if (deptype) - warn_deprecated_use (deptype, NULL_TREE); + cp_warn_deprecated_use (deptype); } /* Top-level qualifiers on the parameters are --- gcc/testsuite/g++.dg/warn/deprecated.C.jj 2017-04-28 22:16:51.986480480 +0200 +++ gcc/testsuite/g++.dg/warn/deprecated.C 2018-03-14 12:51:54.847224549 +0100 @@ -102,7 +102,7 @@ T *p3; // { dg-warning "'T' is deprec inline void T::member1(int) {} -int T::member3(T *p) // { dg-warning "'T' is deprecated" } +int T::member3(T *p) // { dg-bogus "'T' is deprecated" } { p->member1(1); /* { dg-warning "'void T::member1\\(int\\)' is deprecated" } */ (*p).member1(2); /* { dg-warning "'void T::member1\\(int\\)' is deprecated" } */ @@ -113,5 +113,3 @@ int T::member3(T *p) // { dg-warning "' return f1(); /* { dg-warning "'INT1 f1\\(\\)' is deprecated" } */ } #endif - - --- gcc/testsuite/g++.dg/warn/deprecated-6.C.jj 2017-04-28 22:16:51.970480683 +0200 +++ gcc/testsuite/g++.dg/warn/deprecated-6.C 2018-03-14 12:51:15.721213235 +0100 @@ -98,7 +98,7 @@ T *p3; // { dg-warning "'T' is deprec inline void T::member1(int) {} -int T::member3(T *p) // { dg-warning "'T' is deprecated: Please avoid T" } +int T::member3(T *p) // { dg-bogus "'T' is deprecated: Please avoid T" } { p->member1(1); /* { dg-warning "'void T::member1\\(int\\)' is deprecated: Please avoid member1" } */ (*p).member1(2); /* { dg-warning "'void T::member1\\(int\\)' is deprecated: Please avoid member1" } */ --- gcc/testsuite/g++.dg/warn/deprecated-13.C.jj 2018-03-14 12:34:43.523210515 +0100 +++ gcc/testsuite/g++.dg/warn/deprecated-13.C 2018-03-14 12:34:13.103233036 +0100 @@ -0,0 +1,44 @@ +// PR c++/84222 +// { dg-do compile } + +struct __attribute__((deprecated)) C { // { dg-message "declared here" } + C () {} + C (const C &); // { dg-bogus "'C' is deprecated" } + C (const C &x, const C &y) { C z = x; } // { dg-bogus "'C' is deprecated" } + void foo (const C &x, const C &y); // { dg-bogus "'C' is deprecated" } +}; + +void +C::foo (const C &x, const C &y) // { dg-bogus "'C' is deprecated" } +{ + C z = x; // { dg-bogus "'C' is deprecated" } +} + +void +bar (const C &x, const C &y) // { dg-warning "'C' is deprecated" } +{ + C z = x; // { dg-warning "'C' is deprecated" } +} + +template <int N> +struct __attribute__((deprecated)) D { // { dg-message "declared here" } + D () {} + D (const D &); // { dg-bogus "is deprecated" } + D (const D &x, const D &y) { D z = x; } // { dg-bogus "is deprecated" } + void foo (const D &x, const D &y); // { dg-bogus "is deprecated" } +}; + +template <int N> +void +D<N>::foo // { dg-bogus "is deprecated" "" { xfail *-*-* } } +(const D &x, const D &y) // { dg-bogus "is deprecated" } +{ + D z = x; // { dg-bogus "is deprecated" } +} + +template <int N> +void +bar (const D<N> &x, const D<N> &y) // { dg-warning "is deprecated" } +{ + D<N> z = x; // { dg-warning "is deprecated" } +} Jakub