Message ID | 20210923161636.36242-1-polacek@redhat.com |
---|---|
State | New |
Headers |
Return-Path: <gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org> X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 1F66D3858406 for <patchwork@sourceware.org>; Thu, 23 Sep 2021 16:17:31 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1F66D3858406 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1632413851; bh=sTQzXHNflRATiAXcrRS/7i73Pazt8MmoIbyniIPajEM=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=DjBc12AFufDXrEla7t3tb9VAMQvMB9dNanYR+iNguNpymqKAHTVO6OAUKhEhGNF9U W1pZ2u8MmRsNJwkWMfZ2l9SVo/rZnlk51QZGfLCh9IuE/dIAkp4Nr5FzP9tkHsL/A8 o42S8IC4c/oK5u/cb1Pbt4bkeRw5wqsxLuLjy2Lo= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id EA6043858406 for <gcc-patches@gcc.gnu.org>; Thu, 23 Sep 2021 16:16:43 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org EA6043858406 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-476-_tk16HpDOxex7-zUjVU22Q-1; Thu, 23 Sep 2021 12:16:42 -0400 X-MC-Unique: _tk16HpDOxex7-zUjVU22Q-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 6DFE7802921 for <gcc-patches@gcc.gnu.org>; Thu, 23 Sep 2021 16:16:41 +0000 (UTC) Received: from pdp-11.redhat.com (unknown [10.22.10.38]) by smtp.corp.redhat.com (Postfix) with ESMTP id 251827944C for <gcc-patches@gcc.gnu.org>; Thu, 23 Sep 2021 16:16:41 +0000 (UTC) To: GCC Patches <gcc-patches@gcc.gnu.org> Subject: [PATCH] attribs: Allow optional second arg for attr deprecated [PR102049] Date: Thu, 23 Sep 2021 12:16:36 -0400 Message-Id: <20210923161636.36242-1-polacek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII" X-Spam-Status: No, score=-14.9 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list <gcc-patches.gcc.gnu.org> List-Unsubscribe: <https://gcc.gnu.org/mailman/options/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe> List-Archive: <https://gcc.gnu.org/pipermail/gcc-patches/> List-Post: <mailto:gcc-patches@gcc.gnu.org> List-Help: <mailto:gcc-patches-request@gcc.gnu.org?subject=help> List-Subscribe: <https://gcc.gnu.org/mailman/listinfo/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe> From: Marek Polacek via Gcc-patches <gcc-patches@gcc.gnu.org> Reply-To: Marek Polacek <polacek@redhat.com> Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" <gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org> |
Series |
attribs: Allow optional second arg for attr deprecated [PR102049]
|
|
Commit Message
Marek Polacek
Sept. 23, 2021, 4:16 p.m. UTC
Clang implements something we don't have: __attribute__((deprecated("message", "replacement"))); which seems pretty neat so I wrote this patch to add it to gcc. It doesn't allow the optional second argument in the standard [[]] form so as not to clash with possible future standard additions. I had hoped we could print a nice fix-it replacement hint, but that won't be possible until warn_deprecated_use gets something better than input_location. Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? PR c++/102049 gcc/c-family/ChangeLog: * c-attribs.c (c_common_attribute_table): Increase max_len for deprecated. (handle_deprecated_attribute): Allow an optional second argument in the GNU form of attribute deprecated. gcc/c/ChangeLog: * c-parser.c (c_parser_std_attribute): Give a diagnostic when the standard form of an attribute deprecated has a second argument. gcc/ChangeLog: * doc/extend.texi: Document attribute deprecated with an optional second argument. * tree.c (warn_deprecated_use): Print the replacement argument, if any. gcc/testsuite/ChangeLog: * gcc.dg/c2x-attr-deprecated-3.c: Adjust dg-error. * c-c++-common/Wdeprecated-arg-1.c: New test. --- gcc/c-family/c-attribs.c | 17 ++++++++++++- gcc/c/c-parser.c | 8 ++++++ gcc/doc/extend.texi | 24 ++++++++++++++++++ .../c-c++-common/Wdeprecated-arg-1.c | 21 ++++++++++++++++ gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c | 2 +- gcc/tree.c | 25 +++++++++++++++---- 6 files changed, 90 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/Wdeprecated-arg-1.c base-commit: f6a05b23cc2e53c38e8321ddb5d2cbe40737e506
Comments
Any thoughts? On Thu, Sep 23, 2021 at 12:16:36PM -0400, Marek Polacek via Gcc-patches wrote: > Clang implements something we don't have: > > __attribute__((deprecated("message", "replacement"))); > > which seems pretty neat so I wrote this patch to add it to gcc. > > It doesn't allow the optional second argument in the standard [[]] > form so as not to clash with possible future standard additions. > > I had hoped we could print a nice fix-it replacement hint, but that > won't be possible until warn_deprecated_use gets something better than > input_location. > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > PR c++/102049 > > gcc/c-family/ChangeLog: > > * c-attribs.c (c_common_attribute_table): Increase max_len for > deprecated. > (handle_deprecated_attribute): Allow an optional second argument > in the GNU form of attribute deprecated. > > gcc/c/ChangeLog: > > * c-parser.c (c_parser_std_attribute): Give a diagnostic when > the standard form of an attribute deprecated has a second argument. > > gcc/ChangeLog: > > * doc/extend.texi: Document attribute deprecated with an > optional second argument. > * tree.c (warn_deprecated_use): Print the replacement argument, > if any. > > gcc/testsuite/ChangeLog: > > * gcc.dg/c2x-attr-deprecated-3.c: Adjust dg-error. > * c-c++-common/Wdeprecated-arg-1.c: New test. > --- > gcc/c-family/c-attribs.c | 17 ++++++++++++- > gcc/c/c-parser.c | 8 ++++++ > gcc/doc/extend.texi | 24 ++++++++++++++++++ > .../c-c++-common/Wdeprecated-arg-1.c | 21 ++++++++++++++++ > gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c | 2 +- > gcc/tree.c | 25 +++++++++++++++---- > 6 files changed, 90 insertions(+), 7 deletions(-) > create mode 100644 gcc/testsuite/c-c++-common/Wdeprecated-arg-1.c > > diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c > index 007b928c54b..ef857a9ae2c 100644 > --- a/gcc/c-family/c-attribs.c > +++ b/gcc/c-family/c-attribs.c > @@ -409,7 +409,7 @@ const struct attribute_spec c_common_attribute_table[] = > to prevent its usage in source code. */ > { "no vops", 0, 0, true, false, false, false, > handle_novops_attribute, NULL }, > - { "deprecated", 0, 1, false, false, false, false, > + { "deprecated", 0, 2, false, false, false, false, > handle_deprecated_attribute, NULL }, > { "unavailable", 0, 1, false, false, false, false, > handle_unavailable_attribute, NULL }, > @@ -4107,6 +4107,21 @@ handle_deprecated_attribute (tree *node, tree name, > error ("deprecated message is not a string"); > *no_add_attrs = true; > } > + else if (TREE_CHAIN (args) != NULL_TREE) > + { > + /* We allow an optional second argument in the GNU form of > + attribute deprecated, which specifies the replacement. */ > + if (flags & ATTR_FLAG_CXX11) > + { > + error ("replacement argument only allowed in GNU attributes"); > + *no_add_attrs = true; > + } > + else if (TREE_CODE (TREE_VALUE (TREE_CHAIN (args))) != STRING_CST) > + { > + error ("replacement argument is not a string"); > + *no_add_attrs = true; > + } > + } > > if (DECL_P (*node)) > { > diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c > index fa29d2c15fc..2b47f01d166 100644 > --- a/gcc/c/c-parser.c > +++ b/gcc/c/c-parser.c > @@ -4952,6 +4952,14 @@ c_parser_std_attribute (c_parser *parser, bool for_tm) > TREE_VALUE (attribute) > = c_parser_attribute_arguments (parser, takes_identifier, > require_string, false); > + if (c_parser_next_token_is (parser, CPP_COMMA) > + && strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0) > + { > + error_at (open_loc, "replacement argument only allowed in " > + "GNU attributes"); > + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); > + return error_mark_node; > + } > } > else > c_parser_balanced_token_sequence (parser); > diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi > index 9501a60f20e..7d399f4b2bc 100644 > --- a/gcc/doc/extend.texi > +++ b/gcc/doc/extend.texi > @@ -2860,6 +2860,7 @@ StrongAlias (allocate, alloc); > > @item deprecated > @itemx deprecated (@var{msg}) > +@itemx deprecated (@var{msg}, @var{replacement}) > @cindex @code{deprecated} function attribute > The @code{deprecated} attribute results in a warning if the function > is used anywhere in the source file. This is useful when identifying > @@ -2880,6 +2881,13 @@ results in a warning on line 3 but not line 2. The optional @var{msg} > argument, which must be a string, is printed in the warning if > present. > > +This attribute accepts an optional second argument which specifies > +the replacement that ought to be used instead: > + > +@smallexample > +int old_fn () __attribute__ ((deprecated("unsafe", "new_fn"))); > +@end smallexample > + > The @code{deprecated} attribute can also be used for variables and > types (@pxref{Variable Attributes}, @pxref{Type Attributes}.) > > @@ -7409,6 +7417,7 @@ attribute is also not copied. @xref{Common Function Attributes}. > > @item deprecated > @itemx deprecated (@var{msg}) > +@itemx deprecated (@var{msg}, @var{replacement}) > @cindex @code{deprecated} variable attribute > The @code{deprecated} attribute results in a warning if the variable > is used anywhere in the source file. This is useful when identifying > @@ -7429,6 +7438,13 @@ results in a warning on line 3 but not line 2. The optional @var{msg} > argument, which must be a string, is printed in the warning if > present. > > +This attribute accepts an optional second argument which specifies > +the replacement that ought to be used instead: > + > +@smallexample > +extern int old_var __attribute__ ((deprecated("unsafe", "new_var"))); > +@end smallexample > + > The @code{deprecated} attribute can also be used for functions and > types (@pxref{Common Function Attributes}, > @pxref{Common Type Attributes}). > @@ -8492,6 +8508,7 @@ struct __attribute__ ((copy ( (struct A *)0)) B @{ /* @r{@dots{}} */ @}; > > @item deprecated > @itemx deprecated (@var{msg}) > +@itemx deprecated (@var{msg}, @var{replacement}) > @cindex @code{deprecated} type attribute > The @code{deprecated} attribute results in a warning if the type > is used anywhere in the source file. This is useful when identifying > @@ -8522,6 +8539,13 @@ present. Control characters in the string will be replaced with > escape sequences, and if the @option{-fmessage-length} option is set > to 0 (its default value) then any newline characters will be ignored. > > +This attribute accepts an optional second argument which specifies > +the replacement that ought to be used instead: > + > +@smallexample > +typedef int oldtype __attribute__ ((deprecated("unsafe", "newtype"))); > +@end smallexample > + > The @code{deprecated} attribute can also be used for functions and > variables (@pxref{Function Attributes}, @pxref{Variable Attributes}.) > > diff --git a/gcc/testsuite/c-c++-common/Wdeprecated-arg-1.c b/gcc/testsuite/c-c++-common/Wdeprecated-arg-1.c > new file mode 100644 > index 00000000000..b03e0e42ad6 > --- /dev/null > +++ b/gcc/testsuite/c-c++-common/Wdeprecated-arg-1.c > @@ -0,0 +1,21 @@ > +/* PR c++/102049 */ > +/* { dg-do compile } */ > +/* { dg-additional-options "-std=c++11" { target c++ } } */ > + > +typedef int __attribute__((deprecated("obsolete", "newtype"))) oldtype; > +__attribute__((deprecated("unsafe", "get_it_s"))) void get_it (int); /* { dg-message "declared here" } */ > +[[gnu::deprecated("g", "")]] void g(); /* { dg-error "only allowed in GNU attributes" } */ > +[[deprecated("h", "")]] void h(); /* { dg-error "only allowed in GNU attributes" } */ > +__attribute__((deprecated("unsafe", 1))) void f2(); /* { dg-error "argument is not a string" } */ > +__attribute__((deprecated("unsafe", "newvar"))) int oldvar; /* { dg-message "declared here" } */ > + > +int > +main () > +{ > + get_it (42); /* { dg-warning "is deprecated: unsafe" } */ > + /* { dg-message "use .get_it_s. instead" "" { target *-*-* } .-1 } */ > + oldtype t; /* { dg-warning "is deprecated: obsolete" } */ > + /* { dg-message "use .newtype. instead" "" { target *-*-* } .-1 } */ > + int i = oldvar; /* { dg-warning "is deprecated: unsafe" } */ > + /* { dg-message "use .newvar. instead" "" { target *-*-* } .-1 } */ > +} > diff --git a/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c > index 044725e5123..6cb70705bbf 100644 > --- a/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c > +++ b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c > @@ -6,6 +6,6 @@ > > [[deprecated(0)]] int b; /* { dg-error "expected" } */ > > -[[deprecated("", 123)]] int c; /* { dg-error "expected" } */ > +[[deprecated("", 123)]] int c; /* { dg-error "only allowed in GNU attributes" } */ > > [[deprecated((""))]] int d; /* { dg-error "expected" } */ > diff --git a/gcc/tree.c b/gcc/tree.c > index 561b9cd56bd..5cb2d57a960 100644 > --- a/gcc/tree.c > +++ b/gcc/tree.c > @@ -12002,8 +12002,9 @@ bool > warn_deprecated_use (tree node, tree attr) > { > escaped_string msg; > + escaped_string rep; > > - if (node == 0 || !warn_deprecated_decl) > + if (node == NULL_TREE || !warn_deprecated_decl) > return false; > > if (!attr) > @@ -12023,7 +12024,12 @@ warn_deprecated_use (tree node, tree attr) > attr = lookup_attribute ("deprecated", attr); > > if (attr) > - msg.escape (TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr)))); > + { > + tree val = TREE_VALUE (attr); > + msg.escape (TREE_STRING_POINTER (TREE_VALUE (val))); > + if (TREE_CHAIN (val)) > + rep.escape (TREE_STRING_POINTER (TREE_VALUE (TREE_CHAIN (val)))); > + } > > bool w = false; > if (DECL_P (node)) > @@ -12036,7 +12042,11 @@ warn_deprecated_use (tree node, tree attr) > w = warning (OPT_Wdeprecated_declarations, > "%qD is deprecated", node); > if (w) > - inform (DECL_SOURCE_LOCATION (node), "declared here"); > + { > + if (rep) > + inform (input_location, "use %qs instead", (const char *) rep); > + inform (DECL_SOURCE_LOCATION (node), "declared here"); > + } > } > else if (TYPE_P (node)) > { > @@ -12072,8 +12082,13 @@ warn_deprecated_use (tree node, tree attr) > "type is deprecated"); > } > > - if (w && decl) > - inform (DECL_SOURCE_LOCATION (decl), "declared here"); > + if (w) > + { > + if (rep) > + inform (input_location, "use %qs instead", (const char *) rep); > + if (decl) > + inform (DECL_SOURCE_LOCATION (decl), "declared here"); > + } > } > > return w; > > base-commit: f6a05b23cc2e53c38e8321ddb5d2cbe40737e506 > -- > 2.31.1 > Marek
On Mon, Oct 11, 2021 at 11:19 AM Marek Polacek via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > Any thoughts? I think it's a good idea, but then again I can't approve it, so... well, who can, then? > > On Thu, Sep 23, 2021 at 12:16:36PM -0400, Marek Polacek via Gcc-patches wrote: > > Clang implements something we don't have: > > > > __attribute__((deprecated("message", "replacement"))); > > > > which seems pretty neat so I wrote this patch to add it to gcc. > > > > It doesn't allow the optional second argument in the standard [[]] > > form so as not to clash with possible future standard additions. > > > > I had hoped we could print a nice fix-it replacement hint, but that > > won't be possible until warn_deprecated_use gets something better than > > input_location. Looking forward to the fix-it hint support being added! > > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > > > PR c++/102049 > > > > gcc/c-family/ChangeLog: > > > > * c-attribs.c (c_common_attribute_table): Increase max_len for > > deprecated. > > (handle_deprecated_attribute): Allow an optional second argument > > in the GNU form of attribute deprecated. > > > > gcc/c/ChangeLog: > > > > * c-parser.c (c_parser_std_attribute): Give a diagnostic when > > the standard form of an attribute deprecated has a second argument. > > > > gcc/ChangeLog: > > > > * doc/extend.texi: Document attribute deprecated with an > > optional second argument. > > * tree.c (warn_deprecated_use): Print the replacement argument, > > if any. > > > > gcc/testsuite/ChangeLog: > > > > * gcc.dg/c2x-attr-deprecated-3.c: Adjust dg-error. > > * c-c++-common/Wdeprecated-arg-1.c: New test. > > --- > > gcc/c-family/c-attribs.c | 17 ++++++++++++- > > gcc/c/c-parser.c | 8 ++++++ > > gcc/doc/extend.texi | 24 ++++++++++++++++++ > > .../c-c++-common/Wdeprecated-arg-1.c | 21 ++++++++++++++++ > > gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c | 2 +- > > gcc/tree.c | 25 +++++++++++++++---- > > 6 files changed, 90 insertions(+), 7 deletions(-) > > create mode 100644 gcc/testsuite/c-c++-common/Wdeprecated-arg-1.c > > > > diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c > > index 007b928c54b..ef857a9ae2c 100644 > > --- a/gcc/c-family/c-attribs.c > > +++ b/gcc/c-family/c-attribs.c > > @@ -409,7 +409,7 @@ const struct attribute_spec c_common_attribute_table[] = > > to prevent its usage in source code. */ > > { "no vops", 0, 0, true, false, false, false, > > handle_novops_attribute, NULL }, > > - { "deprecated", 0, 1, false, false, false, false, > > + { "deprecated", 0, 2, false, false, false, false, > > handle_deprecated_attribute, NULL }, > > { "unavailable", 0, 1, false, false, false, false, > > handle_unavailable_attribute, NULL }, > > @@ -4107,6 +4107,21 @@ handle_deprecated_attribute (tree *node, tree name, > > error ("deprecated message is not a string"); > > *no_add_attrs = true; > > } > > + else if (TREE_CHAIN (args) != NULL_TREE) > > + { > > + /* We allow an optional second argument in the GNU form of > > + attribute deprecated, which specifies the replacement. */ > > + if (flags & ATTR_FLAG_CXX11) > > + { > > + error ("replacement argument only allowed in GNU attributes"); > > + *no_add_attrs = true; > > + } > > + else if (TREE_CODE (TREE_VALUE (TREE_CHAIN (args))) != STRING_CST) > > + { > > + error ("replacement argument is not a string"); > > + *no_add_attrs = true; > > + } > > + } > > > > if (DECL_P (*node)) > > { > > diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c > > index fa29d2c15fc..2b47f01d166 100644 > > --- a/gcc/c/c-parser.c > > +++ b/gcc/c/c-parser.c > > @@ -4952,6 +4952,14 @@ c_parser_std_attribute (c_parser *parser, bool for_tm) > > TREE_VALUE (attribute) > > = c_parser_attribute_arguments (parser, takes_identifier, > > require_string, false); > > + if (c_parser_next_token_is (parser, CPP_COMMA) > > + && strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0) > > + { > > + error_at (open_loc, "replacement argument only allowed in " > > + "GNU attributes"); > > + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); > > + return error_mark_node; > > + } > > } > > else > > c_parser_balanced_token_sequence (parser); > > diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi > > index 9501a60f20e..7d399f4b2bc 100644 > > --- a/gcc/doc/extend.texi > > +++ b/gcc/doc/extend.texi > > @@ -2860,6 +2860,7 @@ StrongAlias (allocate, alloc); > > > > @item deprecated > > @itemx deprecated (@var{msg}) > > +@itemx deprecated (@var{msg}, @var{replacement}) > > @cindex @code{deprecated} function attribute > > The @code{deprecated} attribute results in a warning if the function > > is used anywhere in the source file. This is useful when identifying > > @@ -2880,6 +2881,13 @@ results in a warning on line 3 but not line 2. The optional @var{msg} > > argument, which must be a string, is printed in the warning if > > present. > > > > +This attribute accepts an optional second argument which specifies > > +the replacement that ought to be used instead: > > + > > +@smallexample > > +int old_fn () __attribute__ ((deprecated("unsafe", "new_fn"))); > > +@end smallexample > > + > > The @code{deprecated} attribute can also be used for variables and > > types (@pxref{Variable Attributes}, @pxref{Type Attributes}.) > > > > @@ -7409,6 +7417,7 @@ attribute is also not copied. @xref{Common Function Attributes}. > > > > @item deprecated > > @itemx deprecated (@var{msg}) > > +@itemx deprecated (@var{msg}, @var{replacement}) > > @cindex @code{deprecated} variable attribute > > The @code{deprecated} attribute results in a warning if the variable > > is used anywhere in the source file. This is useful when identifying > > @@ -7429,6 +7438,13 @@ results in a warning on line 3 but not line 2. The optional @var{msg} > > argument, which must be a string, is printed in the warning if > > present. > > > > +This attribute accepts an optional second argument which specifies > > +the replacement that ought to be used instead: > > + > > +@smallexample > > +extern int old_var __attribute__ ((deprecated("unsafe", "new_var"))); > > +@end smallexample > > + > > The @code{deprecated} attribute can also be used for functions and > > types (@pxref{Common Function Attributes}, > > @pxref{Common Type Attributes}). > > @@ -8492,6 +8508,7 @@ struct __attribute__ ((copy ( (struct A *)0)) B @{ /* @r{@dots{}} */ @}; > > > > @item deprecated > > @itemx deprecated (@var{msg}) > > +@itemx deprecated (@var{msg}, @var{replacement}) > > @cindex @code{deprecated} type attribute > > The @code{deprecated} attribute results in a warning if the type > > is used anywhere in the source file. This is useful when identifying > > @@ -8522,6 +8539,13 @@ present. Control characters in the string will be replaced with > > escape sequences, and if the @option{-fmessage-length} option is set > > to 0 (its default value) then any newline characters will be ignored. > > > > +This attribute accepts an optional second argument which specifies > > +the replacement that ought to be used instead: > > + > > +@smallexample > > +typedef int oldtype __attribute__ ((deprecated("unsafe", "newtype"))); > > +@end smallexample > > + > > The @code{deprecated} attribute can also be used for functions and > > variables (@pxref{Function Attributes}, @pxref{Variable Attributes}.) > > > > diff --git a/gcc/testsuite/c-c++-common/Wdeprecated-arg-1.c b/gcc/testsuite/c-c++-common/Wdeprecated-arg-1.c > > new file mode 100644 > > index 00000000000..b03e0e42ad6 > > --- /dev/null > > +++ b/gcc/testsuite/c-c++-common/Wdeprecated-arg-1.c > > @@ -0,0 +1,21 @@ > > +/* PR c++/102049 */ > > +/* { dg-do compile } */ > > +/* { dg-additional-options "-std=c++11" { target c++ } } */ > > + > > +typedef int __attribute__((deprecated("obsolete", "newtype"))) oldtype; > > +__attribute__((deprecated("unsafe", "get_it_s"))) void get_it (int); /* { dg-message "declared here" } */ > > +[[gnu::deprecated("g", "")]] void g(); /* { dg-error "only allowed in GNU attributes" } */ > > +[[deprecated("h", "")]] void h(); /* { dg-error "only allowed in GNU attributes" } */ > > +__attribute__((deprecated("unsafe", 1))) void f2(); /* { dg-error "argument is not a string" } */ > > +__attribute__((deprecated("unsafe", "newvar"))) int oldvar; /* { dg-message "declared here" } */ > > + > > +int > > +main () > > +{ > > + get_it (42); /* { dg-warning "is deprecated: unsafe" } */ > > + /* { dg-message "use .get_it_s. instead" "" { target *-*-* } .-1 } */ > > + oldtype t; /* { dg-warning "is deprecated: obsolete" } */ > > + /* { dg-message "use .newtype. instead" "" { target *-*-* } .-1 } */ > > + int i = oldvar; /* { dg-warning "is deprecated: unsafe" } */ > > + /* { dg-message "use .newvar. instead" "" { target *-*-* } .-1 } */ > > +} > > diff --git a/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c > > index 044725e5123..6cb70705bbf 100644 > > --- a/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c > > +++ b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c > > @@ -6,6 +6,6 @@ > > > > [[deprecated(0)]] int b; /* { dg-error "expected" } */ > > > > -[[deprecated("", 123)]] int c; /* { dg-error "expected" } */ > > +[[deprecated("", 123)]] int c; /* { dg-error "only allowed in GNU attributes" } */ > > > > [[deprecated((""))]] int d; /* { dg-error "expected" } */ > > diff --git a/gcc/tree.c b/gcc/tree.c > > index 561b9cd56bd..5cb2d57a960 100644 > > --- a/gcc/tree.c > > +++ b/gcc/tree.c > > @@ -12002,8 +12002,9 @@ bool > > warn_deprecated_use (tree node, tree attr) > > { > > escaped_string msg; > > + escaped_string rep; > > > > - if (node == 0 || !warn_deprecated_decl) > > + if (node == NULL_TREE || !warn_deprecated_decl) > > return false; > > > > if (!attr) > > @@ -12023,7 +12024,12 @@ warn_deprecated_use (tree node, tree attr) > > attr = lookup_attribute ("deprecated", attr); > > > > if (attr) > > - msg.escape (TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr)))); > > + { > > + tree val = TREE_VALUE (attr); > > + msg.escape (TREE_STRING_POINTER (TREE_VALUE (val))); > > + if (TREE_CHAIN (val)) > > + rep.escape (TREE_STRING_POINTER (TREE_VALUE (TREE_CHAIN (val)))); > > + } > > > > bool w = false; > > if (DECL_P (node)) > > @@ -12036,7 +12042,11 @@ warn_deprecated_use (tree node, tree attr) > > w = warning (OPT_Wdeprecated_declarations, > > "%qD is deprecated", node); > > if (w) > > - inform (DECL_SOURCE_LOCATION (node), "declared here"); > > + { > > + if (rep) > > + inform (input_location, "use %qs instead", (const char *) rep); > > + inform (DECL_SOURCE_LOCATION (node), "declared here"); > > + } > > } > > else if (TYPE_P (node)) > > { > > @@ -12072,8 +12082,13 @@ warn_deprecated_use (tree node, tree attr) > > "type is deprecated"); > > } > > > > - if (w && decl) > > - inform (DECL_SOURCE_LOCATION (decl), "declared here"); > > + if (w) > > + { > > + if (rep) > > + inform (input_location, "use %qs instead", (const char *) rep); > > + if (decl) > > + inform (DECL_SOURCE_LOCATION (decl), "declared here"); > > + } > > } > > > > return w; > > > > base-commit: f6a05b23cc2e53c38e8321ddb5d2cbe40737e506 > > -- > > 2.31.1 > > > > Marek >
On 10/11/21 9:17 AM, Marek Polacek via Gcc-patches wrote: > Any thoughts? I'm a little unsure. Clang just uses the replacement string as the text of the fix-it note as is, so it does nothing to help programmers make sure the replacement is in sync with what it's supposed to replace. E.g., for this Clang output is below: __attribute__ ((deprecated ("foo is bad", "use bar instead"))) void foo (void); void baz (void) { foo (); } int bar; <source>:2:19: warning: 'foo' is deprecated: foo is bad [-Wdeprecated-declarations] void baz (void) { foo (); } ^~~ use bar instead Since bar is a variable it's hard to see how it might be used instead of the function foo(). Fix-its, as I understand them, are meant not just as a visual clue but also to let IDEs and other tools automatically apply the fixes. With buggy fix-its this obviously wouldn't work. I think the replacement would be useful if it had to reference an existing symbol of the same kind, and if the compiler helped enforce it. Otherwise it seems like a recipe for bit rot and for tings/tools not working well together. Martin > > On Thu, Sep 23, 2021 at 12:16:36PM -0400, Marek Polacek via Gcc-patches wrote: >> Clang implements something we don't have: >> >> __attribute__((deprecated("message", "replacement"))); >> >> which seems pretty neat so I wrote this patch to add it to gcc. >> >> It doesn't allow the optional second argument in the standard [[]] >> form so as not to clash with possible future standard additions. >> >> I had hoped we could print a nice fix-it replacement hint, but that >> won't be possible until warn_deprecated_use gets something better than >> input_location. >> >> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? >> >> PR c++/102049 >> >> gcc/c-family/ChangeLog: >> >> * c-attribs.c (c_common_attribute_table): Increase max_len for >> deprecated. >> (handle_deprecated_attribute): Allow an optional second argument >> in the GNU form of attribute deprecated. >> >> gcc/c/ChangeLog: >> >> * c-parser.c (c_parser_std_attribute): Give a diagnostic when >> the standard form of an attribute deprecated has a second argument. >> >> gcc/ChangeLog: >> >> * doc/extend.texi: Document attribute deprecated with an >> optional second argument. >> * tree.c (warn_deprecated_use): Print the replacement argument, >> if any. >> >> gcc/testsuite/ChangeLog: >> >> * gcc.dg/c2x-attr-deprecated-3.c: Adjust dg-error. >> * c-c++-common/Wdeprecated-arg-1.c: New test. >> --- >> gcc/c-family/c-attribs.c | 17 ++++++++++++- >> gcc/c/c-parser.c | 8 ++++++ >> gcc/doc/extend.texi | 24 ++++++++++++++++++ >> .../c-c++-common/Wdeprecated-arg-1.c | 21 ++++++++++++++++ >> gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c | 2 +- >> gcc/tree.c | 25 +++++++++++++++---- >> 6 files changed, 90 insertions(+), 7 deletions(-) >> create mode 100644 gcc/testsuite/c-c++-common/Wdeprecated-arg-1.c >> >> diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c >> index 007b928c54b..ef857a9ae2c 100644 >> --- a/gcc/c-family/c-attribs.c >> +++ b/gcc/c-family/c-attribs.c >> @@ -409,7 +409,7 @@ const struct attribute_spec c_common_attribute_table[] = >> to prevent its usage in source code. */ >> { "no vops", 0, 0, true, false, false, false, >> handle_novops_attribute, NULL }, >> - { "deprecated", 0, 1, false, false, false, false, >> + { "deprecated", 0, 2, false, false, false, false, >> handle_deprecated_attribute, NULL }, >> { "unavailable", 0, 1, false, false, false, false, >> handle_unavailable_attribute, NULL }, >> @@ -4107,6 +4107,21 @@ handle_deprecated_attribute (tree *node, tree name, >> error ("deprecated message is not a string"); >> *no_add_attrs = true; >> } >> + else if (TREE_CHAIN (args) != NULL_TREE) >> + { >> + /* We allow an optional second argument in the GNU form of >> + attribute deprecated, which specifies the replacement. */ >> + if (flags & ATTR_FLAG_CXX11) >> + { >> + error ("replacement argument only allowed in GNU attributes"); >> + *no_add_attrs = true; >> + } >> + else if (TREE_CODE (TREE_VALUE (TREE_CHAIN (args))) != STRING_CST) >> + { >> + error ("replacement argument is not a string"); >> + *no_add_attrs = true; >> + } >> + } >> >> if (DECL_P (*node)) >> { >> diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c >> index fa29d2c15fc..2b47f01d166 100644 >> --- a/gcc/c/c-parser.c >> +++ b/gcc/c/c-parser.c >> @@ -4952,6 +4952,14 @@ c_parser_std_attribute (c_parser *parser, bool for_tm) >> TREE_VALUE (attribute) >> = c_parser_attribute_arguments (parser, takes_identifier, >> require_string, false); >> + if (c_parser_next_token_is (parser, CPP_COMMA) >> + && strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0) >> + { >> + error_at (open_loc, "replacement argument only allowed in " >> + "GNU attributes"); >> + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); >> + return error_mark_node; >> + } >> } >> else >> c_parser_balanced_token_sequence (parser); >> diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi >> index 9501a60f20e..7d399f4b2bc 100644 >> --- a/gcc/doc/extend.texi >> +++ b/gcc/doc/extend.texi >> @@ -2860,6 +2860,7 @@ StrongAlias (allocate, alloc); >> >> @item deprecated >> @itemx deprecated (@var{msg}) >> +@itemx deprecated (@var{msg}, @var{replacement}) >> @cindex @code{deprecated} function attribute >> The @code{deprecated} attribute results in a warning if the function >> is used anywhere in the source file. This is useful when identifying >> @@ -2880,6 +2881,13 @@ results in a warning on line 3 but not line 2. The optional @var{msg} >> argument, which must be a string, is printed in the warning if >> present. >> >> +This attribute accepts an optional second argument which specifies >> +the replacement that ought to be used instead: >> + >> +@smallexample >> +int old_fn () __attribute__ ((deprecated("unsafe", "new_fn"))); >> +@end smallexample >> + >> The @code{deprecated} attribute can also be used for variables and >> types (@pxref{Variable Attributes}, @pxref{Type Attributes}.) >> >> @@ -7409,6 +7417,7 @@ attribute is also not copied. @xref{Common Function Attributes}. >> >> @item deprecated >> @itemx deprecated (@var{msg}) >> +@itemx deprecated (@var{msg}, @var{replacement}) >> @cindex @code{deprecated} variable attribute >> The @code{deprecated} attribute results in a warning if the variable >> is used anywhere in the source file. This is useful when identifying >> @@ -7429,6 +7438,13 @@ results in a warning on line 3 but not line 2. The optional @var{msg} >> argument, which must be a string, is printed in the warning if >> present. >> >> +This attribute accepts an optional second argument which specifies >> +the replacement that ought to be used instead: >> + >> +@smallexample >> +extern int old_var __attribute__ ((deprecated("unsafe", "new_var"))); >> +@end smallexample >> + >> The @code{deprecated} attribute can also be used for functions and >> types (@pxref{Common Function Attributes}, >> @pxref{Common Type Attributes}). >> @@ -8492,6 +8508,7 @@ struct __attribute__ ((copy ( (struct A *)0)) B @{ /* @r{@dots{}} */ @}; >> >> @item deprecated >> @itemx deprecated (@var{msg}) >> +@itemx deprecated (@var{msg}, @var{replacement}) >> @cindex @code{deprecated} type attribute >> The @code{deprecated} attribute results in a warning if the type >> is used anywhere in the source file. This is useful when identifying >> @@ -8522,6 +8539,13 @@ present. Control characters in the string will be replaced with >> escape sequences, and if the @option{-fmessage-length} option is set >> to 0 (its default value) then any newline characters will be ignored. >> >> +This attribute accepts an optional second argument which specifies >> +the replacement that ought to be used instead: >> + >> +@smallexample >> +typedef int oldtype __attribute__ ((deprecated("unsafe", "newtype"))); >> +@end smallexample >> + >> The @code{deprecated} attribute can also be used for functions and >> variables (@pxref{Function Attributes}, @pxref{Variable Attributes}.) >> >> diff --git a/gcc/testsuite/c-c++-common/Wdeprecated-arg-1.c b/gcc/testsuite/c-c++-common/Wdeprecated-arg-1.c >> new file mode 100644 >> index 00000000000..b03e0e42ad6 >> --- /dev/null >> +++ b/gcc/testsuite/c-c++-common/Wdeprecated-arg-1.c >> @@ -0,0 +1,21 @@ >> +/* PR c++/102049 */ >> +/* { dg-do compile } */ >> +/* { dg-additional-options "-std=c++11" { target c++ } } */ >> + >> +typedef int __attribute__((deprecated("obsolete", "newtype"))) oldtype; >> +__attribute__((deprecated("unsafe", "get_it_s"))) void get_it (int); /* { dg-message "declared here" } */ >> +[[gnu::deprecated("g", "")]] void g(); /* { dg-error "only allowed in GNU attributes" } */ >> +[[deprecated("h", "")]] void h(); /* { dg-error "only allowed in GNU attributes" } */ >> +__attribute__((deprecated("unsafe", 1))) void f2(); /* { dg-error "argument is not a string" } */ >> +__attribute__((deprecated("unsafe", "newvar"))) int oldvar; /* { dg-message "declared here" } */ >> + >> +int >> +main () >> +{ >> + get_it (42); /* { dg-warning "is deprecated: unsafe" } */ >> + /* { dg-message "use .get_it_s. instead" "" { target *-*-* } .-1 } */ >> + oldtype t; /* { dg-warning "is deprecated: obsolete" } */ >> + /* { dg-message "use .newtype. instead" "" { target *-*-* } .-1 } */ >> + int i = oldvar; /* { dg-warning "is deprecated: unsafe" } */ >> + /* { dg-message "use .newvar. instead" "" { target *-*-* } .-1 } */ >> +} >> diff --git a/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c >> index 044725e5123..6cb70705bbf 100644 >> --- a/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c >> +++ b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c >> @@ -6,6 +6,6 @@ >> >> [[deprecated(0)]] int b; /* { dg-error "expected" } */ >> >> -[[deprecated("", 123)]] int c; /* { dg-error "expected" } */ >> +[[deprecated("", 123)]] int c; /* { dg-error "only allowed in GNU attributes" } */ >> >> [[deprecated((""))]] int d; /* { dg-error "expected" } */ >> diff --git a/gcc/tree.c b/gcc/tree.c >> index 561b9cd56bd..5cb2d57a960 100644 >> --- a/gcc/tree.c >> +++ b/gcc/tree.c >> @@ -12002,8 +12002,9 @@ bool >> warn_deprecated_use (tree node, tree attr) >> { >> escaped_string msg; >> + escaped_string rep; >> >> - if (node == 0 || !warn_deprecated_decl) >> + if (node == NULL_TREE || !warn_deprecated_decl) >> return false; >> >> if (!attr) >> @@ -12023,7 +12024,12 @@ warn_deprecated_use (tree node, tree attr) >> attr = lookup_attribute ("deprecated", attr); >> >> if (attr) >> - msg.escape (TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr)))); >> + { >> + tree val = TREE_VALUE (attr); >> + msg.escape (TREE_STRING_POINTER (TREE_VALUE (val))); >> + if (TREE_CHAIN (val)) >> + rep.escape (TREE_STRING_POINTER (TREE_VALUE (TREE_CHAIN (val)))); >> + } >> >> bool w = false; >> if (DECL_P (node)) >> @@ -12036,7 +12042,11 @@ warn_deprecated_use (tree node, tree attr) >> w = warning (OPT_Wdeprecated_declarations, >> "%qD is deprecated", node); >> if (w) >> - inform (DECL_SOURCE_LOCATION (node), "declared here"); >> + { >> + if (rep) >> + inform (input_location, "use %qs instead", (const char *) rep); >> + inform (DECL_SOURCE_LOCATION (node), "declared here"); >> + } >> } >> else if (TYPE_P (node)) >> { >> @@ -12072,8 +12082,13 @@ warn_deprecated_use (tree node, tree attr) >> "type is deprecated"); >> } >> >> - if (w && decl) >> - inform (DECL_SOURCE_LOCATION (decl), "declared here"); >> + if (w) >> + { >> + if (rep) >> + inform (input_location, "use %qs instead", (const char *) rep); >> + if (decl) >> + inform (DECL_SOURCE_LOCATION (decl), "declared here"); >> + } >> } >> >> return w; >> >> base-commit: f6a05b23cc2e53c38e8321ddb5d2cbe40737e506 >> -- >> 2.31.1 >> > > Marek >
On Mon, Nov 01, 2021 at 05:15:03PM -0600, Martin Sebor wrote: > On 10/11/21 9:17 AM, Marek Polacek via Gcc-patches wrote: > > Any thoughts? > > I'm a little unsure. Clang just uses the replacement string > as the text of the fix-it note as is, so it does nothing to > help programmers make sure the replacement is in sync with > what it's supposed to replace. E.g., for this Clang output > is below: > > __attribute__ ((deprecated ("foo is bad", "use bar instead"))) > void foo (void); > void baz (void) { foo (); } > > int bar; > > <source>:2:19: warning: 'foo' is deprecated: foo is bad > [-Wdeprecated-declarations] > void baz (void) { foo (); } > ^~~ > use bar instead > > Since bar is a variable it's hard to see how it might be used > instead of the function foo(). Fix-its, as I understand them, > are meant not just as a visual clue but also to let IDEs and > other tools automatically apply the fixes. With buggy fix-its > this obviously wouldn't work. > > I think the replacement would be useful if it had to reference > an existing symbol of the same kind, and if the compiler helped > enforce it. Otherwise it seems like a recipe for bit rot and > for tings/tools not working well together. OK, I think I'm not going to pursue this further. I'll close the PR and reference my patch in it, should this come up again in the future. Thanks, > > > > On Thu, Sep 23, 2021 at 12:16:36PM -0400, Marek Polacek via Gcc-patches wrote: > > > Clang implements something we don't have: > > > > > > __attribute__((deprecated("message", "replacement"))); > > > > > > which seems pretty neat so I wrote this patch to add it to gcc. > > > > > > It doesn't allow the optional second argument in the standard [[]] > > > form so as not to clash with possible future standard additions. > > > > > > I had hoped we could print a nice fix-it replacement hint, but that > > > won't be possible until warn_deprecated_use gets something better than > > > input_location. > > > > > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > > > > > PR c++/102049 > > > > > > gcc/c-family/ChangeLog: > > > > > > * c-attribs.c (c_common_attribute_table): Increase max_len for > > > deprecated. > > > (handle_deprecated_attribute): Allow an optional second argument > > > in the GNU form of attribute deprecated. > > > > > > gcc/c/ChangeLog: > > > > > > * c-parser.c (c_parser_std_attribute): Give a diagnostic when > > > the standard form of an attribute deprecated has a second argument. > > > > > > gcc/ChangeLog: > > > > > > * doc/extend.texi: Document attribute deprecated with an > > > optional second argument. > > > * tree.c (warn_deprecated_use): Print the replacement argument, > > > if any. > > > > > > gcc/testsuite/ChangeLog: > > > > > > * gcc.dg/c2x-attr-deprecated-3.c: Adjust dg-error. > > > * c-c++-common/Wdeprecated-arg-1.c: New test. > > > --- > > > gcc/c-family/c-attribs.c | 17 ++++++++++++- > > > gcc/c/c-parser.c | 8 ++++++ > > > gcc/doc/extend.texi | 24 ++++++++++++++++++ > > > .../c-c++-common/Wdeprecated-arg-1.c | 21 ++++++++++++++++ > > > gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c | 2 +- > > > gcc/tree.c | 25 +++++++++++++++---- > > > 6 files changed, 90 insertions(+), 7 deletions(-) > > > create mode 100644 gcc/testsuite/c-c++-common/Wdeprecated-arg-1.c > > > > > > diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c > > > index 007b928c54b..ef857a9ae2c 100644 > > > --- a/gcc/c-family/c-attribs.c > > > +++ b/gcc/c-family/c-attribs.c > > > @@ -409,7 +409,7 @@ const struct attribute_spec c_common_attribute_table[] = > > > to prevent its usage in source code. */ > > > { "no vops", 0, 0, true, false, false, false, > > > handle_novops_attribute, NULL }, > > > - { "deprecated", 0, 1, false, false, false, false, > > > + { "deprecated", 0, 2, false, false, false, false, > > > handle_deprecated_attribute, NULL }, > > > { "unavailable", 0, 1, false, false, false, false, > > > handle_unavailable_attribute, NULL }, > > > @@ -4107,6 +4107,21 @@ handle_deprecated_attribute (tree *node, tree name, > > > error ("deprecated message is not a string"); > > > *no_add_attrs = true; > > > } > > > + else if (TREE_CHAIN (args) != NULL_TREE) > > > + { > > > + /* We allow an optional second argument in the GNU form of > > > + attribute deprecated, which specifies the replacement. */ > > > + if (flags & ATTR_FLAG_CXX11) > > > + { > > > + error ("replacement argument only allowed in GNU attributes"); > > > + *no_add_attrs = true; > > > + } > > > + else if (TREE_CODE (TREE_VALUE (TREE_CHAIN (args))) != STRING_CST) > > > + { > > > + error ("replacement argument is not a string"); > > > + *no_add_attrs = true; > > > + } > > > + } > > > if (DECL_P (*node)) > > > { > > > diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c > > > index fa29d2c15fc..2b47f01d166 100644 > > > --- a/gcc/c/c-parser.c > > > +++ b/gcc/c/c-parser.c > > > @@ -4952,6 +4952,14 @@ c_parser_std_attribute (c_parser *parser, bool for_tm) > > > TREE_VALUE (attribute) > > > = c_parser_attribute_arguments (parser, takes_identifier, > > > require_string, false); > > > + if (c_parser_next_token_is (parser, CPP_COMMA) > > > + && strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0) > > > + { > > > + error_at (open_loc, "replacement argument only allowed in " > > > + "GNU attributes"); > > > + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); > > > + return error_mark_node; > > > + } > > > } > > > else > > > c_parser_balanced_token_sequence (parser); > > > diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi > > > index 9501a60f20e..7d399f4b2bc 100644 > > > --- a/gcc/doc/extend.texi > > > +++ b/gcc/doc/extend.texi > > > @@ -2860,6 +2860,7 @@ StrongAlias (allocate, alloc); > > > @item deprecated > > > @itemx deprecated (@var{msg}) > > > +@itemx deprecated (@var{msg}, @var{replacement}) > > > @cindex @code{deprecated} function attribute > > > The @code{deprecated} attribute results in a warning if the function > > > is used anywhere in the source file. This is useful when identifying > > > @@ -2880,6 +2881,13 @@ results in a warning on line 3 but not line 2. The optional @var{msg} > > > argument, which must be a string, is printed in the warning if > > > present. > > > +This attribute accepts an optional second argument which specifies > > > +the replacement that ought to be used instead: > > > + > > > +@smallexample > > > +int old_fn () __attribute__ ((deprecated("unsafe", "new_fn"))); > > > +@end smallexample > > > + > > > The @code{deprecated} attribute can also be used for variables and > > > types (@pxref{Variable Attributes}, @pxref{Type Attributes}.) > > > @@ -7409,6 +7417,7 @@ attribute is also not copied. @xref{Common Function Attributes}. > > > @item deprecated > > > @itemx deprecated (@var{msg}) > > > +@itemx deprecated (@var{msg}, @var{replacement}) > > > @cindex @code{deprecated} variable attribute > > > The @code{deprecated} attribute results in a warning if the variable > > > is used anywhere in the source file. This is useful when identifying > > > @@ -7429,6 +7438,13 @@ results in a warning on line 3 but not line 2. The optional @var{msg} > > > argument, which must be a string, is printed in the warning if > > > present. > > > +This attribute accepts an optional second argument which specifies > > > +the replacement that ought to be used instead: > > > + > > > +@smallexample > > > +extern int old_var __attribute__ ((deprecated("unsafe", "new_var"))); > > > +@end smallexample > > > + > > > The @code{deprecated} attribute can also be used for functions and > > > types (@pxref{Common Function Attributes}, > > > @pxref{Common Type Attributes}). > > > @@ -8492,6 +8508,7 @@ struct __attribute__ ((copy ( (struct A *)0)) B @{ /* @r{@dots{}} */ @}; > > > @item deprecated > > > @itemx deprecated (@var{msg}) > > > +@itemx deprecated (@var{msg}, @var{replacement}) > > > @cindex @code{deprecated} type attribute > > > The @code{deprecated} attribute results in a warning if the type > > > is used anywhere in the source file. This is useful when identifying > > > @@ -8522,6 +8539,13 @@ present. Control characters in the string will be replaced with > > > escape sequences, and if the @option{-fmessage-length} option is set > > > to 0 (its default value) then any newline characters will be ignored. > > > +This attribute accepts an optional second argument which specifies > > > +the replacement that ought to be used instead: > > > + > > > +@smallexample > > > +typedef int oldtype __attribute__ ((deprecated("unsafe", "newtype"))); > > > +@end smallexample > > > + > > > The @code{deprecated} attribute can also be used for functions and > > > variables (@pxref{Function Attributes}, @pxref{Variable Attributes}.) > > > diff --git a/gcc/testsuite/c-c++-common/Wdeprecated-arg-1.c b/gcc/testsuite/c-c++-common/Wdeprecated-arg-1.c > > > new file mode 100644 > > > index 00000000000..b03e0e42ad6 > > > --- /dev/null > > > +++ b/gcc/testsuite/c-c++-common/Wdeprecated-arg-1.c > > > @@ -0,0 +1,21 @@ > > > +/* PR c++/102049 */ > > > +/* { dg-do compile } */ > > > +/* { dg-additional-options "-std=c++11" { target c++ } } */ > > > + > > > +typedef int __attribute__((deprecated("obsolete", "newtype"))) oldtype; > > > +__attribute__((deprecated("unsafe", "get_it_s"))) void get_it (int); /* { dg-message "declared here" } */ > > > +[[gnu::deprecated("g", "")]] void g(); /* { dg-error "only allowed in GNU attributes" } */ > > > +[[deprecated("h", "")]] void h(); /* { dg-error "only allowed in GNU attributes" } */ > > > +__attribute__((deprecated("unsafe", 1))) void f2(); /* { dg-error "argument is not a string" } */ > > > +__attribute__((deprecated("unsafe", "newvar"))) int oldvar; /* { dg-message "declared here" } */ > > > + > > > +int > > > +main () > > > +{ > > > + get_it (42); /* { dg-warning "is deprecated: unsafe" } */ > > > + /* { dg-message "use .get_it_s. instead" "" { target *-*-* } .-1 } */ > > > + oldtype t; /* { dg-warning "is deprecated: obsolete" } */ > > > + /* { dg-message "use .newtype. instead" "" { target *-*-* } .-1 } */ > > > + int i = oldvar; /* { dg-warning "is deprecated: unsafe" } */ > > > + /* { dg-message "use .newvar. instead" "" { target *-*-* } .-1 } */ > > > +} > > > diff --git a/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c > > > index 044725e5123..6cb70705bbf 100644 > > > --- a/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c > > > +++ b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c > > > @@ -6,6 +6,6 @@ > > > [[deprecated(0)]] int b; /* { dg-error "expected" } */ > > > -[[deprecated("", 123)]] int c; /* { dg-error "expected" } */ > > > +[[deprecated("", 123)]] int c; /* { dg-error "only allowed in GNU attributes" } */ > > > [[deprecated((""))]] int d; /* { dg-error "expected" } */ > > > diff --git a/gcc/tree.c b/gcc/tree.c > > > index 561b9cd56bd..5cb2d57a960 100644 > > > --- a/gcc/tree.c > > > +++ b/gcc/tree.c > > > @@ -12002,8 +12002,9 @@ bool > > > warn_deprecated_use (tree node, tree attr) > > > { > > > escaped_string msg; > > > + escaped_string rep; > > > - if (node == 0 || !warn_deprecated_decl) > > > + if (node == NULL_TREE || !warn_deprecated_decl) > > > return false; > > > if (!attr) > > > @@ -12023,7 +12024,12 @@ warn_deprecated_use (tree node, tree attr) > > > attr = lookup_attribute ("deprecated", attr); > > > if (attr) > > > - msg.escape (TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr)))); > > > + { > > > + tree val = TREE_VALUE (attr); > > > + msg.escape (TREE_STRING_POINTER (TREE_VALUE (val))); > > > + if (TREE_CHAIN (val)) > > > + rep.escape (TREE_STRING_POINTER (TREE_VALUE (TREE_CHAIN (val)))); > > > + } > > > bool w = false; > > > if (DECL_P (node)) > > > @@ -12036,7 +12042,11 @@ warn_deprecated_use (tree node, tree attr) > > > w = warning (OPT_Wdeprecated_declarations, > > > "%qD is deprecated", node); > > > if (w) > > > - inform (DECL_SOURCE_LOCATION (node), "declared here"); > > > + { > > > + if (rep) > > > + inform (input_location, "use %qs instead", (const char *) rep); > > > + inform (DECL_SOURCE_LOCATION (node), "declared here"); > > > + } > > > } > > > else if (TYPE_P (node)) > > > { > > > @@ -12072,8 +12082,13 @@ warn_deprecated_use (tree node, tree attr) > > > "type is deprecated"); > > > } > > > - if (w && decl) > > > - inform (DECL_SOURCE_LOCATION (decl), "declared here"); > > > + if (w) > > > + { > > > + if (rep) > > > + inform (input_location, "use %qs instead", (const char *) rep); > > > + if (decl) > > > + inform (DECL_SOURCE_LOCATION (decl), "declared here"); > > > + } > > > } > > > return w; > > > > > > base-commit: f6a05b23cc2e53c38e8321ddb5d2cbe40737e506 > > > -- > > > 2.31.1 > > > > > > > Marek > > > Marek
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c index 007b928c54b..ef857a9ae2c 100644 --- a/gcc/c-family/c-attribs.c +++ b/gcc/c-family/c-attribs.c @@ -409,7 +409,7 @@ const struct attribute_spec c_common_attribute_table[] = to prevent its usage in source code. */ { "no vops", 0, 0, true, false, false, false, handle_novops_attribute, NULL }, - { "deprecated", 0, 1, false, false, false, false, + { "deprecated", 0, 2, false, false, false, false, handle_deprecated_attribute, NULL }, { "unavailable", 0, 1, false, false, false, false, handle_unavailable_attribute, NULL }, @@ -4107,6 +4107,21 @@ handle_deprecated_attribute (tree *node, tree name, error ("deprecated message is not a string"); *no_add_attrs = true; } + else if (TREE_CHAIN (args) != NULL_TREE) + { + /* We allow an optional second argument in the GNU form of + attribute deprecated, which specifies the replacement. */ + if (flags & ATTR_FLAG_CXX11) + { + error ("replacement argument only allowed in GNU attributes"); + *no_add_attrs = true; + } + else if (TREE_CODE (TREE_VALUE (TREE_CHAIN (args))) != STRING_CST) + { + error ("replacement argument is not a string"); + *no_add_attrs = true; + } + } if (DECL_P (*node)) { diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index fa29d2c15fc..2b47f01d166 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -4952,6 +4952,14 @@ c_parser_std_attribute (c_parser *parser, bool for_tm) TREE_VALUE (attribute) = c_parser_attribute_arguments (parser, takes_identifier, require_string, false); + if (c_parser_next_token_is (parser, CPP_COMMA) + && strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0) + { + error_at (open_loc, "replacement argument only allowed in " + "GNU attributes"); + c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL); + return error_mark_node; + } } else c_parser_balanced_token_sequence (parser); diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 9501a60f20e..7d399f4b2bc 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -2860,6 +2860,7 @@ StrongAlias (allocate, alloc); @item deprecated @itemx deprecated (@var{msg}) +@itemx deprecated (@var{msg}, @var{replacement}) @cindex @code{deprecated} function attribute The @code{deprecated} attribute results in a warning if the function is used anywhere in the source file. This is useful when identifying @@ -2880,6 +2881,13 @@ results in a warning on line 3 but not line 2. The optional @var{msg} argument, which must be a string, is printed in the warning if present. +This attribute accepts an optional second argument which specifies +the replacement that ought to be used instead: + +@smallexample +int old_fn () __attribute__ ((deprecated("unsafe", "new_fn"))); +@end smallexample + The @code{deprecated} attribute can also be used for variables and types (@pxref{Variable Attributes}, @pxref{Type Attributes}.) @@ -7409,6 +7417,7 @@ attribute is also not copied. @xref{Common Function Attributes}. @item deprecated @itemx deprecated (@var{msg}) +@itemx deprecated (@var{msg}, @var{replacement}) @cindex @code{deprecated} variable attribute The @code{deprecated} attribute results in a warning if the variable is used anywhere in the source file. This is useful when identifying @@ -7429,6 +7438,13 @@ results in a warning on line 3 but not line 2. The optional @var{msg} argument, which must be a string, is printed in the warning if present. +This attribute accepts an optional second argument which specifies +the replacement that ought to be used instead: + +@smallexample +extern int old_var __attribute__ ((deprecated("unsafe", "new_var"))); +@end smallexample + The @code{deprecated} attribute can also be used for functions and types (@pxref{Common Function Attributes}, @pxref{Common Type Attributes}). @@ -8492,6 +8508,7 @@ struct __attribute__ ((copy ( (struct A *)0)) B @{ /* @r{@dots{}} */ @}; @item deprecated @itemx deprecated (@var{msg}) +@itemx deprecated (@var{msg}, @var{replacement}) @cindex @code{deprecated} type attribute The @code{deprecated} attribute results in a warning if the type is used anywhere in the source file. This is useful when identifying @@ -8522,6 +8539,13 @@ present. Control characters in the string will be replaced with escape sequences, and if the @option{-fmessage-length} option is set to 0 (its default value) then any newline characters will be ignored. +This attribute accepts an optional second argument which specifies +the replacement that ought to be used instead: + +@smallexample +typedef int oldtype __attribute__ ((deprecated("unsafe", "newtype"))); +@end smallexample + The @code{deprecated} attribute can also be used for functions and variables (@pxref{Function Attributes}, @pxref{Variable Attributes}.) diff --git a/gcc/testsuite/c-c++-common/Wdeprecated-arg-1.c b/gcc/testsuite/c-c++-common/Wdeprecated-arg-1.c new file mode 100644 index 00000000000..b03e0e42ad6 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wdeprecated-arg-1.c @@ -0,0 +1,21 @@ +/* PR c++/102049 */ +/* { dg-do compile } */ +/* { dg-additional-options "-std=c++11" { target c++ } } */ + +typedef int __attribute__((deprecated("obsolete", "newtype"))) oldtype; +__attribute__((deprecated("unsafe", "get_it_s"))) void get_it (int); /* { dg-message "declared here" } */ +[[gnu::deprecated("g", "")]] void g(); /* { dg-error "only allowed in GNU attributes" } */ +[[deprecated("h", "")]] void h(); /* { dg-error "only allowed in GNU attributes" } */ +__attribute__((deprecated("unsafe", 1))) void f2(); /* { dg-error "argument is not a string" } */ +__attribute__((deprecated("unsafe", "newvar"))) int oldvar; /* { dg-message "declared here" } */ + +int +main () +{ + get_it (42); /* { dg-warning "is deprecated: unsafe" } */ + /* { dg-message "use .get_it_s. instead" "" { target *-*-* } .-1 } */ + oldtype t; /* { dg-warning "is deprecated: obsolete" } */ + /* { dg-message "use .newtype. instead" "" { target *-*-* } .-1 } */ + int i = oldvar; /* { dg-warning "is deprecated: unsafe" } */ + /* { dg-message "use .newvar. instead" "" { target *-*-* } .-1 } */ +} diff --git a/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c index 044725e5123..6cb70705bbf 100644 --- a/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c +++ b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c @@ -6,6 +6,6 @@ [[deprecated(0)]] int b; /* { dg-error "expected" } */ -[[deprecated("", 123)]] int c; /* { dg-error "expected" } */ +[[deprecated("", 123)]] int c; /* { dg-error "only allowed in GNU attributes" } */ [[deprecated((""))]] int d; /* { dg-error "expected" } */ diff --git a/gcc/tree.c b/gcc/tree.c index 561b9cd56bd..5cb2d57a960 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -12002,8 +12002,9 @@ bool warn_deprecated_use (tree node, tree attr) { escaped_string msg; + escaped_string rep; - if (node == 0 || !warn_deprecated_decl) + if (node == NULL_TREE || !warn_deprecated_decl) return false; if (!attr) @@ -12023,7 +12024,12 @@ warn_deprecated_use (tree node, tree attr) attr = lookup_attribute ("deprecated", attr); if (attr) - msg.escape (TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr)))); + { + tree val = TREE_VALUE (attr); + msg.escape (TREE_STRING_POINTER (TREE_VALUE (val))); + if (TREE_CHAIN (val)) + rep.escape (TREE_STRING_POINTER (TREE_VALUE (TREE_CHAIN (val)))); + } bool w = false; if (DECL_P (node)) @@ -12036,7 +12042,11 @@ warn_deprecated_use (tree node, tree attr) w = warning (OPT_Wdeprecated_declarations, "%qD is deprecated", node); if (w) - inform (DECL_SOURCE_LOCATION (node), "declared here"); + { + if (rep) + inform (input_location, "use %qs instead", (const char *) rep); + inform (DECL_SOURCE_LOCATION (node), "declared here"); + } } else if (TYPE_P (node)) { @@ -12072,8 +12082,13 @@ warn_deprecated_use (tree node, tree attr) "type is deprecated"); } - if (w && decl) - inform (DECL_SOURCE_LOCATION (decl), "declared here"); + if (w) + { + if (rep) + inform (input_location, "use %qs instead", (const char *) rep); + if (decl) + inform (DECL_SOURCE_LOCATION (decl), "declared here"); + } } return w;