PATCH: PR c/36892: Support __attribute__((deprecated("text string")))

H.J. Lu hjl.tools@gmail.com
Fri May 8 04:06:00 GMT 2009


On Thu, May 07, 2009 at 07:07:41PM +0000, Joseph S. Myers wrote:
> On Tue, 5 May 2009, H.J. Lu wrote:
> 
> > 	* gcc.dg/deprecated-4.c: Likewise.
> > 	* gcc.dg/deprecated-5.c: Likewise.
> > 	* gcc.dg/deprecated-6.c: Likewise.
> 
> deprecated-5.c and deprecated-6.c look like copies of deprecated-2.c and 
> deprecated-3.c; why are you adding them?
> 

Ooops. I forgot to add text.

> The dg-warning lines in the new tests don't appear actually to be testing 
> that the "text string" appears in the diagnostic, but that's an important 
> thing to test here.
> 

Here is the updated patch.  dg.exp doesn't support the same
regexp with dg-warning at different lines. I can only put
regexp at the last dg-warning. Are C and C++ parts OK?

Thanks.


H.J.
----
gcc/

2009-05-05  H.J. Lu  <hongjiu.lu@intel.com>
	    Andrew Morrow  <acm@google.com>

	PR c/36892
	* c-common.c (c_common_attribute_table): Permit deprecated
	attribute to take an optional argument.
	(handle_deprecated_attribute): If the optional argument to
	__attribute__((deprecated)) is not a string ignore the attribute
	and emit a warning.

	* c-decl.c (grokdeclarator): Updated warn_deprecated_use call.
	* c-typeck.c (build_component_ref): Likewise.
	(build_external_ref): Likewise.

	* toplev.c (warn_deprecated_use): Add an attribute argument.
	Emit the message associated with __attribute__((deprecated)).

	* toplev.h (warn_deprecated_use): Updated.

	* doc/extend.texi: Document new optional parameter to
	__attribute__((deprecated))

gcc/cp/

2009-05-05  H.J. Lu  <hongjiu.lu@intel.com>

	PR c/36892
	* call.c (build_call_a): Updated warn_deprecated_use call.
	(build_over_call): Likewise.
	* decl.c (grokdeclarator): Likewise.
	(grokparms): Likewise.
	* semantics.c (finish_id_expression): Likewise.
	* typeck.c (build_class_member_access_expr): Likewise.
	(finish_class_member_access_expr): Likewise.

gcc/testsuite/

2009-05-05  H.J. Lu  <hongjiu.lu@intel.com>

	PR c/36892
	* g++.dg/warn/deprecated-6.C: New.
	* gcc.dg/deprecated-4.c: Likewise.
	* gcc.dg/deprecated-5.c: Likewise.
	* gcc.dg/deprecated-6.c: Likewise.

--- gcc/c-common.c.deprecated	2009-05-07 13:07:36.000000000 -0700
+++ gcc/c-common.c	2009-05-07 13:14:39.000000000 -0700
@@ -954,7 +954,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 },
@@ -7179,13 +7179,21 @@ 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;
 
