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]

[PATCH]: __attribute__((deprecated))


Below is my patch for __attribute__((deprecated)).  I've submitted
this patch a few months ago.  There were some comments about
"incompleteness" (missing texi's and test cases) and some other
details.  This patch I think addresses all the previous comments.

Summary:

A function, variable or type id declared with
__attribute__((deprecated)) results in a warning if that id is used
anywhere in the source file.  This is useful when identifying
functions, variables or types that are expected to be removed in a
future version of a program.  If possible, the warning also includes
the location of the declaration of the deprecated identifier, to enable
users to easily find further information about why it is deprecated,
or what they should do instead.  Note that the warnings only occurs
for uses.  Uses of deprecated types or variables are warned only if
they are not also being defined as deprecated.  Defining a type in
terms of a deprecated type also deprecates the new type.

Example (taken from the texi):

1. typedef int T1 __attribute__ ((deprecated));
2. T1 x;
3. typedef T1 T2;
4. T2 y;
5. typedef T2 T3 __attribute__ ((deprecated));
6. T3 z __attribute__ ((deprecated));

results in a warning on line 2, 3, and 4 but not line 5 or 6.  Since
T1 is deprecated then T2 is also deprecated.  But no warning is issued
for line 5 even though T3 is defined in terms of deprecated T2
because T3 itself is being explicitly deprecated.  Similarly for
line 6.

Ira

                        =======================

2001-12-14  Ira Ruben	<ira@apple.com>

	Add __attribute__ ((deprecated)).
	* extend.texi: Document __attribute__ ((deprecated)).
	* invoke.texi: Document -Wno-deprecated-declarations.
	* testsuite/g++.dg/other/deprecated.C: New C++ test.
	* testsuite/gcc.dg/deprecated.c: New C test.
	* attribs.c (enum attrs): Declare handle_deprecated_attribute().
	(c_common_attribute_table): Add "deprecated" entry.
	(handle_deprecated_attribute): New function.
	* c-decl.c (deprecated_states): New enum.
	deprecated_state: State of "deprecated" handling.
	(start_decl): Set deprecated_state based on attributes.
	(grokdeclarator): Test for deprecated uses, propagate attribute.
	* c-typeck.c (build_component_ref): Test for deprecated fields.
	(build_external_ref): Test for deprecated primaries.
	* diagnostic.c (warn_deprecated_use) New function to issue
	warnings about __attribute__ ((depricated)) references.
	* flags.h (warn_deprecated_decl): Extern declared for
	-W[no-]deprecated-declarations option.
	* print-tree.c (print_node): Show deprecated flag status.
	* toplev.c (warn_deprecated_decl): Defined.
	(W_options): Added "deprecated-declaration".
	* toplev.h (warn_deprecated_use): Extern declared.
	* tree.h (struct tree_common): Define deprecated_flag.
	(TREE_DEPRECATED): New macro to access flag.
	* cp/call.c (build_call): Test for deprecated calls.
	* cp/class.c (add_implicitly_declared_members): Set global
	flag to tell grokdeclarator to not issue deprecated warnings.
	* cp/decl.c (deprecated_states): New enum.
	(start_decl): Set deprecated_state based on attributes.
	(grokdeclarator): Test for deprecated uses, propagate attribute.
	* cp/lex.c (do_identifier): Test for deprecated primaries.
	* cp/typeck.c (build_component_ref): Test for deprecated fields.


Index: attribs.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/attribs.c,v
retrieving revision 1.7
diff -c -3 -p -r1.7 attribs.c
*** attribs.c	2001/12/14 06:36:14	1.7
--- attribs.c	2001/12/14 20:35:18
*************** static tree handle_no_limit_stack_attrib
*** 82,87 ****
--- 82,89 ----
   						     bool *));
   static tree handle_pure_attribute	PARAMS ((tree *, tree, tree, int,
   						 bool *));
+ static tree handle_deprecated_attribute	PARAMS ((tree *, 
tree, tree, int,
+ 						 bool *));
   static tree handle_vector_size_attribute PARAMS ((tree *, tree, tree, int,
   						  bool *));
   static tree vector_size_helper PARAMS ((tree, tree));
*************** static const struct attribute_spec c_com
*** 138,143 ****
--- 140,147 ----
   			      handle_no_limit_stack_attribute },
     { "pure",                   0, 0, true,  false, false,
   			      handle_pure_attribute },
+   { "deprecated",             0, 0, false, false, false,
+ 			      handle_deprecated_attribute },
     { "vector_size",	      1, 1, false, true, false,
   			      handle_vector_size_attribute },
     { NULL,                     0, 0, false, false, false, NULL }
