re PR c++/4803 (Inline function never defined)

cp:
	PR c++/4803
	* decl2.c (mark_used): Defer inline functions.
	(finish_file): Merge deferred_fns loops. Check all used
	inline functions have a definition.
	* method.c (make_thunk): Thunks are not inline.
testsuite:
	* g++.dg/warn/inline1.C: New test.
	* g++.old-deja/g++.brendan/crash64.C: Remove spurious inlines.
	* g++.old-deja/g++.jason/synth10.C: Likewise.
	* g++.old-deja/g++.mike/net31.C: Likewise.
	* g++.old-deja/g++.mike/p8786.C: Likewise.

From-SVN: r60521
This commit is contained in:
Nathan Sidwell 2002-12-26 18:20:14 +00:00 committed by Nathan Sidwell
parent ecd4a73b20
commit eab5474f6d
9 changed files with 73 additions and 28 deletions

View File

@ -1,5 +1,11 @@
2002-12-26 Nathan Sidwell <nathan@codesourcery.com>
PR c++/4803
* decl2.c (mark_used): Defer inline functions.
(finish_file): Merge deferred_fns loops. Check all used
inline functions have a definition.
* method.c (make_thunk): Thunks are not inline.
PR c++/5116, c++/764
* call.c (build_new_op): Make sure template class operands are
instantiated.

View File

@ -2791,12 +2791,13 @@ finish_file ()
reconsider = 1;
}
/* Go through the various inline functions, and see if any need
synthesizing. */
for (i = 0; i < deferred_fns_used; ++i)
{
tree decl = VARRAY_TREE (deferred_fns, i);
import_export_decl (decl);
/* Does it need synthesizing? */
if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
&& TREE_USED (decl)
&& (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl)))
@ -2811,30 +2812,21 @@ finish_file ()
pop_from_top_level ();
reconsider = 1;
}
}
/* We lie to the back-end, pretending that some functions are
not defined when they really are. This keeps these functions
from being put out unnecessarily. But, we must stop lying
when the functions are referenced, or if they are not comdat
since they need to be put out now.
This is done in a separate for cycle, because if some deferred
function is contained in another deferred function later in
deferred_fns varray, rest_of_compilation would skip this
function and we really cannot expand the same function twice. */
for (i = 0; i < deferred_fns_used; ++i)
{
tree decl = VARRAY_TREE (deferred_fns, i);
/* We lie to the back-end, pretending that some functions
are not defined when they really are. This keeps these
functions from being put out unnecessarily. But, we must
stop lying when the functions are referenced, or if they
are not comdat since they need to be put out now. This
is done in a separate for cycle, because if some deferred
function is contained in another deferred function later
in deferred_fns varray, rest_of_compilation would skip
this function and we really cannot expand the same
function twice. */
if (DECL_NOT_REALLY_EXTERN (decl)
&& DECL_INITIAL (decl)
&& DECL_NEEDED_P (decl))
DECL_EXTERNAL (decl) = 0;
}
for (i = 0; i < deferred_fns_used; ++i)
{
tree decl = VARRAY_TREE (deferred_fns, i);
/* If we're going to need to write this function out, and
there's already a body for it, create RTL for it now.
@ -2890,6 +2882,16 @@ finish_file ()
}
while (reconsider);
/* All used inline functions must have a definition at this point. */
for (i = 0; i < deferred_fns_used; ++i)
{
tree decl = VARRAY_TREE (deferred_fns, i);
if (TREE_USED (decl) && DECL_DECLARED_INLINE_P (decl)
&& !(TREE_ASM_WRITTEN (decl) || DECL_SAVED_TREE (decl)))
cp_warning_at ("inline function `%D' used but never defined", decl);
}
/* We give C linkage to static constructors and destructors. */
push_lang_context (lang_name_c);
@ -4665,6 +4667,12 @@ mark_used (decl)
TREE_USED (decl) = 1;
if (processing_template_decl)
return;
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
&& !TREE_ASM_WRITTEN (decl))
/* Remember it, so we can check it was defined. */
defer_fn (decl);
if (!skip_evaluation)
assemble_external (decl);

View File

@ -344,6 +344,8 @@ make_thunk (tree function, bool this_adjusting,
DECL_NO_STATIC_CHAIN (thunk) = 1;
/* The THUNK is not a pending inline, even if the FUNCTION is. */
DECL_PENDING_INLINE_P (thunk) = 0;
DECL_INLINE (thunk) = 0;
DECL_DECLARED_INLINE_P (thunk) = 0;
/* Nor has it been deferred. */
DECL_DEFERRED_FN (thunk) = 0;
/* Add it to the list of thunks associated with FUNCTION. */

View File

@ -1,5 +1,11 @@
2002-12-26 Nathan Sidwell <nathan@codesourcery.com>
* g++.dg/warn/inline1.C: New test.
* g++.old-deja/g++.brendan/crash64.C: Remove spurious inlines.
* g++.old-deja/g++.jason/synth10.C: Likewise.
* g++.old-deja/g++.mike/net31.C: Likewise.
* g++.old-deja/g++.mike/p8786.C: Likewise.
* g++.dg/template/friend10.C: New test.
* g++.dg/template/conv5.C: New test.

View File

@ -0,0 +1,23 @@
// { dg-do compile }
// Copyright (C) 2002 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 26 Dec 2002 <nathan@codesourcery.com>
// PR 4803. Used inline functions must have a definition.
inline void Foo1 (); // { dg-warning "inline function" "" }
inline void Bar1 ();
template <typename T> inline void Foo2(T); // { dg-warning "inline function" "" }
template <typename T> inline void Bar2(T);
void Baz ()
{
Foo1 ();
Foo2 (1);
Bar1 ();
Bar2 (1);
}
inline void Bar1 () {}
template <typename T> inline void Bar2(T) {}

View File

@ -4,8 +4,8 @@ typedef long unsigned int size_t;
typedef void (*RF_Ptr)(void *);
struct _im_pers_mem_spec {
inline _im_pers_mem_spec(void );
inline _im_pers_mem_spec(auto int of, auto int n);
_im_pers_mem_spec(void );
_im_pers_mem_spec(auto int of, auto int n);
};
struct _type_desc {

View File

@ -7,14 +7,14 @@ class A;
class AH
{
public:
inline AH ( A * p = 0 );
AH ( A * p = 0 );
AH ( const AH & from )
: pointer( from.pointer ) { inc(); }
~ AH () { dec(); }
private:
A * pointer;
inline void inc() const;
inline void dec() const;
void inc() const;
void dec() const;
};
class A

View File

@ -13,7 +13,7 @@ class foo_b {
foo_b();
~foo_b();
foo_b(const foo_b&);
inline double& operator()(int);
double& operator()(int);
foo_b& operator=(foo_b&);
void bar_a(int);
};

View File

@ -4,7 +4,7 @@
class B {
public:
inline ~B();
~B();
};
class D : public B {