+  if (!args)
+    *no_add_attrs = true;
+  else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
+    {
+      error ("deprecated message is not a string");
+      *no_add_attrs = true;
+    }
+
   if (DECL_P (*node))
     {
       tree decl = *node;
--- gcc/c-decl.c.deprecated	2009-05-07 13:07:36.000000000 -0700
+++ gcc/c-decl.c	2009-05-07 13:14:39.000000000 -0700
@@ -4180,7 +4180,7 @@ grokdeclarator (const struct c_declarato
     decl_context = PARM;
 
   if (declspecs->deprecated_p && deprecated_state != DEPRECATED_SUPPRESS)
-    warn_deprecated_use (declspecs->type);
+    warn_deprecated_use (declspecs->type, declspecs->decl_attr);
 
   if ((decl_context == NORMAL || decl_context == FIELD)
       && current_scope == file_scope
--- gcc/c-typeck.c.deprecated	2009-05-07 13:07:36.000000000 -0700
+++ gcc/c-typeck.c	2009-05-07 17:40:34.000000000 -0700
@@ -1964,7 +1964,7 @@ build_component_ref (tree datum, tree co
 	    TREE_THIS_VOLATILE (ref) = 1;
 
 	  if (TREE_DEPRECATED (subdatum))
-	    warn_deprecated_use (subdatum);
+	    warn_deprecated_use (subdatum, NULL_TREE);
 
 	  datum = ref;
 
@@ -2225,7 +2225,7 @@ build_external_ref (tree id, int fun, lo
     return error_mark_node;
 
   if (TREE_DEPRECATED (ref))
-    warn_deprecated_use (ref);
+    warn_deprecated_use (ref, NULL_TREE);
 
   /* Recursive call does not count as usage.  */
   if (ref != current_function_decl) 
--- gcc/cp/call.c.deprecated	2009-05-07 13:07:03.000000000 -0700
+++ gcc/cp/call.c	2009-05-07 13:14:39.000000000 -0700
@@ -342,7 +342,7 @@ build_call_a (tree function, int n, tree
     current_function_returns_abnormally = 1;
 
   if (decl && TREE_DEPRECATED (decl))
-    warn_deprecated_use (decl);
+    warn_deprecated_use (decl, NULL_TREE);
   require_complete_eh_spec_types (fntype, decl);
 
   if (decl && DECL_CONSTRUCTOR_P (decl))
@@ -5457,7 +5457,7 @@ build_over_call (struct z_candidate *can
       /* Warn about deprecated virtual functions now, since we're about
 	 to throw away the decl.  */
       if (TREE_DEPRECATED (fn))
-	warn_deprecated_use (fn);
+	warn_deprecated_use (fn, NULL_TREE);
 
       argarray[0] = build_base_path (PLUS_EXPR, argarray[0], binfo, 1);
       if (TREE_SIDE_EFFECTS (argarray[0]))
--- gcc/cp/decl.c.deprecated	2009-05-07 13:07:03.000000000 -0700
+++ gcc/cp/decl.c	2009-05-07 16:30:07.000000000 -0700
@@ -7835,7 +7835,7 @@ grokdeclarator (const cp_declarator *dec
      suppress reports of deprecated items.  */
   if (type && TREE_DEPRECATED (type)
       && deprecated_state != DEPRECATED_SUPPRESS)
-    warn_deprecated_use (type);
+    warn_deprecated_use (type, NULL_TREE);
   if (type && TREE_CODE (type) == TYPE_DECL)
     {
       typedef_decl = type;
@@ -7843,7 +7843,7 @@ grokdeclarator (const cp_declarator *dec
       if (TREE_DEPRECATED (type)
 	  && DECL_ARTIFICIAL (typedef_decl)
 	  && deprecated_state != DEPRECATED_SUPPRESS)
-	warn_deprecated_use (type);
+	warn_deprecated_use (type, NULL_TREE);
     }
   /* No type at all: default to `int', and set DEFAULTED_INT
      because it was not a user-defined typedef.  */
@@ -9697,7 +9697,7 @@ grokparms (tree parmlist, tree *parms)
 	    {
 	      tree deptype = type_is_deprecated (type);
 	      if (deptype)
-		warn_deprecated_use (deptype);
+		warn_deprecated_use (deptype, NULL_TREE);
 	    }
 
 	  /* Top-level qualifiers on the parameters are
--- gcc/cp/semantics.c.deprecated	2009-05-07 13:07:03.000000000 -0700
+++ gcc/cp/semantics.c	2009-05-07 13:14:39.000000000 -0700
@@ -3038,7 +3038,7 @@ finish_id_expression (tree id_expression
     }
 
   if (TREE_DEPRECATED (decl))
-    warn_deprecated_use (decl);
+    warn_deprecated_use (decl, NULL_TREE);
 
   return decl;
 }
--- gcc/cp/typeck.c.deprecated	2009-05-07 13:07:03.000000000 -0700
+++ gcc/cp/typeck.c	2009-05-07 13:14:39.000000000 -0700
@@ -1909,7 +1909,7 @@ build_class_member_access_expr (tree obj
       member_scope = DECL_CLASS_CONTEXT (member);
       mark_used (member);
       if (TREE_DEPRECATED (member))
-	warn_deprecated_use (member);
+	warn_deprecated_use (member, NULL_TREE);
     }
   else
     member_scope = BINFO_TYPE (BASELINK_ACCESS_BINFO (member));
@@ -2369,7 +2369,7 @@ finish_class_member_access_expr (tree ob
     }
 
   if (TREE_DEPRECATED (member))
-    warn_deprecated_use (member);
+    warn_deprecated_use (member, NULL_TREE);
 
   if (template_p)
     check_template_keyword (member);
--- gcc/doc/extend.texi.deprecated	2009-05-07 13:06:57.000000000 -0700
+++ gcc/doc/extend.texi	2009-05-07 13:14:39.000000000 -0700
@@ -2069,6 +2069,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
@@ -2084,7 +2085,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}.)
@@ -3849,6 +3852,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
@@ -3864,7 +3868,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}.)
@@ -4494,6 +4500,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.
@@ -4516,7 +4523,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}.)
--- gcc/testsuite/g++.dg/warn/deprecated-6.C.deprecated	2009-05-07 13:14:39.000000000 -0700
+++ gcc/testsuite/g++.dg/warn/deprecated-6.C	2009-05-07 20:58:13.000000000 -0700
@@ -0,0 +1,114 @@
+/* Test __attribute__ ((deprecated("message"))) */
+/* { dg-do compile } */
+/* { dg-options "-Wdeprecated-declarations -fmessage-length=0" } */
+
+/* FIXME: dejagnu doesn't support the same warning with regexp on
+   different lines.  */
+typedef int INT1 __attribute__((deprecated("Please avoid INT1")));
+typedef INT1 INT2 __attribute__ ((__deprecated__("Please avoid INT2")));
+
+typedef INT1 INT1a; 			/* { dg-warning "'INT1' is deprecated" "" } */
+
+INT1 should_be_unavailable; 		/* { dg-warning "'INT1' is deprecated" "" } */
+INT1a should_not_be_deprecated;
+
+INT1 f1(void) __attribute__ ((deprecated("Please avoid f1"))); 
+INT1 f2(void) { return 0; }		/* { dg-warning "'INT1' is deprecated" "" } */
+
+INT2 f3(void) __attribute__ ((__deprecated__("Please avoid f3"))); 
+INT2 f4(void) { return 0; }		/* { dg-warning "'INT2' is deprecated .declared at .*.: Please avoid INT2" "" } */
+int f5(INT2 x);				/* { dg-warning "'INT2' is deprecated" "" } */
+int f6(INT2 x) __attribute__ ((__deprecated__("Please avoid f6")));
+
+typedef enum Color {red, green, blue} Color __attribute__((deprecated("Please avoid Color")));
+
+int g1;
+int g2 __attribute__ ((deprecated("Please avoid g2")));
+int g3 __attribute__ ((__deprecated__("Please avoid g3")));
+Color k;				/* { dg-warning "'Color' is deprecated ..*.: Please avoid Color" "" } */
+
+typedef struct {
+  int field1;
+  int field2 __attribute__ ((deprecated("Please avoid field2")));
+  int field3;
+  int field4 __attribute__ ((__deprecated__("Please avoid field4")));
+  union {
+    int field5;
+    int field6 __attribute__ ((deprecated("Please avoid field6")));
+  } u1;
+  int field7:1;
+  int field8:1 __attribute__ ((deprecated("Please avoid field8")));
+  union {
+    int field9;
+    int field10;
+  } u2 __attribute__ ((deprecated("Please avoid u2")));
+} S1;
+
+int func1()
+{
+   INT1 w;				/* { dg-warning "'INT1' is deprecated" "" } */
+   int x __attribute__ ((deprecated("Please avoid x")));
+   int y __attribute__ ((__deprecated__("Please avoid y")));
+   int z;
+   int (*pf)() = f1;			/* { dg-warning "'INT1 f1\\(\\)' is deprecated" "" } */
+
+   z = w + x + y + g1 + g2 + g3;	/* { dg-warning "'x' is deprecated ..*.: Please avoid x" "" } */
+   					/* { dg-warning "'y' is deprecated ..*.: Please avoid y" "y" { target *-*-* } 55 } */
+   					/* { dg-warning "'g2' is deprecated ..*.: Please avoid g2" "g2" { target *-*-* } 55 } */
+   					/* { dg-warning "'g3' is deprecated ..*.: Please avoid g3" "g3" { target *-*-* } 55 } */
+   return f1(); 			/* { dg-warning "'INT1 f1\\(\\)' is deprecated" "f1" } */
+}
+
+int func2(S1 *p)
+{
+  S1 lp;
+  
+  if (p->field1)
+     return p->field2;			/* { dg-warning "'S1::field2' is deprecated ..*.: Please avoid field2" "" } */
+  else if (lp.field4)			/* { dg-warning "'S1::field4' is deprecated ..*.: Please avoid field4" "" } */
+     return p->field3;
+  
+  p->u1.field5 = g1 + p->field7;
+  p->u2.field9;				/* { dg-warning "'S1::u2' is deprecated ..*.: Please avoid u2" "" } */
+  return p->u1.field6 + p->field8;	/* { dg-warning "'S1::<anonymous union>::field6' is deprecated ..*.: Please avoid field6" "" } */
+  					/* { dg-warning "'S1::field8' is deprecated ..*.: Please avoid field8" "field8" { target *-*-* } 73 } */
+}
+
+struct SS1 {
+  int x;
+  INT1 y; 				/* { dg-warning "'INT1' is deprecated" "" } */
+} __attribute__ ((deprecated("Please avoid SS1")));
+
+struct SS1 *p1;				/* { dg-warning "'SS1' is deprecated ..*.: Please avoid SS1" "" } */
+
+struct __attribute__ ((__deprecated__("Please avoid SS2"))) SS2 {
+  int x;
+  INT1 y; 				/* { dg-warning "'INT1' is deprecated ..*.: Please avoid INT1" "" } */
+};
+
+struct SS2 *p2;				/* { dg-warning "'SS2' is deprecated ..*.: Please avoid SS2" "" } */
+
+#ifdef __cplusplus
+class T {
+  public:
+    void member1(int) __attribute__ ((deprecated("Please avoid member1")));
+    void member2(INT1) __attribute__ ((__deprecated__("Please avoid member2"))); /* { dg-warning "'INT1' is deprecated" "" } */
+    int member3(T *);
+    int x;
+} __attribute__ ((deprecated("Please avoid T")));
+
+T *p3;				// { dg-warning "'T' is deprecated" }
+
+inline void T::member1(int) {}
+
+int T::member3(T *p)		// { dg-warning "'T' is deprecated ..*.: Please avoid T" }
+{
+  p->member1(1);			/* { dg-warning "'void T::member1\\(int\\)' is deprecated" "" } */
+  (*p).member1(2);			/* { dg-warning "'void T::member1\\(int\\)' is deprecated ..*.: Please avoid member1" "" } */
+  p->member2(1);			/* { dg-warning "'void T::member2\\(INT1\\)' is deprecated" "" } */
+  (*p).member2(2);			/* { dg-warning "'void T::member2\\(INT1\\)' is deprecated ..*.: Please avoid member2" "" } */
+  p->member3(p);
+  (*p).member3(p);
+  return f1(); 				/* { dg-warning "'INT1 f1\\(\\)' is deprecated ..*.: Please avoid f1" "" } */
+}
+#endif
--- gcc/testsuite/gcc.dg/deprecated-4.c.deprecated	2009-05-07 13:14:39.000000000 -0700
+++ gcc/testsuite/gcc.dg/deprecated-4.c	2009-05-07 20:56:20.000000000 -0700
@@ -0,0 +1,115 @@
+/* Test __attribute__ ((deprecated("message"))) */
+/* { dg-do compile } */
+/* { dg-options "-Wdeprecated-declarations" } */
+
+/* FIXME: dejagnu doesn't support the same warning with regexp on
+   different lines.  */
+typedef int INT1 __attribute__((deprecated("Please avoid INT1")));
+typedef INT1 INT2 __attribute__ ((__deprecated__("Please avoid INT2")));
+
+typedef INT1 INT1a; 			/* { dg-warning "'INT1' is deprecated: Please avoid INT1" "" } */
+typedef INT1 INT1b __attribute__ ((deprecated("Please avoid INT1b")));
+
+INT1 should_be_unavailable; 		/* { dg-warning "'INT1' is deprecated: Please avoid INT1" "" } */
+INT1a should_not_be_deprecated;
+
+INT1 f1(void) __attribute__ ((deprecated("Please avoid f1"))); 
+INT1 f2(void) { return 0; }		/* { dg-warning "'INT1' is deprecated: Please avoid INT1" "" } */
+
+INT2 f3(void) __attribute__ ((__deprecated__("Please avoid f3"))); 
+INT2 f4(void) { return 0; }		/* { dg-warning "'INT2' is deprecated: Please avoid INT2" "" } */
+int f5(INT2 x);				/* { dg-warning "'INT2' is deprecated: Please avoid INT2" "" } */
+int f6(INT2 x) __attribute__ ((__deprecated__("Please avoid f6"))); /* { dg-warning "'INT2' is deprecated: Please avoid INT2" "" } */
+
+typedef enum {red, green, blue} Color __attribute__((deprecated("Please avoid Color")));
+
+int g1;
+int g2 __attribute__ ((deprecated("Please avoid g2")));
+int g3 __attribute__ ((__deprecated__("Please avoid g3")));
+Color k;				/* { dg-warning "'Color' is deprecated .declared at .*.: Please avoid Color" "" } */
+
+typedef struct {
+  int field1;
+  int field2 __attribute__ ((deprecated("Please avoid field2")));
+  int field3;
+  int field4 __attribute__ ((__deprecated__("Please avoid field4")));
+  union {
+    int field5;
+    int field6 __attribute__ ((deprecated("Please avoid field6")));
+  } u1;
+  int field7:1;
+  int field8:1 __attribute__ ((deprecated("Please avoid field8")));
+  union {
+    int field9;
+    int field10;
+  } u2 __attribute__ ((deprecated("Please avoid u2")));
+} S1;
+
+int func1()
+{
+   INT1 w;				/* { dg-warning "'INT1' is deprecated: Please avoid INT1" "" } */
+   int x __attribute__ ((deprecated("Avoid x")));
+   int y __attribute__ ((__deprecated__("Bad y")));
+   int z;
+   int (*pf)() = f1;			/* { dg-warning "'f1' is deprecated" "" } */
+
+   z = w + x + y + g1 + g2 + g3;	/* { dg-warning "'x' is deprecated .declared at .*.: Avoid x" "" } */
+					/* { dg-warning "'y' is deprecated .declared at .*.: Bad y" "y" { target *-*-* } 56  } */
+					/* { dg-warning "'g2' is deprecated .declared at .*.: Please avoid g2" "g2" { target *-*-* } 56  }  */
+					/* { dg-warning "'g3' is deprecated .declared at .*.: Please avoid g3" "g3" { target *-*-* } 56  } */
+   return f1(); 			/* { dg-warning "'f1' is deprecated .declared at .*.: Please avoid f1" "" } */
+}
+
+int func2(S1 *p)
+{
+  S1 lp;
+  
+  if (p->field1)
+     return p->field2;			/* { dg-warning "'field2' is deprecated .declared at .*.: Please avoid field2" "" } */
+  else if (lp.field4)			/* { dg-warning "'field4' is deprecated .declared at .*.: Please avoid field4" "" } */
+     return p->field3;
+  
+  p->u1.field5 = g1 + p->field7;
+  p->u2.field9;				/* { dg-warning "'u2' is deprecated .declared at .*.: Please avoid u2" "" } */
+  return p->u1.field6 + p->field8;	/* { dg-warning "'field6' is deprecated .declared at .*.: Please avoid field6" "" } */
+  					/* { dg-warning "'field8' is deprecated .declared at .*.: Please avoid field8" "field8" { target *-*-* } 74 } */
+}
+
+struct SS1 {
+  int x;
+  INT1 y; 				/* { dg-warning "'INT1' is deprecated: Please avoid INT1" "" } */
+} __attribute__ ((deprecated("Please avoid SS1")));
+
+struct SS1 *p1;				/* { dg-warning "'SS1' is deprecated .declared at .*.: Please avoid SS1" "" } */
+
+struct __attribute__ ((__deprecated__("Please avoid SS2"))) SS2 {
+  int x;
+  INT1 y; 				/* { dg-warning "'INT1' is deprecated: Please avoid INT1" "" } */
+};
+
+struct SS2 *p2;				/* { dg-warning "'SS2' is deprecated .declared at .*.: Please avoid SS2" "" } */
+
+#ifdef __cplusplus
+class T {
+  public:
+    void member1(int) __attribute__ ((deprecated("Please avoid member1")));
+    void member2(INT1) __attribute__ ((__deprecated__("Please avoid member2")));
+    int member3(T *);
+    int x;
+} __attribute__ ((deprecated("Please avoid T")));
+
+T *p2;
+
+inline void T::member1(int) {}
+
+int T::member2(T *p)
+{
+  p->member1(1);			/* { xxdg-warning "'member1' is deprecated" "" } */
+  (*p).member1(2);			/* { xxdg-warning "'member1' is deprecated" "" } */
+  p->member2(1);			/* { xxdg-warning "'member2' is deprecated" "" } */
+  (*p).member2(2);			/* { xxdg-warning "'member2' is deprecated" "" } */
+  p->member3(p);
+  (*p).member3(p);
+  return f1(); 				/* { xxdg-warning "'f1' is deprecated" "" } */
+}
+#endif
--- gcc/testsuite/gcc.dg/deprecated-5.c.deprecated	2009-05-07 13:14:39.000000000 -0700
+++ gcc/testsuite/gcc.dg/deprecated-5.c	2009-05-07 13:45:35.000000000 -0700
@@ -0,0 +1,7 @@
+/* Test __attribute__((deprecated)).  Test types without names.  */
+/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+struct { int a; } __attribute__((deprecated ("Do not use"))) x; /* { dg-warning "type is deprecated" } */
+typeof(x) y; /* { dg-warning "type is deprecated .declared at .*.: Do not use" } */
--- gcc/testsuite/gcc.dg/deprecated-6.c.deprecated	2009-05-07 13:14:39.000000000 -0700
+++ gcc/testsuite/gcc.dg/deprecated-6.c	2009-05-07 13:46:07.000000000 -0700
@@ -0,0 +1,11 @@
+/* Test __attribute__((deprecated)).  Test merging with multiple
+   declarations.  Bug 7425.  */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+void func(void);
+void func(void) __attribute__((deprecated ("Do not use")));
+
+void f(void) {
+  func(); /* { dg-warning "'func' is deprecated .declared at .*.: Do not use" } */
+}
--- gcc/toplev.c.deprecated	2009-05-07 13:07:35.000000000 -0700
+++ gcc/toplev.c	2009-05-07 13:14:39.000000000 -0700
@@ -908,17 +908,45 @@ emit_debug_global_declarations (tree *ve
 
 /* Warn about a use of an identifier which was marked deprecated.  */
 void
-warn_deprecated_use (tree node)
+warn_deprecated_use (tree node, tree attr)
 {
+  const char *msg;
+
   if (node == 0 || !warn_deprecated_decl)
     return;
 
+  if (!attr)
+    {
+      if (DECL_P (node))
+	attr = DECL_ATTRIBUTES (node);
+      else if (TYPE_P (node))
+	{
+	  tree decl = TYPE_STUB_DECL (node);
+	  if (decl)
+	    attr = lookup_attribute ("deprecated",
+				     TYPE_ATTRIBUTES (TREE_TYPE (decl)));
+	}
+    }
+
+  if (attr)
+    attr = lookup_attribute ("deprecated", attr);
+
+  if (attr)
+    msg = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr)));
+  else
+    msg = NULL;
+
   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);
+      if (msg)
+	warning (OPT_Wdeprecated_declarations,
+		 "%qD is deprecated (declared at %s:%d): %s",
+		 node, xloc.file, xloc.line, msg);
+      else
+	warning (OPT_Wdeprecated_declarations,
+		 "%qD is deprecated (declared at %s:%d)",
+		 node, xloc.file, xloc.line);
     }
   else if (TYPE_P (node))
     {
@@ -939,20 +967,46 @@ warn_deprecated_use (tree node)
 	  expanded_location xloc
 	    = expand_location (DECL_SOURCE_LOCATION (decl));
 	  if (what)
-	    warning (OPT_Wdeprecated_declarations,
-		     "%qE is deprecated (declared at %s:%d)", what,
-		     xloc.file, xloc.line);
+	    {
+	      if (msg)
+		warning (OPT_Wdeprecated_declarations,
+			 "%qE is deprecated (declared at %s:%d): %s",
+			 what, xloc.file, xloc.line, msg);
+	      else
+		warning (OPT_Wdeprecated_declarations,
+			 "%qE is deprecated (declared at %s:%d)", what,
+			 xloc.file, xloc.line);
+	    }
 	  else
-	    warning (OPT_Wdeprecated_declarations,
-		     "type is deprecated (declared at %s:%d)",
-		     xloc.file, xloc.line);
+	    {
+	      if (msg)
+		warning (OPT_Wdeprecated_declarations,
+			 "type is deprecated (declared at %s:%d): %s",
+			 xloc.file, xloc.line, msg);
+	      else
+		warning (OPT_Wdeprecated_declarations,
+			 "type is deprecated (declared at %s:%d)",
+			 xloc.file, xloc.line);
+	    }
 	}
       else
 	{
 	  if (what)
-	    warning (OPT_Wdeprecated_declarations, "%qE is deprecated", what);
+	    {
+	      if (msg)
+		warning (OPT_Wdeprecated_declarations, "%qE is deprecated: %s",
+			 what, msg);
+	      else
+		warning (OPT_Wdeprecated_declarations, "%qE is deprecated", what);
+	    }
 	  else
-	    warning (OPT_Wdeprecated_declarations, "type is deprecated");
+	    {
+	      if (msg)
+		warning (OPT_Wdeprecated_declarations, "type is deprecated: %s",
+			 msg);
+	      else
+		warning (OPT_Wdeprecated_declarations, "type is deprecated");
+	    }
 	}
     }
 }
--- gcc/toplev.h.deprecated	2009-05-07 13:07:35.000000000 -0700
+++ gcc/toplev.h	2009-05-07 13:14:39.000000000 -0700
@@ -83,7 +83,7 @@ extern void announce_function (tree);
 
 extern void error_for_asm (const_rtx, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
 extern void warning_for_asm (const_rtx, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
-extern void warn_deprecated_use (tree);
+extern void warn_deprecated_use (tree, tree);
 extern bool parse_optimize_options (tree, bool);
 
 #ifdef BUFSIZ



More information about the Gcc-patches mailing list