*************** handle_pure_attribute (node, name, args,
*** 1126,1131 ****
--- 1130,1197 ----
       {
         warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
         *no_add_attrs = true;
+     }
+
+   return NULL_TREE;
+ }
+
+ /* Handle a "deprecated" attribute; arguments as in
+    struct attribute_spec.handler.  */
+
+ static tree
+ handle_deprecated_attribute (node, name, args, flags, no_add_attrs)
+      tree *node;
+      tree name;
+      tree args ATTRIBUTE_UNUSED;
+      int flags;
+      bool *no_add_attrs;
+ {
+   tree type = NULL_TREE;
+   int warn = 0;
+   char *what = NULL;
+
+   if (DECL_P (*node))
+     {
+       tree decl = *node;
+       type = TREE_TYPE (decl);
+
+       if (TREE_CODE (decl) == TYPE_DECL)
+       	TREE_DEPRECATED (decl) = 1;
+       else if (TREE_CODE (decl) == PARM_DECL
+ 	  || TREE_CODE (decl) == VAR_DECL
+ 	  || TREE_CODE (decl) == FUNCTION_DECL
+ 	  || TREE_CODE (decl) == FIELD_DECL)
+ 	TREE_DEPRECATED (decl) = 1;
+       else
+ 	warn = 1;
+     }
+   else if (TYPE_P (*node))
+     {
+       if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
+ 	*node = build_type_copy (*node);
+       TREE_DEPRECATED (*node) = 1;
+       type = *node;
+     }
+   else
+     warn = 1;
+
+   if (warn)
+     {
+       *no_add_attrs = true;
+       if (type && TYPE_NAME (type))
+ 	{
+ 	  if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
+ 	    what = IDENTIFIER_POINTER (TYPE_NAME (*node));
+ 	  else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+ 		   && DECL_NAME (TYPE_NAME (type)))
+ 	    what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
+ 	}
+       if (what)
+ 	warning ("`%s' attribute ignored for `%s'",
+ 		  IDENTIFIER_POINTER (name), what);
+       else
+ 	warning ("`%s' attribute ignored",
+ 		      IDENTIFIER_POINTER (name));
       }

     return NULL_TREE;
Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.282
diff -c -3 -p -r1.282 c-decl.c
*** c-decl.c    2001/12/07 22:19:47     1.282
--- c-decl.c    2001/12/14 21:43:41
*************** int warn_multichar = 1;
*** 439,444 ****
--- 439,456 ----
   #endif
   int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;

+ /* States indicating how grokdeclarator() should handle declspecs marked
+    with __attribute__((deprecated)).  An object declared as
+    __attribute__((deprecated)) suppresses warnings of uses of other
+    deprecated items.  */
+
+ enum deprecated_states {
+   DEPRECATED_NORMAL,
+   DEPRECATED_SUPPRESS
+ };
+
+ static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
+
   /* Decode the string P as a language-specific option for C.
      Return the number of strings consumed.  Should not complain
      if it does not recognise the option.  */
