Commit bb885938 by Nathan Sidwell Committed by Nathan Sidwell

PR c++/12698, c++/12699, c++/12700, c++/12566

cp:
	PR c++/12698, c++/12699, c++/12700, c++/12566
	* cp-tree.h (THUNK_ALIAS_P, THUNK_ALIAS): New.
	(debug_class, debug_thunks): New.
	* class.c (dump_class_hierarchy_1): New break out from ...
	(dump_class_hierarchy): ... here.
	(dump_thunk, debug_thunks, debug_class): New.
	(update_vtable_entry_for_fn): Add ssizetype casts. Correct
	continued search for primary binfo via virtual.
	(build_vtbl_initializer): Follow covariant thunk alias.
	* method.c (make_thunk): Clear DECL_THUNKS of the thunk.
	(finish_thunk): Look for an alias of the covariant thunk and point
	to it.
	(use_thunk): We should never use an alias.
	* semantics.c (emit_associated_thunks): Do not emit aliases.

	PR c++/12566
	* cp-tree.h (cp_fname_init): Add TYPE pointer param.
	* decl.c (cp_fname_init): Add TYPE pointer param. Set it. Don't
	create an ad-hoc ERROR_MARK.
	(cp_make_fname_decl): Adjust.
	* pt.c (tsubst_expr): Adjust.
testsuite:
	PR c++/12698, c++/12699, c++/12700, c++/12566
	* g++.dg/inherit/covariant9.C: New test.
	* g++.dg/inherit/covariant10.C: New test.
	* g++.dg/inherit/covariant11.C: New test.

