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:
parent
d3ece023f3
commit
15305a736f
8 changed files with 93 additions and 48 deletions
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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))
|
||||
|
|
50
gcc/cp/pt.c
50
gcc/cp/pt.c
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
18
gcc/testsuite/g++.dg/debug/dwarf2/inline1.C
Normal file
18
gcc/testsuite/g++.dg/debug/dwarf2/inline1.C
Normal 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; }
|
Loading…
Add table
Reference in a new issue