*************** start_decl (declarator, declspecs, initi
*** 3400,3408 ****
        int initialized;
        tree attributes;
   {
!   tree decl = grokdeclarator (declarator, declspecs,
!                             NORMAL, initialized);
     tree tem;

     if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
         && MAIN_NAME_P (DECL_NAME (decl)))
--- 3412,3439 ----
        int initialized;
        tree attributes;
   {
!   tree decl;
     tree tem;
+
+   /* An object declared as __attribute__((deprecated)) suppresses
+      warnings of uses of other deprecated items.  */
+   tree a;
+
+   for (a = attributes; a; a = TREE_CHAIN (a))
+     {
+       tree name = TREE_PURPOSE (a);
+       if (TREE_CODE (name) == IDENTIFIER_NODE)
+        if (strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0)
+          {
+            deprecated_state = DEPRECATED_SUPPRESS;
+            break;
+          }
+     }
+
+   decl = grokdeclarator (declarator, declspecs,
+                        NORMAL, initialized);
+
+   deprecated_state = DEPRECATED_NORMAL;

     if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
         && MAIN_NAME_P (DECL_NAME (decl)))
*************** grokdeclarator (declarator, declspecs, d
*** 4068,4073 ****
--- 4099,4118 ----
     for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
       {
         tree id = TREE_VALUE (spec);
+
+       /* Use of a spec tagged as "deprecated" causes the *use* of that
+          spec to also be tagged as deprecated so that the original tag
+          propagates through all uses.  The returned_attrs is a
+          convenient way to add in the flag.  */
+       if (id && TREE_DEPRECATED (id))
+         {
+         if (deprecated_state != DEPRECATED_SUPPRESS)
+           warn_deprecated_use (id);
+         returned_attrs
+           = chainon (returned_attrs,
+                      build_tree_list (get_identifier ("deprecated"),
+                                       NULL_TREE));
+         }

         if (id == ridpointers[(int) RID_INT])
         explicit_int = 1;
Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-typeck.c,v
retrieving revision 1.159
diff -c -3 -p -r1.159 c-typeck.c
*** c-typeck.c	2001/12/12 19:12:13	1.159
--- c-typeck.c	2001/12/14 20:35:19
*************** build_component_ref (datum, component)
*** 1199,1204 ****
--- 1199,1208 ----
   	    TREE_READONLY (ref) = 1;
   	  if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (subdatum))
   	    TREE_THIS_VOLATILE (ref) = 1;
+
+ 	  if (TREE_DEPRECATED (subdatum))
+ 	    warn_deprecated_use (subdatum);
+
   	  datum = ref;
   	}

*************** build_external_ref (id, fun)
*** 1414,1419 ****
--- 1418,1426 ----
     tree ref;
     tree decl = lookup_name (id);
     tree objc_ivar = lookup_objc_ivar (id);
+
+   if (decl && TREE_DEPRECATED (decl))
+     warn_deprecated_use (decl);

     if (!decl || decl == error_mark_node || C_DECL_ANTICIPATED (decl))
       {
Index: diagnostic.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/diagnostic.c,v
retrieving revision 1.71
diff -c -3 -p -r1.71 diagnostic.c
*** diagnostic.c	2001/11/23 02:05:16	1.71
--- diagnostic.c	2001/12/14 20:35:19
*************** default_diagnostic_finalizer (buffer, dc
*** 1520,1522 ****
--- 1520,1563 ----
   {
     output_destroy_prefix (buffer);
   }
+
+ void
+ warn_deprecated_use (node)
+      tree node;
+ {
+   if (node && warn_deprecated_decl)
+     if (DECL_P (node))
+       {
+ 	warning ("`%s' is deprecated (declared at %s:%d)",
+ 		 IDENTIFIER_POINTER (DECL_NAME (node)),
+ 		 DECL_SOURCE_FILE (node), DECL_SOURCE_LINE (node));
+       }
+     else if (TYPE_P (node))
+       {
+       	char *what = NULL;
+ 	tree decl = TYPE_STUB_DECL (node);
+
+ 	if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
+ 	  what = IDENTIFIER_POINTER (TYPE_NAME (node));
+ 	else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
+ 		 && DECL_NAME (TYPE_NAME (node)))
+ 	  what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node)));
+
+ 	if (what)
+ 	  {
+ 	    if (decl)
+ 	      warning ("`%s' is deprecated (declared at %s:%d)", what,
+ 		       DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
+ 	    else
+ 	      warning ("`%s' is deprecated", what);
+ 	  }
+ 	else
+ 	  {
+ 	    if (decl)
+ 	      warning ("type is deprecated (declared at %s:%d)",
+ 		       DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
+ 	    else
+ 	      warning ("type is deprecated");
+ 	  }
+       }
+ }
Index: flags.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/flags.h,v
retrieving revision 1.74
diff -c -3 -p -r1.74 flags.h
*** flags.h	2001/12/13 11:34:05	1.74
--- flags.h	2001/12/14 20:35:19
*************** extern int warn_padded;
*** 169,174 ****
--- 169,179 ----

   extern int warn_disabled_optimization;

+ /* Nonzero means warn about uses of __attribute__((deprecated))
+    declarations.  */
+
+ extern int warn_deprecated_decl;
+
   /* Nonzero if generating code to do profiling.  */

   extern int profile_flag;
Index: print-tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/print-tree.c,v
retrieving revision 1.51
diff -c -3 -p -r1.51 print-tree.c
*** print-tree.c	2001/12/05 11:54:04	1.51
--- print-tree.c	2001/12/14 20:35:19
*************** print_node (file, prefix, node, indent)
*** 294,299 ****
--- 294,301 ----
       fputs (" protected", file);
     if (TREE_STATIC (node))
       fputs (" static", file);
+   if (TREE_DEPRECATED (node))
+     fputs (" deprecated", file);
     if (TREE_LANG_FLAG_0 (node))
       fputs (" tree_0", file);
     if (TREE_LANG_FLAG_1 (node))
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.557
diff -c -3 -p -r1.557 toplev.c
*** toplev.c	2001/12/13 21:37:27	1.557
--- toplev.c	2001/12/14 20:35:19
*************** int warn_disabled_optimization;
*** 1464,1469 ****
--- 1464,1474 ----

   int warn_missing_noreturn;

+ /* Nonzero means warn about uses of __attribute__((deprecated))
+    declarations.  */
+
+ int warn_deprecated_decl = 1;
+
   /* Likewise for -W.  */

   lang_independent_options W_options[] =
*************** lang_independent_options W_options[] =
*** 1502,1507 ****
--- 1507,1514 ----
      N_("Warn when padding is required to align struct members") },
     {"disabled-optimization", &warn_disabled_optimization, 1,
      N_("Warn when an optimization pass is disabled") },
+   {"deprecated-declarations", &warn_deprecated_decl, 1,
+    N_("Warn about uses of __attribute__((deprecated)) declarations") },
     {"missing-noreturn", &warn_missing_noreturn, 1,
      N_("Warn about functions which might be candidates for attribute 
noreturn") }
   };
Index: toplev.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.h,v
retrieving revision 1.80
diff -c -3 -p -r1.80 toplev.h
*** toplev.h	2001/11/06 21:12:08	1.80
--- toplev.h	2001/12/14 20:35:19
*************** extern void error_for_asm		PARAMS ((stru
*** 92,97 ****
--- 92,98 ----
   						 const char *, ...));
   extern void warning_for_asm		PARAMS ((struct rtx_def *,
   						 const char *, ...));
+ extern void warn_deprecated_use		PARAMS ((union tree_node *));
   extern int do_float_handler PARAMS ((void (*) (PTR), PTR));

   #ifdef BUFSIZ
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.294
diff -c -3 -p -r1.294 tree.h
*** tree.h	2001/12/11 19:33:39	1.294
--- tree.h	2001/12/14 20:35:19
*************** struct tree_common
*** 139,144 ****
--- 139,145 ----
     unsigned private_flag : 1;
     unsigned protected_flag : 1;
     unsigned bounded_flag : 1;
+   unsigned deprecated_flag : 1;

     unsigned lang_flag_0 : 1;
     unsigned lang_flag_1 : 1;
*************** struct tree_common
*** 259,264 ****
--- 260,270 ----
   	   IDENTIFIER_NODE
          TYPE_BOUNDED in
   	   ..._TYPE
+
+    deprecated_flag:
+
+ 	TREE_DEPRECATED in
+ 	   ..._DECL
   */

   /* Define accessors for the fields that all tree nodes have
*************** extern void tree_class_check_failed PARA
*** 646,651 ****
--- 652,661 ----
      argument type(s).  */

   #define TREE_BOUNDED(NODE) ((NODE)->common.bounded_flag)
+
+ /* Nonzero in a IDENTIFIER_NODE if the use of the name is defined as a
+    deprecated feature by __attribute__((deprecated)).  */
+ #define TREE_DEPRECATED(NODE) ((NODE)->common.deprecated_flag)

   /* These flags are available for each language front end to use 
internally.  */
   #define TREE_LANG_FLAG_0(NODE) ((NODE)->common.lang_flag_0)
Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.295
diff -c -3 -p -r1.295 call.c
*** call.c	2001/12/13 01:37:46	1.295
--- call.c	2001/12/14 20:35:20
*************** build_call (function, parms)
*** 405,411 ****
        throw without being declared throw().  */
     nothrow = ((decl && TREE_NOTHROW (decl))
   	     || TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (function))));
!
     if (decl && DECL_CONSTRUCTOR_P (decl))
       is_constructor = 1;

--- 405,414 ----
        throw without being declared throw().  */
     nothrow = ((decl && TREE_NOTHROW (decl))
   	     || TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (function))));
!
!   if (decl && TREE_DEPRECATED (decl))
!     warn_deprecated_use (decl);
!
     if (decl && DECL_CONSTRUCTOR_P (decl))
       is_constructor = 1;

Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.423
diff -c -3 -p -r1.423 class.c
*** class.c	2001/12/13 01:37:47	1.423
--- class.c	2001/12/14 20:35:20
*************** add_implicitly_declared_members (t, cant
*** 2900,2906 ****
--- 2900,2909 ----
     tree implicit_fns = NULL_TREE;
     tree virtual_dtor = NULL_TREE;
     tree *f;
+   extern int adding_implicit_members;

+   ++adding_implicit_members;
+
     /* Destructor.  */
     if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t))
       {
*************** add_implicitly_declared_members (t, cant
*** 2959,2964 ****
--- 2962,2969 ----
       add_method (t, *f, /*error_p=*/0);
     *f = TYPE_METHODS (t);
     TYPE_METHODS (t) = implicit_fns;
+
+   --adding_implicit_members;

     return virtual_dtor;
   }
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.841
diff -c -3 -p -r1.841 decl.c
*** decl.c	2001/12/14 03:01:57	1.841
--- decl.c	2001/12/14 20:35:21
*************** tree anonymous_namespace_name;
*** 302,307 ****
--- 302,324 ----
      (Zero if we are at namespace scope, one inside the body of a
      function, two inside the body of a function in a local class, etc.)  */
   int function_depth;
+
+ /* States indicating how grokdeclarator() should handle declspecs marked
+    with __attribute__((deprecated)).  An object declared as
+    __attribute__((deprecated)) suppresses warnings of uses of other
+    deprecated items.  */
+
+ enum deprecated_states {
+   DEPRECATED_NORMAL,
+   DEPRECATED_SUPPRESS
+ };
+
+ static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
+
+ /* The following is set by add_implicitly_declared_members() to keep
+    those members from being flagged as deprecated or reported as using
+    deprecated types.  */
+ int adding_implicit_members = 0;
   
   /* For each binding contour we allocate a binding_level structure
      which records the names defined in that contour.
*************** start_decl (declarator, declspecs, initi
*** 7145,7150 ****
--- 7162,7168 ----
     tree decl;
     register tree type, tem;
     tree context;
+   tree a;
     extern int have_extern_spec;
     extern int used_extern_spec;

*************** start_decl (declarator, declspecs, initi
*** 7161,7171 ****
--- 7179,7204 ----
         used_extern_spec = 1;
       }

+   /* An object declared as __attribute__((deprecated)) suppresses
+      warnings of uses of other deprecated items.  */
+   for (a = attributes; a; a = TREE_CHAIN (a))
+     {
+       tree name = TREE_PURPOSE (a);
+       if (TREE_CODE (name) == IDENTIFIER_NODE)
+ 	 if (strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0)
+ 	   {
+ 	     deprecated_state = DEPRECATED_SUPPRESS;
+ 	     break;
+ 	   }
+     }
+
     attributes = chainon (attributes, prefix_attributes);

     decl = grokdeclarator (declarator, declspecs, NORMAL, initialized,
   			 &attributes);

+   deprecated_state = DEPRECATED_NORMAL;
+
     if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE)
       return NULL_TREE;

