From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 73459 invoked by alias); 7 May 2015 16:22:50 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 73446 invoked by uid 89); 7 May 2015 16:22:49 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.4 required=5.0 tests=AWL,BAYES_00,SPF_HELO_PASS,SPF_PASS,T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 07 May 2015 16:22:47 +0000 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (Postfix) with ESMTPS id E499CB5C39; Thu, 7 May 2015 16:22:45 +0000 (UTC) Received: from redhat.com (ovpn-204-66.brq.redhat.com [10.40.204.66]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t47GMf3a004961 (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NO); Thu, 7 May 2015 12:22:43 -0400 Date: Thu, 07 May 2015 16:22:00 -0000 From: Marek Polacek To: Ed Smith-Rowland <3dw4rd@verizon.net>, Joseph Myers , Jason Merrill Cc: gcc-patches , Sandra Loosemore Subject: Re: C/C++ PATCH to allow deprecating enum values (PR c/47043) Message-ID: <20150507162240.GF3384@redhat.com> References: <554AD940.3000800@verizon.net> <20150507135955.GE3384@redhat.com> <554B74E8.2060900@verizon.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <554B74E8.2060900@verizon.net> User-Agent: Mutt/1.5.23 (2014-03-12) X-SW-Source: 2015-05/txt/msg00567.txt.bz2 On Thu, May 07, 2015 at 10:21:28AM -0400, Ed Smith-Rowland wrote: > Instead of NULL_TREE in pt.c I grabbed the attrs. > > /* Actually build the enumerator itself. */ > build_enumerator > (DECL_NAME (decl), value, newtag, DECL_ATTRIBUTES (decl), > DECL_SOURCE_LOCATION (decl)); > > Seems to work. Cool! > Also, I haven't tested the testcase in terms of the pattern matching of the > error. Tweak it if necessary. I did some small adjustments, thanks. This (third) version of the patch entails the change in tsubst_enum Ed suggested + new testcase. Bootstrapped/regtested on x86_64-linux, ok for trunk? 2015-05-07 Marek Polacek Edward Smith-Rowland <3dw4rd@verizon.net> PR c/47043 * c-common.c (handle_deprecated_attribute): Allow CONST_DECL. * c-parser.c (c_parser_enum_specifier): Parse and apply enumerator attributes. * cp-tree.h (build_enumerator): Update declaration. * decl.c (build_enumerator): Add attributes parameter. Call cplus_decl_attributes. * init.c (constant_value_1): Pass 0 to mark_used. * parser.c (cp_parser_enumerator_definition): Parse attributes and pass them down to build_enumerator. * pt.c (tsubst_enum): Pass decl attributes to build_enumerator. * semantics.c (finish_id_expression): Don't warn_deprecated_use here. * doc/extend.texi (Enumerator Attributes): New section. Document syntax of enumerator attributes. * c-c++-common/attributes-enum-1.c: New test. * c-c++-common/attributes-enum-2.c: New test. * g++.dg/cpp0x/attributes-enum-1.C: New test. * g++.dg/cpp1y/attributes-enum-1.C: New test. diff --git gcc/c-family/c-common.c gcc/c-family/c-common.c index ada8e8a..36968e5 100644 --- gcc/c-family/c-common.c +++ gcc/c-family/c-common.c @@ -8810,6 +8810,7 @@ handle_deprecated_attribute (tree *node, tree name, || TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == FIELD_DECL + || TREE_CODE (decl) == CONST_DECL || objc_method_decl (TREE_CODE (decl))) TREE_DEPRECATED (decl) = 1; else diff --git gcc/c/c-parser.c gcc/c/c-parser.c index bf0e4c57..889e6d7 100644 --- gcc/c/c-parser.c +++ gcc/c/c-parser.c @@ -2516,6 +2516,13 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs, enumerator: enumeration-constant enumeration-constant = constant-expression + + GNU Extensions: + + enumerator: + enumeration-constant attributes[opt] + enumeration-constant attributes[opt] = constant-expression + */ static struct c_typespec @@ -2575,6 +2582,8 @@ c_parser_enum_specifier (c_parser *parser) c_parser_set_source_position_from_token (token); decl_loc = value_loc = token->location; c_parser_consume_token (parser); + /* Parse any specified attributes. */ + tree enum_attrs = c_parser_attributes (parser); if (c_parser_next_token_is (parser, CPP_EQ)) { c_parser_consume_token (parser); @@ -2584,7 +2593,9 @@ c_parser_enum_specifier (c_parser *parser) else enum_value = NULL_TREE; enum_decl = build_enumerator (decl_loc, value_loc, - &the_enum, enum_id, enum_value); + &the_enum, enum_id, enum_value); + if (enum_attrs) + decl_attributes (&TREE_PURPOSE (enum_decl), enum_attrs, 0); TREE_CHAIN (enum_decl) = values; values = enum_decl; seen_comma = false; diff --git gcc/cp/cp-tree.h gcc/cp/cp-tree.h index e0fbf5e..6b26cb1 100644 --- gcc/cp/cp-tree.h +++ gcc/cp/cp-tree.h @@ -5400,7 +5400,7 @@ extern bool xref_basetypes (tree, tree); extern tree start_enum (tree, tree, tree, bool, bool *); extern void finish_enum_value_list (tree); extern void finish_enum (tree); -extern void build_enumerator (tree, tree, tree, location_t); +extern void build_enumerator (tree, tree, tree, tree, location_t); extern tree lookup_enumerator (tree, tree); extern bool start_preparsed_function (tree, tree, int); extern bool start_function (cp_decl_specifier_seq *, diff --git gcc/cp/decl.c gcc/cp/decl.c index 261a12d..ebbd585 100644 --- gcc/cp/decl.c +++ gcc/cp/decl.c @@ -13067,11 +13067,12 @@ finish_enum (tree enumtype) /* Build and install a CONST_DECL for an enumeration constant of the enumeration type ENUMTYPE whose NAME and VALUE (if any) are provided. - LOC is the location of NAME. + Apply ATTRIBUTES if available. LOC is the location of NAME. Assignment of sequential values by default is handled here. */ void -build_enumerator (tree name, tree value, tree enumtype, location_t loc) +build_enumerator (tree name, tree value, tree enumtype, tree attributes, + location_t loc) { tree decl; tree context; @@ -13234,6 +13235,9 @@ incremented enumerator value is too large for %"); TREE_READONLY (decl) = 1; DECL_INITIAL (decl) = value; + if (attributes) + cplus_decl_attributes (&decl, attributes, 0); + if (context && context == current_class_type && !SCOPED_ENUM_P (enumtype)) /* In something like `struct S { enum E { i = 7 }; };' we put `i' on the TYPE_FIELDS list for `S'. (That's so that you can say diff --git gcc/cp/init.c gcc/cp/init.c index c41e30c..9298f2d 100644 --- gcc/cp/init.c +++ gcc/cp/init.c @@ -2035,7 +2035,7 @@ constant_value_1 (tree decl, bool strict_p, bool return_aggregate_cst_ok_p) specialization, we must instantiate it here. The initializer for the static data member is not processed until needed; we need it now. */ - mark_used (decl); + mark_used (decl, 0); mark_rvalue_use (decl); init = DECL_INITIAL (decl); if (init == error_mark_node) diff --git gcc/cp/parser.c gcc/cp/parser.c index 30a3fab..420759e 100644 --- gcc/cp/parser.c +++ gcc/cp/parser.c @@ -16056,7 +16056,13 @@ cp_parser_enumerator_list (cp_parser* parser, tree type) enumerator = constant-expression enumerator: - identifier */ + identifier + + GNU Extensions: + + enumerator-definition: + enumerator attributes [opt] + enumerator attributes [opt] = constant-expression */ static void cp_parser_enumerator_definition (cp_parser* parser, tree type) @@ -16074,6 +16080,9 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type) if (identifier == error_mark_node) return; + /* Parse any specified attributes. */ + tree attrs = cp_parser_attributes_opt (parser); + /* If the next token is an '=', then there is an explicit value. */ if (cp_lexer_next_token_is (parser->lexer, CPP_EQ)) { @@ -16091,7 +16100,7 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type) value = error_mark_node; /* Create the enumerator. */ - build_enumerator (identifier, value, type, loc); + build_enumerator (identifier, value, type, attrs, loc); } /* Parse a namespace-name. diff --git gcc/cp/pt.c gcc/cp/pt.c index 8e0e789..d5e2b56 100644 --- gcc/cp/pt.c +++ gcc/cp/pt.c @@ -20686,8 +20686,8 @@ tsubst_enum (tree tag, tree newtag, tree args) set_current_access_from_decl (decl); /* Actually build the enumerator itself. */ - build_enumerator - (DECL_NAME (decl), value, newtag, DECL_SOURCE_LOCATION (decl)); + build_enumerator (DECL_NAME (decl), value, newtag, + DECL_ATTRIBUTES (decl), DECL_SOURCE_LOCATION (decl)); } if (SCOPED_ENUM_P (newtag)) diff --git gcc/cp/semantics.c gcc/cp/semantics.c index 701a8eb..b46c6fc 100644 --- gcc/cp/semantics.c +++ gcc/cp/semantics.c @@ -3651,11 +3651,6 @@ finish_id_expression (tree id_expression, } } - /* Handle references (c++/56130). */ - tree t = REFERENCE_REF_P (decl) ? TREE_OPERAND (decl, 0) : decl; - if (TREE_DEPRECATED (t)) - warn_deprecated_use (t, NULL_TREE); - return decl; } diff --git gcc/doc/extend.texi gcc/doc/extend.texi index c290059..4337a32 100644 --- gcc/doc/extend.texi +++ gcc/doc/extend.texi @@ -59,6 +59,7 @@ extensions, accepted by GCC in C90 mode and in C++. * Variable Attributes:: Specifying attributes of variables. * Type Attributes:: Specifying attributes of types. * Label Attributes:: Specifying attributes on labels. +* Enumerator Attributes:: Specifying attributes on enumerators. * Attribute Syntax:: Formal syntax for attributes. * Function Prototypes:: Prototype declarations and old-style definitions. * C++ Comments:: C++ comments are recognized. @@ -2175,6 +2176,7 @@ attribute syntax and placement. GCC also supports attributes on variable declarations (@pxref{Variable Attributes}), labels (@pxref{Label Attributes}), +enumerators (@pxref{Enumerator Attributes}), and types (@pxref{Type Attributes}). There is some overlap between the purposes of attributes and pragmas @@ -5041,8 +5043,9 @@ by an attribute specification inside double parentheses. Some attributes are currently defined generically for variables. Other attributes are defined for variables on particular target systems. Other attributes are available for functions -(@pxref{Function Attributes}), labels (@pxref{Label Attributes}) and for -types (@pxref{Type Attributes}). +(@pxref{Function Attributes}), labels (@pxref{Label Attributes}), +enumerators (@pxref{Enumerator Attributes}), and for types +(@pxref{Type Attributes}). Other front ends might define more attributes (@pxref{C++ Extensions,,Extensions to the C++ Language}). @@ -5837,7 +5840,8 @@ attributes of types. Some type attributes apply only to @code{struct} and @code{union} types, while others can apply to any type defined via a @code{typedef} declaration. Other attributes are defined for functions (@pxref{Function Attributes}), labels (@pxref{Label -Attributes}) and for variables (@pxref{Variable Attributes}). +Attributes}), enumerators (@pxref{Enumerator Attributes}), and for +variables (@pxref{Variable Attributes}). The @code{__attribute__} keyword is followed by an attribute specification inside double parentheses. @@ -6300,7 +6304,8 @@ compilers to match the native Microsoft compiler. GCC allows attributes to be set on C labels. @xref{Attribute Syntax}, for details of the exact syntax for using attributes. Other attributes are available for functions (@pxref{Function Attributes}), variables -(@pxref{Variable Attributes}) and for types (@pxref{Type Attributes}). +(@pxref{Variable Attributes}), enumerators (@xref{Enumerator Attributes}), +and for types (@pxref{Type Attributes}). This example uses the @code{cold} label attribute to indicate the @code{ErrorHandling} branch is unlikely to be taken and that the @@ -6346,6 +6351,45 @@ with computed goto or @code{asm goto}. @end table +@node Enumerator Attributes +@section Enumerator Attributes +@cindex Enumerator Attributes + +GCC allows attributes to be set on enumerators. @xref{Attribute Syntax}, for +details of the exact syntax for using attributes. Other attributes are +available for functions (@pxref{Function Attributes}), variables +(@pxref{Variable Attributes}), labels (@xref{Label Attributes}), +and for types (@pxref{Type Attributes}). + +This example uses the @code{deprecated} enumerator attribute to indicate the +@code{oldval} enumerator is deprecated: + +@smallexample +enum E @{ + oldval __attribute__((deprecated)), + newval +@}; + +int +fn (void) +@{ + return oldval; +@} +@end smallexample + +@table @code +@item deprecated +@cindex @code{deprecated} enumerator attribute +The @code{deprecated} attribute results in a warning if the enumerator +is used anywhere in the source file. This is useful when identifying +enumerators that are expected to be removed in a future version of a +program. The warning also includes the location of the declaration +of the deprecated enumerator, to enable users to easily find further +information about why the enumerator is deprecated, or what they should +do instead. Note that the warnings only occurs for uses. + +@end table + @node Attribute Syntax @section Attribute Syntax @cindex attribute syntax @@ -6371,6 +6415,8 @@ for details of the semantics of attributes applying to structure, union and enumerated types. @xref{Label Attributes}, for details of the semantics of attributes applying to labels. +@xref{Enumerator Attributes}, for details of the semantics of attributes +applying to enumerators. An @dfn{attribute specifier} is of the form @code{__attribute__ ((@var{attribute-list}))}. An @dfn{attribute list} @@ -6428,6 +6474,14 @@ ambiguous, as it is permissible for a declaration, which could begin with an attribute list, to be labelled in C++. Declarations cannot be labelled in C90 or C99, so the ambiguity does not arise there. +@subsubheading Enumerator Attributes + +In GNU C, an attribute specifier list may appear as part of an enumerator. +The attribute goes after the enumeration constant, before @code{=}, if +present. The optional attribute in the enumerator appertains to the +enumeration constant. It is not possible to place the attribute after +the constant expression, if present. + @subsubheading Type Attributes An attribute specifier list may appear as part of a @code{struct}, diff --git gcc/testsuite/c-c++-common/attributes-enum-1.c gcc/testsuite/c-c++-common/attributes-enum-1.c index e69de29..cb5af5b 100644 --- gcc/testsuite/c-c++-common/attributes-enum-1.c +++ gcc/testsuite/c-c++-common/attributes-enum-1.c @@ -0,0 +1,22 @@ +/* Test enumerators with attributes. */ +/* PR c/47043 */ +/* { dg-do compile } */ + +enum E { + A __attribute__((deprecated)), + B __attribute__((deprecated ("foo"))), + C __attribute__((deprecated)) = 10, + D __attribute__((deprecated ("foo"))) = 15, + E +}; + +int +f (int i) +{ + i += A; /* { dg-warning ".A. is deprecated" } */ + i += B; /* { dg-warning ".B. is deprecated" } */ + i += C; /* { dg-warning ".C. is deprecated" } */ + i += D; /* { dg-warning ".D. is deprecated" } */ + i += E; + return i; +} diff --git gcc/testsuite/c-c++-common/attributes-enum-2.c gcc/testsuite/c-c++-common/attributes-enum-2.c index e69de29..f143f15 100644 --- gcc/testsuite/c-c++-common/attributes-enum-2.c +++ gcc/testsuite/c-c++-common/attributes-enum-2.c @@ -0,0 +1,14 @@ +/* Test enumerators with attributes. Test invalid uses. */ +/* PR c/47043 */ +/* { dg-do compile } */ + +enum E { + A __attribute__((foo)), /* { dg-warning "ignored" } */ + B __attribute__((cold)), /* { dg-warning "ignored" } */ + C __attribute__((const)), /* { dg-warning "ignored" } */ + D __attribute__((unused)), /* { dg-warning "ignored" } */ + E __attribute__((flatten)), /* { dg-warning "ignored" } */ + F __attribute__((tm)), /* { dg-warning "ignored" } */ + G __attribute__((common)), /* { dg-warning "ignored" } */ + H __attribute__((volatile)), /* { dg-warning "ignored" } */ +}; diff --git gcc/testsuite/g++.dg/cpp0x/attributes-enum-1.C gcc/testsuite/g++.dg/cpp0x/attributes-enum-1.C index e69de29..fd1b6f0 100644 --- gcc/testsuite/g++.dg/cpp0x/attributes-enum-1.C +++ gcc/testsuite/g++.dg/cpp0x/attributes-enum-1.C @@ -0,0 +1,20 @@ +// PR c/47043 +// { dg-do compile { target c++11 } } + +enum E { + A [[gnu::deprecated]] +}; + +enum class F { + B [[gnu::deprecated]], + C __attribute__ ((deprecated)) +}; + +int +f (int i) +{ + F f1 = F::B; // { dg-warning ".B. is deprecated" } + F f2 = F::C; // { dg-warning ".C. is deprecated" } + i += A; // { dg-warning ".A. is deprecated" } + return i; +} diff --git gcc/testsuite/g++.dg/cpp1y/attributes-enum-1.C gcc/testsuite/g++.dg/cpp1y/attributes-enum-1.C index e69de29..3bd1ba1 100644 --- gcc/testsuite/g++.dg/cpp1y/attributes-enum-1.C +++ gcc/testsuite/g++.dg/cpp1y/attributes-enum-1.C @@ -0,0 +1,35 @@ +// PR c/47043 +// { dg-do compile { target c++14 } } + +class C +{ +public: + enum Foo + { + T, + U [[deprecated("unused")]], + V + }; +}; + +template + class D + { + public: + enum Bar + { + X, + Y [[deprecated("unused")]], + Z + }; + }; + +int +f (int i) +{ + auto j = C::U; // { dg-warning ".U. is deprecated" } + + auto k = D::Y; // { dg-warning ".Y. is deprecated" } + + return i; +} Marek