re PR c/18624 (GCC does not detect local variable set but never used)

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.

From-SVN: r158086
This commit is contained in:
Jakub Jelinek 2010-04-07 22:33:36 +02:00 committed by Jakub Jelinek
parent 0bb8c1342f
commit ebfbbdc556
20 changed files with 586 additions and 40 deletions

View file

@ -1,5 +1,40 @@
2010-04-07 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.
* tree-ssa-pre.c (my_rev_post_order_compute): Remove set but not
used count variable.
* genemit.c (gen_expand, gen_split): Avoid set but not used warnings

View file

@ -6121,6 +6121,8 @@ handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
{
TREE_USED (node) = 1;
DECL_PRESERVE_P (node) = 1;
if (TREE_CODE (node) == VAR_DECL)
DECL_READ_P (node) = 1;
}
else
{
@ -6147,7 +6149,12 @@ handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
|| 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);

View file

@ -1164,14 +1164,21 @@ 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_at (DECL_SOURCE_LOCATION (p),
OPT_Wunused_but_set_variable,
"variable %qD set but not used", p);
}
if (b->inner_comp)
{
@ -2387,6 +2394,8 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
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);
if (DECL_PRESERVE_P (olddecl))
DECL_PRESERVE_P (newdecl) = 1;
else if (DECL_PRESERVE_P (newdecl))
@ -4232,7 +4241,10 @@ finish_decl (tree decl, location_t init_loc, tree 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
@ -4380,6 +4392,7 @@ finish_decl (tree decl, location_t init_loc, tree 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);
}
@ -4472,6 +4485,7 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const)
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);
@ -8060,6 +8074,25 @@ 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_at (DECL_SOURCE_LOCATION (decl),
OPT_Wunused_but_set_parameter,
"parameter %qD 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;

View file

@ -1,6 +1,6 @@
/* Parser for C and Objective-C.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Parser actions based on the old Bison parser; structure somewhat
@ -2171,6 +2171,7 @@ c_parser_typeof_specifier (c_parser *parser)
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, struct c_expr *after)
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_parser *parser)
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, bool convert_p)
}
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 *parser, struct c_expr *after)
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_parser *parser, struct c_expr *after)
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_parser *parser, struct c_expr *after)
(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_parser *parser, struct c_expr *after)
{
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 *parser, struct c_expr *after)
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 *parser, struct c_expr *after)
{
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 *parser, struct c_expr *after)
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 *parser, struct c_expr *after)
{
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 *parser)
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 *parser)
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 *parser)
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 *parser)
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 *parser)
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 *parser)
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_primary (c_parser *parser,
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_primary (c_parser *parser,
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_primary (c_parser *parser,
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, bool convert_p, bool fold_p,
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, bool convert_p, bool fold_p,
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_parser *parser)
{
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);

View file

@ -1,6 +1,6 @@
/* Definitions for C parsing and type checking.
Copyright (C) 1987, 1993, 1994, 1995, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GCC.
@ -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);

View file

@ -1763,6 +1763,35 @@ function_to_pointer_conversion (location_t loc, tree exp)
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 (location_t loc, struct c_expr exp)
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)
@ -8793,6 +8830,7 @@ c_process_expr_stmt (location_t loc, tree expr)
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);
}

View file

@ -212,6 +212,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

View file

@ -262,7 +262,7 @@ Objective-C and Objective-C++ Dialects}.
-Wunknown-pragmas -Wno-pragmas @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
@ -2926,7 +2926,8 @@ name is still supported, but the newer name is more descriptive.)
-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
@ -3321,6 +3322,31 @@ Warn if any trigraphs are encountered that might change the meaning of
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}).
This warning is also enabled by @option{-Wunused} together with
@option{-Wextra}.
@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}).
This warning is also enabled by @option{-Wunused}, which is enabled
by @option{-Wall}.
@item -Wunused-function
@opindex Wunused-function
@opindex Wno-unused-function

View file

@ -1,3 +1,10 @@
2010-04-07 Jakub Jelinek <jakub@redhat.com>
PR c/18624
* 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.
2010-04-07 Iain Sandoe <iains@gcc.gnu.org>
PR objc/35996

View file

@ -1,6 +1,7 @@
/* Implement classes and message passing for Objective C.
Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
2002, 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Steve Naroff.
This file is part of GCC.
@ -1531,6 +1532,7 @@ finish_var_decl (tree var, tree initializer)
mark_decl_referenced (var);
/* Mark the decl to avoid "defined but not used" warning. */
TREE_USED (var) = 1;
DECL_READ_P (var) = 1;
/* We reserve the right for the runtime to use/modify these variables
in ways that are opaque to us. */
DECL_PRESERVE_P (var) = 1;
@ -3867,6 +3869,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). */
@ -8722,7 +8725,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
@ -8799,6 +8804,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);
@ -9422,6 +9428,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);

View file

@ -1,5 +1,14 @@
2010-04-07 Jakub Jelinek <jakub@redhat.com>
PR c/18624
* 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.dg/builtin-choose-expr.c: Avoid set but not used warnings.
* gcc.dg/trunc-1.c: Likewise.
* gcc.dg/vla-9.c: Likewise.

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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));
}

View file

@ -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;
}

View file

@ -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 ();
}

View file

@ -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;
}

View file

@ -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);
}

View file

@ -1796,6 +1796,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;

View file

@ -1317,6 +1317,9 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int,
(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)
@ -2691,8 +2694,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;