From-SVN: r72882
parent 0f334035
2003-10-24 Nathan Sidwell <nathan@codesourcery.com>
PR c++/12698, c++/12699, c++/12700, c++/12566
* cp-tree.h (THUNK_ALIAS_P, THUNK_ALIAS): New.
(debug_class, debug_thunks): New.
* class.c (dump_class_hierarchy_1): New break out from ...
(dump_class_hierarchy): ... here.
(dump_thunk, debug_thunks, debug_class): New.
(update_vtable_entry_for_fn): Add ssizetype casts. Correct
continued search for primary binfo via virtual.
(build_vtbl_initializer): Follow covariant thunk alias.
* method.c (make_thunk): Clear DECL_THUNKS of the thunk.
(finish_thunk): Look for an alias of the covariant thunk and point
to it.
(use_thunk): We should never use an alias.
* semantics.c (emit_associated_thunks): Do not emit aliases.
PR c++/12566
* cp-tree.h (cp_fname_init): Add TYPE pointer param.
* decl.c (cp_fname_init): Add TYPE pointer param. Set it. Don't
create an ad-hoc ERROR_MARK.
(cp_make_fname_decl): Adjust.
* pt.c (tsubst_expr): Adjust.
2003-10-23 Jason Merrill <jason@redhat.com> 2003-10-23 Jason Merrill <jason@redhat.com>
PR c++/12726 PR c++/12726
......
...@@ -166,9 +166,11 @@ static int make_new_vtable (tree, tree); ...@@ -166,9 +166,11 @@ static int make_new_vtable (tree, tree);
static int maybe_indent_hierarchy (FILE *, int, int); static int maybe_indent_hierarchy (FILE *, int, int);
static tree dump_class_hierarchy_r (FILE *, int, tree, tree, int); static tree dump_class_hierarchy_r (FILE *, int, tree, tree, int);
static void dump_class_hierarchy (tree); static void dump_class_hierarchy (tree);
static void dump_class_hierarchy_1 (FILE *, int, tree);
static void dump_array (FILE *, tree); static void dump_array (FILE *, tree);
static void dump_vtable (tree, tree, tree); static void dump_vtable (tree, tree, tree);
static void dump_vtt (tree, tree); static void dump_vtt (tree, tree);
static void dump_thunk (FILE *, int, tree);
static tree build_vtable (tree, tree, tree); static tree build_vtable (tree, tree, tree);
static void initialize_vtable (tree, tree); static void initialize_vtable (tree, tree);
static void initialize_array (tree, tree); static void initialize_array (tree, tree);
...@@ -2178,7 +2180,7 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals, ...@@ -2178,7 +2180,7 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
if (thunk_binfo && (kind == bk_via_virtual if (thunk_binfo && (kind == bk_via_virtual
|| !BINFO_OFFSET_ZEROP (thunk_binfo))) || !BINFO_OFFSET_ZEROP (thunk_binfo)))
{ {
tree offset = BINFO_OFFSET (thunk_binfo); tree offset = convert (ssizetype, BINFO_OFFSET (thunk_binfo));
if (kind == bk_via_virtual) if (kind == bk_via_virtual)
{ {
...@@ -2188,8 +2190,9 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals, ...@@ -2188,8 +2190,9 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
thunk_binfo = BINFO_INHERITANCE_CHAIN (thunk_binfo); thunk_binfo = BINFO_INHERITANCE_CHAIN (thunk_binfo);
virtual_offset = thunk_binfo; virtual_offset = thunk_binfo;
offset = size_binop (MINUS_EXPR, offset, offset = size_diffop
BINFO_OFFSET (virtual_offset)); (offset, convert
(ssizetype, BINFO_OFFSET (virtual_offset)));
} }
if (fixed_offset) if (fixed_offset)
/* There was an existing fixed offset, this must be /* There was an existing fixed offset, this must be
...@@ -2251,15 +2254,13 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals, ...@@ -2251,15 +2254,13 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
primary binfo which first introduced the function into the primary binfo which first introduced the function into the
vtable. If that enters a virtual base, we must use a vcall vtable. If that enters a virtual base, we must use a vcall
this-adjusting thunk. Bleah! */ this-adjusting thunk. Bleah! */
tree probe; tree probe = first_defn;
for (probe = first_defn; (probe = get_primary_binfo (probe));) while ((probe = get_primary_binfo (probe))
{ && (unsigned) list_length (BINFO_VIRTUALS (probe)) > ix)
if (TREE_VIA_VIRTUAL (probe)) if (TREE_VIA_VIRTUAL (probe))
virtual_base = probe; virtual_base = probe;
if ((unsigned) list_length (BINFO_VIRTUALS (probe)) <= ix)
break;
}
if (virtual_base) if (virtual_base)
/* Even if we find a virtual base, the correct delta is /* Even if we find a virtual base, the correct delta is
between the overrider and the binfo we're building a vtable between the overrider and the binfo we're building a vtable
...@@ -2273,8 +2274,8 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals, ...@@ -2273,8 +2274,8 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
if (virtual_base) if (virtual_base)
/* The `this' pointer needs to be adjusted from the declaration to /* The `this' pointer needs to be adjusted from the declaration to
the nearest virtual base. */ the nearest virtual base. */
delta = size_diffop (BINFO_OFFSET (virtual_base), delta = size_diffop (convert (ssizetype, BINFO_OFFSET (virtual_base)),
BINFO_OFFSET (first_defn)); convert (ssizetype, BINFO_OFFSET (first_defn)));
else if (lost) else if (lost)
/* If the nearest definition is in a lost primary, we don't need an /* If the nearest definition is in a lost primary, we don't need an
entry in our vtable. Except possibly in a constructor vtable, entry in our vtable. Except possibly in a constructor vtable,
...@@ -2286,8 +2287,9 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals, ...@@ -2286,8 +2287,9 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
BINFO to pointing at the base where the final overrider BINFO to pointing at the base where the final overrider
appears. */ appears. */
virtual_covariant: virtual_covariant:
delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)), delta = size_diffop (convert (ssizetype,
BINFO_OFFSET (binfo)); BINFO_OFFSET (TREE_VALUE (overrider))),
convert (ssizetype, BINFO_OFFSET (binfo)));
modify_vtable_entry (t, binfo, overrider_fn, delta, virtuals); modify_vtable_entry (t, binfo, overrider_fn, delta, virtuals);
...@@ -6575,14 +6577,8 @@ dump_class_hierarchy_r (FILE *stream, ...@@ -6575,14 +6577,8 @@ dump_class_hierarchy_r (FILE *stream,
/* Dump the BINFO hierarchy for T. */ /* Dump the BINFO hierarchy for T. */
static void static void
dump_class_hierarchy (tree t) dump_class_hierarchy_1 (FILE *stream, int flags, tree t)
{ {
int flags;
FILE *stream = dump_begin (TDI_class, &flags);
if (!stream)
return;
fprintf (stream, "Class %s\n", type_as_string (t, TFF_PLAIN_IDENTIFIER)); fprintf (stream, "Class %s\n", type_as_string (t, TFF_PLAIN_IDENTIFIER));
fprintf (stream, " size=%lu align=%lu\n", fprintf (stream, " size=%lu align=%lu\n",
(unsigned long)(tree_low_cst (TYPE_SIZE (t), 0) / BITS_PER_UNIT), (unsigned long)(tree_low_cst (TYPE_SIZE (t), 0) / BITS_PER_UNIT),
...@@ -6594,7 +6590,27 @@ dump_class_hierarchy (tree t) ...@@ -6594,7 +6590,27 @@ dump_class_hierarchy (tree t)
/ BITS_PER_UNIT)); / BITS_PER_UNIT));
dump_class_hierarchy_r (stream, flags, TYPE_BINFO (t), TYPE_BINFO (t), 0); dump_class_hierarchy_r (stream, flags, TYPE_BINFO (t), TYPE_BINFO (t), 0);
fprintf (stream, "\n"); fprintf (stream, "\n");
}
/* Debug interface to heirarchy dumping. */
extern void
debug_class (tree t)
{
dump_class_hierarchy_1 (stderr, TDF_SLIM, t);
}
static void
dump_class_hierarchy (tree t)
{
int flags;
FILE *stream = dump_begin (TDI_class, &flags);
if (stream)
{
dump_class_hierarchy_1 (stream, flags, t);
dump_end (TDI_class, stream); dump_end (TDI_class, stream);
}
} }
static void static void
...@@ -6669,6 +6685,53 @@ dump_vtt (tree t, tree vtt) ...@@ -6669,6 +6685,53 @@ dump_vtt (tree t, tree vtt)
dump_end (TDI_class, stream); dump_end (TDI_class, stream);
} }
/* Dump a function or thunk and its thunkees. */
static void
dump_thunk (FILE *stream, int indent, tree thunk)
{
static const char spaces[] = " ";
tree name = DECL_NAME (thunk);
tree thunks;
fprintf (stream, "%.*s%p %s %s", indent, spaces,
(void *)thunk,
!DECL_THUNK_P (thunk) ? "function"
: DECL_THIS_THUNK_P (thunk) ? "this-thunk" : "covariant-thunk",
name ? IDENTIFIER_POINTER (name) : "<unset>");
if (!DECL_THUNK_P (thunk))
/*NOP*/;
else if (THUNK_ALIAS_P (thunk))
fprintf (stream, " alias to %p", (void *)THUNK_ALIAS (thunk));
else
{
HOST_WIDE_INT fixed_adjust = THUNK_FIXED_OFFSET (thunk);
tree virtual_adjust = THUNK_VIRTUAL_OFFSET (thunk);
fprintf (stream, " fixed=" HOST_WIDE_INT_PRINT_DEC, fixed_adjust);
if (!virtual_adjust)
/*NOP*/;
else if (DECL_THIS_THUNK_P (thunk))
fprintf (stream, " vcall=" HOST_WIDE_INT_PRINT_DEC,
tree_low_cst (virtual_adjust, 0));
else
fprintf (stream, " vbase=" HOST_WIDE_INT_PRINT_DEC "(%s)",
tree_low_cst (BINFO_VPTR_FIELD (virtual_adjust), 0),
type_as_string (BINFO_TYPE (virtual_adjust), TFF_SCOPE));
}
fprintf (stream, "\n");
for (thunks = DECL_THUNKS (thunk); thunks; thunks = TREE_CHAIN (thunks))
dump_thunk (stream, indent + 2, thunks);
}
/* Dump the thunks for FN. */
extern void
debug_thunks (tree fn)
{
dump_thunk (stderr, 0, fn);
}
/* Virtual function table initialization. */ /* Virtual function table initialization. */
/* Create all the necessary vtables for T and its base classes. */ /* Create all the necessary vtables for T and its base classes. */
...@@ -7327,6 +7390,11 @@ build_vtbl_initializer (tree binfo, ...@@ -7327,6 +7390,11 @@ build_vtbl_initializer (tree binfo,
{ {
if (!DECL_NAME (fn)) if (!DECL_NAME (fn))
finish_thunk (fn); finish_thunk (fn);
if (THUNK_ALIAS_P (fn))
{
fn = THUNK_ALIAS (fn);
BV_FN (v) = fn;
}
fn_original = THUNK_TARGET (fn); fn_original = THUNK_TARGET (fn);
} }
......
...@@ -2855,7 +2855,11 @@ struct lang_decl GTY(()) ...@@ -2855,7 +2855,11 @@ struct lang_decl GTY(())
The constant adjustment is given by THUNK_FIXED_OFFSET. If the The constant adjustment is given by THUNK_FIXED_OFFSET. If the
vcall or vbase offset is required, the index into the vtable is given by vcall or vbase offset is required, the index into the vtable is given by
THUNK_VIRTUAL_OFFSET. */ THUNK_VIRTUAL_OFFSET.
Due to ordering constraints in class layout, it is possible to have
equivalent covariant thunks. THUNK_ALIAS_P and THUNK_ALIAS are used
in those cases. */
/* An integer indicating how many bytes should be subtracted from the /* An integer indicating how many bytes should be subtracted from the
this or result pointer when this function is called. */ this or result pointer when this function is called. */
...@@ -2868,13 +2872,21 @@ struct lang_decl GTY(()) ...@@ -2868,13 +2872,21 @@ struct lang_decl GTY(())
binfo of the relevant virtual base. If NULL, then there is no binfo of the relevant virtual base. If NULL, then there is no
virtual adjust. (The vptr is always located at offset zero from virtual adjust. (The vptr is always located at offset zero from
the this or result pointer.) (If the covariant type is within the the this or result pointer.) (If the covariant type is within the
class hierarchy being layed out, the vbase index is not yet known class hierarchy being laid out, the vbase index is not yet known
at the point we need to create the thunks, hence the need to use at the point we need to create the thunks, hence the need to use
binfos.) */ binfos.) */
#define THUNK_VIRTUAL_OFFSET(DECL) \ #define THUNK_VIRTUAL_OFFSET(DECL) \
(LANG_DECL_U2_CHECK (VAR_OR_FUNCTION_DECL_CHECK (DECL), 0)->virtual_offset) (LANG_DECL_U2_CHECK (VAR_OR_FUNCTION_DECL_CHECK (DECL), 0)->virtual_offset)
/* A thunk which is equivalent to another thunk. */
#define THUNK_ALIAS_P(DECL) \
(THUNK_VIRTUAL_OFFSET (DECL) && DECL_P (THUNK_VIRTUAL_OFFSET (DECL)))
/* When THUNK_ALIAS_P is true, this indicates the thunk which is
aliased. */
#define THUNK_ALIAS(DECL) THUNK_VIRTUAL_OFFSET (DECL)
/* For thunk NODE, this is the FUNCTION_DECL thunked to. */ /* For thunk NODE, this is the FUNCTION_DECL thunked to. */
#define THUNK_TARGET(NODE) \ #define THUNK_TARGET(NODE) \
(DECL_LANG_SPECIFIC (NODE)->u.f.befriending_classes) (DECL_LANG_SPECIFIC (NODE)->u.f.befriending_classes)
...@@ -3566,6 +3578,8 @@ extern void note_name_declared_in_class (tree, tree); ...@@ -3566,6 +3578,8 @@ extern void note_name_declared_in_class (tree, tree);
extern tree get_vtbl_decl_for_binfo (tree); extern tree get_vtbl_decl_for_binfo (tree);
extern tree get_vtt_name (tree); extern tree get_vtt_name (tree);
extern tree get_primary_binfo (tree); extern tree get_primary_binfo (tree);
extern void debug_class (tree);
extern void debug_thunks (tree);
/* in cvt.c */ /* in cvt.c */
extern tree convert_to_reference (tree, tree, int, int, tree); extern tree convert_to_reference (tree, tree, int, int, tree);
...@@ -3681,7 +3695,7 @@ extern int nonstatic_local_decl_p (tree); ...@@ -3681,7 +3695,7 @@ extern int nonstatic_local_decl_p (tree);
extern tree declare_global_var (tree, tree); extern tree declare_global_var (tree, tree);
extern void register_dtor_fn (tree); extern void register_dtor_fn (tree);
extern tmpl_spec_kind current_tmpl_spec_kind (int); extern tmpl_spec_kind current_tmpl_spec_kind (int);
extern tree cp_fname_init (const char *); extern tree cp_fname_init (const char *, tree *);
extern tree check_elaborated_type_specifier (enum tag_types, tree, bool); extern tree check_elaborated_type_specifier (enum tag_types, tree, bool);
extern tree cxx_builtin_type_decls (void); extern tree cxx_builtin_type_decls (void);
extern void warn_extern_redeclared_static (tree, tree); extern void warn_extern_redeclared_static (tree, tree);
......
...@@ -3097,11 +3097,11 @@ cxx_init_decl_processing (void) ...@@ -3097,11 +3097,11 @@ cxx_init_decl_processing (void)
} }
/* Generate an initializer for a function naming variable from /* Generate an initializer for a function naming variable from
NAME. NAME may be NULL, in which case we generate a special NAME. NAME may be NULL, to indicate a dependent name. TYPE_P is
ERROR_MARK node which should be replaced later. */ filled in with the type of the init. */
tree tree
cp_fname_init (const char* name) cp_fname_init (const char* name, tree *type_p)
{ {
tree domain = NULL_TREE; tree domain = NULL_TREE;
tree type; tree type;
...@@ -3118,12 +3118,12 @@ cp_fname_init (const char* name) ...@@ -3118,12 +3118,12 @@ cp_fname_init (const char* name)
type = build_qualified_type (char_type_node, TYPE_QUAL_CONST); type = build_qualified_type (char_type_node, TYPE_QUAL_CONST);
type = build_cplus_array_type (type, domain); type = build_cplus_array_type (type, domain);
*type_p = type;
if (init) if (init)
TREE_TYPE (init) = type; TREE_TYPE (init) = type;
else else
/* We don't know the value until instantiation time. Make init = error_mark_node;
something which will be digested now, but replaced later. */
init = build (ERROR_MARK, type);
return init; return init;
} }
...@@ -3139,8 +3139,9 @@ cp_make_fname_decl (tree id, int type_dep) ...@@ -3139,8 +3139,9 @@ cp_make_fname_decl (tree id, int type_dep)
{ {
const char *const name = (type_dep && processing_template_decl const char *const name = (type_dep && processing_template_decl
? NULL : fname_as_string (type_dep)); ? NULL : fname_as_string (type_dep));
tree init = cp_fname_init (name); tree type;
tree decl = build_decl (VAR_DECL, id, TREE_TYPE (init)); tree init = cp_fname_init (name, &type);
tree decl = build_decl (VAR_DECL, id, type);
/* As we're using pushdecl_with_scope, we must set the context. */ /* As we're using pushdecl_with_scope, we must set the context. */
DECL_CONTEXT (decl) = current_function_decl; DECL_CONTEXT (decl) = current_function_decl;
......
...@@ -107,6 +107,8 @@ make_thunk (tree function, bool this_adjusting, ...@@ -107,6 +107,8 @@ make_thunk (tree function, bool this_adjusting,
my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 20021025); my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 20021025);
/* We can have this thunks to covariant thunks, but not vice versa. */ /* We can have this thunks to covariant thunks, but not vice versa. */
my_friendly_assert (!DECL_THIS_THUNK_P (function), 20021127); my_friendly_assert (!DECL_THIS_THUNK_P (function), 20021127);
my_friendly_assert (!DECL_RESULT_THUNK_P (function) || this_adjusting,
20031123);
/* Scale the VIRTUAL_OFFSET to be in terms of bytes. */ /* Scale the VIRTUAL_OFFSET to be in terms of bytes. */
if (this_adjusting && virtual_offset) if (this_adjusting && virtual_offset)
...@@ -140,6 +142,8 @@ make_thunk (tree function, bool this_adjusting, ...@@ -140,6 +142,8 @@ make_thunk (tree function, bool this_adjusting,
thunk = build_decl (FUNCTION_DECL, NULL_TREE, TREE_TYPE (function)); thunk = build_decl (FUNCTION_DECL, NULL_TREE, TREE_TYPE (function));
DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function); DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function);
cxx_dup_lang_specific_decl (thunk); cxx_dup_lang_specific_decl (thunk);
DECL_THUNKS (thunk) = NULL_TREE;
DECL_CONTEXT (thunk) = DECL_CONTEXT (function); DECL_CONTEXT (thunk) = DECL_CONTEXT (function);
TREE_READONLY (thunk) = TREE_READONLY (function); TREE_READONLY (thunk) = TREE_READONLY (function);
TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (function); TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (function);
...@@ -171,6 +175,7 @@ make_thunk (tree function, bool this_adjusting, ...@@ -171,6 +175,7 @@ make_thunk (tree function, bool this_adjusting,
DECL_DECLARED_INLINE_P (thunk) = 0; DECL_DECLARED_INLINE_P (thunk) = 0;
/* Nor has it been deferred. */ /* Nor has it been deferred. */
DECL_DEFERRED_FN (thunk) = 0; DECL_DEFERRED_FN (thunk) = 0;
/* Add it to the list of thunks associated with FUNCTION. */ /* Add it to the list of thunks associated with FUNCTION. */
TREE_CHAIN (thunk) = DECL_THUNKS (function); TREE_CHAIN (thunk) = DECL_THUNKS (function);
DECL_THUNKS (function) = thunk; DECL_THUNKS (function) = thunk;
...@@ -193,6 +198,27 @@ finish_thunk (tree thunk) ...@@ -193,6 +198,27 @@ finish_thunk (tree thunk)
function = THUNK_TARGET (thunk); function = THUNK_TARGET (thunk);
name = mangle_thunk (function, DECL_THIS_THUNK_P (thunk), name = mangle_thunk (function, DECL_THIS_THUNK_P (thunk),
fixed_offset, virtual_offset); fixed_offset, virtual_offset);
/* We can end up with declarations of (logically) different
covariant thunks, that do identical adjustments. The two thunks
will be adjusting between within different hierarchies, which
happen to have the same layout. We must nullify one of them to
refer to the other. */
if (DECL_RESULT_THUNK_P (thunk))
{
tree cov_probe;
for (cov_probe = DECL_THUNKS (function);
cov_probe; cov_probe = TREE_CHAIN (cov_probe))
if (DECL_NAME (cov_probe) == name)
{
my_friendly_assert (!DECL_THUNKS (thunk), 20031023);
THUNK_ALIAS (thunk) = (THUNK_ALIAS_P (cov_probe)
? THUNK_ALIAS (cov_probe) : cov_probe);
break;
}
}
DECL_NAME (thunk) = name; DECL_NAME (thunk) = name;
SET_DECL_ASSEMBLER_NAME (thunk, name); SET_DECL_ASSEMBLER_NAME (thunk, name);
} }
...@@ -307,6 +333,10 @@ use_thunk (tree thunk_fndecl, bool emit_p) ...@@ -307,6 +333,10 @@ use_thunk (tree thunk_fndecl, bool emit_p)
/* We should have called finish_thunk to give it a name. */ /* We should have called finish_thunk to give it a name. */
my_friendly_assert (DECL_NAME (thunk_fndecl), 20021127); my_friendly_assert (DECL_NAME (thunk_fndecl), 20021127);
/* We should never be using an alias, always refer to the
aliased thunk. */
my_friendly_assert (!THUNK_ALIAS_P (thunk_fndecl), 20031023);
if (TREE_ASM_WRITTEN (thunk_fndecl)) if (TREE_ASM_WRITTEN (thunk_fndecl))
return; return;
......
...@@ -7627,8 +7627,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -7627,8 +7627,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
initializer. */ initializer. */
const char *const name const char *const name
= cxx_printable_name (current_function_decl, 2); = cxx_printable_name (current_function_decl, 2);
init = cp_fname_init (name); init = cp_fname_init (name, &TREE_TYPE (decl));
TREE_TYPE (decl) = TREE_TYPE (init);
} }
else else
init = tsubst_expr (init, args, complain, in_decl); init = tsubst_expr (init, args, complain, in_decl);
......
...@@ -2827,6 +2827,8 @@ emit_associated_thunks (tree fn) ...@@ -2827,6 +2827,8 @@ emit_associated_thunks (tree fn)
for (thunk = DECL_THUNKS (fn); thunk; thunk = TREE_CHAIN (thunk)) for (thunk = DECL_THUNKS (fn); thunk; thunk = TREE_CHAIN (thunk))
{ {
if (!THUNK_ALIAS_P (thunk))
{
use_thunk (thunk, /*emit_p=*/1); use_thunk (thunk, /*emit_p=*/1);
if (DECL_RESULT_THUNK_P (thunk)) if (DECL_RESULT_THUNK_P (thunk))
{ {
...@@ -2837,6 +2839,9 @@ emit_associated_thunks (tree fn) ...@@ -2837,6 +2839,9 @@ emit_associated_thunks (tree fn)
use_thunk (probe, /*emit_p=*/1); use_thunk (probe, /*emit_p=*/1);
} }
} }
else
my_friendly_assert (!DECL_THUNKS (thunk), 20031023);
}
} }
} }
......
2003-10-24 Nathan Sidwell <nathan@codesourcery.com>
PR c++/12698, c++/12699, c++/12700, c++/12566
* g++.dg/inherit/covariant9.C: New test.
* g++.dg/inherit/covariant10.C: New test.
* g++.dg/inherit/covariant11.C: New test.
2003-10-20 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz> 2003-10-20 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
* gcc.dg/old-style-asm-1.c: Also check for (set (pc) on lines * gcc.dg/old-style-asm-1.c: Also check for (set (pc) on lines
......
// { dg-do compile }
// Contributed by Nathan Sidwell 23 Oct 2003 <nathan@codesourcery.com>
// Origin: grigory@stl.sarov.ru
// PR c++/12699 ICE with covariancy
struct c1 {
virtual void f1() const {};
};
struct c5 {};
struct c6 : virtual c1 {
virtual c5* f33() const {};
};
struct c13 : virtual c5 { };
struct c17 : virtual c6
{
virtual c13* f33() const {};
};
// { dg-do compile }
// Contributed by Nathan Sidwell 23 Oct 2003 <nathan@codesourcery.com>
// Origin: grigory@stl.sarov.ru
// PR c++/12700 ICE with covariancy
struct c2 { int i; };
struct c1 {
virtual c2& f8() {};
};
struct c3 : c1, c2 {
virtual c2& f8() {};
};
struct c11 : public c1 {
virtual c3& f8() {};
};
struct c15 : virtual c3 {
virtual c2& f8() {};
};
struct c18 : virtual c11 {
virtual c15& f8();
};
c15& c18::f8() { throw 0; }
// { dg-do link }
// { dg-options "-w -ansi -pedantic" }
// Contributed by Nathan Sidwell 23 Oct 2003 <nathan@codesourcery.com>
// Origin: grigory@stl.sarov.ru
// PR c++/12698. Duplicate covariant thunks emitted.
struct c1 {};
struct c0 {
int i;
virtual c1& f10() {};
};
struct c2 : virtual c1, c0 { };
struct c6 : virtual c2, c0 {
virtual c2& f10() {};
};
struct c14 : virtual c2 { };
struct c19 : virtual ::c6 {
virtual class ::c14& f10() {};
};
int main ()
{
c19 obj;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment