diff mbox

[c++] (__attribute__((deprecated)), part a) Fix PR17729

Message ID 3EC5B677-F737-4B70-AB06-460A97AF915C@sandoe-acoustics.co.uk
State New
Headers show

Commit Message

Iain Sandoe July 19, 2010, 5:11 p.m. UTC
Hi Jason,

It's taken a while to find some more time for this - (ObJC LTO and  
emutls.... etc. etc.)

On 9 Jun 2010, at 04:19, Jason Merrill wrote:

> On 06/08/2010 07:13 PM, IainS wrote:
>> the question then, is how to prevent the duplicates, since those  
>> places
>> are called from more than one part of the process (or, at least, they
>> were when I last looked).
>
> For non-function members, I think removing the call in  
> finish_class_member_access_expr ought to do the trick, letting  
> build_class_member_access_expr handle the warning.

done

> For functions, perhaps just warning in mark_used would work.  Then  
> removing the calls in build_over_call and build_call_a and  
> conditioning the one in finish_id_expression on !is_overloaded_fn.

unfortunately, not
mark_used is called even more often than build_over_call &  
build_call_a (at one stage I ended up with three warning messages)...

It seems that there is no nice place to put these diagnostics, that is  
only visited once (for the current formulation***);
Hence we end up checking in several places (which, I agree, does not  
seem ideal).

The attached patch has been bootstrapped/checked on i686-apple-darwin9

I've added a test-case for overloaded functions, member funcs are  
covered in deprecated-{4,6} iirc.

thoughts?

Iain

*** It seems to me that the diagnostics might be better done at the  
stage that the parser has decided that (other than deprecation) a  
given construct is OK.
(I guess just before swallowing the ";").   However, I don't know if  
this is reasonable, &| there would be enough information preserved to  
make the diagnostic neat (although it seems that there should).


gcc/cp:

	PR c++/17729
	* typeck.c (finish_class_member_access_expr): Remove duplicate
	deprecation check.
	* call.c (build_call_a): Do not check deprecation here.
	(build_over_call): Ditto.
	(build_new_function_call): Check for deprecated overloaded funcs
	here.
	(convert_like_real): Check for deprecated functions.
	(build_new_method_call): Ditto.

gcc/testsuite:

	PR c++/17729
	* g++.dg/warn/pr17729-1-fields.C: New.
	* g++.dg/warn/pr17729-2-funcs.C: New.
	* g++.dg/warn/deprecated-7.C: New.
\ No newline at end of file

Comments

Jason Merrill July 19, 2010, 5:58 p.m. UTC | #1
On 07/19/2010 01:11 PM, IainS wrote:
> unfortunately, not
> mark_used is called even more often than build_over_call & build_call_a
> (at one stage I ended up with three warning messages)...
>
> It seems that there is no nice place to put these diagnostics, that is
> only visited once (for the current formulation***);
> Hence we end up checking in several places (which, I agree, does not
> seem ideal).

How about just using a hash table, as in maybe_explain_implicit_delete?

Jason
Iain Sandoe July 21, 2010, 1:43 p.m. UTC | #2
On 19 Jul 2010, at 18:58, Jason Merrill wrote:

> On 07/19/2010 01:11 PM, IainS wrote:
>> unfortunately, not
>> mark_used is called even more often than build_over_call &  
>> build_call_a
>> (at one stage I ended up with three warning messages)...
>>
>> It seems that there is no nice place to put these diagnostics, that  
>> is
>> only visited once (for the current formulation***);
>> Hence we end up checking in several places (which, I agree, does not
>> seem ideal).
>
> How about just using a hash table, as in  
> maybe_explain_implicit_delete?

I did some more back-tracing yesterday (to find where the duplicate  
calls are coming from);
I'll analyze that a bit more later, and maybe augment it ...

one point that this revealed is the types are not marked as used (at  
least not in this manner).
presumably there is some equivalent action so that we know which ones  
to emit for debug?

cheers,
Iain
diff mbox

Patch

Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 162309)
+++ gcc/cp/typeck.c	(working copy)
@@ -2692,9 +2692,6 @@  finish_class_member_access_expr (tree object, tree
 	}
     }
 
-  if (TREE_DEPRECATED (member))
-    warn_deprecated_use (member, NULL_TREE);
-
   if (template_p)
     check_template_keyword (member);
 
Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c	(revision 162309)
+++ gcc/cp/call.c	(working copy)
@@ -347,8 +347,6 @@  build_call_a (tree function, int n, tree *argarray
   if (decl && TREE_THIS_VOLATILE (decl) && cfun && cp_function_chain)
     current_function_returns_abnormally = 1;
 
-  if (decl && TREE_DEPRECATED (decl))
-    warn_deprecated_use (decl, NULL_TREE);
   require_complete_eh_spec_types (fntype, decl);
 
   if (decl && DECL_CONSTRUCTOR_P (decl))
@@ -3283,8 +3281,11 @@  build_new_function_call (tree fn, VEC(tree,gc) **a
       result = error_mark_node;
     }
   else
-    result = build_over_call (cand, LOOKUP_NORMAL, complain);
-
+    {
+      if (koenig_p && TREE_DEPRECATED (cand->fn))
+	warn_deprecated_use (cand->fn, NULL_TREE);
+      result = build_over_call (cand, LOOKUP_NORMAL, complain);
+    }
   /* Free all the conversions we allocated.  */
   obstack_free (&conversion_obstack, p);
 
@@ -5018,6 +5019,10 @@  convert_like_real (conversion *convs, tree expr, t
 	for (i = 0; i < cand->num_convs; ++i)
 	  cand->convs[i]->user_conv_p = true;
 
+	/* Warn on deprecation of the candidate conversion func.  */
+	if (TREE_DEPRECATED (convfn))
+	  warn_deprecated_use (convfn, NULL_TREE);
+
 	expr = build_over_call (cand, LOOKUP_NORMAL, complain);
 
 	/* If this is a constructor or a function returning an aggr type,
@@ -6010,11 +6015,6 @@  build_over_call (struct z_candidate *cand, int fla
 				ba_any, NULL);
       gcc_assert (binfo && binfo != error_mark_node);
 
-      /* Warn about deprecated virtual functions now, since we're about
-	 to throw away the decl.  */
-      if (TREE_DEPRECATED (fn))
-	warn_deprecated_use (fn, NULL_TREE);
-
       argarray[0] = build_base_path (PLUS_EXPR, argarray[0], binfo, 1);
       if (TREE_SIDE_EFFECTS (argarray[0]))
 	argarray[0] = save_expr (argarray[0]);
@@ -6575,6 +6575,11 @@  build_new_method_call (tree instance, tree fns, VE
 	      /* Now we know what function is being called.  */
 	      if (fn_p)
 		*fn_p = fn;
+
+	      /* Check for deprecation of the function to be called.  */
+	      if (TREE_DEPRECATED (fn))
+		warn_deprecated_use (fn, NULL_TREE);
+	      
 	      /* Build the actual CALL_EXPR.  */
 	      call = build_over_call (cand, flags, complain);
 	      /* In an expression of the form `a->f()' where `f' turns
Index: gcc/testsuite/g++.dg/warn/pr17729-2-funcs.C
===================================================================
--- gcc/testsuite/g++.dg/warn/pr17729-2-funcs.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/pr17729-2-funcs.C	(revision 0)
@@ -0,0 +1,9 @@ 
+/* PR 17729 */
+/* { dg-do compile } */
+int fun (void) __attribute__((deprecated("no fun"))) ;
+
+void foo (void)
+{
+  fun (); // { dg-bogus "int fun.* no fun.*int fun" "duplicate func. warning" }
+	  // { dg-warning "'int fun..' is deprecated .declared at \[^\\)\]*.: no fun" "" { target *-*-* } 7 }
+}
Index: gcc/testsuite/g++.dg/warn/deprecated-7.C
===================================================================
--- gcc/testsuite/g++.dg/warn/deprecated-7.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/deprecated-7.C	(revision 0)
@@ -0,0 +1,16 @@ 
+/* { dg-do compile } */
+
+int f1 (int, int);
+int f1 (float, int) __attribute__((deprecated("no flt, int"))) ;
+int f1 (float, float);
+
+void foo (void)
+{
+  int a, b, r;
+  float c,d;
+  
+  r = f1 (a, b);
+  r = f1 (c, a); // { dg-warning "'int f1.float, int.' is deprecated .declared at \[^\\)\]*.: no flt, int" }
+  r = f1 (c, d);
+
+}
\ No newline at end of file
Index: gcc/testsuite/g++.dg/warn/pr17729-1-fields.C
===================================================================
--- gcc/testsuite/g++.dg/warn/pr17729-1-fields.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/pr17729-1-fields.C	(revision 0)
@@ -0,0 +1,20 @@ 
+/* PR 17729 */
+/* { dg-do compile } */
+typedef int INT1 __attribute__((deprecated("no INT1"))) ;
+
+struct _a {
+  int field1 ;
+  int field2 __attribute__((deprecated("no field2"))) ;
+  INT1 field3; 						/* { dg-warning "'INT1' is deprecated .declared \[^\\)\]*.: no INT1 " } */
+  INT1 field4 __attribute__((deprecated("no field4"))); /* { dg-warning "'INT1' is deprecated .declared .* no INT1 " } */
+} s;
+
+void foo (void)
+{
+  s.field1 = 1;
+  s.field2 = 2; // { dg-bogus "_a::field2.*_a::field2" "duplicate field warning" }
+  		// { dg-warning "'_a::field2' is deprecated .declared at \[^\\)\]*.: no field2" "" { target *-*-* } 15 }
+  s.field3 = 3;
+  s.field4 = 4; // { dg-bogus "_a::field4.*_a::field4" "duplicate field warning" }
+  		// { dg-warning "'_a::field4' is deprecated .declared at .* no field4" "" { target *-*-* } 18 }
+}