cp-tree.def (THUNK_DECL): Remove.

* cp-tree.def (THUNK_DECL): Remove.
	* cp-tree.h (DECL_THUNK_P): New macro.
	(DECL_NON_THUNK_FUNCTION_P): Likewise.
	(DECL_EXTERN_C_FUNCTION_P): Likewise.
	(SET_DECL_THUNK_P): Likewise.
	(DELTA_FROM_VTABLE_ENTRY): Use DECL_THUNK_P.
	(FNADDR_FROM_VTABLE_ENTRY): Likewise.
	(DECL_MAIN_P): Use DECL_EXTERN_C_FUNCTION_P.
	* decl.c (decls_match): Use DECL_EXTERN_C_P.
	(duplicate_decls): Likewise.
	(pushdecl): Likewise.  Adjust thunk handling.
	(grokfndecl): Use DECL_EXTERN_C_P.
	* decl2.c (mark_vtable_entries): Use DECL_THUNK_P.
	* dump.c (dequeue_and_dump): Remove THUNK_DECL handling.
	* except.c (nothrow_libfn_p): Use DECL_EXTERN_C_P.
	* expr.c (cplus_expand_expr): Remove THUNK_DECL handling.
	* method.c (make_thunk): Use SET_DECL_THUNK_P.  Set
	DECL_NO_STATIC_CHAIN.
	(emit_thunk): Don't play games with TREE_CODE on thunks.  Don't
	set DECL_DESTRUCTOR_P or DECL_CONSTRUCTOR_P on a thunk.
	* search.c (covariant_return_p): Remove THUNK_DECL handling.
	* ir.texi: Update.

From-SVN: r33647
This commit is contained in:
Mark Mitchell 2000-05-03 22:25:21 +00:00 committed by Mark Mitchell
parent 6428983a53
commit eb68cb5821
11 changed files with 122 additions and 80 deletions

View file

@ -1,3 +1,28 @@
2000-05-03 Mark Mitchell <mark@codesourcery.com>
* cp-tree.def (THUNK_DECL): Remove.
* cp-tree.h (DECL_THUNK_P): New macro.
(DECL_NON_THUNK_FUNCTION_P): Likewise.
(DECL_EXTERN_C_FUNCTION_P): Likewise.
(SET_DECL_THUNK_P): Likewise.
(DELTA_FROM_VTABLE_ENTRY): Use DECL_THUNK_P.
(FNADDR_FROM_VTABLE_ENTRY): Likewise.
(DECL_MAIN_P): Use DECL_EXTERN_C_FUNCTION_P.
* decl.c (decls_match): Use DECL_EXTERN_C_P.
(duplicate_decls): Likewise.
(pushdecl): Likewise. Adjust thunk handling.
(grokfndecl): Use DECL_EXTERN_C_P.
* decl2.c (mark_vtable_entries): Use DECL_THUNK_P.
* dump.c (dequeue_and_dump): Remove THUNK_DECL handling.
* except.c (nothrow_libfn_p): Use DECL_EXTERN_C_P.
* expr.c (cplus_expand_expr): Remove THUNK_DECL handling.
* method.c (make_thunk): Use SET_DECL_THUNK_P. Set
DECL_NO_STATIC_CHAIN.
(emit_thunk): Don't play games with TREE_CODE on thunks. Don't
set DECL_DESTRUCTOR_P or DECL_CONSTRUCTOR_P on a thunk.
* search.c (covariant_return_p): Remove THUNK_DECL handling.
* ir.texi: Update.
2000-05-01 Jason Merrill <jason@casey.cygnus.com>
* tree.c (walk_tree): Set lineno.

View file

