diff mbox

C/C++ PATCH to allow deprecating enum values (PR c/47043)

Message ID 20150522091013.GR27320@redhat.com
State New
Headers show

Commit Message

Marek Polacek May 22, 2015, 9:10 a.m. UTC
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.


	Marek

Comments

Mikhail Maltsev May 22, 2015, 10:19 p.m. UTC | #1
On 22.05.2015 12:10, Marek Polacek wrote:
> Thanks, applied.  Here's the final version.

By the way, we have a feature test macro, __cpp_attributes=200809 which
can be used to determine, whether C++11 attribute syntax is supported by
the compiler.

I propose to add something similar for this extension (like
__cpp_gnu_enum_attributes=... for C++ and __GCC_HAVE_ENUM_ATTRIBUTES for
C). Thoughts?
Ed Smith-Rowland May 23, 2015, 3:24 p.m. UTC | #2
On 05/22/2015 06:19 PM, Mikhail Maltsev wrote:
> On 22.05.2015 12:10, Marek Polacek wrote:
>> Thanks, applied.  Here's the final version.
> By the way, we have a feature test macro, __cpp_attributes=200809 which
> can be used to determine, whether C++11 attribute syntax is supported by
> the compiler.
>
> I propose to add something similar for this extension (like
> __cpp_gnu_enum_attributes=... for C++ and __GCC_HAVE_ENUM_ATTRIBUTES for
> C). Thoughts?
>
I think SG 10 is or did debate this a weekor two ago.  I haven't heard.
I had made some recommendations along the lines you describe. Another 
member had suggested just bumping the date on

__cpp_attributes

I don't know what/if they decided.

Ed
diff mbox

Patch

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;
+}