*************** grokdeclarator (declarator, declspecs, d
*** 9992,9997 ****
--- 10025,10044 ----
   	return 0;

         id = TREE_VALUE (spec);
+
+       /* Use of a spec tagged as "deprecated" causes the *use* of that
+          spec to also be tagged as deprecated so that the original tag
+          propagates through all uses.  The returned_attrs is a
+          convenient way to add in the flag.  */
+       if (!adding_implicit_members && id && TREE_DEPRECATED (id))
+         {
+ 	  if (deprecated_state != DEPRECATED_SUPPRESS)
+ 	    warn_deprecated_use (id);
+ 	  returned_attrs
+ 	    = chainon (returned_attrs,
+ 		       build_tree_list (get_identifier ("deprecated"),
+ 					NULL_TREE));
+         }

         if (TREE_CODE (id) == IDENTIFIER_NODE)
   	{
Index: cp/lex.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/lex.c,v
retrieving revision 1.260
diff -c -3 -p -r1.260 lex.c
*** lex.c	2001/12/09 07:52:12	1.260
--- lex.c	2001/12/14 20:35:21
*************** do_identifier (token, parsing, args)
*** 1215,1220 ****
--- 1215,1223 ----
     else
       id = lastiddecl;

+   if (lexing && id && TREE_DEPRECATED (id))
+     warn_deprecated_use (id);
+
     /* Do Koenig lookup if appropriate (inside templates we build lookup
        expressions instead).

Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.374
diff -c -3 -p -r1.374 typeck.c
*** typeck.c	2001/12/13 01:37:52	1.374
--- typeck.c	2001/12/14 20:35:21
*************** build_component_ref (datum, component, b
*** 2198,2203 ****
--- 2198,2206 ----
   	}
       }

+   if (TREE_DEPRECATED (field))
+     warn_deprecated_use (field);
+
     /* See if we have to do any conversions so that we pick up the 
field from the
        right context.  */
     if (DECL_FIELD_CONTEXT (field) != basetype)
Index: doc/extend.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/extend.texi,v
retrieving revision 1.48
diff -c -3 -p -r1.48 extend.texi
*** extend.texi 2001/12/14 21:06:31     1.48
--- extend.texi 2001/12/14 22:26:20
*************** attributes are currently defined for fun
*** 1941,1951 ****
   @code{noreturn}, @code{noinline}, @code{pure}, @code{const},
   @code{format}, @code{format_arg}, @code{no_instrument_function},
   @code{section}, @code{constructor}, @code{destructor}, @code{used},
! @code{unused}, @code{weak}, @code{malloc}, and @code{alias}.  Several
! other attributes are defined for functions on particular target systems.
! Other attributes, including @code{section} are supported for variables
! declarations (@pxref{Variable Attributes}) and for types (@pxref{Type
! Attributes}).

   You may also specify attributes with @samp{__} preceding and following
   each keyword.  This allows you to use them in header files without
--- 1941,1951 ----
   @code{noreturn}, @code{noinline}, @code{pure}, @code{const},
   @code{format}, @code{format_arg}, @code{no_instrument_function},
   @code{section}, @code{constructor}, @code{destructor}, @code{used},
! @code{unused}, @code{deprecated}, @code{weak}, @code{malloc}, and
! @code{alias}.  Several other attributes are defined for functions on
! particular target systems.  Other attributes, including @code{section}
! are supported for variables declarations (@pxref{Variable Attributes})
! and for types (@pxref{Type Attributes}).

   You may also specify attributes with @samp{__} preceding and following
   each keyword.  This allows you to use them in header files without
*************** for the function even if it appears that
*** 2205,2210 ****
--- 2205,2231 ----
   This is useful, for example, when the function is referenced only in
   inline assembly.

+ @cindex @code{deprecated} attribute.
+ @item deprecated
+ The @code{deprecated} attribute results in a warning if the function
+ is used anywhere in the source file.  This is useful when identifying
+ functions 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 function, to enable users to easily find further
+ information about why the function is deprecated, or what they should
+ do instead.  Note that the warnings only occurs for uses:
+
+ @smallexample
+ int old_fn () __attribute__ ((deprecated));
+ int old_fn ();
+ int (*fn_ptr)() = old_fn;
+ @end smallexample
+
+ results in a warning on line 3 but not line 2.
+
+ The @code{deprecated} attribute can also be used for variables and
+ types (@pxref{Variable Attributes}, @pxref{Type Attributes}.)
+
   @item weak
   @cindex @code{weak} attribute
   The @code{weak} attribute causes the declaration to be emitted as a weak
*************** section.
*** 2818,2832 ****

   The keyword @code{__attribute__} allows you to specify special
   attributes of variables or structure fields.  This keyword is followed
! by an attribute specification inside double parentheses.  Nine
   attributes are currently defined for variables: @code{aligned},
   @code{mode}, @code{nocommon}, @code{packed}, @code{section},
! @code{transparent_union}, @code{unused}, @code{vector_size}, and
! @code{weak}.  Some other attributes are defined for variables on
! particular target systems.  Other attributes are available for functions
! (@pxref{Function Attributes}) and for types (@pxref{Type Attributes}).
! Other front ends might define more attributes (@pxref{C++
! Extensions,,Extensions to the C++ Language}).

   You may also specify attributes with @samp{__} preceding and following
   each keyword.  This allows you to use them in header files without
--- 2839,2853 ----

   The keyword @code{__attribute__} allows you to specify special
   attributes of variables or structure fields.  This keyword is followed
! by an attribute specification inside double parentheses.  Ten
   attributes are currently defined for variables: @code{aligned},
   @code{mode}, @code{nocommon}, @code{packed}, @code{section},
! @code{transparent_union}, @code{unused}, @code{deprecated},
! @code{vector_size}, and @code{weak}.  Some other attributes are defined
! for variables on particular target systems.  Other attributes are
! available for functions (@pxref{Function Attributes}) and for types
! (@pxref{Type Attributes}).  Other front ends might define more
! attributes (@pxref{C++ Extensions,,Extensions to the C++ Language}).

   You may also specify attributes with @samp{__} preceding and following
   each keyword.  This allows you to use them in header files without
*************** This attribute, attached to a variable,
*** 3028,3033 ****
--- 3049,3074 ----
   to be possibly unused.  GCC will not produce a warning for this
   variable.

+ @item deprecated
+ The @code{deprecated} attribute results in a warning if the variable
+ is used anywhere in the source file.  This is useful when identifying
+ variables 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 variable, to enable users to easily find further
+ information about why the variable is deprecated, or what they should
+ do instead.  Note that the warnings only occurs for uses:
+
+ @smallexample
+ extern int old_var __attribute__ ((deprecated));
+ extern int old_var;
+ int new_fn () @{ return old_var; @}
+ @end smallexample
+
+ results in a warning on line 3 but not line 2.
+
+ The @code{deprecated} attribute can also be used for functions and
+ types (@pxref{Function Attributes}, @pxref{Type Attributes}.)
+
   @item vector_size (@var{bytes})
   This attribute specifies the vector size for the variable, measured in
   bytes.  For example, the declaration:
*************** packed))}.
*** 3087,3096 ****
   The keyword @code{__attribute__} allows you to specify special
   attributes of @code{struct} and @code{union} types when you define such
   types.  This keyword is followed by an attribute specification inside
