* 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
+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
+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.
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;
|| 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)
/* 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. */
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);
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))
{
@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
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)
{
#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);
#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, \
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. */
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. */
+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
--- /dev/null
+// 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 () {}