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  <pola...@redhat.com>
>           Edward Smith-Rowland  <3dw...@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

Reply via email to