Make TREE_USED match the [basic.def.odr] concept for FUNCTION_DECL and VAR_DECL...

Make TREE_USED match the [basic.def.odr] concept for FUNCTION_DECL
	and VAR_DECL, so mark_used only has effect the first time.
	* decl2.c (mark_used): Just return if TREE_USED is already set.
	Don't set TREE_USED if cp_unevaluated_operand is set.
	(tree_used_ok): New fn.
	* init.c (build_offset_ref): Check it instead of TREE_USED.
	* call.c (build_call_a): Likewise.
	* cp-tree.h: Declare it.
	(DECL_NO_LINKAGE_CHECKED): No longer needed.
	(struct lang_decl_base): Remove no_linkage_checked bitfield.

From-SVN: r150807
This commit is contained in:
Jason Merrill 2009-08-16 13:42:56 -04:00 committed by Jason Merrill
parent d3ece023f3
commit 15305a736f
8 changed files with 93 additions and 48 deletions

View File

@ -1,4 +1,15 @@
2009-08-15 Jason Merrill <jason@redhat.com>
2009-08-16 Jason Merrill <jason@redhat.com>
Make TREE_USED match the [basic.def.odr] concept for FUNCTION_DECL
and VAR_DECL, so mark_used only has effect the first time.
* decl2.c (mark_used): Just return if TREE_USED is already set.
Don't set TREE_USED if cp_unevaluated_operand is set.
(tree_used_ok): New fn.
* init.c (build_offset_ref): Check it instead of TREE_USED.
* call.c (build_call_a): Likewise.
* cp-tree.h: Declare it.
(DECL_NO_LINKAGE_CHECKED): No longer needed.
(struct lang_decl_base): Remove no_linkage_checked bitfield.
* decl2.c (finish_static_data_member_decl): Don't set TREE_USED.

View File

@ -318,7 +318,7 @@ build_call_a (tree function, int n, tree *argarray)
&& TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
{
decl = TREE_OPERAND (function, 0);
if (!TREE_USED (decl))
if (!tree_used_ok (decl))
{
/* We invoke build_call directly for several library
functions. These may have been declared normally if

View File

@ -1579,9 +1579,8 @@ struct GTY(()) lang_decl_base {
unsigned anticipated_p : 1; /* fn or type */
unsigned friend_attr : 1; /* fn or type */
unsigned template_conv_p : 1; /* template only? */
unsigned no_linkage_checked : 1; /* var or fn */
unsigned u2sel : 1;
/* 1 spare bit */
/* 2 spare bits */
};
/* True for DECL codes which have template info and access. */
@ -1983,14 +1982,6 @@ struct GTY(()) lang_decl {
(DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL)) \
->u.base.initialized_in_class)
/* Nonzero if we've checked whether DECL uses types without linkage in a
potentially invalid way.
??? Instead, should fix mark_used to only set TREE_USED when we're
really using something, and just return if it's already set. */
#define DECL_NO_LINKAGE_CHECKED(DECL) \
(DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL)) \
->u.base.no_linkage_checked)
/* 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. */
#define DECL_FRIEND_P(NODE) (DECL_LANG_SPECIFIC (NODE)->u.base.friend_attr)
@ -4486,6 +4477,7 @@ extern tree build_cleanup (tree);
extern tree build_offset_ref_call_from_tree (tree, VEC(tree,gc) **);
extern void check_default_args (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 tree cp_build_parm_decl (tree, tree);
extern tree get_guard (tree);
@ -4638,6 +4630,7 @@ extern void mark_decl_instantiated (tree, int);
extern int more_specialized_fn (tree, tree, int);
extern void do_decl_instantiation (tree, tree);
extern void do_type_instantiation (tree, tree, tsubst_flags_t);
extern bool always_instantiate_p (tree);
extern tree instantiate_decl (tree, int, bool);
extern int comp_template_parms (const_tree, const_tree);
extern bool uses_parameter_packs (tree);

View File

@ -3845,20 +3845,24 @@ mark_used (tree decl)
decl = OVL_CURRENT (decl);
}
TREE_USED (decl) = 1;
if (DECL_CLONED_FUNCTION_P (decl))
TREE_USED (DECL_CLONED_FUNCTION (decl)) = 1;
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DELETED_FN (decl))
{
error ("deleted function %q+D", decl);
error ("used here");
TREE_USED (decl) = 1;
return;
}
/* If we don't need a value, then we don't need to synthesize DECL. */
if (cp_unevaluated_operand != 0)
return;
/* 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
we get them compiled before functions that want to inline them. */
if (TREE_USED (decl))
return;
/* If within finish_function, defer the rest until that function
finishes, otherwise it might recurse. */
if (defer_mark_used_calls)
@ -3892,6 +3896,10 @@ mark_used (tree decl)
if (processing_template_decl)
return;
TREE_USED (decl) = 1;
if (DECL_CLONED_FUNCTION_P (decl))
TREE_USED (DECL_CLONED_FUNCTION (decl)) = 1;
/* DR 757: A type without linkage shall not be used as the type of a
variable or function with linkage, unless
o the variable or function has extern "C" linkage (7.5 [dcl.link]), or
@ -3900,10 +3908,8 @@ mark_used (tree decl)
if (TREE_PUBLIC (decl)
&& (TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == VAR_DECL)
&& DECL_LANG_SPECIFIC (decl)
&& !DECL_NO_LINKAGE_CHECKED (decl))
&& DECL_LANG_SPECIFIC (decl))
{
DECL_NO_LINKAGE_CHECKED (decl) = true;
if (!DECL_EXTERN_C_P (decl)
&& !DECL_ARTIFICIAL (decl)
&& !decl_defined_p (decl)
@ -3949,15 +3955,7 @@ mark_used (tree decl)
else if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL)
&& DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
&& (!DECL_EXPLICIT_INSTANTIATION (decl)
|| (TREE_CODE (decl) == FUNCTION_DECL
&& possibly_inlined_p
(DECL_TEMPLATE_RESULT (
template_for_substitution (decl))))
/* We need to instantiate static data members so that there
initializers are available in integral constant
expressions. */
|| (TREE_CODE (decl) == VAR_DECL
&& DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))))
|| always_instantiate_p (decl)))
/* If this is a function or variable that is an instance of some
template, we now know that we will need to actually do the
instantiation. We check that DECL is not an explicit
@ -3973,4 +3971,15 @@ mark_used (tree 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"

View File

@ -1502,7 +1502,7 @@ build_offset_ref (tree type, tree member, bool address_p)
gcc_assert (DECL_P (member) || BASELINK_P (member));
/* Callers should call mark_used before this point. */
gcc_assert (!DECL_P (member) || TREE_USED (member));
gcc_assert (!DECL_P (member) || tree_used_ok (member));
if (!COMPLETE_TYPE_P (complete_type (type))
&& !TYPE_BEING_DEFINED (type))

