aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-family
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c-family')
-rw-r--r--gcc/c-family/ChangeLog5
-rw-r--r--gcc/c-family/c-common.c96
-rw-r--r--gcc/c-family/c-common.h1
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);