! double parentheses.  Four attributes are currently defined for types:
! @code{aligned}, @code{packed}, @code{transparent_union}, and @code{unused}.
! Other attributes are defined for functions (@pxref{Function Attributes}) and
! for variables (@pxref{Variable Attributes}).

   You may also specify any one of these attributes with @samp{__}
   preceding and following its keyword.  This allows you to use these
--- 3128,3137 ----
   The keyword @code{__attribute__} allows you to specify special
   attributes of @code{struct} and @code{union} types when you define such
   types.  This keyword is followed by an attribute specification inside
! double parentheses.  Five attributes are currently defined for types:
! @code{aligned}, @code{packed}, @code{transparent_union}, @code{unused},
! and @code(deprecated).  Other attributes are defined for functions
! (@pxref{Function Attributes}) and for variables (@pxref{Variable 
Attributes}).

   You may also specify any one of these attributes with @samp{__}
   preceding and following its keyword.  This allows you to use these
*************** that type, even if the variable appears
*** 3272,3277 ****
--- 3313,3348 ----
   the case with lock or thread classes, which are usually defined and then
   not referenced, but contain constructors and destructors that have
   nontrivial bookkeeping functions.
+
+ @item deprecated
+ 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.
+ If possible, the warning also includes the location of the declaration
+ of the deprecated type, to enable users to easily find further
+ information about why the type is deprecated, or what they should do
+ instead.  Note that the warnings only occur for uses and then only
+ if the type is being applied to a variable that itself is not being
+ declared as deprecated.  Defining a type in terms of a deprecated
+ type also deprecates that new type.
+
+ @smallexample
+ typedef int T1 __attribute__ ((deprecated));
+ T1 x;
+ typedef T1 T2;
+ T2 y;
+ typedef T2 T3 __attribute__ ((deprecated));
+ T3 z __attribute__ ((deprecated));
+ @end smallexample
+
+ results in a warning on line 2, 3, and 4 but not line 5 or 6.  Since
+ T1 is deprecated then T2 is also deprecated.  But no warning is issued
+ for line 5 even though T3 is defined in terms of deprecated T2
+ because T3 itself is being explicitly deprecated.  Similarly for
+ line 6.
+
+ The @code{deprecated} attribute can also be used for functions and
+ variables (@pxref{Function Attributes}, @pxref{Variables Attributes}.)

   @end table

Index: doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.91
diff -c -3 -p -r1.91 invoke.texi
*** invoke.texi	2001/12/14 11:20:27	1.91
--- invoke.texi	2001/12/14 20:35:22
*************** in the following sections.
*** 212,218 ****
   -fsyntax-only  -pedantic  -pedantic-errors @gol
   -w  -W  -Wall  -Waggregate-return @gol
   -Wcast-align  -Wcast-qual  -Wchar-subscripts  -Wcomment @gol
