-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.
&& 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
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. */
(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)
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);
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);
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)
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
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)
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
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"
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))
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
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);
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
+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
--- /dev/null
+// 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; }