Commit 3146f36f by Jason Merrill Committed by Jason Merrill

re PR c++/41109 (Argument flagged as unused despite use in sizeof())

	PR c++/41109
	PR c++/41110
	PR c++/41134
	* cp-tree.h (DECL_ODR_USED): New macro.
	(struct lang_decl_base): Add odr_used flag.
	* decl.c (duplicate_decls): Propagate it.  Use it for error.
	* pt.c (register_specialization): Use it for error.
	* decl2.c (mark_used): Use it as gating flag rather than TREE_USED.
	(cp_write_global_declarations): Use it for error.
	(tree_used_ok): Remove.
	* cp-tree.h: Remove tree_used_ok.
	* call.c (build_call_a): Don't call it.
	* init.c (build_offset_ref): Likewise.

From-SVN: r151061
parent c767899e
2009-08-21 Jason Merrill <jason@redhat.com>
PR c++/41109
PR c++/41110
PR c++/41134
* cp-tree.h (DECL_ODR_USED): New macro.
(struct lang_decl_base): Add odr_used flag.
* decl.c (duplicate_decls): Propagate it. Use it for error.
* pt.c (register_specialization): Use it for error.
* decl2.c (mark_used): Use it as gating flag rather than TREE_USED.
(cp_write_global_declarations): Use it for error.
(tree_used_ok): Remove.
* cp-tree.h: Remove tree_used_ok.
* call.c (build_call_a): Don't call it.
* init.c (build_offset_ref): Likewise.
2009-08-21 Jakub Jelinek <jakub@redhat.com> 2009-08-21 Jakub Jelinek <jakub@redhat.com>
PR c++/41131 PR c++/41131
......
...@@ -318,7 +318,7 @@ build_call_a (tree function, int n, tree *argarray) ...@@ -318,7 +318,7 @@ build_call_a (tree function, int n, tree *argarray)
&& TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL) && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
{ {
decl = TREE_OPERAND (function, 0); decl = TREE_OPERAND (function, 0);
if (!tree_used_ok (decl)) if (!TREE_USED (decl))
{ {
/* We invoke build_call directly for several library /* We invoke build_call directly for several library
functions. These may have been declared normally if functions. These may have been declared normally if
......
...@@ -1579,8 +1579,9 @@ struct GTY(()) lang_decl_base { ...@@ -1579,8 +1579,9 @@ struct GTY(()) lang_decl_base {
unsigned anticipated_p : 1; /* fn or type */ unsigned anticipated_p : 1; /* fn or type */
unsigned friend_attr : 1; /* fn or type */ unsigned friend_attr : 1; /* fn or type */
unsigned template_conv_p : 1; /* template only? */ unsigned template_conv_p : 1; /* template only? */
unsigned odr_used : 1; /* var or fn */
unsigned u2sel : 1; unsigned u2sel : 1;
/* 2 spare bits */ /* 1 spare bit */
}; };
/* True for DECL codes which have template info and access. */ /* True for DECL codes which have template info and access. */
...@@ -1982,6 +1983,12 @@ struct GTY(()) lang_decl { ...@@ -1982,6 +1983,12 @@ struct GTY(()) lang_decl {
(DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL)) \ (DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL)) \
->u.base.initialized_in_class) ->u.base.initialized_in_class)
/* Nonzero if the DECL is used in the sense of 3.2 [basic.def.odr].
Only available for decls with DECL_LANG_SPECIFIC. */
#define DECL_ODR_USED(DECL) \
(DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL)) \
->u.base.odr_used)
/* Nonzero for DECL means that this decl is just a friend declaration, /* Nonzero for DECL means that this decl is just a friend declaration,
and should not be added to the list of members for this class. */ and should not be added to the list of members for this class. */
#define DECL_FRIEND_P(NODE) (DECL_LANG_SPECIFIC (NODE)->u.base.friend_attr) #define DECL_FRIEND_P(NODE) (DECL_LANG_SPECIFIC (NODE)->u.base.friend_attr)
...@@ -4477,7 +4484,6 @@ extern tree build_cleanup (tree); ...@@ -4477,7 +4484,6 @@ extern tree build_cleanup (tree);
extern tree build_offset_ref_call_from_tree (tree, VEC(tree,gc) **); extern tree build_offset_ref_call_from_tree (tree, VEC(tree,gc) **);
extern void check_default_args (tree); extern void check_default_args (tree);
extern void mark_used (tree); extern void mark_used (tree);
extern bool tree_used_ok (tree);
extern void finish_static_data_member_decl (tree, tree, bool, tree, int); extern void finish_static_data_member_decl (tree, tree, bool, tree, int);
extern tree cp_build_parm_decl (tree, tree); extern tree cp_build_parm_decl (tree, tree);
extern tree get_guard (tree); extern tree get_guard (tree);
......
...@@ -1890,6 +1890,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) ...@@ -1890,6 +1890,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
} }
DECL_TEMPLATE_INSTANTIATED (newdecl) DECL_TEMPLATE_INSTANTIATED (newdecl)
|= DECL_TEMPLATE_INSTANTIATED (olddecl); |= DECL_TEMPLATE_INSTANTIATED (olddecl);
DECL_ODR_USED (newdecl) |= DECL_ODR_USED (olddecl);
/* If the OLDDECL is an instantiation and/or specialization, /* If the OLDDECL is an instantiation and/or specialization,
then the NEWDECL must be too. But, it may not yet be marked then the NEWDECL must be too. But, it may not yet be marked
...@@ -1955,7 +1956,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) ...@@ -1955,7 +1956,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
should have exited above, returning 0. */ should have exited above, returning 0. */
gcc_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl)); gcc_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl));
if (TREE_USED (olddecl)) if (DECL_ODR_USED (olddecl))
/* From [temp.expl.spec]: /* From [temp.expl.spec]:
If a template, a member template or the member of a class If a template, a member template or the member of a class
......
...@@ -3631,7 +3631,7 @@ cp_write_global_declarations (void) ...@@ -3631,7 +3631,7 @@ cp_write_global_declarations (void)
for (i = 0; VEC_iterate (tree, deferred_fns, i, decl); ++i) for (i = 0; VEC_iterate (tree, deferred_fns, i, decl); ++i)
{ {
if (/* Check online inline functions that were actually used. */ if (/* Check online inline functions that were actually used. */
TREE_USED (decl) && DECL_DECLARED_INLINE_P (decl) DECL_ODR_USED (decl) && DECL_DECLARED_INLINE_P (decl)
/* If the definition actually was available here, then the /* If the definition actually was available here, then the
fact that the function was not defined merely represents fact that the function was not defined merely represents
that for some reason (use of a template repository, that for some reason (use of a template repository,
...@@ -3845,22 +3845,33 @@ mark_used (tree decl) ...@@ -3845,22 +3845,33 @@ mark_used (tree decl)
decl = OVL_CURRENT (decl); decl = OVL_CURRENT (decl);
} }
/* Set TREE_USED for the benefit of -Wunused. */
TREE_USED (decl) = 1;
if (DECL_CLONED_FUNCTION_P (decl))
TREE_USED (DECL_CLONED_FUNCTION (decl)) = 1;
if (TREE_CODE (decl) == FUNCTION_DECL if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DELETED_FN (decl)) && DECL_DELETED_FN (decl))
{ {
error ("deleted function %q+D", decl); error ("deleted function %q+D", decl);
error ("used here"); error ("used here");
TREE_USED (decl) = 1;
return; return;
} }
/* If we don't need a value, then we don't need to synthesize DECL. */ /* If we don't need a value, then we don't need to synthesize DECL. */
if (cp_unevaluated_operand != 0) if (cp_unevaluated_operand != 0)
return; return;
/* We can only check DECL_ODR_USED on variables or functions with
DECL_LANG_SPECIFIC set, and these are also the only decls that we
might need special handling for. */
if ((TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
|| DECL_LANG_SPECIFIC (decl) == NULL)
return;
/* We only want to do this processing once. We don't need to keep trying /* We only want to do this processing once. We don't need to keep trying
to instantiate inline templates, because unit-at-a-time will make sure to instantiate inline templates, because unit-at-a-time will make sure
we get them compiled before functions that want to inline them. */ we get them compiled before functions that want to inline them. */
if (TREE_USED (decl)) if (DECL_ODR_USED (decl))
return; return;
/* If within finish_function, defer the rest until that function /* If within finish_function, defer the rest until that function
...@@ -3896,9 +3907,9 @@ mark_used (tree decl) ...@@ -3896,9 +3907,9 @@ mark_used (tree decl)
if (processing_template_decl) if (processing_template_decl)
return; return;
TREE_USED (decl) = 1; DECL_ODR_USED (decl) = 1;
if (DECL_CLONED_FUNCTION_P (decl)) if (DECL_CLONED_FUNCTION_P (decl))
TREE_USED (DECL_CLONED_FUNCTION (decl)) = 1; DECL_ODR_USED (DECL_CLONED_FUNCTION (decl)) = 1;
/* DR 757: A type without linkage shall not be used as the type of a /* DR 757: A type without linkage shall not be used as the type of a
variable or function with linkage, unless variable or function with linkage, unless
...@@ -3981,15 +3992,4 @@ mark_used (tree decl) ...@@ -3981,15 +3992,4 @@ mark_used (tree decl)
processing_template_decl = saved_processing_template_decl; processing_template_decl = saved_processing_template_decl;
} }
/* Use this function to verify that mark_used has been called
previously. That is, either TREE_USED is set, or we're in a
context that doesn't set it. */
bool
tree_used_ok (tree decl)
{
return (TREE_USED (decl) || cp_unevaluated_operand
|| defer_mark_used_calls || processing_template_decl);
}
#include "gt-cp-decl2.h" #include "gt-cp-decl2.h"
...@@ -1502,7 +1502,7 @@ build_offset_ref (tree type, tree member, bool address_p) ...@@ -1502,7 +1502,7 @@ build_offset_ref (tree type, tree member, bool address_p)
gcc_assert (DECL_P (member) || BASELINK_P (member)); gcc_assert (DECL_P (member) || BASELINK_P (member));
/* Callers should call mark_used before this point. */ /* Callers should call mark_used before this point. */
gcc_assert (!DECL_P (member) || tree_used_ok (member)); gcc_assert (!DECL_P (member) || TREE_USED (member));
if (!COMPLETE_TYPE_P (complete_type (type)) if (!COMPLETE_TYPE_P (complete_type (type))
&& !TYPE_BEING_DEFINED (type)) && !TYPE_BEING_DEFINED (type))
......
...@@ -1296,7 +1296,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend, ...@@ -1296,7 +1296,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
{ {
if (DECL_TEMPLATE_INSTANTIATION (fn)) if (DECL_TEMPLATE_INSTANTIATION (fn))
{ {
if (TREE_USED (fn) if (DECL_ODR_USED (fn)
|| DECL_EXPLICIT_INSTANTIATION (fn)) || DECL_EXPLICIT_INSTANTIATION (fn))
{ {
error ("specialization of %qD after instantiation", error ("specialization of %qD after instantiation",
......
2009-08-21 Jason Merrill <jason@redhat.com>
* g++.dg/warn/Wunused-17.C: New.
2009-08-11 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com> 2009-08-11 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
* gcc.target/arm/combine-cmp-shift.c: New test. * gcc.target/arm/combine-cmp-shift.c: New test.
......
// PR c++/41109, 41110, 41134
// { dg-options "-Wunused" }
int memory_consumption(const int &t) { return sizeof(t); }
int s;
int g() { return memory_consumption(s); }
template <int> struct X { static const int s = 2; };
template <typename T> int f() {
const unsigned int dim = 2;
return X<dim>::s;
}
template int f<int>();
static int i;
template <typename> int h() { return i; }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment