From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27395 invoked by alias); 27 Nov 2009 10:47:09 -0000 Received: (qmail 27380 invoked by uid 22791); 27 Nov 2009 10:47:05 -0000 X-SWARE-Spam-Status: No, hits=-1.2 required=5.0 tests=AWL,BAYES_50,SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 27 Nov 2009 10:46:58 +0000 Received: from int-mx08.intmail.prod.int.phx2.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id nARAkuQp003943 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 27 Nov 2009 05:46:56 -0500 Received: from hs20-bc2-1.build.redhat.com (hs20-bc2-1.build.redhat.com [10.10.28.34]) by int-mx08.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id nARAktLQ018716 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Fri, 27 Nov 2009 05:46:55 -0500 Received: from hs20-bc2-1.build.redhat.com (localhost.localdomain [127.0.0.1]) by hs20-bc2-1.build.redhat.com (8.13.1/8.13.1) with ESMTP id nARAksn6017495 for ; Fri, 27 Nov 2009 05:46:54 -0500 Received: (from jakub@localhost) by hs20-bc2-1.build.redhat.com (8.13.1/8.13.1/Submit) id nARAksTi017491 for gcc-patches@gcc.gnu.org; Fri, 27 Nov 2009 05:46:54 -0500 Date: Fri, 27 Nov 2009 10:53:00 -0000 From: Jakub Jelinek To: gcc-patches@gcc.gnu.org Subject: [PATCH] Add set but not used warning support for the C FE (PR c/18624, take 2) Message-ID: <20091127104654.GZ22813@hs20-bc2-1.build.redhat.com> Reply-To: Jakub Jelinek Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4.1i X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2009-11/txt/msg01528.txt.bz2 Hi! Here is the latest version of the set but not used warning patch, which fixes several bugs and makes the warning controlled by a special warning switch, so that people can decide to turn it on/off. The warning defaults to on if -Wunused/-Wall like all other -Wunused-* warnings, alternatively it could even default to -Wunused-variables. Bootstrapped/regtested on x86_64-linux with --disable-werror (there are still warnings left). 2009-11-27 Jakub Jelinek 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. * 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): 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): Call mark_exp_read where needed. * common.opt (Wunused-but-set-variable): New. * toplev.c (warn_unused_but_set_variable): Default to warn_unused. * 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/tree.h.jj 2009-11-25 16:47:35.000000000 +0100 +++ gcc/tree.h 2009-11-26 14:43:56.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-25 16:47:36.000000000 +0100 +++ gcc/c-decl.c 2009-11-26 23:11:12.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); --- gcc/c-common.c.jj 2009-11-25 16:47:37.000000000 +0100 +++ gcc/c-common.c 2009-11-26 14:43:56.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-25 16:47:36.000000000 +0100 +++ gcc/c-tree.h 2009-11-26 14:43:56.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-25 16:47:36.000000000 +0100 +++ gcc/c-typeck.c 2009-11-26 15:42:47.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-25 16:47:37.000000000 +0100 +++ gcc/c-parser.c 2009-11-26 23:26:21.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, "% 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; } } @@ -3840,6 +3841,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 +4457,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 +4608,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 +4650,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 +4677,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 +4695,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 +4848,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 +4957,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 +4966,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 +5037,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 +5090,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, "unary *"); return ret; case CPP_PLUS: @@ -5112,25 +5118,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 +5236,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, "% applied to a bit-field"); @@ -5290,6 +5297,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 +5503,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 +5648,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 +5894,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 +5977,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 +5986,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 +6064,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 +6076,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 +7899,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 +8046,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-04 08:16:05.000000000 +0100 +++ gcc/common.opt 2009-11-26 14:46:44.000000000 +0100 @@ -208,6 +208,10 @@ Wunused Common Var(warn_unused) Init(0) Warning Enable all -Wunused- warnings +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-25 16:47:35.000000000 +0100 +++ gcc/toplev.c 2009-11-26 14:47:59.000000000 +0100 @@ -1785,6 +1785,8 @@ process_options (void) warn_unused_parameter = (warn_unused && extra_warnings); if (warn_unused_variable == -1) warn_unused_variable = warn_unused; + 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-26 17:38:36.000000000 +0100 +++ gcc/objc/objc-act.c 2009-11-27 10:31:55.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/testsuite/gcc.dg/Wunused-var-1.c.jj 2009-11-26 14:43:57.000000000 +0100 +++ gcc/testsuite/gcc.dg/Wunused-var-1.c 2009-11-26 15:24:54.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-26 14:43:57.000000000 +0100 +++ gcc/testsuite/gcc.dg/Wunused-var-2.c 2009-11-26 14:43:57.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-26 14:43:57.000000000 +0100 +++ gcc/testsuite/gcc.dg/Wunused-var-3.c 2009-11-26 14:43:57.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-26 14:43:57.000000000 +0100 +++ gcc/testsuite/gcc.dg/Wunused-var-4.c 2009-11-26 14:43:57.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-26 15:20:44.000000000 +0100 +++ gcc/testsuite/gcc.dg/Wunused-var-5.c 2009-11-26 15:21:18.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-26 23:29:41.000000000 +0100 +++ gcc/testsuite/gcc.dg/Wunused-var-6.c 2009-11-26 23:28:47.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); +} Jakub