Commit d58b7c2d by Mark Mitchell Committed by Mark Mitchell

re PR c++/11131 (Unrelated declaration removes inline flag from function)

	PR c++/11131
	* tree-inline.c (inlinable_function_p): Call the language-specific
	hook early.

	PR c++/11131
	* cp-tree.h (template_for_substitution): Declare.
	* decl2.c (mark_used): Use it when figuring out whether or not a
	function is inline.
	* pt.c (template_for_substitution): Give it external linkage.
	* tree.c (cp_cannot_inline_tree_fn): Instantiate as early as
	possible.

	PR c++/11131
	* g++.dg/opt/template1.C: New test.

From-SVN: r67698
parent c566f9bd
2003-06-10 Mark Mitchell <mark@codesourcery.com>
PR c++/11131
* tree-inline.c (inlinable_function_p): Call the language-specific
hook early.
2003-06-09 David Taylor <dtaylor@emc.com> 2003-06-09 David Taylor <dtaylor@emc.com>
* config/rs6000/rs6000.c (rs6000_va_start, rs6000_va_arg): Skip over * config/rs6000/rs6000.c (rs6000_va_start, rs6000_va_arg): Skip over
......
2003-06-10 Mark Mitchell <mark@codesourcery.com>
PR c++/11131
* cp-tree.h (template_for_substitution): Declare.
* decl2.c (mark_used): Use it when figuring out whether or not a
function is inline.
* pt.c (template_for_substitution): Give it external linkage.
* tree.c (cp_cannot_inline_tree_fn): Instantiate as early as
possible.
2003-06-09 Zack Weinberg <zack@codesourcery.com> 2003-06-09 Zack Weinberg <zack@codesourcery.com>
PR 8861 PR 8861
......
...@@ -3978,6 +3978,7 @@ extern bool type_dependent_expression_p (tree); ...@@ -3978,6 +3978,7 @@ extern bool type_dependent_expression_p (tree);
extern bool value_dependent_expression_p (tree); extern bool value_dependent_expression_p (tree);
extern tree resolve_typename_type (tree, bool); extern tree resolve_typename_type (tree, bool);
extern tree resolve_typename_type_in_current_instantiation (tree); extern tree resolve_typename_type_in_current_instantiation (tree);
extern tree template_for_substitution (tree);
/* in repo.c */ /* in repo.c */
extern void repo_template_used (tree); extern void repo_template_used (tree);
......
...@@ -4590,7 +4590,9 @@ mark_used (tree decl) ...@@ -4590,7 +4590,9 @@ mark_used (tree decl)
if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL) 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 && DECL_INLINE (decl)))) || (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_INLINE (DECL_TEMPLATE_RESULT
(template_for_substitution (decl))))))
{ {
bool defer; bool defer;
......
...@@ -171,7 +171,6 @@ static tree copy_default_args_to_explicit_spec_1 PARAMS ((tree, tree)); ...@@ -171,7 +171,6 @@ static tree copy_default_args_to_explicit_spec_1 PARAMS ((tree, tree));
static void copy_default_args_to_explicit_spec PARAMS ((tree)); static void copy_default_args_to_explicit_spec PARAMS ((tree));
static int invalid_nontype_parm_type_p PARAMS ((tree, tsubst_flags_t)); static int invalid_nontype_parm_type_p PARAMS ((tree, tsubst_flags_t));
static int eq_local_specializations (const void *, const void *); static int eq_local_specializations (const void *, const void *);
static tree template_for_substitution (tree);
static bool dependent_type_p_r (tree); static bool dependent_type_p_r (tree);
static bool dependent_template_id_p (tree, tree); static bool dependent_template_id_p (tree, tree);
static tree tsubst (tree, tree, tsubst_flags_t, tree); static tree tsubst (tree, tree, tsubst_flags_t, tree);
...@@ -10736,7 +10735,7 @@ regenerate_decl_from_template (decl, tmpl) ...@@ -10736,7 +10735,7 @@ regenerate_decl_from_template (decl, tmpl)
/* Return the TEMPLATE_DECL into which DECL_TI_ARGS(DECL) should be /* Return the TEMPLATE_DECL into which DECL_TI_ARGS(DECL) should be
substituted to get DECL. */ substituted to get DECL. */
static tree tree
template_for_substitution (tree decl) template_for_substitution (tree decl)
{ {
tree tmpl = DECL_TI_TEMPLATE (decl); tree tmpl = DECL_TI_TEMPLATE (decl);
......
...@@ -2204,10 +2204,6 @@ cp_cannot_inline_tree_fn (fnp) ...@@ -2204,10 +2204,6 @@ cp_cannot_inline_tree_fn (fnp)
{ {
tree fn = *fnp; tree fn = *fnp;
if (flag_really_no_inline
&& lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL)
return 1;
/* We can inline a template instantiation only if it's fully /* We can inline a template instantiation only if it's fully
instantiated. */ instantiated. */
if (DECL_TEMPLATE_INFO (fn) if (DECL_TEMPLATE_INFO (fn)
...@@ -2218,6 +2214,13 @@ cp_cannot_inline_tree_fn (fnp) ...@@ -2218,6 +2214,13 @@ cp_cannot_inline_tree_fn (fnp)
return 1; return 1;
} }
if (!DECL_INLINE (fn))
return 1;
if (flag_really_no_inline
&& lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL)
return 1;
/* Don't auto-inline anything that might not be bound within /* Don't auto-inline anything that might not be bound within
this unit of translation. */ this unit of translation. */
if (!DECL_DECLARED_INLINE_P (fn) && !(*targetm.binds_local_p) (fn)) if (!DECL_DECLARED_INLINE_P (fn) && !(*targetm.binds_local_p) (fn))
......
2003-06-10 Mark Mitchell <mark@codesourcery.com>
PR c++/11131
* g++.dg/opt/template1.C: New test.
2003-06-09 Mark Mitchell <mark@codesourcery.com> 2003-06-09 Mark Mitchell <mark@codesourcery.com>
* lib/gcc-dg.exp (dg-test): Clear additional_files and * lib/gcc-dg.exp (dg-test): Clear additional_files and
......
// { dg-options "-O2" }
// { dg-final { scan-assembler-not "foo1" } }
template <int>
struct A {
void foo1 () throw ();
void foo2 ();
void UNRELATED ();
};
template <> void A<0>::UNRELATED ();
template <int dim> inline void A<dim>::foo1 () throw () {}
template <int dim> inline void A<dim>::foo2 () {}
void bar (A<0> &a) {
a.foo1 ();
}
...@@ -979,8 +979,10 @@ inlinable_function_p (fn, id, nolimit) ...@@ -979,8 +979,10 @@ inlinable_function_p (fn, id, nolimit)
if (DECL_UNINLINABLE (fn)) if (DECL_UNINLINABLE (fn))
return 0; return 0;
/* Assume it is not inlinable. */ /* See if there is any language-specific reason it cannot be
inlinable = 0; inlined. (It is important that this hook be called early because
in C++ it may result in template instantiation.) */
inlinable = !(*lang_hooks.tree_inlining.cannot_inline_tree_fn) (&fn);
/* We may be here either because fn is declared inline or because /* We may be here either because fn is declared inline or because
we use -finline-functions. For the second case, we are more we use -finline-functions. For the second case, we are more
...@@ -993,7 +995,7 @@ inlinable_function_p (fn, id, nolimit) ...@@ -993,7 +995,7 @@ inlinable_function_p (fn, id, nolimit)
/* If we're not inlining things, then nothing is inlinable. */ /* If we're not inlining things, then nothing is inlinable. */
if (! flag_inline_trees) if (! flag_inline_trees)
; inlinable = 0;
/* If we're not inlining all functions and the function was not /* If we're not inlining all functions and the function was not
declared `inline', we don't inline it. Don't think of declared `inline', we don't inline it. Don't think of
disregarding DECL_INLINE when flag_inline_trees == 2; it's the disregarding DECL_INLINE when flag_inline_trees == 2; it's the
...@@ -1001,11 +1003,11 @@ inlinable_function_p (fn, id, nolimit) ...@@ -1001,11 +1003,11 @@ inlinable_function_p (fn, id, nolimit)
dwarf2out loses if a function is inlined that doesn't have dwarf2out loses if a function is inlined that doesn't have
DECL_INLINE set. */ DECL_INLINE set. */
else if (! DECL_INLINE (fn) && !nolimit) else if (! DECL_INLINE (fn) && !nolimit)
; inlinable = 0;
#ifdef INLINER_FOR_JAVA #ifdef INLINER_FOR_JAVA
/* Synchronized methods can't be inlined. This is a bug. */ /* Synchronized methods can't be inlined. This is a bug. */
else if (METHOD_SYNCHRONIZED (fn)) else if (METHOD_SYNCHRONIZED (fn))
; inlinable = 0;
#endif /* INLINER_FOR_JAVA */ #endif /* INLINER_FOR_JAVA */
/* We can't inline functions that are too big. Only allow a single /* We can't inline functions that are too big. Only allow a single
function to be of MAX_INLINE_INSNS_SINGLE size. Make special function to be of MAX_INLINE_INSNS_SINGLE size. Make special
...@@ -1013,7 +1015,7 @@ inlinable_function_p (fn, id, nolimit) ...@@ -1013,7 +1015,7 @@ inlinable_function_p (fn, id, nolimit)
else if (!nolimit else if (!nolimit
&& ! (*lang_hooks.tree_inlining.disregard_inline_limits) (fn) && ! (*lang_hooks.tree_inlining.disregard_inline_limits) (fn)
&& currfn_insns > max_inline_insns_single) && currfn_insns > max_inline_insns_single)
; inlinable = 0;
/* We can't inline functions that call __builtin_longjmp at all. /* We can't inline functions that call __builtin_longjmp at all.
The non-local goto machenery really requires the destination The non-local goto machenery really requires the destination
be in a different function. If we allow the function calling be in a different function. If we allow the function calling
...@@ -1021,20 +1023,14 @@ inlinable_function_p (fn, id, nolimit) ...@@ -1021,20 +1023,14 @@ inlinable_function_p (fn, id, nolimit)
__builtin_setjmp, Things will Go Awry. */ __builtin_setjmp, Things will Go Awry. */
/* ??? Need front end help to identify "regular" non-local goto. */ /* ??? Need front end help to identify "regular" non-local goto. */
else if (find_builtin_longjmp_call (DECL_SAVED_TREE (fn))) else if (find_builtin_longjmp_call (DECL_SAVED_TREE (fn)))
; inlinable = 0;
/* Refuse to inline alloca call unless user explicitly forced so as this may /* Refuse to inline alloca call unless user explicitly forced so as this may
change program's memory overhead drastically when the function using alloca change program's memory overhead drastically when the function using alloca
is called in loop. In GCC present in SPEC2000 inlining into schedule_block is called in loop. In GCC present in SPEC2000 inlining into schedule_block
cause it to require 2GB of ram instead of 256MB. */ cause it to require 2GB of ram instead of 256MB. */
else if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL else if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL
&& find_alloca_call (DECL_SAVED_TREE (fn))) && find_alloca_call (DECL_SAVED_TREE (fn)))
; inlinable = 0;
/* All is well. We can inline this function. Traditionally, GCC
has refused to inline functions using alloca, or functions whose
values are returned in a PARALLEL, and a few other such obscure
conditions. We are not equally constrained at the tree level. */
else
inlinable = 1;
/* Squirrel away the result so that we don't have to check again. */ /* Squirrel away the result so that we don't have to check again. */
DECL_UNINLINABLE (fn) = ! inlinable; DECL_UNINLINABLE (fn) = ! inlinable;
...@@ -1065,9 +1061,6 @@ inlinable_function_p (fn, id, nolimit) ...@@ -1065,9 +1061,6 @@ inlinable_function_p (fn, id, nolimit)
} }
} }
if (inlinable && (*lang_hooks.tree_inlining.cannot_inline_tree_fn) (&fn))
inlinable = 0;
/* If we don't have the function body available, we can't inline /* If we don't have the function body available, we can't inline
it. */ it. */
if (! DECL_SAVED_TREE (fn)) if (! DECL_SAVED_TREE (fn))
......
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