From 5a4c69ddfc2974d80c300d012b7f7037b5b2648b Mon Sep 17 00:00:00 2001 From: mpolacek Date: Fri, 22 May 2015 09:07:31 +0000 Subject: [PATCH] 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 tf_none 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@223527 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 6 +++ gcc/c-family/ChangeLog | 5 +++ gcc/c-family/c-common.c | 1 + gcc/c/ChangeLog | 6 +++ gcc/c/c-parser.c | 13 +++++- gcc/cp/ChangeLog | 13 ++++++ gcc/cp/cp-tree.h | 2 +- gcc/cp/decl.c | 8 +++- gcc/cp/init.c | 2 +- gcc/cp/parser.c | 13 +++++- gcc/cp/pt.c | 7 +-- gcc/cp/semantics.c | 5 --- gcc/doc/extend.texi | 62 ++++++++++++++++++++++++-- gcc/testsuite/ChangeLog | 8 ++++ gcc/testsuite/c-c++-common/attributes-enum-1.c | 22 +++++++++ gcc/testsuite/c-c++-common/attributes-enum-2.c | 14 ++++++ gcc/testsuite/g++.dg/cpp0x/attributes-enum-1.C | 20 +++++++++ gcc/testsuite/g++.dg/cpp1y/attributes-enum-1.C | 35 +++++++++++++++ 18 files changed, 223 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/attributes-enum-1.c create mode 100644 gcc/testsuite/c-c++-common/attributes-enum-2.c create mode 100644 gcc/testsuite/g++.dg/cpp0x/attributes-enum-1.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/attributes-enum-1.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 090dcddd3f8..aaa6aab930f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2015-05-22 Marek Polacek + + PR c/47043 + * doc/extend.texi (Enumerator Attributes): New section. + Document syntax of enumerator attributes. + 2015-05-22 Richard Biener * tree-vect-loop.c (get_reduction_op): New function. diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 126301bf4cd..1dd20674e26 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,8 @@ +2015-05-22 Marek Polacek + + PR c/47043 + * c-common.c (handle_deprecated_attribute): Allow CONST_DECL. + 2015-05-20 Trevor Saunders * c-cppbuiltin.c (c_cpp_builtins): Use if instead of #if with diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index a2b37931911..36c984cd18f 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -9088,6 +9088,7 @@ handle_deprecated_attribute (tree *node, tree name, || TREE_CODE (decl) == PARM_DECL || VAR_OR_FUNCTION_DECL_P (decl) || TREE_CODE (decl) == FIELD_DECL + || TREE_CODE (decl) == CONST_DECL || objc_method_decl (TREE_CODE (decl))) TREE_DEPRECATED (decl) = 1; else diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 59da72db578..8af417baaa4 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,9 @@ +2015-05-22 Marek Polacek + + PR c/47043 + * c-parser.c (c_parser_enum_specifier): Parse and apply enumerator + attributes. + 2015-05-21 Marek Polacek * c-typeck.c (inform_declaration): Use DECL_IS_BUILTIN instead of diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index f496733b8a9..965b4b9e5f3 100644 --- a/gcc/c/c-parser.c +++ b/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 a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f9ede2dcf62..4dd8ec65cd8 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2015-05-22 Marek Polacek + Edward Smith-Rowland <3dw4rd@verizon.net> + + PR c/47043 + * cp-tree.h (build_enumerator): Update declaration. + * decl.c (build_enumerator): Add attributes parameter. Call + cplus_decl_attributes. + * init.c (constant_value_1): Pass tf_none 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. + 2015-05-21 Nathan Sidwell PR c++/60943 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4136d98682c..91619e2cb3c 100644 --- a/gcc/cp/cp-tree.h +++ b/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 a/gcc/cp/decl.c b/gcc/cp/decl.c index e4d3c1db696..5396994f7fe 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -13057,11 +13057,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; @@ -13224,6 +13225,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 a/gcc/cp/init.c b/gcc/cp/init.c index c41e30cff5c..30774070d3c 100644 --- a/gcc/cp/init.c +++ b/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, tf_none); mark_rvalue_use (decl); init = DECL_INITIAL (decl); if (init == error_mark_node) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 4f429a2d60d..bc48c11cbc6 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -16083,7 +16083,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) @@ -16101,6 +16107,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)) { @@ -16118,7 +16127,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 a/gcc/cp/pt.c b/gcc/cp/pt.c index 7555114ca6f..407ef7d7d0a 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -20771,9 +20771,10 @@ tsubst_enum (tree tag, tree newtag, tree args) /* Give this enumeration constant the correct access. */ set_current_access_from_decl (decl); - /* Actually build the enumerator itself. */ - build_enumerator - (DECL_NAME (decl), value, newtag, DECL_SOURCE_LOCATION (decl)); + /* Actually build the enumerator itself. Here we're assuming that + enumerators can't have dependent attributes. */ + build_enumerator (DECL_NAME (decl), value, newtag, + DECL_ATTRIBUTES (decl), DECL_SOURCE_LOCATION (decl)); } if (SCOPED_ENUM_P (newtag)) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index e1d18fb9f3d..565941f0f5e 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -3652,11 +3652,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 a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 60046810af2..55391992a35 100644 --- a/gcc/doc/extend.texi +++ b/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 a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index db2048072af..912dd1549f4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2015-05-22 Marek Polacek + + PR c/47043 + * 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. + 2015-05-21 Sandra Loosemore * gcc.target/arm/simd/simd.exp: Skip all tests if no arm_neon_ok diff --git a/gcc/testsuite/c-c++-common/attributes-enum-1.c b/gcc/testsuite/c-c++-common/attributes-enum-1.c new file mode 100644 index 00000000000..cb5af5b9d05 --- /dev/null +++ b/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 a/gcc/testsuite/c-c++-common/attributes-enum-2.c b/gcc/testsuite/c-c++-common/attributes-enum-2.c new file mode 100644 index 00000000000..f143f15f6e8 --- /dev/null +++ b/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 a/gcc/testsuite/g++.dg/cpp0x/attributes-enum-1.C b/gcc/testsuite/g++.dg/cpp0x/attributes-enum-1.C new file mode 100644 index 00000000000..fd1b6f04b40 --- /dev/null +++ b/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 a/gcc/testsuite/g++.dg/cpp1y/attributes-enum-1.C b/gcc/testsuite/g++.dg/cpp1y/attributes-enum-1.C new file mode 100644 index 00000000000..3bd1ba1929d --- /dev/null +++ b/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; +} -- 2.11.4.GIT