aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2004-08-31 20:29:28 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2004-08-31 20:29:28 +0000
commitaf287697443400b33dbfd2297bdcf63121e7bc86 (patch)
treeee8a8ed7c7cd3d552d036001e3c45b585e180905
parent678584fc80fc69fbd3c4f5f15d484ed6006f41be (diff)
downloadgcc-af287697443400b33dbfd2297bdcf63121e7bc86.zip
gcc-af287697443400b33dbfd2297bdcf63121e7bc86.tar.gz
gcc-af287697443400b33dbfd2297bdcf63121e7bc86.tar.bz2
hooks.c (hook_bool_void_true): New function.
* hooks.c (hook_bool_void_true): New function. * hooks.h (hook_bool_void_true): Declare. * target-def.h (TARGET_CXX): Add TARGET_CXX_KEY_METHOD_MAY_BE_INLINE. * target.h (struct cxx): Add key_method_may_be_inline. * config/arm/arm.c (arm_cxx_key_method_may_be_inline): New function. (TARGET_CXX_KEY_METHOD_MAY_BE_INLINE): New macro. * config/arm/bpabi.h: Use __THUMB_INTERWORK__ instead of __THUMB_INTERWORK. * class.c (key_method): Rename to ... (determine_key_method): ... this. (finish_struct_1): Adjust accordingly. * cp-tree.h (key_method): Declare. * decl2.c (maybe_emit_vtables): Determine the key method here if it has not already been done. * g++.dg/abi/key1.C: New test. From-SVN: r86843
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/class.c32
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl2.c6
-rw-r--r--gcc/doc/tm.texi10
-rw-r--r--gcc/hooks.c9
-rw-r--r--gcc/hooks.h1
-rw-r--r--gcc/target-def.h7
-rw-r--r--gcc/target.h5
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/abi/key1.C26
12 files changed, 113 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 26916e8..af60798 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2004-08-31 Mark Mitchell <mark@codesourcery.com>
+
+ * hooks.c (hook_bool_void_true): New function.
+ * hooks.h (hook_bool_void_true): Declare.
+ * target-def.h (TARGET_CXX): Add
+ TARGET_CXX_KEY_METHOD_MAY_BE_INLINE.
+ * target.h (struct cxx): Add key_method_may_be_inline.
+ * config/arm/arm.c (arm_cxx_key_method_may_be_inline): New
+ function.
+ (TARGET_CXX_KEY_METHOD_MAY_BE_INLINE): New macro.
+ * config/arm/bpabi.h: Use __THUMB_INTERWORK__ instead of
+ __THUMB_INTERWORK.
+
2004-08-31 Denis Chertykov <denisc@overta.ru>
PR target/15417
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b942b82..0a0fdfd 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2004-08-31 Mark Mitchell <mark@codesourcery.com>
+
+ * class.c (key_method): Rename to ...
+ (determine_key_method): ... this.
+ (finish_struct_1): Adjust accordingly.
+ * cp-tree.h (key_method): Declare.
+ * decl2.c (maybe_emit_vtables): Determine the key method here if
+ it has not already been done.
+
2004-08-31 Ziemowit Laski <zlaski@apple.com>
* Make-lang.in (CXX_AND_OBJCXX_OBJS): Add cp/cp-objcp-common.o.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 21bdfdd..84c7587 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4886,11 +4886,11 @@ layout_class_type (tree t, tree *virtuals_p)
splay_tree_delete (empty_base_offsets);
}
-/* Returns the virtual function with which the vtable for TYPE is
- emitted, or NULL_TREE if that heuristic is not applicable to TYPE. */
+/* Determine the "key method" for the class type indicated by TYPE,
+ and set CLASSTYPE_KEY_METHOD accordingly. */
-static tree
-key_method (tree type)
+void
+determine_key_method (tree type)
{
tree method;
@@ -4898,16 +4898,23 @@ key_method (tree type)
|| processing_template_decl
|| CLASSTYPE_TEMPLATE_INSTANTIATION (type)
|| CLASSTYPE_INTERFACE_KNOWN (type))
- return NULL_TREE;
+ return;
+ /* The key method is the first non-pure virtual function that is not
+ inline at the point of class definition. On some targets the
+ key function may not be inline; those targets should not call
+ this function until the end of the translation unit. */
for (method = TYPE_METHODS (type); method != NULL_TREE;
method = TREE_CHAIN (method))
if (DECL_VINDEX (method) != NULL_TREE
&& ! DECL_DECLARED_INLINE_P (method)
&& ! DECL_PURE_VIRTUAL_P (method))
- return method;
+ {
+ CLASSTYPE_KEY_METHOD (type) = method;
+ break;
+ }
- return NULL_TREE;
+ return;
}
/* Perform processing required when the definition of T (a class type)
@@ -4950,7 +4957,16 @@ finish_struct_1 (tree t)
/* Find the key method. */
if (TYPE_CONTAINS_VPTR_P (t))
{
- CLASSTYPE_KEY_METHOD (t) = key_method (t);
+ /* The Itanium C++ ABI permits the key method to be chosen when
+ the class is defined -- even though the key method so
+ selected may later turn out to be an inline function. On
+ some systems (such as ARM Symbian OS) the key method cannot
+ be determined until the end of the translation unit. On such
+ systems, we leave CLASSTYPE_KEY_METHOD set to NULL, which
+ will cause the class to be added to KEYED_CLASSES. Then, in
+ finish_file we will determine the key method. */
+ if (targetm.cxx.key_method_may_be_inline ())
+ determine_key_method (t);
/* If a polymorphic class has no key method, we may emit the vtable
in every translation unit where the class definition appears. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8267f72..a6db553 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3673,6 +3673,7 @@ extern void debug_class (tree);
extern void debug_thunks (tree);
extern tree cp_fold_obj_type_ref (tree, tree);
extern void set_linkage_according_to_type (tree, tree);
+extern void determine_key_method (tree);
/* in cvt.c */
extern tree convert_to_reference (tree, tree, int, int, tree);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 33a9ef5..d02180a 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1559,6 +1559,12 @@ maybe_emit_vtables (tree ctype)
if (TREE_TYPE (primary_vtbl) == void_type_node)
return false;
+ /* On some targets, we cannot determine the key method until the end
+ of the translation unit -- which is when this function is
+ called. */
+ if (!targetm.cxx.key_method_may_be_inline ())
+ determine_key_method (ctype);
+
/* See if any of the vtables are needed. */
for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
{
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 2a87398..d1e59cf 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -8528,6 +8528,16 @@ the address of the object created/destroyed. The default is to return
@code{false}.
@end deftypefn
+@deftypefn {Target Hook} bool TARGET_CXX_KEY_METHOD_MAY_BE_INLINE (void)
+This hook returns true if the key method for a class (i.e., the method
+which, if defined in the current translation unit, causes the virtual
+table to be emitted) may be an inline function. Under the standard
+Itanium C++ ABI the key method may be an inline function so long as
+the function is not declared inline in the class definition. Under
+some variants of the ABI, an inline function can never be the key
+method. The default is to return @code{true}.
+@end deftypefn
+
@node Misc
@section Miscellaneous Parameters
@cindex parameters, miscellaneous
diff --git a/gcc/hooks.c b/gcc/hooks.c
index 077f9bf..6c17a5f 100644
--- a/gcc/hooks.c
+++ b/gcc/hooks.c
@@ -41,7 +41,14 @@ hook_bool_void_false (void)
return false;
}
-/* The same, but formally returning NO_REGS. */
+/* Generic hook that takes no arguments and returns true. */
+bool
+hook_bool_void_true (void)
+{
+ return true;
+}
+
+/* Generic hook that takes no arguments and returns NO_REGS. */
int
hook_int_void_no_regs (void)
{
diff --git a/gcc/hooks.h b/gcc/hooks.h
index a611ba1..8eef06f 100644
--- a/gcc/hooks.h
+++ b/gcc/hooks.h
@@ -25,6 +25,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "machmode.h"
extern bool hook_bool_void_false (void);
+extern bool hook_bool_void_true (void);
extern bool hook_bool_bool_false (bool);
extern bool hook_bool_mode_false (enum machine_mode);
extern bool hook_bool_tree_false (tree);
diff --git a/gcc/target-def.h b/gcc/target-def.h
index 156ebef..e49d055 100644
--- a/gcc/target-def.h
+++ b/gcc/target-def.h
@@ -437,6 +437,10 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define TARGET_CXX_CDTOR_RETURNS_THIS hook_bool_void_false
#endif
+#ifndef TARGET_CXX_KEY_METHOD_MAY_BE_INLINE
+#define TARGET_CXX_KEY_METHOD_MAY_BE_INLINE hook_bool_void_true
+#endif
+
#define TARGET_CXX \
{ \
TARGET_CXX_GUARD_TYPE, \
@@ -444,7 +448,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
TARGET_CXX_GET_COOKIE_SIZE, \
TARGET_CXX_COOKIE_HAS_SIZE, \
TARGET_CXX_IMPORT_EXPORT_CLASS, \
- TARGET_CXX_CDTOR_RETURNS_THIS \
+ TARGET_CXX_CDTOR_RETURNS_THIS, \
+ TARGET_CXX_KEY_METHOD_MAY_BE_INLINE \
}
/* The whole shebang. */
diff --git a/gcc/target.h b/gcc/target.h
index 27e4086..57b38cf 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -516,6 +516,11 @@ struct gcc_target
int (*import_export_class) (tree, int);
/* Returns true if constructors and destructors return "this". */
bool (*cdtor_returns_this) (void);
+ /* Returns true if the key method for a class can be an inline
+ function, so long as it is not declared inline in the class
+ itself. Returning true is the behavior required by the Itanium
+ C++ ABI. */
+ bool (*key_method_may_be_inline) (void);
} cxx;
/* Leave the boolean fields at the end. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e7a17d3..5e8be36 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2004-08-31 Mark Mitchell <mark@codesourcery.com>
+
+ * g++.dg/abi/key1.C: New test.
+
2004-08-31 Richard Henderson <rth@redhat.com>
* g++.dg/other/offsetof1.C: Include cstddef, use non-builtin
diff --git a/gcc/testsuite/g++.dg/abi/key1.C b/gcc/testsuite/g++.dg/abi/key1.C
new file mode 100644
index 0000000..6c03809
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/key1.C
@@ -0,0 +1,26 @@
+// On ARM EABI platforms, key methods may never be inline.
+// { dg-do compile { target arm*-*-eabi* arm*-*-symbianelf* } }
+// { dg-final { scan-assembler-not _ZTV1S } }
+// { dg-final { scan-assembler-not _ZTV1T } }
+// { dg-final { scan-assembler _ZTV1U } }
+
+struct S {
+ virtual void f();
+};
+
+inline void S::f() {}
+
+struct T {
+ virtual void g();
+ virtual void h();
+};
+
+inline void T::g() {}
+
+struct U {
+ virtual void i();
+ virtual void j();
+};
+
+inline void U::i() {}
+void U::j () {}