re PR c++/18143 (Duplicated thunk with a huge member in the hierarchy)
.: * tree.c (tree_check_failed): Emit general error if the list of node types is empty. cp: PR c++/18143 * cp-tree.h (NON_THUNK_FUNCTION_CHECK, THUNK_FUNCTION_CHECK): New. (struct lang_decl_flags): Add thunk_p flag. (struct lang_decl): Remove separate fixed_offset. Place cloned_function and fixed_offset into union. (DECL_CLONED_FUNCTION_P, DECL_CLONED_FUNCTION): Adjust. (DECL_THUNK_P, SET_DECL_THUNK_P): Adjust. (THUNK_FIXED_OFFSET): Adjust. * method.c (make_thunk): Adjust. From-SVN: r90399
This commit is contained in:
parent
22d8d62798
commit
ea1763b1e4
@ -1,3 +1,8 @@
|
||||
2004-11-10 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* tree.c (tree_check_failed): Emit general error if the list of
|
||||
node types is empty.
|
||||
|
||||
2004-11-10 Eric Botcazou <ebotcazou@libertysurf.fr>
|
||||
|
||||
* config/sparc/sparc.c (function_arg_union_value): New 'slotno'
|
||||
|
@ -1,3 +1,15 @@
|
||||
2004-11-10 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
PR c++/18143
|
||||
* cp-tree.h (NON_THUNK_FUNCTION_CHECK, THUNK_FUNCTION_CHECK): New.
|
||||
(struct lang_decl_flags): Add thunk_p flag.
|
||||
(struct lang_decl): Remove separate fixed_offset. Place
|
||||
cloned_function and fixed_offset into union.
|
||||
(DECL_CLONED_FUNCTION_P, DECL_CLONED_FUNCTION): Adjust.
|
||||
(DECL_THUNK_P, SET_DECL_THUNK_P): Adjust.
|
||||
(THUNK_FIXED_OFFSET): Adjust.
|
||||
* method.c (make_thunk): Adjust.
|
||||
|
||||
2004-11-09 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR c++/18369
|
||||
|
@ -163,6 +163,24 @@ struct diagnostic_context;
|
||||
#define BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK(NODE) \
|
||||
TREE_CHECK(NODE,BOUND_TEMPLATE_TEMPLATE_PARM)
|
||||
|
||||
#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
|
||||
#define NON_THUNK_FUNCTION_CHECK(NODE) __extension__ \
|
||||
({ const tree __t = (NODE); \
|
||||
if (TREE_CODE (__t) != FUNCTION_DECL && \
|
||||
TREE_CODE (__t) != TEMPLATE_DECL && __t->decl.lang_specific \
|
||||
&& __t->decl.lang_specific->decl_flags.thunk_p) \
|
||||
tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, 0); \
|
||||
__t; })
|
||||
#define THUNK_FUNCTION_CHECK(NODE) __extension__ \
|
||||
({ const tree __t = (NODE); \
|
||||
if (TREE_CODE (__t) != FUNCTION_DECL || !__t->decl.lang_specific \
|
||||
|| !__t->decl.lang_specific->decl_flags.thunk_p) \
|
||||
tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, 0); \
|
||||
__t; })
|
||||
#else
|
||||
#define NON_THUNK_FUNCTION_CHECK(NODE) (NODE)
|
||||
#define THUNK_FUNCTION_CHECK(NODE) (NODE)
|
||||
#endif
|
||||
|
||||
/* Language-dependent contents of an identifier. */
|
||||
|
||||
@ -1496,9 +1514,10 @@ struct lang_decl_flags GTY(())
|
||||
|
||||
unsigned u2sel : 1;
|
||||
unsigned can_be_full : 1;
|
||||
unsigned thunk_p : 1;
|
||||
unsigned this_thunk_p : 1;
|
||||
unsigned repo_available_p : 1;
|
||||
unsigned dummy : 4;
|
||||
unsigned dummy : 3;
|
||||
|
||||
union lang_decl_u {
|
||||
/* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is
|
||||
@ -1540,15 +1559,8 @@ struct lang_decl GTY(())
|
||||
|
||||
unsigned u3sel : 1;
|
||||
unsigned pending_inline_p : 1;
|
||||
unsigned spare : 3;
|
||||
unsigned spare : 22;
|
||||
|
||||
/* In a FUNCTION_DECL for which THUNK_P holds this is the
|
||||
THUNK_FIXED_OFFSET. The largest object that can be
|
||||
thunked is thus 262144, which is what is required [limits].
|
||||
We have to store a signed value as for regular thunks this
|
||||
is <= 0, and for covariant thunks it is >= 0. */
|
||||
signed fixed_offset : 19;
|
||||
|
||||
/* For a non-thunk function decl, this is a tree list of
|
||||
friendly classes. For a thunk function decl, it is the
|
||||
thunked to function decl. */
|
||||
@ -1562,9 +1574,17 @@ struct lang_decl GTY(())
|
||||
will be chained on the return pointer thunk. */
|
||||
tree context;
|
||||
|
||||
/* In a FUNCTION_DECL, this is DECL_CLONED_FUNCTION. */
|
||||
tree cloned_function;
|
||||
|
||||
union lang_decl_u5
|
||||
{
|
||||
/* In a non-thunk FUNCTION_DECL or TEMPLATE_DECL, this is
|
||||
DECL_CLONED_FUNCTION. */
|
||||
tree GTY ((tag ("0"))) cloned_function;
|
||||
|
||||
/* In a FUNCTION_DECL for which THUNK_P holds this is the
|
||||
THUNK_FIXED_OFFSET. */
|
||||
HOST_WIDE_INT GTY ((tag ("1"))) fixed_offset;
|
||||
} GTY ((desc ("%0.decl_flags.thunk_p"))) u5;
|
||||
|
||||
union lang_decl_u3
|
||||
{
|
||||
struct sorted_fields_type * GTY ((tag ("0"), reorder ("resort_sorted_fields")))
|
||||
@ -1667,16 +1687,17 @@ struct lang_decl GTY(())
|
||||
|
||||
/* Nonzero if NODE (a FUNCTION_DECL) is a cloned constructor or
|
||||
destructor. */
|
||||
#define DECL_CLONED_FUNCTION_P(NODE) \
|
||||
((TREE_CODE (NODE) == FUNCTION_DECL \
|
||||
|| TREE_CODE (NODE) == TEMPLATE_DECL) \
|
||||
&& DECL_LANG_SPECIFIC (NODE) \
|
||||
#define DECL_CLONED_FUNCTION_P(NODE) \
|
||||
((TREE_CODE (NODE) == FUNCTION_DECL \
|
||||
|| TREE_CODE (NODE) == TEMPLATE_DECL) \
|
||||
&& DECL_LANG_SPECIFIC (NODE) \
|
||||
&& !DECL_LANG_SPECIFIC (NODE)->decl_flags.thunk_p \
|
||||
&& DECL_CLONED_FUNCTION (NODE) != NULL_TREE)
|
||||
|
||||
/* If DECL_CLONED_FUNCTION_P holds, this is the function that was
|
||||
cloned. */
|
||||
#define DECL_CLONED_FUNCTION(NODE) \
|
||||
(DECL_LANG_SPECIFIC (NODE)->u.f.cloned_function)
|
||||
(DECL_LANG_SPECIFIC (NON_THUNK_FUNCTION_CHECK(NODE))->u.f.u5.cloned_function)
|
||||
|
||||
/* Perform an action for each clone of FN, if FN is a function with
|
||||
clones. This macro should be used like:
|
||||
@ -1868,7 +1889,14 @@ struct lang_decl GTY(())
|
||||
/* Nonzero if NODE is a thunk, rather than an ordinary function. */
|
||||
#define DECL_THUNK_P(NODE) \
|
||||
(TREE_CODE (NODE) == FUNCTION_DECL \
|
||||
&& DECL_LANG_FLAG_7 (NODE))
|
||||
&& DECL_LANG_SPECIFIC (NODE) \
|
||||
&& DECL_LANG_SPECIFIC (NODE)->decl_flags.thunk_p)
|
||||
|
||||
/* Set DECL_THUNK_P for node. */
|
||||
#define SET_DECL_THUNK_P(NODE, THIS_ADJUSTING) \
|
||||
(DECL_LANG_SPECIFIC (NODE)->decl_flags.thunk_p = 1, \
|
||||
DECL_LANG_SPECIFIC (NODE)->u.f.u3sel = 1, \
|
||||
DECL_LANG_SPECIFIC (NODE)->decl_flags.this_thunk_p = (THIS_ADJUSTING))
|
||||
|
||||
/* Nonzero if NODE is a this pointer adjusting thunk. */
|
||||
#define DECL_THIS_THUNK_P(NODE) \
|
||||
@ -1890,12 +1918,6 @@ struct lang_decl GTY(())
|
||||
#define DECL_EXTERN_C_FUNCTION_P(NODE) \
|
||||
(DECL_NON_THUNK_FUNCTION_P (NODE) && DECL_EXTERN_C_P (NODE))
|
||||
|
||||
/* Set DECL_THUNK_P for node. */
|
||||
#define SET_DECL_THUNK_P(NODE, THIS_ADJUSTING) \
|
||||
(DECL_LANG_FLAG_7 (NODE) = 1, \
|
||||
DECL_LANG_SPECIFIC (NODE)->u.f.u3sel = 1, \
|
||||
DECL_LANG_SPECIFIC (NODE)->decl_flags.this_thunk_p = (THIS_ADJUSTING))
|
||||
|
||||
/* True iff DECL is an entity with vague linkage whose definition is
|
||||
available in this translation unit. */
|
||||
#define DECL_REPO_AVAILABLE_P(NODE) \
|
||||
@ -2818,7 +2840,7 @@ struct lang_decl GTY(())
|
||||
/* An integer indicating how many bytes should be subtracted from the
|
||||
this or result pointer when this function is called. */
|
||||
#define THUNK_FIXED_OFFSET(DECL) \
|
||||
(DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL))->u.f.fixed_offset)
|
||||
(DECL_LANG_SPECIFIC (THUNK_FUNCTION_CHECK (DECL))->u.f.u5.fixed_offset)
|
||||
|
||||
/* A tree indicating how to perform the virtual adjustment. For a this
|
||||
adjusting thunk it is the number of bytes to be added to the vtable
|
||||
|
@ -150,8 +150,6 @@ make_thunk (tree function, bool this_adjusting,
|
||||
DECL_SAVED_FUNCTION_DATA (thunk) = NULL;
|
||||
DECL_DESTRUCTOR_P (thunk) = 0;
|
||||
DECL_CONSTRUCTOR_P (thunk) = 0;
|
||||
/* And neither is it a clone. */
|
||||
DECL_CLONED_FUNCTION (thunk) = NULL_TREE;
|
||||
DECL_EXTERNAL (thunk) = 1;
|
||||
DECL_ARTIFICIAL (thunk) = 1;
|
||||
/* Even if this thunk is a member of a local class, we don't
|
||||
|
32
gcc/tree.c
32
gcc/tree.c
@ -5402,8 +5402,9 @@ get_set_constructor_bytes (tree init, unsigned char *buffer, int wd_size)
|
||||
#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
|
||||
|
||||
/* Complain that the tree code of NODE does not match the expected 0
|
||||
terminated list of trailing codes. FILE, LINE, and FUNCTION are of
|
||||
the caller. */
|
||||
terminated list of trailing codes. The trailing code list can be
|
||||
empty, for a more vague error message. FILE, LINE, and FUNCTION
|
||||
are of the caller. */
|
||||
|
||||
void
|
||||
tree_check_failed (const tree node, const char *file,
|
||||
@ -5418,22 +5419,27 @@ tree_check_failed (const tree node, const char *file,
|
||||
while ((code = va_arg (args, int)))
|
||||
length += 4 + strlen (tree_code_name[code]);
|
||||
va_end (args);
|
||||
va_start (args, function);
|
||||
buffer = alloca (length);
|
||||
length = 0;
|
||||
while ((code = va_arg (args, int)))
|
||||
if (length)
|
||||
{
|
||||
if (length)
|
||||
va_start (args, function);
|
||||
length += strlen ("expected ");
|
||||
buffer = alloca (length);
|
||||
length = 0;
|
||||
while ((code = va_arg (args, int)))
|
||||
{
|
||||
strcpy (buffer + length, " or ");
|
||||
length += 4;
|
||||
const char *prefix = length ? " or " : "expected ";
|
||||
|
||||
strcpy (buffer + length, prefix);
|
||||
length += strlen (prefix);
|
||||
strcpy (buffer + length, tree_code_name[code]);
|
||||
length += strlen (tree_code_name[code]);
|
||||
}
|
||||
strcpy (buffer + length, tree_code_name[code]);
|
||||
length += strlen (tree_code_name[code]);
|
||||
va_end (args);
|
||||
}
|
||||
va_end (args);
|
||||
else
|
||||
buffer = (char *)"unexpected node";
|
||||
|
||||
internal_error ("tree check: expected %s, have %s in %s, at %s:%d",
|
||||
internal_error ("tree check: %s, have %s in %s, at %s:%d",
|
||||
buffer, tree_code_name[TREE_CODE (node)],
|
||||
function, trim_filename (file), line);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user