public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: C/C++ PATCH to allow deprecating enum values (PR c/47043)
@ 2015-05-07  3:17 Ed Smith-Rowland
  2015-05-07 14:00 ` Marek Polacek
  0 siblings, 1 reply; 18+ messages in thread
From: Ed Smith-Rowland @ 2015-05-07  3:17 UTC (permalink / raw)
  To: gcc-patches, polacek, Joseph S. Myers, Jason Merrill

In addition to a PR this is 1/2 of a C=+17 feature. (The other half - 
really a separate thing - is attributes on namespaces).

I wonder if we should pedwarn for < C++17?
Or it could be just an extension for < C++17 - I guess that would match 
with clang.


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

Why did this bit get removed?

Do we handle enums in template specializations?

Ed


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: C/C++ PATCH to allow deprecating enum values (PR c/47043)
  2015-05-07  3:17 C/C++ PATCH to allow deprecating enum values (PR c/47043) Ed Smith-Rowland
@ 2015-05-07 14:00 ` Marek Polacek
  2015-05-07 14:22   ` Ed Smith-Rowland
  0 siblings, 1 reply; 18+ messages in thread
From: Marek Polacek @ 2015-05-07 14:00 UTC (permalink / raw)
  To: Ed Smith-Rowland; +Cc: gcc-patches, Joseph S. Myers, Jason Merrill

On Wed, May 06, 2015 at 11:17:20PM -0400, Ed Smith-Rowland wrote:
> In addition to a PR this is 1/2 of a C=+17 feature. (The other half - really
> a separate thing - is attributes on namespaces).

Ah, nice, I wasn't aware.  For the record, this is
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4266.html>.
 
> I wonder if we should pedwarn for < C++17?
> Or it could be just an extension for < C++17 - I guess that would match with
> clang.
 
Yeah, it is meant as a GNU extension.  (clang supports this extension for
several years already.)  I'd rather let Jason decide what to do wrt C++17.
 
> @@ -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;
>  }
> 
> Why did this bit get removed?

This hunk got added in r201906 to address c++/56130 - we didn't warn for
deprecated references:

int g_nn;
int& g_n __attribute__((deprecated)) = g_nn;

int main()
{
    g_n = 1;
}

But then Jason added warn_deprecated_use to mark_used in r217677 and we
warned twice.  So I figured the warning in finish_id_expression isn't
needed anymore.
 
> Do we handle enums in template specializations?

Not sure, could you provide a testcase?  Thanks,

	Marek

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: C/C++ PATCH to allow deprecating enum values (PR c/47043)
  2015-05-07 14:00 ` Marek Polacek
@ 2015-05-07 14:22   ` Ed Smith-Rowland
  2015-05-07 16:22     ` Marek Polacek
  0 siblings, 1 reply; 18+ messages in thread
From: Ed Smith-Rowland @ 2015-05-07 14:22 UTC (permalink / raw)
  To: Marek Polacek; +Cc: gcc-patches, Joseph S. Myers, Jason Merrill

[-- Attachment #1: Type: text/plain, Size: 1886 bytes --]

On 05/07/2015 09:59 AM, Marek Polacek wrote:
> On Wed, May 06, 2015 at 11:17:20PM -0400, Ed Smith-Rowland wrote:
>> In addition to a PR this is 1/2 of a C=+17 feature. (The other half - really
>> a separate thing - is attributes on namespaces).
> Ah, nice, I wasn't aware.  For the record, this is
> <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4266.html>.
>   
>> I wonder if we should pedwarn for < C++17?
>> Or it could be just an extension for < C++17 - I guess that would match with
>> clang.
>   
> Yeah, it is meant as a GNU extension.  (clang supports this extension for
> several years already.)  I'd rather let Jason decide what to do wrt C++17.
>   
>> @@ -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;
>>   }
>>
>> Why did this bit get removed?
> This hunk got added in r201906 to address c++/56130 - we didn't warn for
> deprecated references:
>
> int g_nn;
> int& g_n __attribute__((deprecated)) = g_nn;
>
> int main()
> {
>      g_n = 1;
> }
>
> But then Jason added warn_deprecated_use to mark_used in r217677 and we
> warned twice.  So I figured the warning in finish_id_expression isn't
> needed anymore.
>   
>> Do we handle enums in template specializations?
> Not sure, could you provide a testcase?  Thanks,
>
> 	Marek
>
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.

Also, I haven't tested the testcase in terms of the pattern matching of 
the error.  Tweak it if necessary.

Thanks for this.

Ed



[-- Attachment #2: attributes-enum-2.C --]
[-- Type: text/x-c++src, Size: 427 bytes --]

// PR c/47046
// { dg-do compile { target c++11 } }

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 ".C::U. is deprecated" }

  auto k = D<int>::Y; // { dg-warning ".D<int>::Y. is deprecated" }

  return i;
}

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: C/C++ PATCH to allow deprecating enum values (PR c/47043)
  2015-05-07 14:22   ` Ed Smith-Rowland
@ 2015-05-07 16:22     ` Marek Polacek
  2015-05-07 17:25       ` Sandra Loosemore
                         ` (2 more replies)
  0 siblings, 3 replies; 18+ messages in thread
From: Marek Polacek @ 2015-05-07 16:22 UTC (permalink / raw)
  To: Ed Smith-Rowland, Joseph Myers, Jason Merrill
  Cc: gcc-patches, Sandra Loosemore

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  <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 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 %<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..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<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

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: C/C++ PATCH to allow deprecating enum values (PR c/47043)
  2015-05-07 16:22     ` Marek Polacek
@ 2015-05-07 17:25       ` Sandra Loosemore
  2015-05-07 19:26         ` Marek Polacek
  2015-05-14  8:54       ` Marek Polacek
  2015-05-21 18:14       ` Jason Merrill
  2 siblings, 1 reply; 18+ messages in thread
From: Sandra Loosemore @ 2015-05-07 17:25 UTC (permalink / raw)
  To: Marek Polacek; +Cc: Ed Smith-Rowland, Joseph Myers, Jason Merrill, gcc-patches

On 05/07/2015 10:22 AM, Marek Polacek wrote:
> [snip]	
>
> 	* doc/extend.texi (Enumerator Attributes): New section.
> 	Document syntax of enumerator attributes.

How about making the new Enumerator Attributes node a subsection of the 
Type Attributes section, instead of a section of its own at the same level?

I've kind of been scratching my head over the existing entry for 
bnd_variable_size in the Type Attributes section; it applies to members 
of a structure rather than a structure type.  Now that there's another 
similar special case being proposed, I think it makes sense to give both 
of these type-related attributes parallel treatment, and pull 
bnd_variable_size out into its own subsection as well.  I can take care 
of that part, or shuffle the Enumerator Attributes section around too if 
you just want to commit what you have before I have time to get around 
to finishing the reorganization of this material.

-Sandra

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: C/C++ PATCH to allow deprecating enum values (PR c/47043)
  2015-05-07 17:25       ` Sandra Loosemore
@ 2015-05-07 19:26         ` Marek Polacek
  0 siblings, 0 replies; 18+ messages in thread
From: Marek Polacek @ 2015-05-07 19:26 UTC (permalink / raw)
  To: Sandra Loosemore
  Cc: Ed Smith-Rowland, Joseph Myers, Jason Merrill, gcc-patches

On Thu, May 07, 2015 at 11:23:51AM -0600, Sandra Loosemore wrote:
> How about making the new Enumerator Attributes node a subsection of the Type
> Attributes section, instead of a section of its own at the same level?
 
Sorry, I don't particularly like this idea.  I think an enumerator is not
closely related to a type.  The current state makes it clear that so far
only the "deprecated" attribute can appertain to an enumerator.

> I've kind of been scratching my head over the existing entry for
> bnd_variable_size in the Type Attributes section; it applies to members of a
> structure rather than a structure type.  Now that there's another similar
> special case being proposed, I think it makes sense to give both of these
> type-related attributes parallel treatment, and pull bnd_variable_size out
> into its own subsection as well.  I can take care of that part, or shuffle
> the Enumerator Attributes section around too if you just want to commit what
> you have before I have time to get around to finishing the reorganization of
> this material.

Thanks -- I'm keeping the docs as it was then.

	Marek

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: C/C++ PATCH to allow deprecating enum values (PR c/47043)
  2015-05-07 16:22     ` Marek Polacek
  2015-05-07 17:25       ` Sandra Loosemore
@ 2015-05-14  8:54       ` Marek Polacek
  2015-05-14 21:47         ` Joseph Myers
  2015-05-21 11:02         ` Marek Polacek
  2015-05-21 18:14       ` Jason Merrill
  2 siblings, 2 replies; 18+ messages in thread
From: Marek Polacek @ 2015-05-14  8:54 UTC (permalink / raw)
  To: Ed Smith-Rowland, Joseph Myers, Jason Merrill
  Cc: gcc-patches, Sandra Loosemore

Ping.
Joseph, do you have any further comments on the patch?
Jason, can you review the C++ parts?

Thanks,

On Thu, May 07, 2015 at 06:22:40PM +0200, Marek Polacek wrote:
> 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  <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 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 %<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..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<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

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: C/C++ PATCH to allow deprecating enum values (PR c/47043)
  2015-05-14  8:54       ` Marek Polacek
