aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/decl2.c50
-rw-r--r--gcc/cp/method.c2
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/warn/inline1.C23
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/crash64.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/synth10.C6
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/net31.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/p8786.C2
9 files changed, 73 insertions, 28 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 2291b73..08177c0 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 3d717e8..1607e37 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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);
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 12a66f6..e5a3bd9 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -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. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a68ab21..c54c1c2 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/g++.dg/warn/inline1.C b/gcc/testsuite/g++.dg/warn/inline1.C
new file mode 100644
index 0000000..24836e7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/inline1.C
@@ -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) {}
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash64.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash64.C
index ccba22e..6c28258 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/crash64.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash64.C
@@ -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 {
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/synth10.C b/gcc/testsuite/g++.old-deja/g++.jason/synth10.C
index d94e6bd..07a3725 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/synth10.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/synth10.C
@@ -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
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/net31.C b/gcc/testsuite/g++.old-deja/g++.mike/net31.C
index 3ecf81c..05617a8 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/net31.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/net31.C
@@ -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);
};
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p8786.C b/gcc/testsuite/g++.old-deja/g++.mike/p8786.C
index b5443c0..0565fb2 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/p8786.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/p8786.C
@@ -4,7 +4,7 @@
class B {
public:
- inline ~B();
+ ~B();
};
class D : public B {