gcc/cp/ChangeLog:
PR 18624
* cp-tree.h (mark_exp_read, mark_rvalue_use, mark_lvalue_use,
mark_type_use): Declare ...
* expr.c (mark_exp_read, mark_rvalue_use, mark_lvalue_use,
mark_type_use): ... new fns.
* typeck.c (cxx_sizeof_expr, cxx_alignof_expr): Call mark_type_use.
(perform_integral_promotions): Call mark_rvalue_use.
(cp_build_unary_op): Call mark_lvalue_use.
(decay_conversion): Update comment. Call mark_lvalue.
* decl.c (unused_but_set_errorcount): New variable.
(poplevel): Issue -Wunused-but-set-variable diagnostics.
(duplicate_decls): Merge DECL_READ_P flags.
(start_cleanup_fn): Set DECL_READ_P flag.
(finish_function): Issue -Wunused-but-set-parameter diagnostics.
* tree.c (rvalue): Call mark_rvalue_use.
* pt.c (convert_nontype_argument): Likewise.
* semantics.c (finish_typeof, finish_decltype_type): Call
mark_type_use.
(finish_asm_stmt): Call mark_lvalue_use.
(finish_expr_stmt): Call mark_exp_read.
* call.c (convert_like_real) <ck_identity, ck_user>: Call
mark_rvalue_use.
(build_x_va_arg): Call mark_lvalue_use.
(build_over_call): Call mark_type_use.
* init.c (build_new, build_delete): Call mark_value_use.
* rtti.c (build_typeid): Call mark_lvalue_use or mark_type_use.
(build_dynamic_cast_1): call mark_lvalue_use or mark_rvalue_use.
gcc/testsuite/ChangeLog:
PR 18624
* g++.dg/warn/Wunused-7.C: Add dg-warning.
* g++.dg/template/sfinae16.C: Likewise.
* gcc.dg/Wunused-var-1.c: Moved to...
* c-c++-common/Wunused-var-1.c: ...here. New test.
* gcc.dg/Wunused-var-2.c: Moved to...
* c-c++-common/Wunused-var-2.c: ...here. New test.
* gcc.dg/Wunused-var-3.c: Moved to...
* c-c++-common/Wunused-var-3.c: ...here. New test.
* gcc.dg/Wunused-var-4.c: Moved to...
* gcc.dg/Wunused-var-1.c: ... here.
* gcc.dg/Wunused-var-5.c: Moved to...
* c-c++-common/Wunused-var-4.c: ...here. New test.
* gcc.dg/Wunused-var-7.c: Moved to...
* c-c++-common/Wunused-var-5.c: ...here. New test.
* gcc.dg/Wunused-var-6.c: Moved to...
* gcc.dg/Wunused-var-2.c: ... here.
* c-c++-common/Wunused-var-1.c: New test.
* c-c++-common/Wunused-var-2.c: New test.
* c-c++-common/Wunused-var-3.c: New test.
* c-c++-common/Wunused-var-4.c: New test.
* c-c++-common/Wunused-var-5.c: New test.
* g++.dg/warn/Wunused-var-1.C: New test.
* g++.dg/warn/Wunused-var-2.C: New test.
* g++.dg/warn/Wunused-var-3.C: New test.
* g++.dg/warn/Wunused-var-4.C: New test.
* g++.dg/warn/Wunused-var-5.C: New test.
* g++.dg/warn/Wunused-var-6.C: New test.
* g++.dg/warn/Wunused-var-7.C: New test.
* g++.dg/warn/Wunused-var-8.C: New test.
* g++.dg/warn/Wunused-parm-1.C: New test.
* g++.dg/warn/Wunused-parm-2.C: New test.
* g++.dg/warn/Wunused-parm-3.C: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@159096
138bc75d-0d04-0410-961f-
82ee72b054a4
+2010-04-22 Jakub Jelinek <jakub@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ PR c/18624
+ * cp-tree.h (mark_exp_read, rvalue_use, lvalue_use, type_use):
+ Declare ...
+ * expr.c (mark_exp_read, rvalue_use, lvalue_use, type_use): ... new fns.
+ * typeck.c (cxx_sizeof_expr, cxx_alignof_expr): Call type_use.
+ (decay_conversion, perform_integral_promotions): Call rvalue_use.
+ (cp_build_unary_op): Call lvalue_use.
+ * decl.c (unused_but_set_errorcount): New variable.
+ (poplevel): Issue -Wunused-but-set-variable diagnostics.
+ (duplicate_decls): Merge DECL_READ_P flags.
+ (start_cleanup_fn): Set DECL_READ_P flag.
+ (finish_function): Issue -Wunused-but-set-parameter diagnostics.
+ * tree.c (rvalue): Call rvalue_use.
+ * pt.c (convert_nontype_argument): Likewise.
+ * semantics.c (finish_expr_stmt, finish_asm_stmt, finish_typeof,
+ finish_decltype_type): Likewise.
+ * call.c (convert_like_real) <ck_identity, ck_user>: Call rvalue use.
+ (build_x_va_arg, build_new_method_call, build_over_call): Call lvalue_use
+ or rvalue_use depending on the expr.
+ * init.c (build_new, build_delete): Likewise.
+ * rtti.c (build_typeid, build_dynamic_cast_1): Likewise.
+
2010-05-05 Jason Merrill <jason@redhat.com>
PR c++/43787
tree convfn = cand->fn;
unsigned i;
+ expr = mark_rvalue_use (expr);
+
/* When converting from an init list we consider explicit
constructors, but actually trying to call one is an error. */
if (DECL_NONCONVERTING_P (convfn) && DECL_CONSTRUCTOR_P (convfn))
return expr;
}
case ck_identity:
+ expr = mark_rvalue_use (expr);
if (BRACE_ENCLOSED_INITIALIZER_P (expr))
{
int nelts = CONSTRUCTOR_NELTS (expr);
if (expr == error_mark_node || !type)
return error_mark_node;
+ expr = mark_lvalue_use (expr);
+
if (type_has_nontrivial_copy_init (type)
|| TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
|| TREE_CODE (type) == REFERENCE_TYPE)
{
tree a = VEC_index (tree, args, arg_index);
if (magic_varargs_p (fn))
- /* Do no conversions for magic varargs. */;
+ /* Do no conversions for magic varargs. */
+ a = mark_type_use (a);
else
a = convert_arg_to_ellipsis (a);
argarray[j++] = a;
/* in expr.c */
extern tree cplus_expand_constant (tree);
+extern tree mark_rvalue_use (tree);
+extern tree mark_lvalue_use (tree);
+extern tree mark_type_use (tree);
+extern void mark_exp_read (tree);
/* friend.c */
extern int is_friend (tree, tree);
return 1;
}
+/* Saved errorcount to avoid -Wunused-but-set-{parameter,variable} warnings
+ when errors were reported, except for -Werror-unused-but-set-*. */
+static int unused_but_set_errorcount;
+
/* Exit a binding level.
Pop the level off, and restore the state of the identifier-decl mappings
that were in effect when this level was entered.
= current_binding_level->kind == sk_for && flag_new_for_scope == 1;
/* Before we remove the declarations first check for unused variables. */
- if (warn_unused_variable
+ if ((warn_unused_variable || warn_unused_but_set_variable)
&& !processing_template_decl)
for (decl = getdecls (); decl; decl = TREE_CHAIN (decl))
if (TREE_CODE (decl) == VAR_DECL
- && ! TREE_USED (decl)
+ && (! TREE_USED (decl) || !DECL_READ_P (decl))
&& ! DECL_IN_SYSTEM_HEADER (decl)
&& DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
- warning (OPT_Wunused_variable, "unused variable %q+D", decl);
+ {
+ if (! TREE_USED (decl))
+ warning (OPT_Wunused_variable, "unused variable %q+D", decl);
+ else if (DECL_CONTEXT (decl) == current_function_decl
+ && TREE_TYPE (decl) != error_mark_node
+ && TREE_CODE (TREE_TYPE (decl)) != REFERENCE_TYPE
+ && errorcount == unused_but_set_errorcount
+ && (!CLASS_TYPE_P (TREE_TYPE (decl))
+ || !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl))))
+ {
+ warning (OPT_Wunused_but_set_variable,
+ "variable %q+D set but not used", decl);
+ unused_but_set_errorcount = errorcount;
+ }
+ }
/* Remove declarations for all the DECLs in this level. */
for (link = decls; link; link = TREE_CHAIN (link))
TREE_USED (newdecl) = 1;
else if (TREE_USED (newdecl))
TREE_USED (olddecl) = 1;
+ if (TREE_CODE (newdecl) == VAR_DECL)
+ {
+ if (DECL_READ_P (olddecl))
+ DECL_READ_P (newdecl) = 1;
+ else if (DECL_READ_P (newdecl))
+ DECL_READ_P (olddecl) = 1;
+ }
if (DECL_PRESERVE_P (olddecl))
DECL_PRESERVE_P (newdecl) = 1;
else if (DECL_PRESERVE_P (newdecl))
parmdecl = cp_build_parm_decl (NULL_TREE, ptr_type_node);
DECL_CONTEXT (parmdecl) = fndecl;
TREE_USED (parmdecl) = 1;
+ DECL_READ_P (parmdecl) = 1;
DECL_ARGUMENTS (fndecl) = parmdecl;
}
info for the epilogue. */
cfun->function_end_locus = input_location;
+ /* Complain about parameters that are only set, but never otherwise used. */
+ if (warn_unused_but_set_parameter
+ && !processing_template_decl
+ && errorcount == unused_but_set_errorcount
+ && !DECL_CLONED_FUNCTION_P (fndecl))
+ {
+ 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)
+ && !DECL_IN_SYSTEM_HEADER (decl)
+ && TREE_TYPE (decl) != error_mark_node
+ && TREE_CODE (TREE_TYPE (decl)) != REFERENCE_TYPE
+ && (!CLASS_TYPE_P (TREE_TYPE (decl))
+ || !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl))))
+ warning (OPT_Wunused_but_set_parameter,
+ "parameter %q+D set but not used", decl);
+ unused_but_set_errorcount = errorcount;
+ }
+
/* Genericize before inlining. */
if (!processing_template_decl)
{
else
return error_mark_node;
}
+ nelts = mark_rvalue_use (nelts);
nelts = cp_save_expr (cp_convert (sizetype, nelts));
}
type = TYPE_MAIN_VARIANT (type);
+ addr = mark_rvalue_use (addr);
+
if (TREE_CODE (type) == POINTER_TYPE)
{
bool complete_p = true;
if (error_operand_p (expr))
return error_mark_node;
expr_type = TREE_TYPE (expr);
+ expr = mark_rvalue_use (expr);
/* HACK: Due to double coercion, we can get a
NOP_EXPR<REFERENCE_TYPE>(ADDR_EXPR<POINTER_TYPE> (arg)) here,
{
if (warn_sequence_point)
verify_sequence_points (expr);
+ if (TREE_CODE (expr) != MODIFY_EXPR)
+ /* Expr is not being 'used' here, otherwise we whould have
+ called mark_{rl}value_use use here, which would have in turn
+ called mark_exp_read. Rather, we call mark_exp_read directly
+ to avoid some warnings when
+ -Wunused-but-set-{variable,parameter} is in effect. */
+ mark_exp_read (expr);
expr = convert_to_void (expr, "statement", tf_warning_or_error);
}
else if (!type_dependent_expression_p (expr))
otherwise we'll get an error. Gross, but ... */
STRIP_NOPS (operand);
+ operand = mark_lvalue_use (operand);
+
if (!lvalue_or_else (operand, lv_asm, tf_warning_or_error))
operand = error_mark_node;
return type;
}
+ expr = mark_type_use (expr);
+
type = unlowered_expr_type (expr);
if (!type || type == unknown_type_node)
case PARM_DECL:
case RESULT_DECL:
case TEMPLATE_PARM_INDEX:
+ expr = mark_type_use (expr);
type = TREE_TYPE (expr);
break;
break;
case COMPONENT_REF:
+ mark_type_use (expr);
type = is_bitfield_expr_with_lowered_type (expr);
if (!type)
type = TREE_TYPE (TREE_OPERAND (expr, 1));
if (error_operand_p (expr))
return expr;
+ expr = mark_rvalue_use (expr);
+
/* [basic.lval]
Non-class rvalues always have cv-unqualified types. */
&& DECL_TEMPLATE_INSTANTIATION (e))
instantiate_decl (e, /*defer_ok*/true, /*expl_inst_mem*/false);
+ e = mark_type_use (e);
+
if (TREE_CODE (e) == COMPONENT_REF
&& TREE_CODE (TREE_OPERAND (e, 1)) == FIELD_DECL
&& DECL_C_BIT_FIELD (TREE_OPERAND (e, 1)))
return e;
}
+ e = mark_type_use (e);
+
if (TREE_CODE (e) == VAR_DECL)
t = size_int (DECL_ALIGN_UNIT (e));
else if (TREE_CODE (e) == COMPONENT_REF
in an rvalue context: the lvalue-to-rvalue, array-to-pointer, and
function-to-pointer conversions. In addition, manifest constants
are replaced by their values, and bitfield references are converted
- to their declared types.
+ to their declared types. Note that this function does not perform the
+ lvalue-to-rvalue conversion for class types. If you need that conversion
+ to for class types, then you probably need to use force_rvalue.
Although the returned value is being used as an rvalue, this
function does not wrap the returned expression in a
if (type == error_mark_node)
return error_mark_node;
+ exp = mark_rvalue_use (exp);
+
exp = resolve_nondeduced_context (exp);
if (type_unknown_p (exp))
{
tree type;
tree promoted_type;
+ expr = mark_rvalue_use (expr);
+
/* [conv.prom]
If the bitfield has an enumerated type, it is treated as any
if (val != 0)
return val;
+ arg = mark_lvalue_use (arg);
+
/* Increment or decrement the real part of the value,
and don't change the imaginary part. */
if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
argtype = lvalue_type (arg);
+ arg = mark_lvalue_use (arg);
+
if (TREE_CODE (arg) == OFFSET_REF)
goto offset_ref;
return win;
}
+
+2010-04-22 Jakub Jelinek <jakub@redhat.com>
+ Dodji Seketeli <dodji@redhat.com>
+
+ PR c/18624
+ * g++.dg/warn/Wunused-7.C: Add dg-warning.
+ * g++.dg/template/sfinae16.C: Likewise.
+ * gcc.dg/Wunused-var-1.c: Moved to...
+ * c-c++-common/Wunused-var-1.c: ...here. New test.
+ * gcc.dg/Wunused-var-2.c: Moved to...
+ * c-c++-common/Wunused-var-2.c: ...here. New test.
+ * gcc.dg/Wunused-var-3.c: Moved to...
+ * c-c++-common/Wunused-var-3.c: ...here. New test.
+ * gcc.dg/Wunused-var-4.c: Moved to...
+ * gcc.dg/Wunused-var-1.c: ... here.
+ * gcc.dg/Wunused-var-5.c: Moved to...
+ * c-c++-common/Wunused-var-4.c: ...here. New test.
+ * gcc.dg/Wunused-var-7.c: Moved to...
+ * c-c++-common/Wunused-var-5.c: ...here. New test.
+ * gcc.dg/Wunused-var-6.c: Moved to...
+ * gcc.dg/Wunused-var-2.c: ... here.
+ * c-c++-common/Wunused-var-1.c: New test.
+ * c-c++-common/Wunused-var-2.c: New test.
+ * c-c++-common/Wunused-var-3.c: New test.
+ * c-c++-common/Wunused-var-4.c: New test.
+ * c-c++-common/Wunused-var-5.c: New test.
+ * g++.dg/warn/Wunused-var-1.C: New test.
+ * g++.dg/warn/Wunused-var-2.C: New test.
+ * g++.dg/warn/Wunused-var-3.C: New test.
+ * g++.dg/warn/Wunused-var-4.C: New test.
+ * g++.dg/warn/Wunused-var-5.C: New test.
+ * g++.dg/warn/Wunused-var-6.C: New test.
+ * g++.dg/warn/Wunused-var-7.C: New test.
+ * g++.dg/warn/Wunused-var-8.C: New test.
+ * g++.dg/warn/Wunused-parm-1.C: New test.
+ * g++.dg/warn/Wunused-parm-2.C: New test.
+ * g++.dg/warn/Wunused-parm-3.C: New test.
+
2010-05-06 Tobias Burnus <burnus@net-b.de>
PR fortran/43985
/* { 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)
+f1 (void)
{
int a;
+ int foo (void)
+ {
+ return a;
+ }
a = 1;
- a; /* { dg-warning "statement with no effect" } */
+ return foo ();
}
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)
+f2 (void)
{
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;
+ void foo (void)
+ {
+ a = 2;
+ }
+ a = 1;
+ foo ();
}
int
f1 (void)
{
- int c = ({
- int a;
- a = 1;
- a; });
- return c;
-}
-
-void
-f2 (void)
-{
- int f;
- f = 0;
- __asm__ __volatile__ ("" : "+r" (f));
+ 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);
}
+++ /dev/null
-/* { 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;
-}
+++ /dev/null
-/* { 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 ();
-}
+++ /dev/null
-/* { 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;
-}
+++ /dev/null
-/* { 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);
-}
+++ /dev/null
-/* { dg-do compile } */
-/* { dg-options "-Wunused -W" } */
-
-int
-f1 (unsigned int x)
-{
- int c = ({ union { unsigned int a; int b; } u; u.a = x; u.b; });
- return c;
-}
-
-void
-f2 (void)
-{
- struct S { int i; } a;
- int b[1];
- a.i = 1;
- a.i; /* { dg-warning "with no effect" } */
- b[0] = 1;
- b[0]; /* { dg-warning "with no effect" } */
-}
-
-void
-f3 (void)
-{
- struct S { int i; } a; /* { dg-warning "set but not used" } */
- int b[1]; /* { dg-warning "set but not used" } */
- a.i = 1;
- b[0] = 1;
-}