From patchwork Fri Nov 15 00:07:10 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joseph Myers X-Patchwork-Id: 1195242 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-513517-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=codesourcery.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="aQj1823X"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47Ddvk5b9dz9s4Y for ; Fri, 15 Nov 2019 11:07:28 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=cMzgTD5ekmCep42BbJYGlPhkIh91bifvEgEmZ1xXAVZXZE/Ugotvs gGOVN/99xVZAj8rc8I7rfbW+DPG70kRazBaJckWbO6zO8wQ4pK1I1LqclRH21xri Z9B1kqp1iJrOMbXZQ51mpTrZLEdAjkuzJD+4LbIVB+myClpbcfYu/I= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=WcMZasNNBXG4CM6jydGSZWw8D6Q=; b=aQj1823XID0rMPhu6nke ZaLPc+1zAOth/Z6pI5jYGVATEUBFivkr4YuXalAdRa6+r+dtXaOM92Xfso9tUITz ot767AdXxpKOUQg1Ou4Iv+tSNT8bKL5xZwJK25zcrOAdawmAyija+eQEf/DoFNbt wxhG1TEd0crS42TiSQl5wX4= Received: (qmail 88647 invoked by alias); 15 Nov 2019 00:07:20 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 88635 invoked by uid 89); 15 Nov 2019 00:07:20 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-7.3 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS autolearn=ham version=3.3.1 spammy=wiring, c-common.h, ya, ccommonh X-HELO: esa3.mentor.iphmx.com Received: from esa3.mentor.iphmx.com (HELO esa3.mentor.iphmx.com) (68.232.137.180) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 15 Nov 2019 00:07:18 +0000 IronPort-SDR: xNRe0jC/HO811K+tLxlB5cUB0YaVNPh7z+sC3TGbClqaCb81B5pZoJnUTWTi8PTJlDQsz98nP+ iCKK+qi6uNS2Tq0ygoNP6o/5afJGx+rFXutqI3BdrzIuMdmqUUIH01Lt/spMtUWxR6DoLHYwQQ GrG8xwcFqL/4caERGMd0iUiAqeK/jCDArBi4D/bsgG8HAQn1mKTXq3R18Ud2e8H/X2sXyZtWGy 1VvvTGemNc+A/WpdVcP5N3VyezPA0ghhzZNmZVtSEe27yH295l8xFgjvzEepKAigo+rPPMXXer UTQ= Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa3.mentor.iphmx.com with ESMTP; 14 Nov 2019 16:07:16 -0800 IronPort-SDR: tdp0yhY5GK67MLz7knRYU0gvEvZA7iGV8GBiY/Vm3ETJjp2ybwJTjZy/Mr+xb+8A5qDP3JpPPi 6fidud6P1m3+CIQCXrenhBXMQXXzWYa8JoR/RHupQFehpxn3/MUb/UFvy4nTSW46PRR/hG/iqR SN3CTIv2GL6p5t1ohVnVztOGl4pQI6ZQ+unY1ObnP/Eyb8adp/tTxSVByp9C0l1NHqIpAPmGgX 6GUba4KHgIH/g4VSpPbwgAVReWpSm/B4sJDsReuUDQO+1Vpg8Fozsm/TkWHdibKx2JpLCTmqnB dy0= Date: Fri, 15 Nov 2019 00:07:10 +0000 From: Joseph Myers To: Subject: Support C2x [[deprecated]] attribute Message-ID: User-Agent: Alpine 2.21 (DEB 202 2017-01-01) MIME-Version: 1.0 This patch adds support for the C2x [[deprecated]] attribute. All the actual logic for generating warnings can be identical to the GNU __attribute__ ((deprecated)), as can the attribute handler, so this is just a matter of wiring things up appropriately and adding the checks specified in the standard. Unlike for C++, this patch gives "deprecated" an entry in a table of standard attributes rather than remapping it internally to the GNU attribute, as that seems a cleaner approach to me. Specifically, the only form of arguments to the attribute permitted in the standard is (string-literal); empty parentheses are not permitted in the case of no arguments, and a string literal (which includes concatenated adjacent string literals, because concatenation is an earlier phase of translation) cannot have further redundant parentheses around it. For the case of empty parentheses, this patch makes the C parser disallow them for all known attributes using the [[]] syntax, as done for C++. For string literals (where the C++ front end is missing the check to avoid redundant parentheses, 92521 filed for that issue), a special case is inserted in the C parser. A known issue that I think can be addressed later as a bug fix is that the warnings for the attribute being ignored in certain cases (attribute declarations, statements, most uses on types) ought to be pedwarns, as those usages are constraint violations. Bad handling of wide string literals with this attribute is also a pre-existing bug (91182 - although that's filed as a C++ bug, the code in question is language-independent, in tree.c). Bootstrapped with no regressions on x86_64-pc-linux-gnu. Applied to mainline. gcc/c: 2019-11-15 Joseph Myers * c-decl.c (std_attribute_table): New. (c_init_decl_processing): Register attributes from std_attribute_table. * c-parser.c (c_parser_attribute_arguments): Add arguments require_string and allow_empty_args. All callers changed. (c_parser_std_attribute): Set require_string argument for "deprecated" attribute. gcc/c-family: 2019-11-15 Joseph Myers * c-attribs.c (handle_deprecated_attribute): Remove static. * c-common.h (handle_deprecated_attribute): Declare. gcc/testsuite: 2019-11-15 Joseph Myers * gcc.dg/c2x-attr-deprecated-1.c, gcc.dg/c2x-attr-deprecated-2.c, gcc.dg/c2x-attr-deprecated-3.c: New tests. Index: gcc/c/c-decl.c =================================================================== --- gcc/c/c-decl.c (revision 278265) +++ gcc/c/c-decl.c (working copy) @@ -4336,6 +4336,16 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuz } +/* Table of supported standard (C2x) attributes. */ +const struct attribute_spec std_attribute_table[] = +{ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, + affects_type_identity, handler, exclude } */ + { "deprecated", 0, 1, false, false, false, false, + handle_deprecated_attribute, NULL }, + { NULL, 0, 0, false, false, false, false, NULL, NULL } +}; + /* Create the predefined scalar types of C, and some nodes representing standard constants (0, 1, (void *) 0). Initialize the global scope. @@ -4349,6 +4359,8 @@ c_init_decl_processing (void) /* Initialize reserved words for parser. */ c_parse_init (); + register_scoped_attributes (std_attribute_table, NULL); + current_function_decl = NULL_TREE; gcc_obstack_init (&parser_obstack); Index: gcc/c/c-parser.c =================================================================== --- gcc/c/c-parser.c (revision 278265) +++ gcc/c/c-parser.c (working copy) @@ -4478,7 +4478,8 @@ c_parser_gnu_attribute_any_word (c_parser *parser) allow identifiers declared as types to start the arguments? */ static tree -c_parser_attribute_arguments (c_parser *parser, bool takes_identifier) +c_parser_attribute_arguments (c_parser *parser, bool takes_identifier, + bool require_string, bool allow_empty_args) { vec *expr_list; tree attr_args; @@ -4518,7 +4519,21 @@ static tree else { if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) - attr_args = NULL_TREE; + { + if (!allow_empty_args) + error_at (c_parser_peek_token (parser)->location, + "parentheses must be omitted if " + "attribute argument list is empty"); + attr_args = NULL_TREE; + } + else if (require_string) + { + /* The only valid argument for this attribute is a string + literal. Handle this specially here to avoid accepting + string literals with excess parentheses. */ + tree string = c_parser_string_literal (parser, false, true).value; + attr_args = build_tree_list (NULL_TREE, string); + } else { expr_list = c_parser_expr_list (parser, false, true, @@ -4601,7 +4616,8 @@ c_parser_gnu_attribute (c_parser *parser, tree att tree attr_args = c_parser_attribute_arguments (parser, - attribute_takes_identifier_p (attr_name)); + attribute_takes_identifier_p (attr_name), + false, true); attr = build_tree_list (attr_name, attr_args); if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) @@ -4835,8 +4851,12 @@ c_parser_std_attribute (c_parser *parser) = (ns != NULL_TREE && strcmp (IDENTIFIER_POINTER (ns), "gnu") == 0 && attribute_takes_identifier_p (name)); + bool require_string + = (ns == NULL_TREE + && strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0); TREE_VALUE (attribute) - = c_parser_attribute_arguments (parser, takes_identifier); + = c_parser_attribute_arguments (parser, takes_identifier, + require_string, false); } else c_parser_balanced_token_sequence (parser); Index: gcc/c-family/c-attribs.c =================================================================== --- gcc/c-family/c-attribs.c (revision 278265) +++ gcc/c-family/c-attribs.c (working copy) @@ -115,8 +115,6 @@ static tree handle_pure_attribute (tree *, tree, t static tree handle_tm_attribute (tree *, tree, tree, int, bool *); static tree handle_tm_wrap_attribute (tree *, tree, tree, int, bool *); static tree handle_novops_attribute (tree *, tree, tree, int, bool *); -static tree handle_deprecated_attribute (tree *, tree, tree, int, - bool *); static tree handle_vector_size_attribute (tree *, tree, tree, int, bool *); static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *); @@ -3468,7 +3466,7 @@ handle_novops_attribute (tree *node, tree ARG_UNUS /* Handle a "deprecated" attribute; arguments as in struct attribute_spec.handler. */ -static tree +tree handle_deprecated_attribute (tree *node, tree name, tree args, int flags, bool *no_add_attrs) Index: gcc/c-family/c-common.h =================================================================== --- gcc/c-family/c-common.h (revision 278265) +++ gcc/c-family/c-common.h (working copy) @@ -1357,6 +1357,7 @@ extern void warn_for_multistatement_macros (locati /* In c-attribs.c. */ extern bool attribute_takes_identifier_p (const_tree); +extern tree handle_deprecated_attribute (tree *, tree, tree, int, bool *); extern tree handle_unused_attribute (tree *, tree, tree, int, bool *); extern int parse_tm_stmt_attr (tree, int); extern int tm_attr_to_mask (tree); Index: gcc/testsuite/gcc.dg/c2x-attr-deprecated-1.c =================================================================== --- gcc/testsuite/gcc.dg/c2x-attr-deprecated-1.c (nonexistent) +++ gcc/testsuite/gcc.dg/c2x-attr-deprecated-1.c (working copy) @@ -0,0 +1,91 @@ +/* Test C2x deprecated attribute: valid uses. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +/* Similar to tests from gnu2x-attrs-1.c, but using the standard + attribute instead of gnu::deprecated, and sometimes using + __deprecated__ or a string-literal argument. */ + +[[deprecated]] void f1 (void); + +[[deprecated]] typedef int dep_int; + +dep_int dv; /* { dg-warning "deprecated" } */ + +void +g (void) +{ + f1 (); /* { dg-warning "deprecated" } */ +} + +int +f2 (void) +{ + [[deprecated ("for this reason")]] int a = 1; + return a; /* { dg-warning "for this reason" } */ +} + +int +f3 (void) +{ + int a [[__deprecated__]] = 1; + return a; /* { dg-warning "deprecated" } */ +} + +struct s2 { [[__deprecated__("some other message")]] int a; int b [[deprecated]]; } x; + +int +f4 (void) +{ + return x.a; /* { dg-warning "some other message" } */ +} + +int +f5 (void) +{ + return x.b; /* { dg-warning "deprecated" } */ +} + +enum e { E1 [[deprecated("third message")]] }; + +enum e +f6 (void) +{ + return E1; /* { dg-warning "third message" } */ +} + +int +f7 ([[deprecated]] int y) +{ + return y; /* { dg-warning "deprecated" } */ +} + +union [[__deprecated__]] u { int x; }; + +void +f8 (void) +{ + union u var; /* { dg-warning "deprecated" } */ +} + +enum [[deprecated("edep reason")]] edep { E2 }; + +void +f9 (void) +{ + enum edep var; /* { dg-warning "edep reason" } */ +} + +union u2 { [[__deprecated__]] int a; int b [[deprecated]]; } y; + +int +f10 (void) +{ + return y.a; /* { dg-warning "deprecated" } */ +} + +int +f11 (void) +{ + return y.b; /* { dg-warning "deprecated" } */ +} Index: gcc/testsuite/gcc.dg/c2x-attr-deprecated-2.c =================================================================== --- gcc/testsuite/gcc.dg/c2x-attr-deprecated-2.c (nonexistent) +++ gcc/testsuite/gcc.dg/c2x-attr-deprecated-2.c (working copy) @@ -0,0 +1,25 @@ +/* Test C2x deprecated attribute: invalid contexts. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +/* This attribute is not valid in most cases on types other than their + definitions, or on statements, or as an attribute-declaration. */ + +[[deprecated]]; /* { dg-warning "ignored" } */ + +int [[deprecated]] var; /* { dg-warning "ignored" } */ +/* { dg-message "that appertains to a type-specifier" "appertains" { target *-*-* } .-1 } */ + +int array_with_dep_type[2] [[deprecated]]; /* { dg-warning "ignored" } */ +/* { dg-message "that appertains to a type-specifier" "appertains" { target *-*-* } .-1 } */ + +void fn_with_dep_type () [[deprecated]]; /* { dg-warning "ignored" } */ +/* { dg-message "that appertains to a type-specifier" "appertains" { target *-*-* } .-1 } */ + +void +f (void) +{ + int a; + [[deprecated]]; /* { dg-warning "ignored" } */ + [[deprecated]] a = 1; /* { dg-warning "ignored" } */ +} Index: gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c =================================================================== --- gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c (nonexistent) +++ gcc/testsuite/gcc.dg/c2x-attr-deprecated-3.c (working copy) @@ -0,0 +1,11 @@ +/* Test C2x deprecated attribute: invalid syntax. */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +[[deprecated()]] int a; /* { dg-error "parentheses must be omitted if attribute argument list is empty" } */ + +[[deprecated(0)]] int b; /* { dg-error "expected" } */ + +[[deprecated("", 123)]] int c; /* { dg-error "expected" } */ + +[[deprecated((""))]] int d; /* { dg-error "expected" } */