@ -158,28 +158,6 @@ DEFTREECODE (TYPENAME_TYPE, "typename_type", 't', 0)
expression in question. */
DEFTREECODE (TYPEOF_TYPE, "typeof_type", 't', 0)
/* A thunk is a stub function.
A THUNK_DECL is an alternate entry point for an ordinary
FUNCTION_DECL. The address of the ordinary FUNCTION_DECL is given
by the DECL_INITIAL, which is always an ADDR_EXPR whose operand is
a FUNCTION_DECL. The job of the thunk is to adjust the `this'
pointer before transferring control to the FUNCTION_DECL.
A thunk may perform either, or both, of the following operations:
o Adjust the `this' pointer by a constant offset.
o Adjust the `this' pointer by looking up a vcall-offset
in the vtable.
If both operations are performed, then the constant adjument to
`this' is performed first.
The constant adjustment is given by THUNK_DELTA. If the
vcall-offset is required, the index into the vtable is given by
THUNK_VCALL_OFFSET. */
DEFTREECODE (THUNK_DECL, "thunk_decl", 'd', 0)
/* A using declaration. DECL_INITIAL contains the specified scope.
This is not an alias, but is later expanded into multiple aliases. */
DEFTREECODE (USING_DECL, "using_decl", 'd', 0)

View file

