summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2009-08-16 17:42:56 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2009-08-16 17:42:56 +0000
commit67702eb899864e03a05b9cf0f0ef542533900d7c (patch)
tree9014dfecbe0670edc4ce4c440e01edcb80786afd /gcc
parentd6ab15112852d95d7cb9fe2d54c7fc39b03a44e0 (diff)
downloadgcc-67702eb899864e03a05b9cf0f0ef542533900d7c.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@150807 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog13
-rw-r--r--gcc/cp/call.c2
-rw-r--r--gcc/cp/cp-tree.h13
-rw-r--r--gcc/cp/decl2.c39
-rw-r--r--gcc/cp/init.c2
-rw-r--r--gcc/cp/pt.c50
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/inline1.C18
8 files changed, 93 insertions, 48 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9a694d922fa..b98842ee34d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index f6a083bd677..30a1b45a1ed 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index ae39110588b..bbd1a42f559 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index f78508b99c3..e4ed9632b2d 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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"
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index ef18a6c1041..9dac7de400e 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 36f1b00fa6b..eb43271e850 100644
--- a/gcc/cp/pt.c
+++ b/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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index acbc928700c..83eda2ffac2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/inline1.C b/gcc/testsuite/g++.dg/debug/dwarf2/inline1.C
new file mode 100644
index 00000000000..ea405f85339
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/inline1.C
@@ -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; }