View File

@ -15635,6 +15635,27 @@ template_for_substitution (tree decl)
return tmpl;
}
/* Returns true if we need to instantiate this template instance even if we
know we aren't going to emit it.. */
bool
always_instantiate_p (tree decl)
{
/* We always instantiate inline functions so that we can inline them. An
explicit instantiation declaration prohibits implicit instantiation of
non-inline functions. With high levels of optimization, we would
normally inline non-inline functions -- but we're not allowed to do
that for "extern template" functions. Therefore, we check
DECL_DECLARED_INLINE_P, rather than possibly_inlined_p. */
return ((TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl))
/* And we need to instantiate static data members so that
their initializers are available in integral constant
expressions. */
|| (TREE_CODE (decl) == VAR_DECL
&& DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)));
}
/* Produce the definition of D, a _DECL generated from a template. If
DEFER_OK is nonzero, then we don't have to actually do the
instantiation now; we just have to do it sometime. Normally it is
@ -15688,6 +15709,15 @@ instantiate_decl (tree d, int defer_ok,
the instantiation. */
return d;
/* Check to see whether we know that this template will be
instantiated in some other file, as with "extern template"
extension. */
external_p = (DECL_INTERFACE_KNOWN (d) && DECL_REALLY_EXTERN (d));
/* In general, we do not instantiate such templates. */
if (external_p && !always_instantiate_p (d))
return d;
gen_tmpl = most_general_template (tmpl);
gen_args = DECL_TI_ARGS (d);
@ -15781,26 +15811,6 @@ instantiate_decl (tree d, int defer_ok,
pop_access_scope (d);
}
/* Check to see whether we know that this template will be
instantiated in some other file, as with "extern template"
extension. */
external_p = (DECL_INTERFACE_KNOWN (d) && DECL_REALLY_EXTERN (d));
/* In general, we do not instantiate such templates... */
if (external_p
/* ... but we instantiate inline functions so that we can inline
them. An explicit instantiation declaration prohibits implicit
instantiation of non-inline functions. With high levels of
optimization, we would normally inline non-inline functions
-- but we're not allowed to do that for "extern template" functions.
Therefore, we check DECL_DECLARED_INLINE_P, rather than
possibly_inlined_p. And ... */
&& ! (TREE_CODE (d) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (d))
/* ... we instantiate static data members whose values are
needed in integral constant expressions. */
&& ! (TREE_CODE (d) == VAR_DECL
&& DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (d)))
goto out;
/* Defer all other templates, unless we have been explicitly
forbidden from doing so. */
if (/* If there is no definition, we cannot instantiate the

View File

@ -1,3 +1,7 @@
2009-08-16 Jason Merrill <jason@redhat.com>
* g++.dg/debug/dwarf2/inline1.C: New.
2009-08-16 Richard Sandiford <rdsandiford@googlemail.com>
PR target/38599

View File

@ -0,0 +1,18 @@
// This isn't really testing dwarf output, but rather that we can inline f
// even though the call precedes the definition.
// { dg-options "-gdwarf-2 -dA -O" }
// { dg-final { scan-assembler "DW_TAG_inlined_subroutine" } }
template <class T>
inline T f(T);
int main()
{
f(1);
}
int i;
template <class T>
inline T f(T t) { ++i; return t; }