@ 2015-05-14 21:47         ` Joseph Myers
  2015-05-21 11:02         ` Marek Polacek
  1 sibling, 0 replies; 18+ messages in thread
From: Joseph Myers @ 2015-05-14 21:47 UTC (permalink / raw)
  To: Marek Polacek
  Cc: Ed Smith-Rowland, Jason Merrill, gcc-patches, Sandra Loosemore

On Thu, 14 May 2015, Marek Polacek wrote:

> Ping.
> Joseph, do you have any further comments on the patch?

The C front-end changes are OK.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: C/C++ PATCH to allow deprecating enum values (PR c/47043)
  2015-05-14  8:54       ` Marek Polacek
  2015-05-14 21:47         ` Joseph Myers
@ 2015-05-21 11:02         ` Marek Polacek
  1 sibling, 0 replies; 18+ messages in thread
From: Marek Polacek @ 2015-05-21 11:02 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

I'm pinging the C++ parts.

Thanks,

> On Thu, May 07, 2015 at 06:22:40PM +0200, Marek Polacek wrote:
> > 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  <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 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 %<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..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<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

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: C/C++ PATCH to allow deprecating enum values (PR c/47043)
  2015-05-07 16:22     ` Marek Polacek
  2015-05-07 17:25       ` Sandra Loosemore
  2015-05-14  8:54       ` Marek Polacek
@ 2015-05-21 18:14       ` Jason Merrill
  2015-05-21 18:19         ` Jason Merrill
  2015-05-22  9:27         ` Marek Polacek
  2 siblings, 2 replies; 18+ messages in thread
From: Jason Merrill @ 2015-05-21 18:14 UTC (permalink / raw)
  To: Marek Polacek, Ed Smith-Rowland, Joseph Myers
  Cc: gcc-patches, Sandra Loosemore

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.

> +      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.

OK with those changes.

Jason

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: C/C++ PATCH to allow deprecating enum values (PR c/47043)
  2015-05-21 18:14       ` Jason Merrill
@ 2015-05-21 18:19         ` Jason Merrill
  2015-05-22  9:27         ` Marek Polacek
  1 sibling, 0 replies; 18+ messages in thread
From: Jason Merrill @ 2015-05-21 18:19 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-patches, Sandra Loosemore

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.

> +      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.

OK with those changes.

Jason


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: C/C++ PATCH to allow deprecating enum values (PR c/47043)
  2015-05-21 18:14       ` Jason Merrill
  2015-05-21 18:19         ` Jason Merrill
@ 2015-05-22  9:27         ` Marek Polacek
  2015-05-22 23:05           ` Mikhail Maltsev
  1 sibling, 1 reply; 18+ messages in thread
From: Marek Polacek @ 2015-05-22  9:27 UTC (permalink / raw)
  To: Jason Merrill
  Cc: Ed Smith-Rowland, Joseph Myers, gcc-patches, Sandra Loosemore

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

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: C/C++ PATCH to allow deprecating enum values (PR c/47043)
  2015-05-22  9:27         ` Marek Polacek
@ 2015-05-22 23:05           ` Mikhail Maltsev
  2015-05-23 20:25             ` Ed Smith-Rowland
  0 siblings, 1 reply; 18+ messages in thread
From: Mikhail Maltsev @ 2015-05-22 23:05 UTC (permalink / raw)
  To: Marek Polacek, Jason Merrill
  Cc: Ed Smith-Rowland, Joseph Myers, gcc-patches, Sandra Loosemore

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?

-- 
Regards,
    Mikhail Maltsev

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: C/C++ PATCH to allow deprecating enum values (PR c/47043)
  2015-05-22 23:05           ` Mikhail Maltsev
@ 2015-05-23 20:25             ` Ed Smith-Rowland
  0 siblings, 0 replies; 18+ messages in thread
From: Ed Smith-Rowland @ 2015-05-23 20:25 UTC (permalink / raw)
  To: Mikhail Maltsev, Marek Polacek, Jason Merrill
  Cc: Joseph Myers, gcc-patches, Sandra Loosemore

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

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: C/C++ PATCH to allow deprecating enum values (PR c/47043)
  2015-05-06 18:44   ` Marek Polacek
@ 2015-05-07 11:03     ` Marek Polacek
  0 siblings, 0 replies; 18+ messages in thread
From: Marek Polacek @ 2015-05-07 11:03 UTC (permalink / raw)
  To: Joseph Myers; +Cc: GCC Patches, Jason Merrill, Sandra Loosemore

[ CC'ing Sandra: since you were recently cleaning up the attributes docs
  (thanks), the doc/extend.texi bits in this patch might be of interest to
  you. ]

On Wed, May 06, 2015 at 08:44:10PM +0200, Marek Polacek wrote:
> 2015-05-06  Marek Polacek  <polacek@redhat.com>
> 
> 	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 NULL_TREE 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.
> 
> 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 %<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..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..c3a452d 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, NULL_TREE,
> +			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..df5bc9c 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..4146116 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/47046
> +// { 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;
> +}
> 
> 	Marek

	Marek

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: C/C++ PATCH to allow deprecating enum values (PR c/47043)
  2015-05-06 16:13 ` Joseph Myers
@ 2015-05-06 18:44   ` Marek Polacek
  2015-05-07 11:03     ` Marek Polacek
  0 siblings, 1 reply; 18+ messages in thread
From: Marek Polacek @ 2015-05-06 18:44 UTC (permalink / raw)
  To: Joseph Myers; +Cc: GCC Patches, Jason Merrill

On Wed, May 06, 2015 at 04:13:05PM +0000, Joseph Myers wrote:
> On Wed, 6 May 2015, Marek Polacek wrote:
> 
> > 2015-05-06  Marek Polacek  <polacek@redhat.com>
> > 
> > 	PR c/47043
> > 	* c-common.c (handle_deprecated_attribute): Allow CONST_DECL.
> 
> Do all other attributes already reject CONST_DECL?  I don't see any tests 
> for unsupported attributes on enum values being properly diagnosed (adding 
> tests for every unsupported attribute would seem excessive, but there 
> should be a few).

I've tried a bunch of them manually and all seemed to just ignore CONST_DECLs.
This version of the patch contains a new test to test invalid attributes.

> > diff --git gcc/c/c-parser.c gcc/c/c-parser.c
> > index bf0e4c57..f06a6b3 100644
> > --- gcc/c/c-parser.c
> > +++ gcc/c/c-parser.c
> > @@ -2584,7 +2584,11 @@ 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);
> > +	  /* Parse any specified attributes.  */
> > +	  tree enum_attrs = c_parser_attributes (parser);
> > +	  if (enum_attrs)
> > +	    decl_attributes (&TREE_PURPOSE (enum_decl), enum_attrs, 0);
> 
> You need to update the syntax comment to include the new syntax.  

Done (and for C++ as well).

> You also 
> need to update the user documentation of attributes (syntax and semantics) 
> in extend.texi to include this case.
 
Right, apparently I posted the patch too soon.  So this version updates
the documentation, hopefully what I wrote is enough.

> Why is the attribute going after the "= value"?  That seems inconsistent 
> with positioning of attributes in initialized variable declarations, for 
> example.

A thinko of mine: I didn't properly check what we do for variables with an
initializer...  Fixed by moving the attribute parsing slightly above.

Thanks.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2015-05-06  Marek Polacek  <polacek@redhat.com>

	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 NULL_TREE 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.

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 %<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..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..c3a452d 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, NULL_TREE,
+			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..df5bc9c 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..4146116 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/47046
+// { 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;
+}

	Marek

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: C/C++ PATCH to allow deprecating enum values (PR c/47043)
  2015-05-06 15:48 Marek Polacek
@ 2015-05-06 16:13 ` Joseph Myers
  2015-05-06 18:44   ` Marek Polacek
  0 siblings, 1 reply; 18+ messages in thread
From: Joseph Myers @ 2015-05-06 16:13 UTC (permalink / raw)
  To: Marek Polacek; +Cc: GCC Patches, Jason Merrill

On Wed, 6 May 2015, Marek Polacek wrote:

> 2015-05-06  Marek Polacek  <polacek@redhat.com>
> 
> 	PR c/47043
> 	* c-common.c (handle_deprecated_attribute): Allow CONST_DECL.