! -Wconversion  -Wdisabled-optimization  -Wdiv-by-zero  -Werror @gol
   -Wfloat-equal  -Wformat  -Wformat=2 @gol
   -Wformat-nonliteral  -Wformat-security @gol
   -Wimplicit  -Wimplicit-int  @gol
--- 212,219 ----
   -fsyntax-only  -pedantic  -pedantic-errors @gol
   -w  -W  -Wall  -Waggregate-return @gol
   -Wcast-align  -Wcast-qual  -Wchar-subscripts  -Wcomment @gol
! -Wconversion  -Wno-deprecated-declarations @gol
! -Wdisabled-optimization  -Wdiv-by-zero  -Werror @gol
   -Wfloat-equal  -Wformat  -Wformat=2 @gol
   -Wformat-nonliteral  -Wformat-security @gol
   -Wimplicit  -Wimplicit-int  @gol
*************** like @code{vprintf} or @code{vscanf}, bu
*** 2503,2508 ****
--- 2504,2516 ----
   case, and some functions for which @code{format} attributes are
   appropriate may not be detected.  This option has no effect unless
   @option{-Wformat} is enabled (possibly by @option{-Wall}).
+
+ @item -Wno-deprecated-declarations
+ @opindex Wno-deprecated-declarations
+ Do not warn about uses of functions, variables, and types marked as
+ deprecated by using the @code{deprecated} attribute.
+ (@pxref{Function Attributes}, @pxref{Variable Attributes},
+ @pxref{Type Attributes}.)

   @item -Wpacked
   @opindex Wpacked
