Commit 15305a73 by Jason Merrill Committed by Jason Merrill

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
parent d3ece023
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. * decl2.c (finish_static_data_member_decl): Don't set TREE_USED.
......
...@@ -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 (decl)) if (!tree_used_ok (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,9 +1579,8 @@ struct GTY(()) lang_decl_base { ...@@ -1579,9 +1579,8 @@ 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 no_linkage_checked : 1; /* var or fn */
unsigned u2sel : 1; unsigned u2sel : 1;
/* 1 spare bit */ /* 2 spare bits */
}; };
/* True for DECL codes which have template info and access. */ /* True for DECL codes which have template info and access. */
...@@ -1983,14 +1982,6 @@ struct GTY(()) lang_decl { ...@@ -1983,14 +1982,6 @@ 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 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, /* 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)
...@@ -4486,6 +4477,7 @@ extern tree build_cleanup (tree); ...@@ -4486,6 +4477,7 @@ 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);
...@@ -4638,6 +4630,7 @@ extern void mark_decl_instantiated (tree, int); ...@@ -4638,6 +4630,7 @@ extern void mark_decl_instantiated (tree, int);
extern int more_specialized_fn (tree, tree, int); extern int more_specialized_fn (tree, tree, int);
extern void do_decl_instantiation (tree, tree); extern void do_decl_instantiation (tree, tree);
extern void do_type_instantiation (tree, tree, tsubst_flags_t); extern void do_type_instantiation (tree, tree, tsubst_flags_t);
extern bool always_instantiate_p (tree);
extern tree instantiate_decl (tree, int, bool); extern tree instantiate_decl (tree, int, bool);
extern int comp_template_parms (const_tree, const_tree); extern int comp_template_parms (const_tree, const_tree);
extern bool uses_parameter_packs (tree); extern bool uses_parameter_packs (tree);
......
...@@ -3845,20 +3845,24 @@ mark_used (tree decl) ...@@ -3845,20 +3845,24 @@ mark_used (tree decl)
decl = OVL_CURRENT (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 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 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 /* If within finish_function, defer the rest until that function
finishes, otherwise it might recurse. */ finishes, otherwise it might recurse. */
if (defer_mark_used_calls) if (defer_mark_used_calls)
...@@ -3892,6 +3896,10 @@ mark_used (tree decl) ...@@ -3892,6 +3896,10 @@ mark_used (tree decl)
if (processing_template_decl) if (processing_template_decl)
return; 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 /* 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
o the variable or function has extern "C" linkage (7.5 [dcl.link]), or o the variable or function has extern "C" linkage (7.5 [dcl.link]), or
...@@ -3900,10 +3908,8 @@ mark_used (tree decl) ...@@ -3900,10 +3908,8 @@ mark_used (tree decl)
if (TREE_PUBLIC (decl) if (TREE_PUBLIC (decl)
&& (TREE_CODE (decl) == FUNCTION_DECL && (TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == VAR_DECL) || TREE_CODE (decl) == VAR_DECL)
&& DECL_LANG_SPECIFIC (decl) && DECL_LANG_SPECIFIC (decl))
&& !DECL_NO_LINKAGE_CHECKED (decl))
{ {
DECL_NO_LINKAGE_CHECKED (decl) = true;
if (!DECL_EXTERN_C_P (decl) if (!DECL_EXTERN_C_P (decl)
&& !DECL_ARTIFICIAL (decl) && !DECL_ARTIFICIAL (decl)
&& !decl_defined_p (decl) && !decl_defined_p (decl)
...@@ -3949,15 +3955,7 @@ mark_used (tree decl) ...@@ -3949,15 +3955,7 @@ mark_used (tree decl)
else if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL) else if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL)
&& DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl) && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
&& (!DECL_EXPLICIT_INSTANTIATION (decl) && (!DECL_EXPLICIT_INSTANTIATION (decl)
|| (TREE_CODE (decl) == FUNCTION_DECL || always_instantiate_p (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))))
/* If this is a function or variable that is an instance of some /* 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 template, we now know that we will need to actually do the
instantiation. We check that DECL is not an explicit instantiation. We check that DECL is not an explicit
...@@ -3973,4 +3971,15 @@ mark_used (tree decl) ...@@ -3973,4 +3971,15 @@ 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 (member)); gcc_assert (!DECL_P (member) || tree_used_ok (member));
if (!COMPLETE_TYPE_P (complete_type (type)) if (!COMPLETE_TYPE_P (complete_type (type))
&& !TYPE_BEING_DEFINED (type)) && !TYPE_BEING_DEFINED (type))
......
...@@ -15635,6 +15635,27 @@ template_for_substitution (tree decl) ...@@ -15635,6 +15635,27 @@ template_for_substitution (tree decl)
return tmpl; 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 /* 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 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 instantiation now; we just have to do it sometime. Normally it is
...@@ -15688,6 +15709,15 @@ instantiate_decl (tree d, int defer_ok, ...@@ -15688,6 +15709,15 @@ instantiate_decl (tree d, int defer_ok,
the instantiation. */ the instantiation. */
return d; 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_tmpl = most_general_template (tmpl);
gen_args = DECL_TI_ARGS (d); gen_args = DECL_TI_ARGS (d);
...@@ -15781,26 +15811,6 @@ instantiate_decl (tree d, int defer_ok, ...@@ -15781,26 +15811,6 @@ instantiate_decl (tree d, int defer_ok,
pop_access_scope (d); 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 /* Defer all other templates, unless we have been explicitly
forbidden from doing so. */ forbidden from doing so. */
if (/* If there is no definition, we cannot instantiate the if (/* If there is no definition, we cannot instantiate the
......
2009-08-16 Jason Merrill <jason@redhat.com>
* g++.dg/debug/dwarf2/inline1.C: New.
2009-08-16 Richard Sandiford <rdsandiford@googlemail.com> 2009-08-16 Richard Sandiford <rdsandiford@googlemail.com>
PR target/38599 PR target/38599
......
// 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; }
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