* target-def.h (TARGET_CXX_EXPORT_CLASS_DATA): Remove.
(TARGET_CXX_DETERMINE_CLASS_VISIBILITY): New macro.
(TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT): Likewise.
(TARGET_CXX): Adjust accordingly.
* target.h (struct gcc_target): Remove epxort_class_data. Add
determine_class_data_visibility and class_data_always_comdat.
* doc/tm.texi (TARGET_CXX_EXPORT_CLASS_DATA): Remove.
(TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY): Document.
(TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT): Likewise.
* config/arm/arm.c (arm_cxx_export_class_data): Remove.
(arm_cxx_determine_class_data_visibility): New.
(arm_cxx_class_data_always_comdat): Likewise.
(TARGET_CXX_EXPORT_CLASS_DATA): Remove.
(TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY): Define.
(TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT): Likewise.
* config/arm/arm.h (TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P): Define.
* config/arm/symbian.h (TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P):
Define.
* decl2.c (determine_visibility): Don't use export_class_data.
(import_export_decl): Honor TARGET_CXX_CLASS_DATA_ALWAYS_WEAK and
TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY.
* testsuite/g++.dg/ext/visibility/arm2.C: New test.
* testsuite/g++.dg/ext/visibility/arm3.C: Likewise.
* testsuite/g++.dg/ext/visibility/symbian2.C: Likewise.
From-SVN: r98010
+2005-04-11 Mark Mitchell <mark@codesourcery.com>
+
+ * target-def.h (TARGET_CXX_EXPORT_CLASS_DATA): Remove.
+ (TARGET_CXX_DETERMINE_CLASS_VISIBILITY): New macro.
+ (TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT): Likewise.
+ (TARGET_CXX): Adjust accordingly.
+ * target.h (struct gcc_target): Remove epxort_class_data. Add
+ determine_class_data_visibility and class_data_always_comdat.
+ * doc/tm.texi (TARGET_CXX_EXPORT_CLASS_DATA): Remove.
+ (TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY): Document.
+ (TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT): Likewise.
+ * config/arm/arm.c (arm_cxx_export_class_data): Remove.
+ (arm_cxx_determine_class_data_visibility): New.
+ (arm_cxx_class_data_always_comdat): Likewise.
+ (TARGET_CXX_EXPORT_CLASS_DATA): Remove.
+ (TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY): Define.
+ (TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT): Likewise.
+ * config/arm/arm.h (TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P): Define.
+ * config/arm/symbian.h (TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P):
+ Define.
+
2005-04-11 Devang Patel <dpatel@apple.com>
* tree-data-ref.c (build_classic_dist_vector,
static bool arm_cookie_has_size (void);
static bool arm_cxx_cdtor_returns_this (void);
static bool arm_cxx_key_method_may_be_inline (void);
-static bool arm_cxx_export_class_data (void);
+static void arm_cxx_determine_class_data_visibility (tree);
+static bool arm_cxx_class_data_always_comdat (void);
static void arm_init_libfuncs (void);
static unsigned HOST_WIDE_INT arm_shift_truncation_mask (enum machine_mode);
\f
#undef TARGET_CXX_KEY_METHOD_MAY_BE_INLINE
#define TARGET_CXX_KEY_METHOD_MAY_BE_INLINE arm_cxx_key_method_may_be_inline
-#undef TARGET_CXX_EXPORT_CLASS_DATA
-#define TARGET_CXX_EXPORT_CLASS_DATA arm_cxx_export_class_data
+#undef TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY
+#define TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY \
+ arm_cxx_determine_class_data_visibility
+
+#undef TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT
+#define TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT arm_cxx_class_data_always_comdat
struct gcc_target targetm = TARGET_INITIALIZER;
\f
return !TARGET_AAPCS_BASED;
}
-/* The EABI says that the virtual table, etc., for a class must be
- exported if it has a key method. The EABI does not specific the
- behavior if there is no key method, but there is no harm in
- exporting the class data in that case too. */
+static void
+arm_cxx_determine_class_data_visibility (tree decl)
+{
+ if (!TARGET_AAPCS_BASED)
+ return;
+ /* In general, \S 3.2.5.5 of the ARM EABI requires that class data
+ is exported. However, on systems without dynamic vague linkage,
+ \S 3.2.5.6 says that COMDAT class data has hidden linkage. */
+ if (!TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P && DECL_COMDAT (decl))
+ DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+ else
+ DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
+ DECL_VISIBILITY_SPECIFIED (decl) = 1;
+}
+
static bool
-arm_cxx_export_class_data (void)
+arm_cxx_class_data_always_comdat (void)
{
- return TARGET_AAPCS_BASED;
+ /* \S 3.2.5.4 of the ARM C++ ABI says that class data only have
+ vague linkage if the class has no key function. */
+ return !TARGET_AAPCS_BASED;
}
void
#define ASM_OUTPUT_LABELREF(FILE, NAME) \
arm_asm_output_labelref (FILE, NAME)
+/* True if the operating system can merge entities with vague linkage
+ (e.g., symbols in COMDAT group) during dynamic linking. */
+#ifndef TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P
+#define TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P true
+#endif
+
/* Set the short-call flag for any function compiled in the current
compilation unit. We skip this for functions with the section
attribute when long-calls are in effect as this tells the compiler
builtin_define ("__symbian__"); \
} \
while (false)
+
+
+/* SymbianOS cannot merge entities with vague linkage at runtime. */
+#define TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P false
+2005-04-11 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (determine_visibility): Don't use export_class_data.
+ (import_export_decl): Honor TARGET_CXX_CLASS_DATA_ALWAYS_WEAK and
+ TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY.
+
2005-04-09 Kazu Hirata <kazu@cs.umass.edu>
* cp-tree.h (cxx_alignof): Remove.
DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type);
DECL_VISIBILITY_SPECIFIED (decl) = 1;
}
- /* If no explicit visibility information has been provided for
- this class, some targets require that class data be
- exported. */
- else if (TREE_CODE (decl) == VAR_DECL
- && targetm.cxx.export_class_data ()
- && (DECL_TINFO_P (decl)
- || (DECL_VTABLE_OR_VTT_P (decl)
- /* Construction virtual tables are not emitted
- because they cannot be referred to from other
- object files; their name is not standardized by
- the ABI. */
- && !DECL_CONSTRUCTION_VTABLE_P (decl))))
- DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
- else
+ else if (!DECL_VISIBILITY_SPECIFIED (decl))
{
DECL_VISIBILITY (decl) = CLASSTYPE_VISIBILITY (class_type);
DECL_VISIBILITY_SPECIFIED (decl) = 0;
int emit_p;
bool comdat_p;
bool import_p;
+ tree class_type = NULL_TREE;
if (DECL_INTERFACE_KNOWN (decl))
return;
;
else if (TREE_CODE (decl) == VAR_DECL && DECL_VTABLE_OR_VTT_P (decl))
{
- tree type = DECL_CONTEXT (decl);
- import_export_class (type);
- if (TYPE_FOR_JAVA (type))
+ class_type = DECL_CONTEXT (decl);
+ import_export_class (class_type);
+ if (TYPE_FOR_JAVA (class_type))
import_p = true;
- else if (CLASSTYPE_INTERFACE_KNOWN (type)
- && CLASSTYPE_INTERFACE_ONLY (type))
+ else if (CLASSTYPE_INTERFACE_KNOWN (class_type)
+ && CLASSTYPE_INTERFACE_ONLY (class_type))
import_p = true;
else if ((!flag_weak || TARGET_WEAK_NOT_IN_ARCHIVE_TOC)
- && !CLASSTYPE_USE_TEMPLATE (type)
- && CLASSTYPE_KEY_METHOD (type)
- && !DECL_DECLARED_INLINE_P (CLASSTYPE_KEY_METHOD (type)))
+ && !CLASSTYPE_USE_TEMPLATE (class_type)
+ && CLASSTYPE_KEY_METHOD (class_type)
+ && !DECL_DECLARED_INLINE_P (CLASSTYPE_KEY_METHOD (class_type)))
/* The ABI requires that all virtual tables be emitted with
COMDAT linkage. However, on systems where COMDAT symbols
don't show up in the table of contents for a static
emitted in only one translation unit, we make the virtual
table an ordinary definition with external linkage. */
DECL_EXTERNAL (decl) = 0;
- else if (CLASSTYPE_INTERFACE_KNOWN (type))
+ else if (CLASSTYPE_INTERFACE_KNOWN (class_type))
{
- /* TYPE is being exported from this translation unit, so DECL
- should be defined here. */
- if (!flag_weak && CLASSTYPE_EXPLICIT_INSTANTIATION (type))
+ /* CLASS_TYPE is being exported from this translation unit,
+ so DECL should be defined here. */
+ if (!flag_weak && CLASSTYPE_EXPLICIT_INSTANTIATION (class_type))
/* If a class is declared in a header with the "extern
template" extension, then it will not be instantiated,
even in translation units that would normally require
DECL_EXTERNAL (decl) = 0;
else
{
- /* The ABI requires COMDAT linkage. Normally, we only
- emit COMDAT things when they are needed; make sure
- that we realize that this entity is indeed
- needed. */
- comdat_p = true;
- mark_needed (decl);
+ /* The generic C++ ABI says that class data is always
+ COMDAT, even if there is a key function. Some
+ variants (e.g., the ARM EABI) says that class data
+ only has COMDAT linkage if the the class data might
+ be emitted in more than one translation unit. */
+ if (!CLASSTYPE_KEY_METHOD (class_type)
+ || targetm.cxx.class_data_always_comdat ())
+ {
+ /* The ABI requires COMDAT linkage. Normally, we
+ only emit COMDAT things when they are needed;
+ make sure that we realize that this entity is
+ indeed needed. */
+ comdat_p = true;
+ mark_needed (decl);
+ }
}
}
else if (!flag_implicit_templates
- && CLASSTYPE_IMPLICIT_INSTANTIATION (type))
+ && CLASSTYPE_IMPLICIT_INSTANTIATION (class_type))
import_p = true;
else
comdat_p = true;
tree type = TREE_TYPE (DECL_NAME (decl));
if (CLASS_TYPE_P (type))
{
+ class_type = type;
import_export_class (type);
if (CLASSTYPE_INTERFACE_KNOWN (type)
&& TYPE_POLYMORPHIC_P (type)
import_p = true;
else
{
- comdat_p = true;
if (CLASSTYPE_INTERFACE_KNOWN (type)
&& !CLASSTYPE_INTERFACE_ONLY (type))
{
+ comdat_p = targetm.cxx.class_data_always_comdat ();
mark_needed (decl);
if (!flag_weak)
{
DECL_EXTERNAL (decl) = 0;
}
}
+ else
+ comdat_p = true;
}
}
else
comdat_linkage (decl);
}
+ /* Give the target a chance to override the visibility associated
+ with DECL. */
+ if (TREE_CODE (decl) == VAR_DECL
+ && (DECL_TINFO_P (decl)
+ || (DECL_VTABLE_OR_VTT_P (decl)
+ /* Construction virtual tables are not exported because
+ they cannot be referred to from other object files;
+ their name is not standardized by the ABI. */
+ && !DECL_CONSTRUCTION_VTABLE_P (decl)))
+ && TREE_PUBLIC (decl)
+ && !DECL_REALLY_EXTERN (decl)
+ && DECL_VISIBILITY_SPECIFIED (decl)
+ && (!class_type || !CLASSTYPE_VISIBILITY_SPECIFIED (class_type)))
+ targetm.cxx.determine_class_data_visibility (decl);
+
DECL_INTERFACE_KNOWN (decl) = 1;
}
method. The default is to return @code{true}.
@end deftypefn
-@deftypefn {Target Hook} bool TARGET_CXX_EXPORT_CLASS_DATA (void)
-If this hook returns false (the default), then virtual tables and RTTI
-data structures will have the ELF visibility of their containing
-class. If this hook returns true, then these data structures will
-have ELF ``default'' visibility, independently of the visibility of
-the containing class.
+@deftypefn {Target Hook} void TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY (tree @var{decl})
+@var{decl} is a virtual table, virtual table table, typeinfo object,
+or other similar implicit class data object that will be emitted with
+external linkage in this translation unit. No ELF visibility has been
+explicitly specified. If the target needs to specify a visibility
+other than that of the containing class, use this hook to set
+@code{DECL_VISIBILITY} and @code{DECL_VISIBILITY_SPECIFIED}.
+@end deftypefn
+
+@deftypefn {Target Hook} bool TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT (void)
+This hook returns true (the default) if virtual tables and other
+similar implicit class data objects are always COMDAT if they have
+external linkage. If this hook returns false, then class data for
+classes whose virtual table will be emitted in only one translation
+unit will not be COMDAT.
@end deftypefn
@node Misc
#define TARGET_CXX_KEY_METHOD_MAY_BE_INLINE hook_bool_void_true
#endif
-#ifndef TARGET_CXX_EXPORT_CLASS_DATA
-#define TARGET_CXX_EXPORT_CLASS_DATA hook_bool_void_false
+#ifndef TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY
+#define TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY hook_void_tree
+#endif
+
+#ifndef TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT
+#define TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT hook_bool_void_true
#endif
#define TARGET_CXX \
TARGET_CXX_IMPORT_EXPORT_CLASS, \
TARGET_CXX_CDTOR_RETURNS_THIS, \
TARGET_CXX_KEY_METHOD_MAY_BE_INLINE, \
- TARGET_CXX_EXPORT_CLASS_DATA \
+ TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY, \
+ TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT, \
}
/* The whole shebang. */
itself. Returning true is the behavior required by the Itanium
C++ ABI. */
bool (*key_method_may_be_inline) (void);
- /* Returns true if all class data (virtual tables, type info,
- etc.) should be exported from the current DLL, even when the
- associated class is not exported. */
- bool (*export_class_data) (void);
+ /* DECL is a virtual table, virtual table table, typeinfo object,
+ or other similar implicit class data object that will be
+ emitted with external linkage in this translation unit. No ELF
+ visibility has been explicitly specified. If the target needs
+ to specify a visibility other than that of the containing class,
+ use this hook to set DECL_VISIBILITY and
+ DECL_VISIBILITY_SPECIFIED. */
+ void (*determine_class_data_visibility) (tree decl);
+ /* Returns true (the default) if virtual tables and other
+ similar implicit class data objects are always COMDAT if they
+ have external linkage. If this hook returns false, then
+ class data for classes whose virtual table will be emitted in
+ only one translation unit will not be COMDAT. */
+ bool (*class_data_always_comdat) (void);
} cxx;
/* Leave the boolean fields at the end. */
+2005-04-11 Mark Mitchell <mark@codesourcery.com>
+
+ * target-def.h (TARGET_CXX_EXPORT_CLASS_DATA): Remove.
+ (TARGET_CXX_DETERMINE_CLASS_VISIBILITY): New macro.
+ (TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT): Likewise.
+ (TARGET_CXX): Adjust accordingly.
+ * target.h (struct gcc_target): Remove epxort_class_data. Add
+ determine_class_data_visibility and class_data_always_comdat.
+ * doc/tm.texi (TARGET_CXX_EXPORT_CLASS_DATA): Remove.
+ (TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY): Document.
+ (TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT): Likewise.
+ * config/arm/arm.c (arm_cxx_export_class_data): Remove.
+ (arm_cxx_determine_class_data_visibility): New.
+ (arm_cxx_class_data_always_comdat): Likewise.
+ (TARGET_CXX_EXPORT_CLASS_DATA): Remove.
+ (TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY): Define.
+ (TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT): Likewise.
+ * config/arm/arm.h (TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P): Define.
+ * config/arm/symbian.h (TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P):
+ Define.
+
2005-04-11 Mark Mitchell <mark@codesourcery.com>
* lib/wrapper.exp (${tool}_maybe_build_wrapper): Don't unset gluefile.
--- /dev/null
+// { dg-do compile { target arm*-*-*eabi* arm*-*-symbianelf* } }
+// Class data should be exported.
+// { dg-final { scan-not-hidden "_ZTV1S" } }
+// { dg-final { scan-not-hidden "_ZTI1S" } }
+// { dg-final { scan-not-hidden "_ZTS1S" } }
+
+struct S {
+ virtual void f();
+};
+
+void S::f() {}
--- /dev/null
+// { dg-do compile { target arm*-*-*eabi* } }
+// { dg-options "-fvisibility=hidden" }
+// Class data should be exported.
+// { dg-final { scan-not-hidden "_ZTI1A" } }
+// { dg-final { scan-not-hidden "_ZTS1A" } }
+// { dg-final { scan-not-hidden "_ZTV1B" } }
+// { dg-final { scan-not-hidden "_ZTI1B" } }
+// { dg-final { scan-not-hidden "_ZTS1B" } }
+
+struct A {};
+struct B : virtual public A {};
+B b;
--- /dev/null
+// { dg-do compile { target arm*-*-symbianelf* } }
+// Class data should not be exported.
+// { dg-final { scan-hidden "_ZTI1A" } }
+// { dg-final { scan-hidden "_ZTS1A" } }
+// { dg-final { scan-hidden "_ZTV1B" } }
+// { dg-final { scan-hidden "_ZTI1B" } }
+// { dg-final { scan-hidden "_ZTS1B" } }
+
+struct A {};
+struct B : virtual public A {};
+B b;