Do all other attributes already reject CONST_DECL?  I don't see any tests 
for unsupported attributes on enum values being properly diagnosed (adding 
tests for every unsupported attribute would seem excessive, but there 
should be a few).

> diff --git gcc/c/c-parser.c gcc/c/c-parser.c
> index bf0e4c57..f06a6b3 100644
> --- gcc/c/c-parser.c
> +++ gcc/c/c-parser.c
> @@ -2584,7 +2584,11 @@ 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);
> +	  /* Parse any specified attributes.  */
> +	  tree enum_attrs = c_parser_attributes (parser);
> +	  if (enum_attrs)
> +	    decl_attributes (&TREE_PURPOSE (enum_decl), enum_attrs, 0);

You need to update the syntax comment to include the new syntax.  You also 
need to update the user documentation of attributes (syntax and semantics) 
in extend.texi to include this case.

Why is the attribute going after the "= value"?  That seems inconsistent 
with positioning of attributes in initialized variable declarations, for 
example.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 18+ messages in thread

* C/C++ PATCH to allow deprecating enum values (PR c/47043)
@ 2015-05-06 15:48 Marek Polacek
  2015-05-06 16:13 ` Joseph Myers
  0 siblings, 1 reply; 18+ messages in thread
From: Marek Polacek @ 2015-05-06 15:48 UTC (permalink / raw)
  To: GCC Patches, Joseph Myers, Jason Merrill

This patch implements a feature quite a lot of people wanted: allow using
__attribute__ ((deprecated)) on an enumerator.  Implementing it was quite
straightforward: parse the attributes and apply them to the CONST_DECL.

I hit an issue in the C++ FE though: since r217677 we produce the deprecated
diagnostic twice.  In finish_id_expression I've just removed the code that
isn't needed anymore (since we've already warned via mark_used), and in
constant_value_1 I'm passing 0 to mark_used to mollify the warning.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2015-05-06  Marek Polacek  <polacek@redhat.com>

	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 NULL_TREE to build_enumerator.
	* semantics.c (finish_id_expression): Don't warn_deprecated_use here.

	* c-c++-common/attributes-enum-1.c: New test.
	* g++.dg/cpp0x/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..f06a6b3 100644
--- gcc/c/c-parser.c
+++ gcc/c/c-parser.c
@@ -2584,7 +2584,11 @@ 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);
+	  /* Parse any specified attributes.  */
+	  tree enum_attrs = c_parser_attributes (parser);
+	  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 %<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..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..b083c02 100644
--- gcc/cp/parser.c
+++ gcc/cp/parser.c
@@ -16090,8 +16090,11 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type)
   if (check_for_bare_parameter_packs (value))
     value = error_mark_node;
 
+  /* Parse any specified attributes.  */
+  tree attrs = cp_parser_attributes_opt (parser);
+
   /* 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..c3a452d 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, NULL_TREE,
+			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/testsuite/c-c++-common/attributes-enum-1.c gcc/testsuite/c-c++-common/attributes-enum-1.c
index e69de29..a02d91d 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 = 10 __attribute__((deprecated)),
+  D = 15 __attribute__((deprecated ("foo"))),
+  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/g++.dg/cpp0x/attributes-enum-1.C gcc/testsuite/g++.dg/cpp0x/attributes-enum-1.C
index e69de29..4146116 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/47046
+// { 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;
+}

	Marek

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2015-05-23 15:25 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-07  3:17 C/C++ PATCH to allow deprecating enum values (PR c/47043) Ed Smith-Rowland
2015-05-07 14:00 ` Marek Polacek
2015-05-07 14:22   ` Ed Smith-Rowland
2015-05-07 16:22     ` Marek Polacek
2015-05-07 17:25       ` Sandra Loosemore
2015-05-07 19:26         ` Marek Polacek
2015-05-14  8:54       ` Marek Polacek
2015-05-14 21:47         ` Joseph Myers
2015-05-21 11:02         ` Marek Polacek
2015-05-21 18:14       ` Jason Merrill
2015-05-21 18:19         ` Jason Merrill
2015-05-22  9:27         ` Marek Polacek
2015-05-22 23:05           ` Mikhail Maltsev
2015-05-23 20:25             ` Ed Smith-Rowland
  -- strict thread matches above, loose matches on Subject: below --
2015-05-06 15:48 Marek Polacek
2015-05-06 16:13 ` Joseph Myers
2015-05-06 18:44   ` Marek Polacek
2015-05-07 11:03     ` Marek Polacek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).