@ -1297,7 +1297,8 @@ enum languages { lang_c, lang_cplusplus, lang_java };
#define DELTA_FROM_VTABLE_ENTRY(ENTRY) \
(!flag_vtable_thunks ? \
TREE_VALUE (CONSTRUCTOR_ELTS (ENTRY)) \
: TREE_CODE (TREE_OPERAND ((ENTRY), 0)) != THUNK_DECL ? integer_zero_node \
: !DECL_THUNK_P (TREE_OPERAND ((ENTRY), 0)) \
? integer_zero_node \
: build_int_2 (THUNK_DELTA (TREE_OPERAND ((ENTRY), 0)), 0))
/* Virtual function addresses can be gotten from a virtual function
@ -1305,8 +1306,10 @@ enum languages { lang_c, lang_cplusplus, lang_java };
#define FNADDR_FROM_VTABLE_ENTRY(ENTRY) \
(!flag_vtable_thunks ? \
TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (ENTRY)))) \
: TREE_CODE (TREE_OPERAND ((ENTRY), 0)) != THUNK_DECL ? (ENTRY) \
: !DECL_THUNK_P (TREE_OPERAND ((ENTRY), 0)) \
? (ENTRY) \
: DECL_INITIAL (TREE_OPERAND ((ENTRY), 0)))
#define SET_FNADDR_FROM_VTABLE_ENTRY(ENTRY,VALUE) \
(TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (ENTRY)))) = (VALUE))
#define FUNCTION_ARG_CHAIN(NODE) (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (NODE))))
@ -2099,6 +2102,27 @@ struct lang_decl
must be overridden by derived classes. */
#define DECL_NEEDS_FINAL_OVERRIDER_P(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.needs_final_overrider)
/* 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))
/* Nonzero if NODE is a FUNCTION_DECL, but not a thunk. */
#define DECL_NON_THUNK_FUNCTION_P(NODE) \
(TREE_CODE (NODE) == FUNCTION_DECL && !DECL_THUNK_P (NODE))
/* Nonzero if NODE is `extern "C"'. */
#define DECL_EXTERN_C_P(NODE) \
(DECL_LANGUAGE (NODE) == lang_c)
/* Nonzero if NODE is an `extern "C"' function. */
#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) \
(DECL_LANG_FLAG_7 (NODE) = 1)
/* Nonzero if this DECL is the __PRETTY_FUNCTION__ variable in a
template function. */
#define DECL_PRETTY_FUNCTION_P(NODE) \
@ -2986,6 +3010,27 @@ extern int flag_new_for_scope;
#define DECL_REALLY_EXTERN(NODE) \
(DECL_EXTERNAL (NODE) && ! DECL_NOT_REALLY_EXTERN (NODE))
/* A thunk is a stub function.
A thunk is an alternate entry point for an ordinary FUNCTION_DECL.
The address of the ordinary FUNCTION_DECL is given by the
DECL_INITIAL, which is always an ADDR_EXPR whose operand is a
FUNCTION_DECL. The job of the thunk is to adjust the `this'
pointer before transferring control to the FUNCTION_DECL.
A thunk may perform either, or both, of the following operations:
o Adjust the `this' pointer by a constant offset.
o Adjust the `this' pointer by looking up a vcall-offset
in the vtable.
If both operations are performed, then the constant adjument to
`this' is performed first.
The constant adjustment is given by THUNK_DELTA. If the
vcall-offset is required, the index into the vtable is given by
THUNK_VCALL_OFFSET. */
/* An integer indicating how many bytes should be subtracted from the
`this' pointer when this function is called. */
#define THUNK_DELTA(DECL) (DECL_CHECK (DECL)->decl.u1.i)
@ -3472,8 +3517,7 @@ extern tree original_function_name;
/* Returns non-zero iff NODE is a declaration for the global function
`main'. */
#define DECL_MAIN_P(NODE) \
(TREE_CODE (NODE) == FUNCTION_DECL \
&& DECL_LANGUAGE (NODE) == lang_c \
(DECL_EXTERN_C_FUNCTION_P (NODE) \
&& DECL_NAME (NODE) != NULL_TREE \
&& MAIN_NAME_P (DECL_NAME (NODE)))

View file

@ -2927,8 +2927,8 @@ decls_match (newdecl, olddecl)
tree p2 = TYPE_ARG_TYPES (f2);
if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl)
&& ! (DECL_LANGUAGE (newdecl) == lang_c
&& DECL_LANGUAGE (olddecl) == lang_c))
&& ! (DECL_EXTERN_C_P (newdecl)
&& DECL_EXTERN_C_P (olddecl)))
return 0;
if (TREE_CODE (f1) != TREE_CODE (f2))
@ -2937,15 +2937,17 @@ decls_match (newdecl, olddecl)
if (same_type_p (TREE_TYPE (f1), TREE_TYPE (f2)))
{
if ((! strict_prototypes_lang_c || DECL_BUILT_IN (olddecl))
&& DECL_LANGUAGE (olddecl) == lang_c
&& DECL_EXTERN_C_P (olddecl)
&& p2 == NULL_TREE)
{
types_match = self_promoting_args_p (p1);
if (p1 == void_list_node)
TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
}
else if (!strict_prototypes_lang_c && DECL_LANGUAGE (olddecl)==lang_c
&& DECL_LANGUAGE (newdecl) == lang_c && p1 == NULL_TREE)
else if (!strict_prototypes_lang_c
&& DECL_EXTERN_C_P (olddecl)
&& DECL_EXTERN_C_P (newdecl)
&& p1 == NULL_TREE)
{
types_match = self_promoting_args_p (p2);
TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
@ -3094,8 +3096,8 @@ duplicate_decls (newdecl, olddecl)
}
else if (!types_match)
{
if ((DECL_LANGUAGE (newdecl) == lang_c
&& DECL_LANGUAGE (olddecl) == lang_c)
if ((DECL_EXTERN_C_P (newdecl)
&& DECL_EXTERN_C_P (olddecl))
|| compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
{
@ -3203,8 +3205,7 @@ duplicate_decls (newdecl, olddecl)
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_LANGUAGE (newdecl) == lang_c
&& DECL_LANGUAGE (olddecl) == lang_c)
if (DECL_EXTERN_C_P (newdecl) && DECL_EXTERN_C_P (olddecl))
{
cp_error ("declaration of C function `%#D' conflicts with",
newdecl);
@ -3801,7 +3802,7 @@ pushdecl (x)
if (duplicate_decls (x, t))
return t;
}
else if (((TREE_CODE (x) == FUNCTION_DECL && DECL_LANGUAGE (x) == lang_c)
else if ((DECL_EXTERN_C_FUNCTION_P (x)
|| DECL_FUNCTION_TEMPLATE_P (x))
&& is_overloaded_fn (t))
/* Don't do anything just yet. */;
@ -3877,14 +3878,13 @@ pushdecl (x)
/* If this is a function conjured up by the backend, massage it
so it looks friendly. */
if (TREE_CODE (x) == FUNCTION_DECL
&& ! DECL_LANG_SPECIFIC (x))
if (DECL_NON_THUNK_FUNCTION_P (x) && ! DECL_LANG_SPECIFIC (x))
{
retrofit_lang_decl (x);
DECL_LANGUAGE (x) = lang_c;
}
if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
if (DECL_NON_THUNK_FUNCTION_P (x) && ! DECL_FUNCTION_MEMBER_P (x))
{
t = push_overloaded_decl (x, PUSH_LOCAL);
if (t != x)
@ -3980,8 +3980,7 @@ pushdecl (x)
the mangled name (i.e., NAME) to the DECL. But, for
an `extern "C"' function, the mangled name and the
ordinary name are the same so we need not do this. */
&& !(TREE_CODE (x) == FUNCTION_DECL &&
DECL_LANGUAGE (x) == lang_c))
&& !DECL_EXTERN_C_FUNCTION_P (x))
{
if (TREE_CODE (x) == FUNCTION_DECL)
my_friendly_assert
@ -8711,7 +8710,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
{
if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
{
if (DECL_LANGUAGE (decl) == lang_c)
if (DECL_EXTERN_C_P (decl))
/* Allow this; it's pretty common in C. */;
else
cp_pedwarn ("non-local function `%#D' uses anonymous type",
@ -8802,7 +8801,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
/* Plain overloading: will not be grok'd by grokclassfn. */
if (! ctype && ! processing_template_decl
&& DECL_LANGUAGE (decl) != lang_c
&& !DECL_EXTERN_C_P (decl)
&& (! DECL_USE_TEMPLATE (decl) || name_mangling_version < 1))
set_mangled_name_for_decl (decl);

View file

@ -2338,7 +2338,7 @@ mark_vtable_entries (decl)
fn = TREE_OPERAND (fnaddr, 0);
TREE_ADDRESSABLE (fn) = 1;
if (TREE_CODE (fn) == THUNK_DECL && DECL_EXTERNAL (fn))
if (DECL_THUNK_P (fn) && DECL_EXTERNAL (fn))
{
DECL_EXTERNAL (fn) = 0;
emit_thunk (fn);

View file

@ -556,7 +556,6 @@ dequeue_and_dump (di)
break;
case FUNCTION_DECL:
case THUNK_DECL:
dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
dump_child ("args", DECL_ARGUMENTS (t));
if (DECL_EXTERNAL (t))

View file

@ -1097,7 +1097,7 @@ nothrow_libfn_p (fn)
if (TREE_PUBLIC (fn)
&& DECL_EXTERNAL (fn)
&& DECL_LANGUAGE (fn) == lang_c)
&& DECL_EXTERN_C_P (fn))
/* OK */;
else
/* Can't be a C library function. */

View file

@ -128,10 +128,6 @@ cplus_expand_expr (exp, target, tmode, modifier)
target, tmode, EXPAND_NORMAL);
}
case THUNK_DECL:
my_friendly_assert (DECL_RTL (exp) != NULL_RTX, 20000115);
return DECL_RTL (exp);
case THROW_EXPR:
expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
expand_internal_throw ();

View file

@ -885,21 +885,6 @@ contains the instantiations. The @code{TREE_VALUE} of each node is an
instantiation of the class. The @code{DECL_TEMPLATE_SPECIALIZATIONS}
contains partial specializations of the class.
@item THUNK_DECL
These nodes represent stub code that adjusts the @code{this} pointer and
then jumps to another function. When the jumped-to function returns,
control is transferred directly to the caller, without returning to the
thunk. The first parameter to the thunk is always the @code{this}
pointer; the thunk should add @code{THUNK_DELTA} to this value. (The
@code{THUNK_DELTA} is an @code{int}, not an @code{INTEGER_CST}.) Then,
the thunk should jump to the location given by @code{DECL_INITIAL}; this
will always be an expression for the address of a function.
You can use @code{DECL_ASSEMBLER_NAME}, @code{TREE_PUBLIC}, and
@code{DECL_ARGUMENTS} with a @code{THUNK_DECL}, just as with a
@code{FUNCTION_DECL}.
@item USING_DECL
Back-ends can safely ignore these nodes.
@ -1044,6 +1029,19 @@ function.
This predicate holds if the function is a file-scope finalization
function.
@item DECL_THUNK_P
This predicate holds if the function is a thunk.
These functions represent stub code that adjusts the @code{this} pointer
and then jumps to another function. When the jumped-to function
returns, control is transferred directly to the caller, without
returning to the thunk. The first parameter to the thunk is always the
@code{this} pointer; the thunk should add @code{THUNK_DELTA} to this
value. (The @code{THUNK_DELTA} is an @code{int}, not an
@code{INTEGER_CST}.) Then, the thunk should jump to the location given
by @code{DECL_INITIAL}; this will always be an expression for the
address of a function.
@item GLOBAL_INIT_PRIORITY
If either @code{DECL_GLOBAL_CTOR_P} or @code{DECL_GLOBAL_DTOR_P} holds,
then this gives the initialization priority for the function. The
@ -1895,7 +1893,7 @@ by the last @code{EXPR_STMT} in the outermost scope of the
@end example
the value is @code{3} while in:
@example
(@{ if (x) { 3; } @})
(@{ if (x) @{ 3; @} @})
@end example
(represented by a nested @code{COMPOUND_STMT}), there is no value. If
the @code{STMT_EXPR} does not yield a value, it's type will be

View file

@ -2046,7 +2046,7 @@ make_thunk (function, delta, vcall_index)
thunk_id = get_identifier (obstack_base (&scratch_obstack));
thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id);
if (thunk && TREE_CODE (thunk) != THUNK_DECL)
if (thunk && !DECL_THUNK_P (thunk))
{
cp_error ("implementation-reserved name `%D' used", thunk_id);
thunk = NULL_TREE;
@ -2058,7 +2058,7 @@ make_thunk (function, delta, vcall_index)
TREE_READONLY (thunk) = TREE_READONLY (func_decl);
TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (func_decl);
comdat_linkage (thunk);
TREE_SET_CODE (thunk, THUNK_DECL);
SET_DECL_THUNK_P (thunk);
DECL_INITIAL (thunk) = function;
THUNK_DELTA (thunk) = delta;
THUNK_VCALL_OFFSET (thunk)
@ -2066,6 +2066,9 @@ make_thunk (function, delta, vcall_index)
DECL_EXTERNAL (thunk) = 1;
DECL_ARTIFICIAL (thunk) = 1;
DECL_CONTEXT (thunk) = DECL_CONTEXT (func_decl);
/* Even if this thunk is a member of a local class, we don't
need a static chain. */
DECL_NO_STATIC_CHAIN (thunk) = 1;
/* So that finish_file can write out any thunks that need to be: */
pushdecl_top_level (thunk);
}
@ -2094,8 +2097,6 @@ emit_thunk (thunk_fndecl)
if (current_function_decl)
abort ();
TREE_SET_CODE (thunk_fndecl, FUNCTION_DECL);
#ifdef ASM_OUTPUT_MI_THUNK
if (!flag_syntax_only && vcall_offset == 0)
{
@ -2146,6 +2147,11 @@ emit_thunk (thunk_fndecl)
DECL_NOT_REALLY_EXTERN (thunk_fndecl) = 1;
DECL_SAVED_FUNCTION_DATA (thunk_fndecl) = NULL;
/* The thunk itself is not a constructor or destructor, even if
the thing it is thunking to is. */
DECL_DESTRUCTOR_P (thunk_fndecl) = 0;
DECL_CONSTRUCTOR_P (thunk_fndecl) = 0;
push_to_top_level ();
start_function (NULL_TREE, thunk_fndecl, NULL_TREE, SF_PRE_PARSED);
store_parm_decls ();
@ -2207,8 +2213,6 @@ emit_thunk (thunk_fndecl)
if (DECL_DEFER_OUTPUT (thunk_fndecl))
output_inline_function (thunk_fndecl);
}
TREE_SET_CODE (thunk_fndecl, THUNK_DECL);
}
/* Code for synthesizing methods which have default semantics defined. */

View file

@ -1989,8 +1989,7 @@ covariant_return_p (brettype, drettype)
{
tree binfo;
if (TREE_CODE (brettype) == FUNCTION_DECL
|| TREE_CODE (brettype) == THUNK_DECL)
if (TREE_CODE (brettype) == FUNCTION_DECL)
{
brettype = TREE_TYPE (TREE_TYPE (brettype));
drettype = TREE_TYPE (TREE_TYPE (drettype));