[PATCH] Extend __attribute__((deprecated)) with an optional message

Andrew C. Morrow acm@google.com
Fri Nov 14 22:46:00 GMT 2008


Hi -

The following patch extends __attribute__((deprecated)) with an
optional string to be emitted in the deprecation warning:

int foo __attribute__((deprecated("use new_foo")));
int bar = foo;

Will emit a warning like: warning: 'foo' is deprecated (declared at
...) with message 'use new_foo'

Thanks,
Andrew


2008-11-14  Andrew Morrow  <acm@google.com>

	* doc/extend.texi: Document new optional parameter to
	__attribute__((deprecated))
	* toplev.c (get_deprecation_message): New function.
	* toplev.c (warn_deprecated_use): If a deprecation attribute has
	an associated message, emit the message as part of the warning.
	* c-common.c (c_common_attribute_table): Permit deprecated
	attribute to take an optional argument.
	* c-common.c (handle_deprecated_attribute): If the optional
	argument to __attribute__((deprecated)) is not a string ignore the
	attribute and emit a warning.

testsuite/ChangeLog
	* gcc.dg/deprecated-4.c: New file.

Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 141865)
+++ gcc/doc/extend.texi	(working copy)
@@ -2036,6 +2036,7 @@ objects (@pxref{C++ Attributes}).
 These attributes are not currently implemented for Objective-C@.

 @item deprecated
+@itemx deprecated (@var{msg})
 @cindex @code{deprecated} attribute.
 The @code{deprecated} attribute results in a warning if the function
 is used anywhere in the source file.  This is useful when identifying
@@ -2051,7 +2052,9 @@ int old_fn ();
 int (*fn_ptr)() = old_fn;
 @end smallexample

-results in a warning on line 3 but not line 2.
+results in a warning on line 3 but not line 2.  The optional msg
+argument, which must be a string, will be printed in the warning if
+present.

 The @code{deprecated} attribute can also be used for variables and
 types (@pxref{Variable Attributes}, @pxref{Type Attributes}.)
@@ -3761,6 +3764,7 @@ These attributes override the default ch
 @option{-fno-common} and @option{-fcommon} flags respectively.

 @item deprecated
+@itemx deprecated (@var{msg})
 @cindex @code{deprecated} attribute
 The @code{deprecated} attribute results in a warning if the variable
 is used anywhere in the source file.  This is useful when identifying
@@ -3776,7 +3780,9 @@ extern int old_var;
 int new_fn () @{ return old_var; @}
 @end smallexample

-results in a warning on line 3 but not line 2.
+results in a warning on line 3 but not line 2.  The optional msg
+argument, which must be a string, will be printed in the warning if
+present.

 The @code{deprecated} attribute can also be used for functions and
 types (@pxref{Function Attributes}, @pxref{Type Attributes}.)
@@ -4399,6 +4405,7 @@ not referenced, but contain constructors
 nontrivial bookkeeping functions.

 @item deprecated
+@itemx deprecated (@var{msg})
 The @code{deprecated} attribute results in a warning if the type
 is used anywhere in the source file.  This is useful when identifying
 types that are expected to be removed in a future version of a program.
@@ -4421,7 +4428,9 @@ T3 z __attribute__ ((deprecated));
 results in a warning on line 2 and 3 but not lines 4, 5, or 6.  No
 warning is issued for line 4 because T2 is not explicitly
 deprecated.  Line 5 has no warning because T3 is explicitly
-deprecated.  Similarly for line 6.
+deprecated.  Similarly for line 6.  The optional msg
+argument, which must be a string, will be printed in the warning if
+present.

 The @code{deprecated} attribute can also be used for functions and
 variables (@pxref{Function Attributes}, @pxref{Variable Attributes}.)
Index: gcc/toplev.c
===================================================================
--- gcc/toplev.c	(revision 141865)
+++ gcc/toplev.c	(working copy)
@@ -895,19 +895,59 @@ emit_debug_global_declarations (tree *ve
   timevar_pop (TV_SYMOUT);
 }

