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
This commit is contained in:
parent
0f3340356d
commit
bb88593883
|
@ -1,3 +1,27 @@
|
|||
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>
|
||||
|
||||
PR c++/12726
|
||||
|
|
114
gcc/cp/class.c
114
gcc/cp/class.c
|
@ -166,9 +166,11 @@ static int make_new_vtable (tree, tree);
|
|||
static int maybe_indent_hierarchy (FILE *, int, int);
|
||||
static tree dump_class_hierarchy_r (FILE *, int, tree, tree, int);
|
||||
static void dump_class_hierarchy (tree);
|
||||
static void dump_class_hierarchy_1 (FILE *, int, tree);
|
||||
static void dump_array (FILE *, tree);
|
||||
static void dump_vtable (tree, tree, tree);
|
||||
static void dump_vtt (tree, tree);
|
||||
static void dump_thunk (FILE *, int, tree);
|
||||
static tree build_vtable (tree, tree, tree);
|
||||
static void initialize_vtable (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,
|
|||
if (thunk_binfo && (kind == bk_via_virtual
|
||||
|| !BINFO_OFFSET_ZEROP (thunk_binfo)))
|
||||
{
|
||||
tree offset = BINFO_OFFSET (thunk_binfo);
|
||||
tree offset = convert (ssizetype, BINFO_OFFSET (thunk_binfo));
|
||||
|
||||
if (kind == bk_via_virtual)
|
||||
{
|
||||
|
@ -2188,8 +2190,9 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
|
|||
thunk_binfo = BINFO_INHERITANCE_CHAIN (thunk_binfo);
|
||||
|
||||
virtual_offset = thunk_binfo;
|
||||
offset = size_binop (MINUS_EXPR, offset,
|
||||
BINFO_OFFSET (virtual_offset));
|
||||
offset = size_diffop
|
||||
(offset, convert
|
||||
(ssizetype, BINFO_OFFSET (virtual_offset)));
|
||||
}
|
||||
if (fixed_offset)
|
||||
/* 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,
|
|||
primary binfo which first introduced the function into the
|
||||
vtable. If that enters a virtual base, we must use a vcall
|
||||
this-adjusting thunk. Bleah! */
|
||||
tree probe;
|
||||
tree probe = first_defn;
|
||||
|
||||
while ((probe = get_primary_binfo (probe))
|
||||
&& (unsigned) list_length (BINFO_VIRTUALS (probe)) > ix)
|
||||
if (TREE_VIA_VIRTUAL (probe))
|
||||
virtual_base = probe;
|
||||
|
||||
for (probe = first_defn; (probe = get_primary_binfo (probe));)
|
||||
{
|
||||
if (TREE_VIA_VIRTUAL (probe))
|
||||
virtual_base = probe;
|
||||
if ((unsigned) list_length (BINFO_VIRTUALS (probe)) <= ix)
|
||||
break;
|
||||
}
|
||||
if (virtual_base)
|
||||
/* Even if we find a virtual base, the correct delta is
|
||||
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,
|
|||
if (virtual_base)
|
||||
/* The `this' pointer needs to be adjusted from the declaration to
|
||||
the nearest virtual base. */
|
||||
delta = size_diffop (BINFO_OFFSET (virtual_base),
|
||||
BINFO_OFFSET (first_defn));
|
||||
delta = size_diffop (convert (ssizetype, BINFO_OFFSET (virtual_base)),
|
||||
convert (ssizetype, BINFO_OFFSET (first_defn)));
|
||||
else if (lost)
|
||||
/* If the nearest definition is in a lost primary, we don't need an
|
||||
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,
|
|||
BINFO to pointing at the base where the final overrider
|
||||
appears. */
|
||||
virtual_covariant:
|
||||
delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)),
|
||||
BINFO_OFFSET (binfo));
|
||||
delta = size_diffop (convert (ssizetype,
|
||||
BINFO_OFFSET (TREE_VALUE (overrider))),
|
||||
convert (ssizetype, BINFO_OFFSET (binfo)));
|
||||
|
||||
modify_vtable_entry (t, binfo, overrider_fn, delta, virtuals);
|
||||
|
||||
|
@ -6575,14 +6577,8 @@ dump_class_hierarchy_r (FILE *stream,
|
|||
/* Dump the BINFO hierarchy for T. */
|
||||
|
||||
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, " size=%lu align=%lu\n",
|
||||
(unsigned long)(tree_low_cst (TYPE_SIZE (t), 0) / BITS_PER_UNIT),
|
||||
|
@ -6594,7 +6590,27 @@ dump_class_hierarchy (tree t)
|
|||
/ BITS_PER_UNIT));
|
||||
dump_class_hierarchy_r (stream, flags, TYPE_BINFO (t), TYPE_BINFO (t), 0);
|
||||
fprintf (stream, "\n");
|
||||
dump_end (TDI_class, stream);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -6669,6 +6685,53 @@ dump_vtt (tree t, tree vtt)
|
|||
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. */
|
||||
|
||||
/* Create all the necessary vtables for T and its base classes. */
|
||||
|
@ -7327,6 +7390,11 @@ build_vtbl_initializer (tree binfo,
|
|||
{
|
||||
if (!DECL_NAME (fn))
|
||||
finish_thunk (fn);
|
||||
if (THUNK_ALIAS_P (fn))
|
||||
{
|
||||
fn = THUNK_ALIAS (fn);
|
||||
BV_FN (v) = fn;
|
||||
}
|
||||
fn_original = THUNK_TARGET (fn);
|
||||
}
|
||||
|
||||
|
|
|
@ -2855,7 +2855,11 @@ struct lang_decl GTY(())
|
|||
|
||||
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
|
||||
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
|
||||
this or result pointer when this function is called. */
|
||||
|
@ -2868,13 +2872,21 @@ struct lang_decl GTY(())
|
|||
binfo of the relevant virtual base. If NULL, then there is no
|
||||
virtual adjust. (The vptr is always located at offset zero from
|
||||
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
|
||||
binfos.) */
|
||||
|
||||
#define THUNK_VIRTUAL_OFFSET(DECL) \
|
||||
(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. */
|
||||
#define THUNK_TARGET(NODE) \
|
||||
(DECL_LANG_SPECIFIC (NODE)->u.f.befriending_classes)
|
||||
|
@ -3566,6 +3578,8 @@ extern void note_name_declared_in_class (tree, tree);
|
|||
extern tree get_vtbl_decl_for_binfo (tree);
|
||||
extern tree get_vtt_name (tree);
|
||||
extern tree get_primary_binfo (tree);
|
||||
extern void debug_class (tree);
|
||||
extern void debug_thunks (tree);
|
||||
|
||||
/* in cvt.c */
|
||||
extern tree convert_to_reference (tree, tree, int, int, tree);
|
||||
|
@ -3681,7 +3695,7 @@ extern int nonstatic_local_decl_p (tree);
|
|||
extern tree declare_global_var (tree, tree);
|
||||
extern void register_dtor_fn (tree);
|
||||
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 cxx_builtin_type_decls (void);
|
||||
extern void warn_extern_redeclared_static (tree, tree);
|
||||
|
|
|
@ -3097,11 +3097,11 @@ cxx_init_decl_processing (void)
|
|||
}
|
||||
|
||||
/* Generate an initializer for a function naming variable from
|
||||
NAME. NAME may be NULL, in which case we generate a special
|
||||
ERROR_MARK node which should be replaced later. */
|
||||
NAME. NAME may be NULL, to indicate a dependent name. TYPE_P is
|
||||
filled in with the type of the init. */
|
||||
|
||||
tree
|
||||
cp_fname_init (const char* name)
|
||||
cp_fname_init (const char* name, tree *type_p)
|
||||
{
|
||||
tree domain = NULL_TREE;
|
||||
tree type;
|
||||
|
@ -3118,12 +3118,12 @@ cp_fname_init (const char* name)
|
|||
type = build_qualified_type (char_type_node, TYPE_QUAL_CONST);
|
||||
type = build_cplus_array_type (type, domain);
|
||||
|
||||
*type_p = type;
|
||||
|
||||
if (init)
|
||||
TREE_TYPE (init) = type;
|
||||
else
|
||||
/* We don't know the value until instantiation time. Make
|
||||
something which will be digested now, but replaced later. */
|
||||
init = build (ERROR_MARK, type);
|
||||
init = error_mark_node;
|
||||
|
||||
return init;
|
||||
}
|
||||
|
@ -3139,8 +3139,9 @@ cp_make_fname_decl (tree id, int type_dep)
|
|||
{
|
||||
const char *const name = (type_dep && processing_template_decl
|
||||
? NULL : fname_as_string (type_dep));
|
||||
tree init = cp_fname_init (name);
|
||||
tree decl = build_decl (VAR_DECL, id, TREE_TYPE (init));
|
||||
tree type;
|
||||
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. */
|
||||
DECL_CONTEXT (decl) = current_function_decl;
|
||||
|
|
|
@ -107,6 +107,8 @@ make_thunk (tree function, bool this_adjusting,
|
|||
my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 20021025);
|
||||
/* 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_RESULT_THUNK_P (function) || this_adjusting,
|
||||
20031123);
|
||||
|
||||
/* Scale the VIRTUAL_OFFSET to be in terms of bytes. */
|
||||
if (this_adjusting && virtual_offset)
|
||||
|
@ -140,6 +142,8 @@ make_thunk (tree function, bool this_adjusting,
|
|||
thunk = build_decl (FUNCTION_DECL, NULL_TREE, TREE_TYPE (function));
|
||||
DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function);
|
||||
cxx_dup_lang_specific_decl (thunk);
|
||||
DECL_THUNKS (thunk) = NULL_TREE;
|
||||
|
||||
DECL_CONTEXT (thunk) = DECL_CONTEXT (function);
|
||||
TREE_READONLY (thunk) = TREE_READONLY (function);
|
||||
TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (function);
|
||||
|
@ -171,6 +175,7 @@ make_thunk (tree function, bool this_adjusting,
|
|||
DECL_DECLARED_INLINE_P (thunk) = 0;
|
||||
/* Nor has it been deferred. */
|
||||
DECL_DEFERRED_FN (thunk) = 0;
|
||||
|
||||
/* Add it to the list of thunks associated with FUNCTION. */
|
||||
TREE_CHAIN (thunk) = DECL_THUNKS (function);
|
||||
DECL_THUNKS (function) = thunk;
|
||||
|
@ -193,6 +198,27 @@ finish_thunk (tree thunk)
|
|||
function = THUNK_TARGET (thunk);
|
||||
name = mangle_thunk (function, DECL_THIS_THUNK_P (thunk),
|
||||
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;
|
||||
SET_DECL_ASSEMBLER_NAME (thunk, name);
|
||||
}
|
||||
|
@ -307,6 +333,10 @@ use_thunk (tree thunk_fndecl, bool emit_p)
|
|||
/* We should have called finish_thunk to give it a name. */
|
||||
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))
|
||||
return;
|
||||
|
||||
|
|
|
@ -7627,8 +7627,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|
|||
initializer. */
|
||||
const char *const name
|
||||
= cxx_printable_name (current_function_decl, 2);
|
||||
init = cp_fname_init (name);
|
||||
TREE_TYPE (decl) = TREE_TYPE (init);
|
||||
init = cp_fname_init (name, &TREE_TYPE (decl));
|
||||
}
|
||||
else
|
||||
init = tsubst_expr (init, args, complain, in_decl);
|
||||
|
|
|
@ -2827,15 +2827,20 @@ emit_associated_thunks (tree fn)
|
|||
|
||||
for (thunk = DECL_THUNKS (fn); thunk; thunk = TREE_CHAIN (thunk))
|
||||
{
|
||||
use_thunk (thunk, /*emit_p=*/1);
|
||||
if (DECL_RESULT_THUNK_P (thunk))
|
||||
if (!THUNK_ALIAS_P (thunk))
|
||||
{
|
||||
tree probe;
|
||||
|
||||
for (probe = DECL_THUNKS (thunk);
|
||||
probe; probe = TREE_CHAIN (probe))
|
||||
use_thunk (probe, /*emit_p=*/1);
|
||||
use_thunk (thunk, /*emit_p=*/1);
|
||||
if (DECL_RESULT_THUNK_P (thunk))
|
||||
{
|
||||
tree probe;
|
||||
|
||||
for (probe = DECL_THUNKS (thunk);
|
||||
probe; probe = TREE_CHAIN (probe))
|
||||
use_thunk (probe, /*emit_p=*/1);
|
||||
}
|
||||
}
|
||||
else
|
||||
my_friendly_assert (!DECL_THUNKS (thunk), 20031023);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
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>
|
||||
|
||||
* gcc.dg/old-style-asm-1.c: Also check for (set (pc) on lines
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
// { 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 {};
|
||||
};
|
|
@ -0,0 +1,29 @@
|
|||
// { 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; }
|
|
@ -0,0 +1,32 @@
|
|||
// { 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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue