diff options
Diffstat (limited to 'gcc/c-family')
-rw-r--r-- | gcc/c-family/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/c-family/c-common.c | 96 | ||||
-rw-r--r-- | gcc/c-family/c-common.h | 1 |
3 files changed, 102 insertions, 0 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 6c4ac8b1edb..558c6a736e9 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,8 @@ +2012-04-10 Manuel López-Ibáñez <manu@gcc.gnu.org> + + * c-common.c (warn_if_unused_value): Move definition to here. + * c-common.h (warn_if_unused_value): Move declaration to here. + 2012-03-23 William Bader <williambader@hotmail.com> * c-lex.c (c_lex_with_flags): Avoid declarations after stmts. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index fc83b04c8a1..a9e7ec1d14d 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -1649,6 +1649,102 @@ warn_logical_operator (location_t location, enum tree_code code, tree type, } +/* Warn if EXP contains any computations whose results are not used. + Return true if a warning is printed; false otherwise. LOCUS is the + (potential) location of the expression. */ + +bool +warn_if_unused_value (const_tree exp, location_t locus) +{ + restart: + if (TREE_USED (exp) || TREE_NO_WARNING (exp)) + return false; + + /* Don't warn about void constructs. This includes casting to void, + void function calls, and statement expressions with a final cast + to void. */ + if (VOID_TYPE_P (TREE_TYPE (exp))) + return false; + + if (EXPR_HAS_LOCATION (exp)) + locus = EXPR_LOCATION (exp); + + switch (TREE_CODE (exp)) + { + case PREINCREMENT_EXPR: + case POSTINCREMENT_EXPR: + case PREDECREMENT_EXPR: + case POSTDECREMENT_EXPR: + case MODIFY_EXPR: + case INIT_EXPR: + case TARGET_EXPR: + case CALL_EXPR: + case TRY_CATCH_EXPR: + case WITH_CLEANUP_EXPR: + case EXIT_EXPR: + case VA_ARG_EXPR: + return false; + + case BIND_EXPR: + /* For a binding, warn if no side effect within it. */ + exp = BIND_EXPR_BODY (exp); + goto restart; + + case SAVE_EXPR: + case NON_LVALUE_EXPR: + exp = TREE_OPERAND (exp, 0); + goto restart; + + case TRUTH_ORIF_EXPR: + case TRUTH_ANDIF_EXPR: + /* In && or ||, warn if 2nd operand has no side effect. */ + exp = TREE_OPERAND (exp, 1); + goto restart; + + case COMPOUND_EXPR: + if (warn_if_unused_value (TREE_OPERAND (exp, 0), locus)) + return true; + /* Let people do `(foo (), 0)' without a warning. */ + if (TREE_CONSTANT (TREE_OPERAND (exp, 1))) + return false; + exp = TREE_OPERAND (exp, 1); + goto restart; + + case COND_EXPR: + /* If this is an expression with side effects, don't warn; this + case commonly appears in macro expansions. */ + if (TREE_SIDE_EFFECTS (exp)) + return false; + goto warn; + + case INDIRECT_REF: + /* Don't warn about automatic dereferencing of references, since + the user cannot control it. */ + if (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == REFERENCE_TYPE) + { + exp = TREE_OPERAND (exp, 0); + goto restart; + } + /* Fall through. */ + + default: + /* Referencing a volatile value is a side effect, so don't warn. */ + if ((DECL_P (exp) || REFERENCE_CLASS_P (exp)) + && TREE_THIS_VOLATILE (exp)) + return false; + + /* If this is an expression which has no operands, there is no value + to be unused. There are no such language-independent codes, + but front ends may define such. */ + if (EXPRESSION_CLASS_P (exp) && TREE_OPERAND_LENGTH (exp) == 0) + return false; + + warn: + return warning_at (locus, OPT_Wunused_value, "value computed is not used"); + } +} + + /* Print a warning about casts that might indicate violation of strict aliasing rules if -Wstrict-aliasing is used and strict aliasing mode is in effect. OTYPE is the original diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 8552f0c92e9..cab7b439661 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -772,6 +772,7 @@ extern bool strict_aliasing_warning (tree, tree, tree); extern void warnings_for_convert_and_check (tree, tree, tree); extern tree convert_and_check (tree, tree); extern void overflow_warning (location_t, tree); +extern bool warn_if_unused_value (const_tree, location_t); extern void warn_logical_operator (location_t, enum tree_code, tree, enum tree_code, tree, enum tree_code, tree); extern void check_main_parameter_types (tree decl); |