This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]