summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/cp/decl2.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/cp/decl2.c')
-rw-r--r--contrib/gcc/cp/decl2.c95
1 files changed, 85 insertions, 10 deletions
diff --git a/contrib/gcc/cp/decl2.c b/contrib/gcc/cp/decl2.c
index bdeadb5..069aaaf 100644
--- a/contrib/gcc/cp/decl2.c
+++ b/contrib/gcc/cp/decl2.c
@@ -224,14 +224,21 @@ int warn_long_long = 1;
int warn_ctor_dtor_privacy = 1;
-/* True if we want to implement vtables using "thunks".
- The default is off. */
+/* 1 or 2 if we want to implement vtables using "thunks".
+ The default is off. Version 1 indicates "old" implementation;
+ Version 2 passes the __vlist argument in pvbase cases. */
#ifndef DEFAULT_VTABLE_THUNKS
#define DEFAULT_VTABLE_THUNKS 0
#endif
int flag_vtable_thunks = DEFAULT_VTABLE_THUNKS;
+#if DEFAULT_VTABLE_THUNKS == 2
+int flag_vtable_thunks_compat = 1;
+#else
+int flag_vtable_thunks_compat = 0;
+#endif
+
/* True if we want to deal with repository information. */
int flag_use_repository;
@@ -633,6 +640,31 @@ lang_decode_option (argc, argv)
found = 1;
cp_deprecated ("-fexternal-templates");
}
+ else if (!strncmp (p, "vtable-thunks", 13))
+ {
+ if (p[13] == '=')
+ {
+ flag_vtable_thunks =
+ read_integral_parameter (p+14, p, 1);
+ }
+ else
+ {
+ /* If the machine file has a default setting, use that
+ for -fvtable-thunks. Otherwise, set it to version
+ 2. */
+#if DEFAULT_VTABLE_THUNKS
+ flag_vtable_thunks = DEFAULT_VTABLE_THUNKS;
+#else
+ flag_vtable_thunks = 1;
+#endif
+ }
+ if (flag_vtable_thunks == 2)
+ /* v2 is a compatibility mode between v1 and v3. */
+ flag_vtable_thunks_compat = 1;
+ else if(flag_vtable_thunks == 3)
+ flag_vtable_thunks_compat = 0;
+ found = 1;
+ }
else if (!strcmp (p, "handle-signatures"))
{
flag_handle_signatures = 1;
@@ -644,7 +676,7 @@ lang_decode_option (argc, argv)
flag_new_abi = 1;
flag_do_squangling = 1;
flag_honor_std = 1;
- flag_vtable_thunks = 1;
+ flag_vtable_thunks = 2;
}
else if (!strcmp (p, "no-new-abi"))
{
@@ -917,17 +949,27 @@ grok_x_components (specs)
This function adds the "in-charge" flag to member function FN if
appropriate. It is called from grokclassfn and tsubst.
- FN must be either a constructor or destructor. */
+ FN must be either a constructor or destructor.
+
+ For vtable thunks, types with polymorphic virtual bases need an
+ additional "vlist" argument which is an array of virtual tables.
+ In addition, if backwards-compatibility to v1 thunks is requested,
+ a wrapper constructor may be needed as well. */
void
maybe_retrofit_in_chrg (fn)
tree fn;
{
tree basetype, arg_types, parms, parm, fntype;
+ tree wrapper;
+
+ if (CLASSTYPE_IS_TEMPLATE (DECL_CLASS_CONTEXT (fn)))
+ /* Never retrofit arguments on template methods. */
+ return;
if (DECL_CONSTRUCTOR_P (fn)
&& TYPE_USES_VIRTUAL_BASECLASSES (DECL_CLASS_CONTEXT (fn))
- && ! DECL_CONSTRUCTOR_FOR_VBASE_P (fn))
+ && DECL_CONSTRUCTOR_FOR_VBASE (fn) == 0)
/* OK */;
else if (! DECL_CONSTRUCTOR_P (fn)
&& TREE_CHAIN (DECL_ARGUMENTS (fn)) == NULL_TREE)
@@ -936,7 +978,37 @@ maybe_retrofit_in_chrg (fn)
return;
if (DECL_CONSTRUCTOR_P (fn))
- DECL_CONSTRUCTOR_FOR_VBASE_P (fn) = 1;
+ {
+ if (TYPE_USES_PVBASES (DECL_CLASS_CONTEXT (fn)))
+ DECL_CONSTRUCTOR_FOR_VBASE (fn) = CONSTRUCTOR_FOR_PVBASE;
+ else
+ DECL_CONSTRUCTOR_FOR_VBASE (fn) = CONSTRUCTOR_FOR_VBASE;
+ }
+ else if (TYPE_USES_PVBASES (DECL_CLASS_CONTEXT (fn)))
+ DECL_CONSTRUCTOR_FOR_VBASE (fn) = DESTRUCTOR_FOR_PVBASE;
+
+ /* Retrieve the arguments, because it is potentially modified twice. */
+ arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ basetype = TREE_TYPE (TREE_VALUE (arg_types));
+ arg_types = TREE_CHAIN (arg_types);
+
+ if (DECL_CONSTRUCTOR_FOR_PVBASE_P (fn)
+ || DECL_DESTRUCTOR_FOR_PVBASE_P (fn))
+ {
+ /* Add the __vlist argument first. See __in_chrg below. */
+ tree id = vlist_identifier;
+ if (DECL_DESTRUCTOR_FOR_PVBASE_P (fn))
+ id = get_identifier (VLIST1_NAME);
+ parm = build_decl (PARM_DECL, id, vlist_type_node);
+ SET_DECL_ARTIFICIAL (parm);
+ DECL_ARG_TYPE (parm) = vlist_type_node;
+ parms = DECL_ARGUMENTS (fn);
+ /* Add it after 'this'. */
+ TREE_CHAIN (parm) = TREE_CHAIN (parms);
+ TREE_CHAIN (parms) = parm;
+
+ arg_types = hash_tree_chain (vlist_type_node, arg_types);
+ }
/* First add it to DECL_ARGUMENTS... */
parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node);
@@ -949,15 +1021,17 @@ maybe_retrofit_in_chrg (fn)
TREE_CHAIN (parms) = parm;
/* ...and then to TYPE_ARG_TYPES. */
- arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
- basetype = TREE_TYPE (TREE_VALUE (arg_types));
- arg_types = hash_tree_chain (integer_type_node, TREE_CHAIN (arg_types));
+ arg_types = hash_tree_chain (integer_type_node, arg_types);
fntype = build_cplus_method_type (basetype, TREE_TYPE (TREE_TYPE (fn)),
arg_types);
if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)))
fntype = build_exception_variant (fntype,
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)));
TREE_TYPE (fn) = fntype;
+
+ if (flag_vtable_thunks_compat
+ && DECL_CONSTRUCTOR_FOR_PVBASE_P (fn))
+ make_vlist_ctor_wrapper (fn);
}
/* Classes overload their constituent function names automatically.
@@ -1042,7 +1116,8 @@ grokclassfn (ctype, function, flags, quals)
if (flags == DTOR_FLAG)
{
- DECL_ASSEMBLER_NAME (function) = build_destructor_name (ctype);
+ DECL_ASSEMBLER_NAME (function) =
+ build_destructor_name (ctype, DECL_DESTRUCTOR_FOR_PVBASE_P (function));
TYPE_HAS_DESTRUCTOR (ctype) = 1;
}
else
OpenPOWER on IntegriCloud