[PATCH] Latest version of the -Wunused-but-set-{variable,parameter} patches (C part)

Jakub Jelinek jakub@redhat.com
Fri Jan 22 16:11:00 GMT 2010


Hi!

Here is the C part of the -Wunused-but-set-* patchset,
bootstrapped/regtested on x86_64-linux and i686-linux with the other 2
patches.
Ok for 4.6?

	Jakub
-------------- next part --------------
2010-01-22  Jakub Jelinek  <jakub@redhat.com>

	PR c/18624
	* tree.h (DECL_READ_P): Define.
	(struct tree_decl_common): Add decl_read_flag.
	* c-decl.c (pop_scope): If TREE_USED but !DECL_READ_P, issue
	a set but not used warning.
	(merge_decls): Merge DECL_READ_P flag.
	(finish_decl, build_compound_literal): Set DECL_READ_P flag.
	(finish_function): Issue -Wunused-but-set-parameter diagnostics.
	* c-common.c (handle_used_attribute, handle_unused_attribute):
	Likewise.
	* c-tree.h (default_function_array_read_conversion, mark_exp_read):
	New prototypes.
	* c-typeck.c (default_function_array_read_conversion, mark_exp_read):
	New functions.
	(default_conversion, c_process_expr_stmt): Call mark_exp_read.
	* c-parser.c (c_parser_initializer, c_parser_expr_no_commas,
	c_parser_binary_expression, c_parser_cast_expression,
	c_parser_expr_list, c_parser_omp_atomic, c_parser_omp_for_loop):
	Call default_function_array_read_conversion instead of
	default_function_array_conversion where needed.
	(c_parser_unary_expression, c_parser_conditional_expression,
	c_parser_postfix_expression_after_primary, c_parser_initelt):
	Likewise.  Call mark_exp_read where needed.
	(c_parser_statement_after_labels, c_parser_asm_operands,
	c_parser_typeof_specifier, c_parser_sizeof_expression,
	c_parser_alignof_expression, c_parser_initval): Call mark_exp_read
	where needed.
	* common.opt (Wunused-but-set-variable, Wunused-but-set-parameter):
	New.
	* toplev.c (warn_unused_but_set_variable): Default to warn_unused.
	(warn_unused_but_set_parameter): Default to warn_unused
	&& extra_warnings.
	* doc/invoke.texi: Document -Wunused-but-set-variable and
	-Wunused-but-set-parameter.

	* objc-act.c (finish_var_decl, objc_begin_catch_clause,
	really_start_method, get_super_receiver, handle_class_ref): Set
	DECL_READ_P in addition to TREE_USED.

	* gcc.dg/Wunused-var-1.c: New test.
	* gcc.dg/Wunused-var-2.c: New test.
	* gcc.dg/Wunused-var-3.c: New test.
	* gcc.dg/Wunused-var-4.c: New test.
	* gcc.dg/Wunused-var-5.c: New test.
	* gcc.dg/Wunused-var-6.c: New test.
	* gcc.dg/Wunused-parm-1.c: New test.

--- gcc/tree.h.jj	2009-11-27 12:25:18.000000000 +0100
+++ gcc/tree.h	2009-11-27 16:14:33.000000000 +0100
@@ -1317,6 +1317,9 @@ extern void omp_clause_range_check_faile
   (TREE_CHECK3 (NODE, VAR_DECL, PARM_DECL, \
 		RESULT_DECL)->decl_common.decl_restricted_flag)
 
+#define DECL_READ_P(NODE) \
+  (TREE_CHECK2 (NODE, VAR_DECL, PARM_DECL)->decl_common.decl_read_flag)
+
 /* In a CALL_EXPR, means that the call is the jump from a thunk to the
    thunked-to function.  */
 #define CALL_FROM_THUNK_P(NODE) (CALL_EXPR_CHECK (NODE)->base.protected_flag)
@@ -2689,8 +2692,12 @@ struct GTY(()) tree_decl_common {
   /* In VAR_DECL, PARM_DECL and RESULT_DECL, this is DECL_RESTRICTED_P.  */
   unsigned decl_restricted_flag : 1;
 
+  /* In VAR_DECL and PARM_DECL set when the decl has been used except for
+     being set.  */
+  unsigned decl_read_flag : 1;
+
   /* Padding so that 'off_align' can be on a 32-bit boundary.  */
-  unsigned decl_common_unused : 2;
+  unsigned decl_common_unused : 1;
 
   /* DECL_OFFSET_ALIGN, used only for FIELD_DECLs.  */
   unsigned int off_align : 8;
--- gcc/c-decl.c.jj	2009-11-27 12:25:19.000000000 +0100
+++ gcc/c-decl.c	2009-11-27 18:06:33.000000000 +0100
@@ -1164,14 +1164,20 @@ pop_scope (void)
 
 	case VAR_DECL:
 	  /* Warnings for unused variables.  */
-	  if (!TREE_USED (p)
+	  if ((!TREE_USED (p) || !DECL_READ_P (p))
 	      && !TREE_NO_WARNING (p)
 	      && !DECL_IN_SYSTEM_HEADER (p)
 	      && DECL_NAME (p)
 	      && !DECL_ARTIFICIAL (p)
 	      && scope != file_scope
 	      && scope != external_scope)
-	    warning (OPT_Wunused_variable, "unused variable %q+D", p);
+	    {
+	      if (!TREE_USED (p))
+		warning (OPT_Wunused_variable, "unused variable %q+D", p);
+	      else if (DECL_CONTEXT (p) == current_function_decl)
+		warning (OPT_Wunused_but_set_variable,
+			 "variable %q+D set but not used", p);
+	    }
 
 	  if (b->inner_comp)
 	    {
@@ -2387,6 +2393,8 @@ merge_decls (tree newdecl, tree olddecl,
     TREE_USED (newdecl) = 1;
   else if (TREE_USED (newdecl))
     TREE_USED (olddecl) = 1;
+  if (TREE_CODE (olddecl) == VAR_DECL || TREE_CODE (olddecl) == PARM_DECL)
+    DECL_READ_P (newdecl) |= DECL_READ_P (olddecl);
 
   /* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
      But preserve OLDDECL's DECL_UID, DECL_CONTEXT and
@@ -4229,7 +4237,10 @@ finish_decl (tree decl, location_t init_
 	}
 
       if (TREE_USED (type))
-	TREE_USED (decl) = 1;
+	{
+	  TREE_USED (decl) = 1;
+	  DECL_READ_P (decl) = 1;
+	}
     }
 
   /* If this is a function and an assembler name is specified, reset DECL_RTL
@@ -4377,6 +4388,7 @@ finish_decl (tree decl, location_t init_
 	  /* Don't warn about decl unused; the cleanup uses it.  */
 	  TREE_USED (decl) = 1;
 	  TREE_USED (cleanup_decl) = 1;
+	  DECL_READ_P (decl) = 1;
 
 	  push_cleanup (decl, cleanup, false);
 	}
@@ -4468,6 +4480,7 @@ build_compound_literal (location_t loc, 
   TREE_STATIC (decl) = (current_scope == file_scope);
   DECL_CONTEXT (decl) = current_function_decl;
   TREE_USED (decl) = 1;
+  DECL_READ_P (decl) = 1;
   TREE_TYPE (decl) = type;
   TREE_READONLY (decl) = TYPE_READONLY (type);
   store_init_value (loc, decl, init, NULL_TREE);
@@ -8031,6 +8044,24 @@ finish_function (void)
       TREE_NO_WARNING (fndecl) = 1;
     }
 
+  /* Complain about parameters that are only set, but never otherwise used.  */
+  if (warn_unused_but_set_parameter)
+    {
+      tree decl;
+
+      for (decl = DECL_ARGUMENTS (fndecl);
+	   decl;
+	   decl = TREE_CHAIN (decl))
+	if (TREE_USED (decl)
+	    && TREE_CODE (decl) == PARM_DECL
+	    && !DECL_READ_P (decl)
+	    && DECL_NAME (decl)
+	    && !DECL_ARTIFICIAL (decl)
+	    && !TREE_NO_WARNING (decl))
+	  warning (OPT_Wunused_but_set_parameter,
+		   "parameter %q+D set but not used", decl);
+    }
+
   /* Store the end of the function, so that we get good line number
      info for the epilogue.  */
   cfun->function_end_locus = input_location;
--- gcc/c-common.c.jj	2009-11-27 12:25:19.000000000 +0100
+++ gcc/c-common.c	2009-11-27 13:00:10.000000000 +0100
@@ -6116,6 +6116,8 @@ handle_used_attribute (tree *pnode, tree
     {
       TREE_USED (node) = 1;
       DECL_PRESERVE_P (node) = 1;
+      if (TREE_CODE (node) == VAR_DECL)
+	DECL_READ_P (node) = 1;
     }
   else
     {
@@ -6142,7 +6144,12 @@ handle_unused_attribute (tree *node, tre
 	  || TREE_CODE (decl) == FUNCTION_DECL
 	  || TREE_CODE (decl) == LABEL_DECL
 	  || TREE_CODE (decl) == TYPE_DECL)
-	TREE_USED (decl) = 1;
+	{
+	  TREE_USED (decl) = 1;
+	  if (TREE_CODE (decl) == VAR_DECL
+	      || TREE_CODE (decl) == PARM_DECL)
+	    DECL_READ_P (decl) = 1;
+	}
       else
 	{
 	  warning (OPT_Wattributes, "%qE attribute ignored", name);
--- gcc/c-tree.h.jj	2009-11-27 12:25:19.000000000 +0100
+++ gcc/c-tree.h	2009-11-27 13:00:10.000000000 +0100
@@ -511,7 +511,10 @@ extern bool c_mark_addressable (tree);
 extern void c_incomplete_type_error (const_tree, const_tree);
 extern tree c_type_promotes_to (tree);
 extern struct c_expr default_function_array_conversion (location_t,
-    							struct c_expr);
+							struct c_expr);
+extern struct c_expr default_function_array_read_conversion (location_t,
+							     struct c_expr);
+extern void mark_exp_read (tree);
 extern tree composite_type (tree, tree);
 extern tree build_component_ref (location_t, tree, tree);
 extern tree build_array_ref (location_t, tree, tree);
--- gcc/c-typeck.c.jj	2009-11-27 12:25:19.000000000 +0100
+++ gcc/c-typeck.c	2009-11-27 13:00:10.000000000 +0100
@@ -1763,6 +1763,35 @@ function_to_pointer_conversion (location
   return build_unary_op (loc, ADDR_EXPR, exp, 0);
 }
 
+/* Mark EXP as read, not just set, for set but not used -Wunused
+   warning purposes.  */
+
+void
+mark_exp_read (tree exp)
+{
+  switch (TREE_CODE (exp))
+    {
+    case VAR_DECL:
+    case PARM_DECL:
+      DECL_READ_P (exp) = 1;
+      break;
+    case ARRAY_REF:
+    case COMPONENT_REF:
+    case MODIFY_EXPR:
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+    CASE_CONVERT:
+    case ADDR_EXPR:
+      mark_exp_read (TREE_OPERAND (exp, 0));
+      break;
+    case COMPOUND_EXPR:
+      mark_exp_read (TREE_OPERAND (exp, 1));
+      break;
+    default:
+      break;
+    }
+}
+
 /* Perform the default conversion of arrays and functions to pointers.
    Return the result of converting EXP.  For any other expression, just
    return EXP.
@@ -1818,6 +1847,12 @@ default_function_array_conversion (locat
   return exp;
 }
 
+struct c_expr
+default_function_array_read_conversion (location_t loc, struct c_expr exp)
+{
+  mark_exp_read (exp.value);
+  return default_function_array_conversion (loc, exp);
+}
 
 /* EXP is an expression of integer type.  Apply the integer promotions
    to it and return the promoted value.  */
@@ -1879,6 +1914,8 @@ default_conversion (tree exp)
   enum tree_code code = TREE_CODE (type);
   tree promoted_type;
 
+  mark_exp_read (exp);
+
   /* Functions and arrays have been converted during parsing.  */
   gcc_assert (code != FUNCTION_TYPE);
   if (code == ARRAY_TYPE)
@@ -8738,6 +8775,7 @@ c_process_expr_stmt (location_t loc, tre
      number, wrap the thing in a no-op NOP_EXPR.  */
   if (DECL_P (expr) || CONSTANT_CLASS_P (expr))
     {
+      mark_exp_read (expr);
       expr = build1 (NOP_EXPR, TREE_TYPE (expr), expr);
       SET_EXPR_LOCATION (expr, loc);
     }
--- gcc/c-parser.c.jj	2009-11-27 12:25:19.000000000 +0100
+++ gcc/c-parser.c	2009-11-27 13:00:10.000000000 +0100
@@ -2171,6 +2171,7 @@ c_parser_typeof_specifier (c_parser *par
       if (TREE_CODE (expr.value) == COMPONENT_REF
 	  && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
 	error_at (here, "%<typeof%> applied to a bit-field");
+      mark_exp_read (expr.value);
       ret.spec = TREE_TYPE (expr.value);
       was_vm = variably_modified_type_p (ret.spec, NULL_TREE);
       /* This is returned with the type so that when the type is
@@ -3073,7 +3074,7 @@ c_parser_initializer (c_parser *parser)
       ret = c_parser_expr_no_commas (parser, NULL);
       if (TREE_CODE (ret.value) != STRING_CST
 	  && TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR)
-	ret = default_function_array_conversion (loc, ret);
+	ret = default_function_array_read_conversion (loc, ret);
       return ret;
     }
 }
@@ -3229,6 +3230,7 @@ c_parser_initelt (c_parser *parser)
 		      goto parse_message_args;
 		    }
 		  first = c_parser_expr_no_commas (parser, NULL).value;
+		  mark_exp_read (first);
 		  if (c_parser_next_token_is (parser, CPP_ELLIPSIS)
 		      || c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
 		    goto array_desig_after_first;
@@ -3244,7 +3246,8 @@ c_parser_initelt (c_parser *parser)
 		      c_parser_consume_token (parser);
 		      exp_loc = c_parser_peek_token (parser)->location;
 		      next = c_parser_expr_no_commas (parser, NULL);
-		      next = default_function_array_conversion (exp_loc, next);
+		      next = default_function_array_read_conversion (exp_loc,
+								     next);
 		      rec = build_compound_expr (comma_loc, rec, next.value);
 		    }
 		parse_message_args:
@@ -3264,12 +3267,14 @@ c_parser_initelt (c_parser *parser)
 		}
 	      c_parser_consume_token (parser);
 	      first = c_parser_expr_no_commas (parser, NULL).value;
+	      mark_exp_read (first);
 	    array_desig_after_first:
 	      if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
 		{
 		  ellipsis_loc = c_parser_peek_token (parser)->location;
 		  c_parser_consume_token (parser);
 		  second = c_parser_expr_no_commas (parser, NULL).value;
+		  mark_exp_read (second);
 		}
 	      else
 		second = NULL_TREE;
@@ -3337,7 +3342,7 @@ c_parser_initval (c_parser *parser, stru
       if (init.value != NULL_TREE
 	  && TREE_CODE (init.value) != STRING_CST
 	  && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR)
-	init = default_function_array_conversion (loc, init);
+	init = default_function_array_read_conversion (loc, init);
     }
   process_init_element (init, false);
 }
@@ -3840,6 +3845,7 @@ c_parser_statement_after_labels (c_parse
 	  else
 	    {
 	      struct c_expr expr = c_parser_expression_conv (parser);
+	      mark_exp_read (expr.value);
 	      stmt = c_finish_return (loc, expr.value, expr.original_type);
 	      goto expect_semicolon;
 	    }
@@ -4455,6 +4461,7 @@ c_parser_asm_operands (c_parser *parser,
 	}
       loc = c_parser_peek_token (parser)->location;
       expr = c_parser_expression (parser);
+      mark_exp_read (expr.value);
       if (convert_p)
 	expr = default_function_array_conversion (loc, expr);
       expr.value = c_fully_fold (expr.value, false, NULL);
@@ -4605,7 +4612,7 @@ c_parser_expr_no_commas (c_parser *parse
   c_parser_consume_token (parser);
   exp_location = c_parser_peek_token (parser)->location;
   rhs = c_parser_expr_no_commas (parser, NULL);
-  rhs = default_function_array_conversion (exp_location, rhs);
+  rhs = default_function_array_read_conversion (exp_location, rhs);
   ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
 				 code, exp_location, rhs.value,
 				 rhs.original_type);
@@ -4647,7 +4654,7 @@ c_parser_conditional_expression (c_parse
   if (c_parser_next_token_is_not (parser, CPP_QUERY))
     return cond;
   cond_loc = c_parser_peek_token (parser)->location;
-  cond = default_function_array_conversion (cond_loc, cond);
+  cond = default_function_array_read_conversion (cond_loc, cond);
   c_parser_consume_token (parser);
   if (c_parser_next_token_is (parser, CPP_COLON))
     {
@@ -4674,6 +4681,7 @@ c_parser_conditional_expression (c_parse
 	(cond_loc, default_conversion (cond.value));
       c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
       exp1 = c_parser_expression_conv (parser);
+      mark_exp_read (exp1.value);
       c_inhibit_evaluation_warnings +=
 	((cond.value == truthvalue_true_node)
 	 - (cond.value == truthvalue_false_node));
@@ -4691,7 +4699,7 @@ c_parser_conditional_expression (c_parse
   {
     location_t exp2_loc = c_parser_peek_token (parser)->location;
     exp2 = c_parser_conditional_expression (parser, NULL);
-    exp2 = default_function_array_conversion (exp2_loc, exp2);
+    exp2 = default_function_array_read_conversion (exp2_loc, exp2);
   }
   c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
   ret.value = build_conditional_expr (colon_loc, cond.value,
@@ -4844,10 +4852,11 @@ c_parser_binary_expression (c_parser *pa
 	break;								      \
       }									      \
     stack[sp - 1].expr							      \
-      = default_function_array_conversion (stack[sp - 1].loc,		      \
-					   stack[sp - 1].expr);		      \
+      = default_function_array_read_conversion (stack[sp - 1].loc,	      \
+						stack[sp - 1].expr);	      \
     stack[sp].expr							      \
-      = default_function_array_conversion (stack[sp].loc, stack[sp].expr);    \
+      = default_function_array_read_conversion (stack[sp].loc,		      \
+						stack[sp].expr);	      \
     stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc,		      \
 						 stack[sp].op,		      \
 						 stack[sp - 1].expr,	      \
@@ -4952,8 +4961,8 @@ c_parser_binary_expression (c_parser *pa
 	{
 	case TRUTH_ANDIF_EXPR:
 	  stack[sp].expr
-	    = default_function_array_conversion (stack[sp].loc,
-						 stack[sp].expr);
+	    = default_function_array_read_conversion (stack[sp].loc,
+						      stack[sp].expr);
 	  stack[sp].expr.value = c_objc_common_truthvalue_conversion
 	    (stack[sp].loc, default_conversion (stack[sp].expr.value));
 	  c_inhibit_evaluation_warnings += (stack[sp].expr.value
@@ -4961,8 +4970,8 @@ c_parser_binary_expression (c_parser *pa
 	  break;
 	case TRUTH_ORIF_EXPR:
 	  stack[sp].expr
-	    = default_function_array_conversion (stack[sp].loc,
-						 stack[sp].expr);
+	    = default_function_array_read_conversion (stack[sp].loc,
+						      stack[sp].expr);
 	  stack[sp].expr.value = c_objc_common_truthvalue_conversion
 	    (stack[sp].loc, default_conversion (stack[sp].expr.value));
 	  c_inhibit_evaluation_warnings += (stack[sp].expr.value
@@ -5032,7 +5041,7 @@ c_parser_cast_expression (c_parser *pars
       {
 	location_t expr_loc = c_parser_peek_token (parser)->location;
 	expr = c_parser_cast_expression (parser, NULL);
-	expr = default_function_array_conversion (expr_loc, expr);
+	expr = default_function_array_read_conversion (expr_loc, expr);
       }
       ret.value = c_cast_expr (cast_loc, type_name, expr.value);
       ret.original_code = ERROR_MARK;
@@ -5085,23 +5094,24 @@ c_parser_unary_expression (c_parser *par
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (exp_loc, op);
+      op = default_function_array_read_conversion (exp_loc, op);
       return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
     case CPP_MINUS_MINUS:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (exp_loc, op);
+      op = default_function_array_read_conversion (exp_loc, op);
       return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
     case CPP_AND:
       c_parser_consume_token (parser);
-      return parser_build_unary_op (op_loc, ADDR_EXPR,
-				    c_parser_cast_expression (parser, NULL));
+      op = c_parser_cast_expression (parser, NULL);
+      mark_exp_read (op.value);
+      return parser_build_unary_op (op_loc, ADDR_EXPR, op);
     case CPP_MULT:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (exp_loc, op);
+      op = default_function_array_read_conversion (exp_loc, op);
       ret.value = build_indirect_ref (op_loc, op.value, RO_UNARY_STAR);
       return ret;
     case CPP_PLUS:
@@ -5112,25 +5122,25 @@ c_parser_unary_expression (c_parser *par
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (exp_loc, op);
+      op = default_function_array_read_conversion (exp_loc, op);
       return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
     case CPP_MINUS:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (exp_loc, op);
+      op = default_function_array_read_conversion (exp_loc, op);
       return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
     case CPP_COMPL:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (exp_loc, op);
+      op = default_function_array_read_conversion (exp_loc, op);
       return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
     case CPP_NOT:
       c_parser_consume_token (parser);
       exp_loc = c_parser_peek_token (parser)->location;
       op = c_parser_cast_expression (parser, NULL);
-      op = default_function_array_conversion (exp_loc, op);
+      op = default_function_array_read_conversion (exp_loc, op);
       return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
     case CPP_AND_AND:
       /* Refer to the address of a label as a pointer.  */
@@ -5230,6 +5240,7 @@ c_parser_sizeof_expression (c_parser *pa
     sizeof_expr:
       c_inhibit_evaluation_warnings--;
       in_sizeof--;
+      mark_exp_read (expr.value);
       if (TREE_CODE (expr.value) == COMPONENT_REF
 	  && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
 	error_at (expr_loc, "%<sizeof%> applied to a bit-field");
@@ -5290,6 +5301,7 @@ c_parser_alignof_expression (c_parser *p
       struct c_expr ret;
       expr = c_parser_unary_expression (parser);
     alignof_expr:
+      mark_exp_read (expr.value);
       c_inhibit_evaluation_warnings--;
       in_alignof--;
       ret.value = c_alignof_expr (loc, expr.value);
@@ -5495,6 +5507,7 @@ c_parser_postfix_expression (c_parser *p
 	      break;
 	    }
 	  e1 = c_parser_expr_no_commas (parser, NULL);
+	  mark_exp_read (e1.value);
 	  e1.value = c_fully_fold (e1.value, false, NULL);
 	  if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
 	    {
@@ -5639,6 +5652,8 @@ c_parser_postfix_expression (c_parser *p
 	    tree c;
 
 	    c = e1.value;
+	    mark_exp_read (e2.value);
+	    mark_exp_read (e3.value);
 	    if (TREE_CODE (c) != INTEGER_CST
 		|| !INTEGRAL_TYPE_P (TREE_TYPE (c)))
 	      error_at (loc,
@@ -5883,6 +5898,7 @@ c_parser_postfix_expression_after_primar
 	  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
 				     "expected %<)%>");
 	  orig_expr = expr;
+	  mark_exp_read (expr.value);
 	  /* FIXME diagnostics: Ideally we want the FUNCNAME, not the
 	     "(" after the FUNCNAME, which is what we have now.    */
 	  expr.value = build_function_call_vec (op_loc, expr.value, exprlist,
@@ -5965,7 +5981,7 @@ c_parser_postfix_expression_after_primar
 	case CPP_PLUS_PLUS:
 	  /* Postincrement.  */
 	  c_parser_consume_token (parser);
-	  expr = default_function_array_conversion (expr_loc, expr);
+	  expr = default_function_array_read_conversion (expr_loc, expr);
 	  expr.value = build_unary_op (op_loc,
 				       POSTINCREMENT_EXPR, expr.value, 0);
 	  expr.original_code = ERROR_MARK;
@@ -5974,7 +5990,7 @@ c_parser_postfix_expression_after_primar
 	case CPP_MINUS_MINUS:
 	  /* Postdecrement.  */
 	  c_parser_consume_token (parser);
-	  expr = default_function_array_conversion (expr_loc, expr);
+	  expr = default_function_array_read_conversion (expr_loc, expr);
 	  expr.value = build_unary_op (op_loc,
 				       POSTDECREMENT_EXPR, expr.value, 0);
 	  expr.original_code = ERROR_MARK;
@@ -6052,7 +6068,7 @@ c_parser_expr_list (c_parser *parser, bo
 
   expr = c_parser_expr_no_commas (parser, NULL);
   if (convert_p)
-    expr = default_function_array_conversion (loc, expr);
+    expr = default_function_array_read_conversion (loc, expr);
   if (fold_p)
     expr.value = c_fully_fold (expr.value, false, NULL);
   VEC_quick_push (tree, ret, expr.value);
@@ -6064,7 +6080,7 @@ c_parser_expr_list (c_parser *parser, bo
       loc = c_parser_peek_token (parser)->location;
       expr = c_parser_expr_no_commas (parser, NULL);
       if (convert_p)
-	expr = default_function_array_conversion (loc, expr);
+	expr = default_function_array_read_conversion (loc, expr);
       if (fold_p)
 	expr.value = c_fully_fold (expr.value, false, NULL);
       VEC_safe_push (tree, gc, ret, expr.value);
@@ -7887,7 +7903,7 @@ c_parser_omp_atomic (location_t loc, c_p
       {
 	location_t rhs_loc = c_parser_peek_token (parser)->location;
 	rhs_expr = c_parser_expression (parser);
-	rhs_expr = default_function_array_conversion (rhs_loc, rhs_expr);
+	rhs_expr = default_function_array_read_conversion (rhs_loc, rhs_expr);
       }
       rhs = rhs_expr.value;
       rhs = c_fully_fold (rhs, false, NULL);
@@ -8034,7 +8050,8 @@ c_parser_omp_for_loop (location_t loc,
 
 	  init_loc = c_parser_peek_token (parser)->location;
 	  init_exp = c_parser_expr_no_commas (parser, NULL);
-	  init_exp = default_function_array_conversion (init_loc, init_exp);
+	  init_exp = default_function_array_read_conversion (init_loc,
+							     init_exp);
 	  init = build_modify_expr (init_loc, decl, decl_exp.original_type,
 				    NOP_EXPR, init_loc, init_exp.value,
 				    init_exp.original_type);
--- gcc/common.opt.jj	2009-11-27 12:25:19.000000000 +0100
+++ gcc/common.opt	2009-11-27 18:07:20.000000000 +0100
@@ -208,6 +208,14 @@ Wunused
 Common Var(warn_unused) Init(0) Warning
 Enable all -Wunused- warnings
 
+Wunused-but-set-parameter
+Common Var(warn_unused_but_set_parameter) Init(-1) Warning
+Warn when a function parameter is only set, otherwise unused
+
+Wunused-but-set-variable
+Common Var(warn_unused_but_set_variable) Init(-1) Warning
+Warn when a variable is only set, otherwise unused
+
 Wunused-function
 Common Var(warn_unused_function) Init(-1) Warning
 Warn when a function is unused
--- gcc/toplev.c.jj	2009-11-27 12:25:18.000000000 +0100
+++ gcc/toplev.c	2009-11-27 18:09:08.000000000 +0100
@@ -1785,6 +1785,12 @@ process_options (void)
     warn_unused_parameter = (warn_unused && extra_warnings);
   if (warn_unused_variable == -1)
     warn_unused_variable = warn_unused;
+  /* Wunused-but-set-parameter is enabled if both -Wunused -Wextra are
+     enabled.  */
+  if (warn_unused_but_set_parameter == -1)
+    warn_unused_but_set_parameter = (warn_unused && extra_warnings);
+  if (warn_unused_but_set_variable == -1)
+    warn_unused_but_set_variable = warn_unused;
   if (warn_unused_value == -1)
     warn_unused_value = warn_unused;
 
--- gcc/objc/objc-act.c.jj	2009-11-27 12:25:18.000000000 +0100
+++ gcc/objc/objc-act.c	2009-11-27 16:38:23.000000000 +0100
@@ -1524,6 +1524,7 @@ finish_var_decl (tree var, tree initiali
   mark_decl_referenced (var);
   /* Mark the decl to avoid "defined but not used" warning.  */
   TREE_USED (var) = 1;
+  DECL_READ_P (var) = 1;
 }
 
 /* Find the decl for the constant string class reference.  This is only
@@ -3851,6 +3852,7 @@ objc_begin_catch_clause (tree decl)
   /* ??? As opposed to __attribute__((unused))?  Anyway, this appears to
      be what the previous objc implementation did.  */
   TREE_USED (decl) = 1;
+  DECL_READ_P (decl) = 1;
 
   /* Verify that the type of the catch is valid.  It must be a pointer
      to an Objective-C class, or "id" (which is catch-all).  */
@@ -8719,7 +8721,9 @@ really_start_method (tree method,
 
   /* Suppress unused warnings.  */
   TREE_USED (self_decl) = 1;
+  DECL_READ_P (self_decl) = 1;
   TREE_USED (TREE_CHAIN (self_decl)) = 1;
+  DECL_READ_P (TREE_CHAIN (self_decl)) = 1;
 #ifdef OBJCPLUS
   pop_lang_context ();
 #endif
@@ -8796,6 +8800,7 @@ get_super_receiver (void)
 				       objc_super_template);
 	/* This prevents `unused variable' warnings when compiling with -Wall.  */
 	TREE_USED (UOBJC_SUPER_decl) = 1;
+	DECL_READ_P (UOBJC_SUPER_decl) = 1;
 	lang_hooks.decls.pushdecl (UOBJC_SUPER_decl);
         finish_decl (UOBJC_SUPER_decl, input_location, NULL_TREE, NULL_TREE,
 	    	     NULL_TREE);
@@ -9419,6 +9424,7 @@ handle_class_ref (tree chain)
   DECL_INITIAL (decl) = exp;
   TREE_STATIC (decl) = 1;
   TREE_USED (decl) = 1;
+  DECL_READ_P (decl) = 1;
   /* Force the output of the decl as this forces the reference of the class.  */
   mark_decl_referenced (decl);
 
--- gcc/doc/invoke.texi.jj	2009-11-23 13:04:19.000000000 +0100
+++ gcc/doc/invoke.texi	2009-11-27 18:18:13.000000000 +0100
@@ -262,7 +262,7 @@ Objective-C and Objective-C++ Dialects}.
 -Wunknown-pragmas  -Wno-pragmas -Wunreachable-code @gol
 -Wunsuffixed-float-constants  -Wunused  -Wunused-function @gol
 -Wunused-label  -Wunused-parameter -Wno-unused-result -Wunused-value  -Wunused-variable @gol
--Wvariadic-macros -Wvla @gol
+-Wunused-but-set-parameter -Wunused-but-set-variable -Wvariadic-macros -Wvla @gol
 -Wvolatile-register-var  -Wwrite-strings}
 
 @item C and Objective-C-only Warning Options
@@ -2895,7 +2895,8 @@ name is still supported, but the newer n
 -Wsign-compare  @gol
 -Wtype-limits  @gol
 -Wuninitialized  @gol
--Wunused-parameter @r{(only with} @option{-Wunused} @r{or} @option{-Wall}@r{)}  @gol
+-Wunused-parameter @r{(only with} @option{-Wunused} @r{or} @option{-Wall}@r{)} @gol
+-Wunused-but-set-parameter @r{(only with} @option{-Wunused} @r{or} @option{-Wall}@r{)}  @gol
 }
 
 The option @option{-Wextra} also prints warning messages for the
@@ -3285,6 +3286,25 @@ Warn if any trigraphs are encountered th
 the program (trigraphs within comments are not warned about).
 This warning is enabled by @option{-Wall}.
 
+@item -Wunused-but-set-parameter
+@opindex Wunused-but-set-parameter
+@opindex Wno-unused-but-set-parameter
+Warn whenever a function parameter is assigned to, but otherwise unused
+(aside from its declaration).
+
+To suppress this warning use the @samp{unused} attribute
+(@pxref{Variable Attributes}).
+
+@item -Wunused-but-set-variable
+@opindex Wunused-but-set-variable
+@opindex Wno-unused-but-set-variable
+Warn whenever a local variable is assigned to, but otherwise unused
+(aside from its declaration).
+This warning is enabled by @option{-Wall}.
+
+To suppress this warning use the @samp{unused} attribute
+(@pxref{Variable Attributes}).
+
 @item -Wunused-function
 @opindex Wunused-function
 @opindex Wno-unused-function
--- gcc/testsuite/gcc.dg/Wunused-var-1.c.jj	2009-11-27 13:00:10.000000000 +0100
+++ gcc/testsuite/gcc.dg/Wunused-var-1.c	2009-11-27 13:00:10.000000000 +0100
@@ -0,0 +1,179 @@
+/* { dg-do compile } */
+/* { dg-options "-Wunused" } */
+
+void
+f1 (void)
+{
+  int a;	/* { dg-warning "set but not used" } */
+  int b;
+  int c;
+  c = 1;
+  a = b = c;
+}
+
+void
+f2 (int x)
+{
+  int a;	/* { dg-warning "set but not used" } */
+  int b;
+  int c;	/* { dg-warning "set but not used" } */
+  c = (a = x, b = x);
+}
+
+int
+f3 (int x)
+{
+  int a;
+  return a = x;
+}
+
+int
+f4 (int x)
+{
+  int a;
+  a = x;
+  return a;
+}
+
+void
+f5 (int x)
+{
+  int a[2];	/* { dg-warning "set but not used" } */
+  int b;
+  int *c, d[2];
+  c = d;
+  b = x;
+  a[b] = 1;
+  c[b] = 1;
+}
+
+int
+f6 (int x)
+{
+  int a[2];
+  int b;
+  b = x;
+  a[b] = 1;
+  return a[b];
+}
+
+void
+f7 (int x, int *p)
+{
+  int *a[2];
+  a[x] = p;
+  a[x][x] = x;
+}
+
+struct S { int i; };
+
+void
+f8 (void)
+{
+  struct S s;	/* { dg-warning "set but not used" } */
+  s.i = 6;
+}
+
+int
+f9 (void)
+{
+  struct S s;
+  s.i = 6;
+  return s.i;
+}
+
+struct S
+f10 (void)
+{
+  struct S s;
+  s.i = 6;
+  return s;
+}
+
+extern int foo11 (int *);
+
+void
+f11 (void)
+{
+  int a[2];
+  foo11 (a);
+}
+
+void
+f12 (void)
+{
+  int a;
+  a = 1;
+  a;	/* { dg-warning "statement with no effect" } */
+}
+
+void
+f13 (void (*x) (void))
+{
+  void (*a) (void);
+  a = x;
+  a ();
+}
+
+void
+f14 (void (*x) (void))
+{
+  void (*a) (void);	/* { dg-warning "set but not used" } */
+  a = x;
+}
+
+extern void foo15 (int *);
+
+void
+f15 (void)
+{
+  int a[10];
+  int *b = a + 2;
+  foo15 (b);
+}
+
+extern void foo16 (int **);
+
+void
+f16 (void)
+{
+  int a[10];
+  int *b[] = { a, a + 2 };
+  foo16 (b);
+}
+
+void
+f17 (int x)
+{
+  long a;	/* { dg-warning "set but not used" } */
+  int b;
+  a = b = x;
+}
+
+void
+f18 (int x)
+{
+  int a;	/* { dg-warning "set but not used" } */
+  int b;
+  a = (char) (b = x);
+}
+
+int
+f19 (int x, int y, int z)
+{
+  int a;
+  int b;
+  a = x;
+  b = y;
+  return z ? a : b;
+}
+
+int *
+f20 (int x)
+{
+  static int a[] = { 3, 4, 5, 6 };
+  static int b[] = { 4, 5, 6, 7 };
+  static int c[] = { 5, 6, 7, 8 };	/* { dg-warning "set but not used" } */
+  c[1] = 1;
+  return x ? a : b;
+}
--- gcc/testsuite/gcc.dg/Wunused-var-2.c.jj	2009-11-27 13:00:10.000000000 +0100
+++ gcc/testsuite/gcc.dg/Wunused-var-2.c	2009-11-27 13:00:10.000000000 +0100
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-Wunused" } */
+
+int
+f1 (void)
+{
+  int c = ({
+    int a;
+    a = 1;
+    a; });
+  return c;
+}
+
+void
+f2 (void)
+{
+  int f;
+  f = 0;
+  __asm__ __volatile__ ("" : "+r" (f));
+}
--- gcc/testsuite/gcc.dg/Wunused-var-3.c.jj	2009-11-27 13:00:10.000000000 +0100
+++ gcc/testsuite/gcc.dg/Wunused-var-3.c	2009-11-27 13:00:10.000000000 +0100
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-Wunused" } */
+
+void
+f1 (void)
+{
+  _Complex int a;	/* { dg-warning "set but not used" } */
+  _Complex double b;	/* { dg-warning "set but not used" } */
+  __real__ a = 1;
+  __imag__ a = 2;
+  __real__ b = 3.0;
+  __imag__ b = 4.0;
+}
+
+int
+f2 (void)
+{
+  _Complex int a;
+  _Complex double b;
+  __real__ a = 1;
+  __imag__ a = 2;
+  __real__ b = 3.0;
+  __imag__ b = 4.0;
+  return __real__ a + __imag__ b;
+}
+
+_Complex double
+f3 (void)
+{
+  _Complex int a;
+  _Complex double b;
+  __real__ a = 1;
+  __imag__ a = 2;
+  __real__ b = 3.0;
+  __imag__ b = 4.0;
+  return a + b;
+}
--- gcc/testsuite/gcc.dg/Wunused-var-4.c.jj	2009-11-27 13:00:10.000000000 +0100
+++ gcc/testsuite/gcc.dg/Wunused-var-4.c	2009-11-27 13:00:10.000000000 +0100
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-Wunused" } */
+
+int
+f1 (void)
+{
+  int a;
+  int foo (void)
+  {
+    return a;
+  }
+  a = 1;
+  return foo ();
+}
+
+void
+f2 (void)
+{
+  int a;	/* { dg-warning "set but not used" } */
+  void foo (void)
+  {
+    a = 2;
+  }
+  a = 1;
+  foo ();
+}
--- gcc/testsuite/gcc.dg/Wunused-var-5.c.jj	2009-11-27 13:00:10.000000000 +0100
+++ gcc/testsuite/gcc.dg/Wunused-var-5.c	2009-11-27 13:00:10.000000000 +0100
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-Wunused" } */
+
+void
+f1 (void)
+{
+  extern int extvari;
+  extvari = 1;
+}
+
+int extvarj;
+
+void
+f2 (void)
+{
+  extern int extvarj;
+  extvarj = 1;
+}
+
+static int extvark;
+
+void
+f3 (void)
+{
+  extern int extvark;
+  extvark = 1;
+}
+
+int
+f4 (void)
+{
+  return extvark;
+}
--- gcc/testsuite/gcc.dg/Wunused-var-6.c.jj	2009-11-27 13:00:10.000000000 +0100
+++ gcc/testsuite/gcc.dg/Wunused-var-6.c	2009-11-27 13:00:10.000000000 +0100
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-Wunused" } */
+
+int
+f1 (void)
+{
+  int a;
+  int b;
+  int c;
+  int d;
+  int e;
+  a = 1;
+  b = 2;
+  c = 3;
+  d = 4;
+  e = 5;
+  return sizeof (a) + ((__typeof (b)) 1) + __alignof__ (c)
+         + __builtin_choose_expr (1, d, e);
+}
--- gcc/testsuite/gcc.dg/Wunused-parm-1.c.jj	2009-11-27 21:17:05.000000000 +0100
+++ gcc/testsuite/gcc.dg/Wunused-parm-1.c	2009-11-27 21:16:32.000000000 +0100
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-Wunused -W" } */
+
+long
+f1 (unsigned long long x)
+{
+  unsigned long long a = 1;
+  const union { unsigned long long l; unsigned int p[2]; } b = { .l = x };
+  const union { unsigned long long l; unsigned int p[2]; } c = { .l = a };
+  return b.p[0] + c.p[0];
+}
+
+int
+f2 (int x, int y)
+{
+  int a = 1;
+  int b[] = { 1, 2, x, a, 3, 4 };
+  return b[y];
+}
+
+int
+f3 (int a,	/* { dg-warning "unused parameter" } */
+    int b,	/* { dg-warning "set but not used" } */
+    int c)
+{
+  b = 1;
+  c = 1;
+  return c;
+}


More information about the Gcc-patches mailing list