+/* If the given tree, which must be a decl or type, has an associated
+   deprecation attribute with a message, then return the message.  */
+
+static const char *
+get_deprecation_message (tree node)
+{
+  tree attributes = NULL_TREE;
+  if (DECL_P (node))
+    attributes = DECL_ATTRIBUTES (node);
+  else if (TYPE_P (node))
+    attributes = TYPE_ATTRIBUTES (node);
+
+  if (attributes != NULL_TREE)
+    {
+      tree deprecation = lookup_attribute ("deprecated", attributes);
+      if (deprecation != NULL_TREE)
+        {
+          tree argument_list = TREE_VALUE (deprecation);
+          if (argument_list != NULL_TREE)
+            if (TREE_CODE (TREE_VALUE (argument_list)) == STRING_CST)
+              return TREE_STRING_POINTER (TREE_VALUE (argument_list));
+        }
+    }
+
+  return NULL;
+}
+
 /* Warn about a use of an identifier which was marked deprecated.  */
 void
 warn_deprecated_use (tree node)
 {
+  char *deprecation_message = NULL;
+  const char *deprecation_arg = NULL;
+
   if (node == 0 || !warn_deprecated_decl)
     return;

+  /* If the deprecation has a message, construct a string containing
+     the message that we can emit as part of the warning. Otherwise,
+     build an empty string that we can print silently.  */
+
+  if ((deprecation_arg = get_deprecation_message (node)) != NULL)
+    asprintf (&deprecation_message, " with message '%s'",
+              deprecation_arg);
+  else
+    deprecation_message = xstrdup ("");
+
   if (DECL_P (node))
     {
       expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (node));
       warning (OPT_Wdeprecated_declarations,
-	       "%qD is deprecated (declared at %s:%d)",
-	       node, xloc.file, xloc.line);
+               "%qD is deprecated (declared at %s:%d)%s",
+               node, xloc.file, xloc.line, deprecation_message);
     }
   else if (TYPE_P (node))
     {
@@ -929,21 +969,25 @@ warn_deprecated_use (tree node)
 	    = expand_location (DECL_SOURCE_LOCATION (decl));
 	  if (what)
 	    warning (OPT_Wdeprecated_declarations,
-		     "%qs is deprecated (declared at %s:%d)", what,
-		     xloc.file, xloc.line);
+		     "%qs is deprecated (declared at %s:%d)%s", what,
+		     xloc.file, xloc.line, deprecation_message);
 	  else
 	    warning (OPT_Wdeprecated_declarations,
-		     "type is deprecated (declared at %s:%d)",
-		     xloc.file, xloc.line);
+		     "type is deprecated (declared at %s:%d)%s",
+		     xloc.file, xloc.line, deprecation_message);
 	}
       else
 	{
 	  if (what)
-	    warning (OPT_Wdeprecated_declarations, "%qs is deprecated", what);
+	    warning (OPT_Wdeprecated_declarations, "%qs is deprecated%s", what,
+                     deprecation_message);
 	  else
-	    warning (OPT_Wdeprecated_declarations, "type is deprecated");
+	    warning (OPT_Wdeprecated_declarations, "type is deprecated%s",
+                     deprecation_message);
 	}
     }
+
+  free (deprecation_message);
 }

 /* Compile an entire translation unit.  Write a file of assembly
Index: gcc/testsuite/gcc.dg/deprecated-4.c
===================================================================
--- gcc/testsuite/gcc.dg/deprecated-4.c	(revision 0)
+++ gcc/testsuite/gcc.dg/deprecated-4.c	(revision 0)
@@ -0,0 +1,25 @@
+/* Test __attribute__((deprecated)).  Test deprecation attribute tags.  */
+/* Origin: Andrew Morrow <acm@google.com> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+int value_bad_tag __attribute__((deprecated(1)));  /* { dg-warning
"non-string message ignored" } */
+
+int value_is_deprecated __attribute__((deprecated("Use
value_is_not_deprecated instead")));
+
+void use_value_is_deprecated() {
+   int useit = value_is_deprecated; /* { dg-warning "with message
'Use value_is_not_deprecated instead'" } */
+}
+
+struct __attribute__((deprecated("See some_other_type for
replacement"))) type_is_deprecated {
+};
+
+void use_type_is_deprecated() {
+  struct type_is_deprecated x;  /* { dg-warning "with message 'See
some_other_type for replacement'" } */
+}
+
+void function_is_deprecated() __attribute__((deprecated("@deprecated
http://deprecationdb/293847")));
+void function_is_deprecated() {}
+
+void use_function_is_deprecated() {
+  function_is_deprecated();  /* { dg-warning "with message
'@deprecated http://deprecationdb/293847'" } */
+}
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c	(revision 141865)
+++ gcc/c-common.c	(working copy)
@@ -823,7 +823,7 @@ const struct attribute_spec c_common_att
      to prevent its usage in source code.  */
   { "no vops",                0, 0, true,  false, false,
 			      handle_novops_attribute },
-  { "deprecated",             0, 0, false, false, false,
+  { "deprecated",             0, 1, false, false, false,
 			      handle_deprecated_attribute },
   { "vector_size",	      1, 1, false, true, false,
 			      handle_vector_size_attribute },
@@ -6444,13 +6444,23 @@ handle_novops_attribute (tree *node, tre

 static tree
 handle_deprecated_attribute (tree *node, tree name,
-			     tree ARG_UNUSED (args), int flags,
+			     tree args, int flags,
 			     bool *no_add_attrs)
 {
   tree type = NULL_TREE;
   int warn = 0;
   tree what = NULL_TREE;

+  /* Validate any argument is a string or ignore the attribute.  */
+  if (args != NULL_TREE && TREE_CODE (TREE_VALUE (args)) != STRING_CST)
+    {
+      warning (OPT_Wattributes,
+               "%qE attribute with non-string message ignored",
+               name);
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+
   if (DECL_P (*node))
     {
       tree decl = *node;



More information about the Gcc-patches mailing list