re PR c/47043 (allow deprecating enum values)
authorMarek Polacek <polacek@redhat.com>
Fri, 22 May 2015 09:07:31 +0000 (09:07 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Fri, 22 May 2015 09:07:31 +0000 (09:07 +0000)
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.

Co-Authored-By: Edward Smith-Rowland <3dw4rd@verizon.net>
From-SVN: r223527

18 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c/ChangeLog
gcc/c/c-parser.c
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/init.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/doc/extend.texi
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/attributes-enum-1.c [new file with mode: 0644]
gcc/testsuite/c-c++-common/attributes-enum-2.c [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/attributes-enum-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/attributes-enum-1.C [new file with mode: 0644]

index 090dcddd3f828a0c41a424f1660b2e9a69f6be76..aaa6aab930fb46b100b76b964be79618a4e3d7ac 100644 (file)
@@ -1,3 +1,9 @@
+2015-05-22  Marek Polacek  <polacek@redhat.com>
+
+       PR c/47043
+       * doc/extend.texi (Enumerator Attributes): New section.
+       Document syntax of enumerator attributes.
+
 2015-05-22  Richard Biener  <rguenther@suse.de>
 
        * tree-vect-loop.c (get_reduction_op): New function.
index 126301bf4cdc8ecabe47f5d42b86e501e245afd3..1dd20674e26a0a7da2a5905fb6597ff41c7fbf3f 100644 (file)
@@ -1,3 +1,8 @@
+2015-05-22  Marek Polacek  <polacek@redhat.com>
+
+       PR c/47043
+       * c-common.c (handle_deprecated_attribute): Allow CONST_DECL.
+
 2015-05-20  Trevor Saunders  <tbsaunde+gcc@tbsaunde.org>
 
        * c-cppbuiltin.c (c_cpp_builtins): Use if instead of #if with
index a2b37931911c0516f9be3cf03a6c269dcbb07fcc..36c984cd18fb58b2c61a10503c667030ebe80745 100644 (file)
@@ -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
index 59da72db578dd4a46e9c8ab3ead56ac573f7ef69..8af417baaa450eca3204b8c8d1a9c36c05261f60 100644 (file)
@@ -1,3 +1,9 @@
+2015-05-22  Marek Polacek  <polacek@redhat.com>
+
+       PR c/47043
+       * c-parser.c (c_parser_enum_specifier): Parse and apply enumerator
+       attributes.
+
 2015-05-21  Marek Polacek  <polacek@redhat.com>
 
        * c-typeck.c (inform_declaration): Use DECL_IS_BUILTIN instead of
index f496733b8a9544cb7c58f52dfdc4432b87389335..965b4b9e5f3c8bbad1e5f8beec7c90edc85315ff 100644 (file)
@@ -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;
index f9ede2dcf62f4164fd5a29be6879bf2d7f3cf219..4dd8ec65cd8e17c4276d4989e2b59dea2251b154 100644 (file)
@@ -1,3 +1,16 @@
+2015-05-22  Marek Polacek  <polacek@redhat.com>
+           Edward Smith-Rowland  <3dw4rd@verizon.net>
+
+       PR c/47043
+       * cp-tree.h (build_enumerator): Update declaration.
+       * decl.c (build_enumerator): Add attributes parameter.  Call
+       cplus_decl_attributes.
+       * init.c (constant_value_1): Pass tf_none to mark_used.
+       * parser.c (cp_parser_enumerator_definition): Parse attributes and
+       pass them down to build_enumerator.
+       * pt.c (tsubst_enum): Pass decl attributes to build_enumerator.
+       * semantics.c (finish_id_expression): Don't warn_deprecated_use here.
+
 2015-05-21  Nathan Sidwell  <nathan@acm.org>
 
        PR c++/60943
index 4136d98682cd9bed574fa7929157a1550cdb23d5..91619e2cb3ca3b28c024c6780b8c1f4aed396ce3 100644 (file)
@@ -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 *,
index e4d3c1db6965f48ef2772bdf138401d0b5185b16..5396994f7fe0a66d2c95883e896d3de4e59576ef 100644 (file)
@@ -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
index c41e30cff5c807836efb2c486b292ddb3471d732..30774070d3c487608f17cc260cc6f499616d50d9 100644 (file)
@@ -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)
index 4f429a2d60d98771ff9894f3d687632283b456aa..bc48c11cbc6c8a1fa84e045c21bb3ba3ccfe0325 100644 (file)
@@ -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.
index 7555114ca6f18c3007f59d773d18be29a0826490..407ef7d7d0a63a465b9cc41677d5983fe439e535 100644 (file)
@@ -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))
index e1d18fb9f3dddfb99168fa76cfe5e12267683aef..565941f0f5e6c9c4879790757362384dd121070c 100644 (file)
@@ -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;
 }
 