Index: testsuite/g++.dg/other/deprecated.C
===================================================================
RCS file: deprecated.C
diff -N deprecated.C
*** /dev/null	Tue May  5 13:32:27 1998
--- deprecated.C	Fri Dec 14 12:35:23 2001
***************
*** 0 ****
--- 1,99 ----
+ /* Test __attribute__ ((deprecated)) */
+ /* { dg-do compile } */
+ /* { dg-options "-Wdeprecated-declarations" } */
+
+ #if 1
+ typedef int INT1 __attribute__((deprecated));
+ typedef INT1 INT2 __attribute__ ((deprecated));
+
+ typedef INT1 INT1a; 			/* { dg-warning "`INT1' is 
deprecated" "" } */
+ typedef INT1 INT1b __attribute__ ((deprecated));
+
+ INT1 should_be_unavailable; 		/* { dg-warning "`INT1' is 
deprecated" "" } */
+ INT1a should_be_deprecated;   		/* { dg-warning 
"`INT1a' is deprecated" "" } */
+
+ INT1 f(void) __attribute__ ((deprecated));
+ INT1 f(void) {}				/* { dg-warning 
"`INT1' is deprecated" "" } */
+
+ typedef enum {red, green, blue} Color __attribute__((deprecated));
+
+ int g1;
+ int g2 __attribute__ ((deprecated));
+ Color k;				/* { dg-warning "`Color' is 
deprecated" "" } */
+
+ typedef struct {
+   int field1;
+   int field2 __attribute__ ((deprecated));
+   int field3;
+   int field4 __attribute__ ((deprecated));
+   union {
+     int field5;
+     int field6 __attribute__ ((deprecated));
+   } u1;
+   int field7:1;
+   int field8:1 __attribute__ ((deprecated));
+   union {
+     int field9;
+     int field10;
+   } u2 __attribute__ ((deprecated));
+ } S1;
+
+ int f1()
+ {
+    INT1 x;				/* { dg-warning "`INT1' is 
deprecated" "" } */
+    int y __attribute__ ((deprecated));
+    int z;
+    int (*pf)() = f;			/* { dg-warning "`f' is 
deprecated" "" } */
+
+    z = x + y + g1 + g2;			/* { dg-warning "`x' 
is deprecated" "" } */
+    					/* { dg-warning "`y' is 
deprecated" "" { target *-*-* } 48 } */
+    					/* { dg-warning "`g2' is 
deprecated" "" { target *-*-* } 48 } */
+    return f(); 				/* { dg-warning "`f' 
is deprecated" "" } */
+ }
+
+ int f2(S1 *p)
+ {
+   S1 lp;
+
+   if (p->field1)
+      return p->field2;			/* { dg-warning 
"`field2' is deprecated" "" } */
+   else if (lp.field4)			/* { dg-warning "`field4' is 
deprecated" "" } */
+      return p->field3;
+
+   p->u1.field5 = g1 + p->field7;
+   p->u2.field9;				/* { dg-warning "`u2' 
is deprecated" "" } */
+   return p->u1.field6 + p->field8;	/* { dg-warning "`field6' is 
deprecated" "" } */
+   					/* { dg-warning "`field8' is 
deprecated" "" { target *-*-* } 65 } */
+ }
+
+ struct SS {
+   int x;
+   INT1 y; 				/* { dg-warning "`INT1' is 
deprecated" "" } */
+ } __attribute__ ((deprecated));
+
+ struct SS *p1;				/* { dg-warning "`SS' 
is deprecated" "" } */
+ #endif
+
+ #ifdef __cplusplus
+ class T {
+   public:
+     void member1(int) __attribute__ ((deprecated));
+     int member2(T *);
+     int x;
+ } __attribute__ ((deprecated));
+
+ T *p2;
+
+ inline void T::member1(int) {}
+
+ int T::member2(T *p)
+ {
+   p->member1(1);			/* { dg-warning "`member1' is 
deprecated" "" } */
+   (*p).member1(2);			/* { dg-warning "`member1' is 
deprecated" "" } */
+   p->member2(p);
+   (*p).member2(p);
+   return f(); 				/* { dg-warning "`f' 
is deprecated" "" } */
+ }
+ #endif
+
+
Index: testsuite/gcc.dg/deprecated.c
===================================================================
RCS file: deprecated.c
diff -N deprecated.c
*** /dev/null	Tue May  5 13:32:27 1998
--- deprecated.c	Fri Dec 14 12:35:24 2001
***************
*** 0 ****
--- 1,99 ----
+ /* Test __attribute__ ((deprecated)) */
+ /* { dg-do compile } */
+ /* { dg-options "-Wdeprecated-declarations" } */
+
+ #if 1
+ typedef int INT1 __attribute__((deprecated));
+ typedef INT1 INT2 __attribute__ ((deprecated));
+
+ typedef INT1 INT1a; 			/* { dg-warning "`INT1' is 
deprecated" "" } */
+ typedef INT1 INT1b __attribute__ ((deprecated));
+
+ INT1 should_be_unavailable; 		/* { dg-warning "`INT1' is 
deprecated" "" } */
+ INT1a should_be_deprecated;   		/* { dg-warning 
"`INT1a' is deprecated" "" } */
+
+ INT1 f(void) __attribute__ ((deprecated));
+ INT1 f(void) {}				/* { dg-warning 
"`INT1' is deprecated" "" } */
+
+ typedef enum {red, green, blue} Color __attribute__((deprecated));
+
+ int g1;
+ int g2 __attribute__ ((deprecated));
+ Color k;				/* { dg-warning "`Color' is 
deprecated" "" } */
+
+ typedef struct {
+   int field1;
+   int field2 __attribute__ ((deprecated));
+   int field3;
+   int field4 __attribute__ ((deprecated));
+   union {
+     int field5;
+     int field6 __attribute__ ((deprecated));
+   } u1;
+   int field7:1;
+   int field8:1 __attribute__ ((deprecated));
+   union {
+     int field9;
+     int field10;
+   } u2 __attribute__ ((deprecated));
+ } S1;
+
+ int f1()
+ {
+    INT1 x;				/* { dg-warning "`INT1' is 
deprecated" "" } */
+    int y __attribute__ ((deprecated));
+    int z;
+    int (*pf)() = f;			/* { dg-warning "`f' is 
deprecated" "" } */
+
+    z = x + y + g1 + g2;			/* { dg-warning "`x' 
is deprecated" "" } */
+    					/* { dg-warning "`y' is 
deprecated" "" { target *-*-* } 48 } */
+    					/* { dg-warning "`g2' is 
deprecated" "" { target *-*-* } 48 } */
+    return f(); 				/* { dg-warning "`f' 
is deprecated" "" } */
+ }
+
+ int f2(S1 *p)
+ {
+   S1 lp;
+
+   if (p->field1)
+      return p->field2;			/* { dg-warning 
"`field2' is deprecated" "" } */
+   else if (lp.field4)			/* { dg-warning "`field4' is 
deprecated" "" } */
+      return p->field3;
+
+   p->u1.field5 = g1 + p->field7;
+   p->u2.field9;				/* { dg-warning "`u2' 
is deprecated" "" } */
+   return p->u1.field6 + p->field8;	/* { dg-warning "`field6' is 
deprecated" "" } */
+   					/* { dg-warning "`field8' is 
deprecated" "" { target *-*-* } 65 } */
+ }
+
+ struct SS {
+   int x;
+   INT1 y; 				/* { dg-warning "`INT1' is 
deprecated" "" } */
+ } __attribute__ ((deprecated));
+
+ struct SS *p1;				/* { dg-warning "`SS' 
is deprecated" "" } */
+ #endif
+
+ #ifdef __cplusplus
+ class T {
+   public:
+     void member1(int) __attribute__ ((deprecated));
+     int member2(T *);
+     int x;
+ } __attribute__ ((deprecated));
+
+ T *p2;
+
+ inline void T::member1(int) {}
+
+ int T::member2(T *p)
+ {
+   p->member1(1);			/* { xxxdg-warning "`member1' 
is deprecated" "" } */
+   (*p).member1(2);			/* { xxdg-warning "`member1' 
is deprecated" "" } */
+   p->member2(p);
+   (*p).member2(p);
+   return f(); 				/* { xxdg-warning 
"`f' is deprecated" "" } */
+ }
+ #endif
+
+


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