C/C++ PATCH to allow deprecating enum values (PR c/47043)
Marek Polacek
polacek@redhat.com
Fri May 22 09:27:00 GMT 2015
On Thu, May 21, 2015 at 02:00:26PM -0400, Jason Merrill wrote:
> On 05/07/2015 12:22 PM, Marek Polacek wrote:
> >- mark_used (decl);
> >+ mark_used (decl, 0);
>
> This should use tf_none rather than 0.
Fixed.
> >+ build_enumerator (DECL_NAME (decl), value, newtag,
> >+ DECL_ATTRIBUTES (decl), DECL_SOURCE_LOCATION (decl));
>
> This is assuming that enumerators can't have dependent attributes. I guess
> that's currently true, but please add a comment about it.
Done.
> OK with those changes.
Thanks, applied. Here's the final version.
2015-05-22 Marek Polacek <polacek@redhat.com>
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 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.
diff --git gcc/c-family/c-common.c gcc/c-family/c-common.c
index a2b3793..36c984c 100644
--- gcc/c-family/c-common.c
+++ 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 gcc/c/c-parser.c gcc/c/c-parser.c
index f496733..965b4b9 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 4136d98..91619e2 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 e4d3c1d..5396994 100644
--- gcc/cp/decl.c
+++ 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 %<long%>");
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..3077407 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, tf_none);
mark_rvalue_use (decl);
init = DECL_INITIAL (decl);
if (init == error_mark_node)
diff --git gcc/cp/parser.c gcc/cp/parser.c
index 4f429a2..bc48c11 100644
--- gcc/cp/parser.c
+++ 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 gcc/cp/pt.c gcc/cp/pt.c
index 7555114..407ef7d 100644
--- gcc/cp/pt.c
+++ 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 gcc/cp/semantics.c gcc/cp/semantics.c
index e1d18fb..565941f 100644
--- gcc/cp/semantics.c
+++ 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 gcc/doc/extend.texi gcc/doc/extend.texi
index 6004681..5539199 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<typename Tp>
+ 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<int>::Y; // { dg-warning ".Y. is deprecated" }
+
+ return i;
+}
Marek
More information about the Gcc-patches
mailing list