index 60046810af25d5e6117116ff653224bb4d8991a4..55391992a350870507420e83001dd0c8569cfbac 100644 (file)
@@ -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},
index db2048072afe3946704279e6939e1fefbb191604..912dd1549f4300dfe9d43fc8d4b5ed639bbc5dbb 100644 (file)
@@ -1,3 +1,11 @@
+2015-05-22  Marek Polacek  <polacek@redhat.com>
+
+       PR c/47043
+       * c-c++-common/attributes-enum-1.c: New test.
+       * c-c++-common/attributes-enum-2.c: New test.
+       * g++.dg/cpp0x/attributes-enum-1.C: New test.
+       * g++.dg/cpp1y/attributes-enum-1.C: New test.
+
 2015-05-21  Sandra Loosemore  <sandra@codesourcery.com>
 
        * gcc.target/arm/simd/simd.exp: Skip all tests if no arm_neon_ok
diff --git a/gcc/testsuite/c-c++-common/attributes-enum-1.c b/gcc/testsuite/c-c++-common/attributes-enum-1.c
new file mode 100644 (file)
index 0000000..cb5af5b
--- /dev/null
@@ -0,0 +1,22 @@
+/* Test enumerators with attributes.  */
+/* PR c/47043 */
+/* { dg-do compile } */
+
+enum E {
+  A __attribute__((deprecated)),
+  B __attribute__((deprecated ("foo"))),
+  C __attribute__((deprecated)) = 10,
+  D __attribute__((deprecated ("foo"))) = 15,
+  E
+};
+
+int
+f (int i)
+{
+  i += A; /* { dg-warning ".A. is deprecated" } */
+  i += B; /* { dg-warning ".B. is deprecated" } */
+  i += C; /* { dg-warning ".C. is deprecated" } */
+  i += D; /* { dg-warning ".D. is deprecated" } */
+  i += E;
+  return i;
+}
diff --git a/gcc/testsuite/c-c++-common/attributes-enum-2.c b/gcc/testsuite/c-c++-common/attributes-enum-2.c
new file mode 100644 (file)
index 0000000..f143f15
--- /dev/null
@@ -0,0 +1,14 @@
+/* Test enumerators with attributes.  Test invalid uses.  */
+/* PR c/47043 */
+/* { dg-do compile } */
+
+enum E {
+  A __attribute__((foo)),      /* { dg-warning "ignored" } */
+  B __attribute__((cold)),     /* { dg-warning "ignored" } */
+  C __attribute__((const)),    /* { dg-warning "ignored" } */
+  D __attribute__((unused)),   /* { dg-warning "ignored" } */
+  E __attribute__((flatten)),  /* { dg-warning "ignored" } */
+  F __attribute__((tm)),       /* { dg-warning "ignored" } */
+  G __attribute__((common)),   /* { dg-warning "ignored" } */
+  H __attribute__((volatile)), /* { dg-warning "ignored" } */
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/attributes-enum-1.C b/gcc/testsuite/g++.dg/cpp0x/attributes-enum-1.C
new file mode 100644 (file)
index 0000000..fd1b6f0
--- /dev/null
@@ -0,0 +1,20 @@
+// PR c/47043
+// { dg-do compile { target c++11 } }
+
+enum E {
+  A [[gnu::deprecated]]
+};
+
+enum class F {
+  B [[gnu::deprecated]],
+  C __attribute__ ((deprecated))
+};
+
+int
+f (int i)
+{
+  F f1 = F::B; // { dg-warning ".B. is deprecated" }
+  F f2 = F::C; // { dg-warning ".C. is deprecated" }
+  i += A; // { dg-warning ".A. is deprecated" }
+  return i;
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/attributes-enum-1.C b/gcc/testsuite/g++.dg/cpp1y/attributes-enum-1.C
new file mode 100644 (file)
index 0000000..3bd1ba1
--- /dev/null
@@ -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;
+}