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

Reply via email to