Commit 44d10c10 by Paul Brook Committed by Paul Brook

target-def.h (TARGET_CXX_CDTOR_RETURNS_THIS): Define.

gcc/
	* target-def.h (TARGET_CXX_CDTOR_RETURNS_THIS): Define.
	(TARGET_CXX): Use it.
	* target.h (struct gcc_target): Add cdtor_returns_this.
	* config/arm/arm.c (arm_cxx_cdtor_returns_this): New function.
	(TARGET_CXX_CDTOR_RETURNS_THIS): Define.
	* doc/tm.texi: Document TARGET_CXX_CDTOR_RETURNS_THIS.
gcc/cp/
	* Make-lang.in (cp/semantics.o, cp/optimize.o): Depend on TARGET_H.
	* cp-tree.h (struct language_function): Rename x_dtor_label to
	x_cdtor_label.
	(dtor_label): Rename ...
	(cdtor_label): ... to this.
	* decl.c (begin_constructor_body): Remove.
	(check_special_function_return_type): Maybe change the return type.
	(grokdeclarator): Pass the class type.
	(start_preparsed_function): Constructors may need a return label.
	(finish_constructor_body, finish_destructor_body): Set the return
	value.
	(begin_function_body): Don't call begin_constructor_body.
	(finish_function): Don't warn for constructors or destructors.
	(implicitly_declare_fn): Maybe change the return type.
	* optimize.c: Include target.h.
	(maybe_clone_body): Remap the function result.
	* semantics.c: Include target.h.
	(finish_return_stmt): Maybe jump to return label for constructors.

From-SVN: r85561
parent 20c176ab
2004-08-04 Paul Brook <paul@codesourcery.com>
* target-def.h (TARGET_CXX_CDTOR_RETURNS_THIS): Define.
(TARGET_CXX): Use it.
* target.h (struct gcc_target): Add cdtor_returns_this.
* config/arm/arm.c (arm_cxx_cdtor_returns_this): New function.
(TARGET_CXX_CDTOR_RETURNS_THIS): Define.
* doc/tm.texi: Document TARGET_CXX_CDTOR_RETURNS_THIS.
2004-08-03 Nathan Sidwell <nathan@codesourcery.com> 2004-08-03 Nathan Sidwell <nathan@codesourcery.com>
* c-lex.c (narrowest_unsigned_type, narrowest_signed_type): Take * c-lex.c (narrowest_unsigned_type, narrowest_signed_type): Take
......
...@@ -168,6 +168,7 @@ static tree arm_cxx_guard_type (void); ...@@ -168,6 +168,7 @@ static tree arm_cxx_guard_type (void);
static bool arm_cxx_guard_mask_bit (void); static bool arm_cxx_guard_mask_bit (void);
static tree arm_get_cookie_size (tree); static tree arm_get_cookie_size (tree);
static bool arm_cookie_has_size (void); static bool arm_cookie_has_size (void);
static bool arm_cxx_cdtor_returns_this (void);
/* Initialize the GCC target structure. */ /* Initialize the GCC target structure. */
...@@ -282,6 +283,9 @@ static bool arm_cookie_has_size (void); ...@@ -282,6 +283,9 @@ static bool arm_cookie_has_size (void);
#undef TARGET_CXX_COOKIE_HAS_SIZE #undef TARGET_CXX_COOKIE_HAS_SIZE
#define TARGET_CXX_COOKIE_HAS_SIZE arm_cookie_has_size #define TARGET_CXX_COOKIE_HAS_SIZE arm_cookie_has_size
#undef TARGET_CXX_CDTOR_RETURNS_THIS
#define TARGET_CXX_CDTOR_RETURNS_THIS arm_cxx_cdtor_returns_this
struct gcc_target targetm = TARGET_INITIALIZER; struct gcc_target targetm = TARGET_INITIALIZER;
/* Obstack for minipool constant handling. */ /* Obstack for minipool constant handling. */
...@@ -14578,3 +14582,13 @@ arm_cookie_has_size (void) ...@@ -14578,3 +14582,13 @@ arm_cookie_has_size (void)
{ {
return TARGET_AAPCS_BASED; return TARGET_AAPCS_BASED;
} }
/* The EABI says constructors and destructors should return a pointer to
the object constructed/destroyed. */
static bool
arm_cxx_cdtor_returns_this (void)
{
return TARGET_AAPCS_BASED;
}
2004-08-04 Paul Brook <paul@codesourcery.com>
* Make-lang.in (cp/semantics.o, cp/optimize.o): Depend on TARGET_H.
* cp-tree.h (struct language_function): Rename x_dtor_label to
x_cdtor_label.
(dtor_label): Rename ...
(cdtor_label): ... to this.
* decl.c (begin_constructor_body): Remove.
(check_special_function_return_type): Maybe change the return type.
(grokdeclarator): Pass the class type.
(start_preparsed_function): Constructors may need a return label.
(finish_constructor_body, finish_destructor_body): Set the return
value.
(begin_function_body): Don't call begin_constructor_body.
(finish_function): Don't warn for constructors or destructors.
(implicitly_declare_fn): Maybe change the return type.
* optimize.c: Include target.h.
(maybe_clone_body): Remap the function result.
* semantics.c: Include target.h.
(finish_return_stmt): Maybe jump to return label for constructors.
2004-08-03 Mark Mitchell <mark@codesourcery.com> 2004-08-03 Mark Mitchell <mark@codesourcery.com>
* class.c (build_vtable): Do not set DECL_VISIBILITY here. * class.c (build_vtable): Do not set DECL_VISIBILITY here.
......
...@@ -260,10 +260,10 @@ cp/repo.o: cp/repo.c $(CXX_TREE_H) $(TM_H) toplev.h diagnostic.h \ ...@@ -260,10 +260,10 @@ cp/repo.o: cp/repo.c $(CXX_TREE_H) $(TM_H) toplev.h diagnostic.h \
gt-cp-repo.h gt-cp-repo.h
cp/semantics.o: cp/semantics.c $(CXX_TREE_H) $(TM_H) except.h toplev.h \ cp/semantics.o: cp/semantics.c $(CXX_TREE_H) $(TM_H) except.h toplev.h \
flags.h debug.h output.h $(RTL_H) $(TIMEVAR_H) $(EXPR_H) \ flags.h debug.h output.h $(RTL_H) $(TIMEVAR_H) $(EXPR_H) \
tree-inline.h cgraph.h tree-inline.h cgraph.h $(TAREGT_H)
cp/dump.o: cp/dump.c $(CXX_TREE_H) $(TM_H) tree-dump.h cp/dump.o: cp/dump.c $(CXX_TREE_H) $(TM_H) tree-dump.h
cp/optimize.o: cp/optimize.c $(CXX_TREE_H) $(TM_H) rtl.h integrate.h insn-config.h \ cp/optimize.o: cp/optimize.c $(CXX_TREE_H) $(TM_H) rtl.h integrate.h insn-config.h \
input.h $(PARAMS_H) debug.h tree-inline.h tree-gimple.h input.h $(PARAMS_H) debug.h tree-inline.h tree-gimple.h $(TARGET_H)
cp/mangle.o: cp/mangle.c $(CXX_TREE_H) $(TM_H) toplev.h real.h gt-cp-mangle.h \ cp/mangle.o: cp/mangle.c $(CXX_TREE_H) $(TM_H) toplev.h real.h gt-cp-mangle.h \
$(TARGET_H) $(TM_P_H) $(TARGET_H) $(TM_P_H)
......
...@@ -708,7 +708,7 @@ struct language_function GTY(()) ...@@ -708,7 +708,7 @@ struct language_function GTY(())
{ {
struct c_language_function base; struct c_language_function base;
tree x_dtor_label; tree x_cdtor_label;
tree x_current_class_ptr; tree x_current_class_ptr;
tree x_current_class_ref; tree x_current_class_ref;
tree x_eh_spec_block; tree x_eh_spec_block;
...@@ -735,10 +735,12 @@ struct language_function GTY(()) ...@@ -735,10 +735,12 @@ struct language_function GTY(())
#define cp_function_chain (cfun->language) #define cp_function_chain (cfun->language)
/* In a destructor, the point at which all derived class destroying /* In a constructor destructor, the point at which all derived class
has been done, just before any base class destroying will be done. */ destroying/contruction has been has been done. Ie. just before a
constuctor returns, or before any base class destroying will be done
in a destructor. */
#define dtor_label cp_function_chain->x_dtor_label #define cdtor_label cp_function_chain->x_cdtor_label
/* When we're processing a member function, current_class_ptr is the /* When we're processing a member function, current_class_ptr is the
PARM_DECL for the `this' pointer. The current_class_ref is an PARM_DECL for the `this' pointer. The current_class_ref is an
......
...@@ -100,7 +100,6 @@ static tree check_initializer (tree, tree, int, tree *); ...@@ -100,7 +100,6 @@ static tree check_initializer (tree, tree, int, tree *);
static void make_rtl_for_nonlocal_decl (tree, tree, const char *); static void make_rtl_for_nonlocal_decl (tree, tree, const char *);
static void save_function_data (tree); static void save_function_data (tree);
static void check_function_type (tree, tree); static void check_function_type (tree, tree);
static void begin_constructor_body (void);
static void finish_constructor_body (void); static void finish_constructor_body (void);
static void begin_destructor_body (void); static void begin_destructor_body (void);
static void finish_destructor_body (void); static void finish_destructor_body (void);
...@@ -6182,7 +6181,8 @@ create_array_type_for_decl (tree name, tree type, tree size) ...@@ -6182,7 +6181,8 @@ create_array_type_for_decl (tree name, tree type, tree size)
/* Check that it's OK to declare a function with the indicated TYPE. /* Check that it's OK to declare a function with the indicated TYPE.
SFK indicates the kind of special function (if any) that this SFK indicates the kind of special function (if any) that this
function is. OPTYPE is the type given in a conversion operator function is. OPTYPE is the type given in a conversion operator
declaration. Returns the actual return type of the function; that declaration, or the class type for a constructor/destructor.
Returns the actual return type of the function; that
may be different than TYPE if an error occurs, or for certain may be different than TYPE if an error occurs, or for certain
special functions. */ special functions. */
...@@ -6197,13 +6197,23 @@ check_special_function_return_type (special_function_kind sfk, ...@@ -6197,13 +6197,23 @@ check_special_function_return_type (special_function_kind sfk,
if (type) if (type)
error ("return type specification for constructor invalid"); error ("return type specification for constructor invalid");
type = void_type_node; if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (optype))
type = build_pointer_type (optype);
else
type = void_type_node;
break; break;
case sfk_destructor: case sfk_destructor:
if (type) if (type)
error ("return type specification for destructor invalid"); error ("return type specification for destructor invalid");
type = void_type_node; /* We can't use the proper return type here because we run into
problems with abiguous bases and covariant returns.
Java classes are left unchanged because (void *) isn't a valid
Java type, and we don't want to change the Java ABI. */
if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (optype))
type = build_pointer_type (void_type_node);
else
type = void_type_node;
break; break;
case sfk_conversion: case sfk_conversion:
...@@ -6589,6 +6599,9 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -6589,6 +6599,9 @@ grokdeclarator (const cp_declarator *declarator,
typedef_type = type; typedef_type = type;
if (sfk != sfk_conversion)
ctor_return_type = ctype;
if (sfk != sfk_none) if (sfk != sfk_none)
type = check_special_function_return_type (sfk, type, type = check_special_function_return_type (sfk, type,
ctor_return_type); ctor_return_type);
...@@ -9879,10 +9892,12 @@ start_preparsed_function (tree decl1, tree attrs, int flags) ...@@ -9879,10 +9892,12 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
++function_depth; ++function_depth;
if (DECL_DESTRUCTOR_P (decl1)) if (DECL_DESTRUCTOR_P (decl1)
|| (DECL_CONSTRUCTOR_P (decl1)
&& targetm.cxx.cdtor_returns_this ()))
{ {
dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); cdtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
DECL_CONTEXT (dtor_label) = current_function_decl; DECL_CONTEXT (cdtor_label) = current_function_decl;
} }
start_fname_decls (); start_fname_decls ();
...@@ -10050,22 +10065,27 @@ save_function_data (tree decl) ...@@ -10050,22 +10065,27 @@ save_function_data (tree decl)
f->x_local_names = NULL; f->x_local_names = NULL;
} }
/* Add a note to mark the beginning of the main body of the constructor.
This is used to set up the data structures for the cleanup regions for
fully-constructed bases and members. */
static void /* Set the return value of the constructor (if present). */
begin_constructor_body (void)
{
}
/* Add a note to mark the end of the main body of the constructor. This is
used to end the cleanup regions for fully-constructed bases and
members. */
static void static void
finish_constructor_body (void) finish_constructor_body (void)
{ {
tree val;
tree exprstmt;
if (targetm.cxx.cdtor_returns_this ())
{
/* Any return from a constructor will end up here. */
add_stmt (build_stmt (LABEL_EXPR, cdtor_label));
val = DECL_ARGUMENTS (current_function_decl);
val = build (MODIFY_EXPR, TREE_TYPE (val),
DECL_RESULT (current_function_decl), val);
/* Return the address of the object. */
exprstmt = build_stmt (RETURN_EXPR, val);
add_stmt (exprstmt);
}
} }
/* Do all the processing for the beginning of a destructor; set up the /* Do all the processing for the beginning of a destructor; set up the
...@@ -10125,7 +10145,7 @@ finish_destructor_body (void) ...@@ -10125,7 +10145,7 @@ finish_destructor_body (void)
/* Any return from a destructor will end up here; that way all base /* Any return from a destructor will end up here; that way all base
and member cleanups will be run when the function returns. */ and member cleanups will be run when the function returns. */
add_stmt (build_stmt (LABEL_EXPR, dtor_label)); add_stmt (build_stmt (LABEL_EXPR, cdtor_label));
/* In a virtual destructor, we must call delete. */ /* In a virtual destructor, we must call delete. */
if (DECL_VIRTUAL_P (current_function_decl)) if (DECL_VIRTUAL_P (current_function_decl))
...@@ -10152,6 +10172,18 @@ finish_destructor_body (void) ...@@ -10152,6 +10172,18 @@ finish_destructor_body (void)
finish_then_clause (if_stmt); finish_then_clause (if_stmt);
finish_if_stmt (if_stmt); finish_if_stmt (if_stmt);
} }
if (targetm.cxx.cdtor_returns_this ())
{
tree val;
val = DECL_ARGUMENTS (current_function_decl);
val = build (MODIFY_EXPR, TREE_TYPE (val),
DECL_RESULT (current_function_decl), val);
/* Return the address of the object. */
exprstmt = build_stmt (RETURN_EXPR, val);
add_stmt (exprstmt);
}
} }
/* Do the necessary processing for the beginning of a function body, which /* Do the necessary processing for the beginning of a function body, which
...@@ -10177,8 +10209,6 @@ begin_function_body (void) ...@@ -10177,8 +10209,6 @@ begin_function_body (void)
if (processing_template_decl) if (processing_template_decl)
/* Do nothing now. */; /* Do nothing now. */;
else if (DECL_CONSTRUCTOR_P (current_function_decl))
begin_constructor_body ();
else if (DECL_DESTRUCTOR_P (current_function_decl)) else if (DECL_DESTRUCTOR_P (current_function_decl))
begin_destructor_body (); begin_destructor_body ();
...@@ -10363,7 +10393,10 @@ finish_function (int flags) ...@@ -10363,7 +10393,10 @@ finish_function (int flags)
&& !DECL_NAME (DECL_RESULT (fndecl)) && !DECL_NAME (DECL_RESULT (fndecl))
/* Normally, with -Wreturn-type, flow will complain. Unless we're an /* Normally, with -Wreturn-type, flow will complain. Unless we're an
inline function, as we might never be compiled separately. */ inline function, as we might never be compiled separately. */
&& (DECL_INLINE (fndecl) || processing_template_decl)) && (DECL_INLINE (fndecl) || processing_template_decl)
/* Structor return values (if any) are set by the compiler. */
&& !DECL_CONSTRUCTOR_P (fndecl)
&& !DECL_DESTRUCTOR_P (fndecl))
warning ("no return statement in function returning non-void"); warning ("no return statement in function returning non-void");
/* Store the end of the function, so that we get good line number /* Store the end of the function, so that we get good line number
......
...@@ -929,7 +929,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) ...@@ -929,7 +929,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
{ {
tree fn; tree fn;
tree parameter_types = void_list_node; tree parameter_types = void_list_node;
tree return_type = void_type_node; tree return_type;
tree fn_type; tree fn_type;
tree raises = empty_except_spec; tree raises = empty_except_spec;
tree rhs_parm_type = NULL_TREE; tree rhs_parm_type = NULL_TREE;
...@@ -937,6 +937,17 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) ...@@ -937,6 +937,17 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
type = TYPE_MAIN_VARIANT (type); type = TYPE_MAIN_VARIANT (type);
if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (type))
{
if (kind == sfk_destructor)
/* See comment in check_special_function_return_type. */
return_type = build_pointer_type (void_type_node);
else
return_type = build_pointer_type (type);
}
else
return_type = void_type_node;
switch (kind) switch (kind)
{ {
case sfk_destructor: case sfk_destructor:
......
...@@ -34,6 +34,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA ...@@ -34,6 +34,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "varray.h" #include "varray.h"
#include "params.h" #include "params.h"
#include "hashtab.h" #include "hashtab.h"
#include "target.h"
#include "debug.h" #include "debug.h"
#include "tree-inline.h" #include "tree-inline.h"
#include "flags.h" #include "flags.h"
...@@ -184,6 +185,13 @@ maybe_clone_body (tree fn) ...@@ -184,6 +185,13 @@ maybe_clone_body (tree fn)
} }
} }
if (targetm.cxx.cdtor_returns_this ())
{
parm = DECL_RESULT (fn);
clone_parm = DECL_RESULT (clone);
splay_tree_insert (decl_map, (splay_tree_key) parm,
(splay_tree_value) clone_parm);
}
/* Clone the body. */ /* Clone the body. */
clone_body (clone, fn, decl_map); clone_body (clone, fn, decl_map);
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
#include "cgraph.h" #include "cgraph.h"
#include "tree-iterator.h" #include "tree-iterator.h"
#include "vec.h" #include "vec.h"
#include "target.h"
/* There routines provide a modular interface to perform many parsing /* There routines provide a modular interface to perform many parsing
operations. They may therefore be used during actual parsing, or operations. They may therefore be used during actual parsing, or
...@@ -703,13 +704,15 @@ finish_return_stmt (tree expr) ...@@ -703,13 +704,15 @@ finish_return_stmt (tree expr)
expr = check_return_expr (expr); expr = check_return_expr (expr);
if (!processing_template_decl) if (!processing_template_decl)
{ {
if (DECL_DESTRUCTOR_P (current_function_decl)) if (DECL_DESTRUCTOR_P (current_function_decl)
|| (DECL_CONSTRUCTOR_P (current_function_decl)
&& targetm.cxx.cdtor_returns_this ()))
{ {
/* Similarly, all destructors must run destructors for /* Similarly, all destructors must run destructors for
base-classes before returning. So, all returns in a base-classes before returning. So, all returns in a
destructor get sent to the DTOR_LABEL; finish_function emits destructor get sent to the DTOR_LABEL; finish_function emits
code to return a value there. */ code to return a value there. */
return finish_goto_stmt (dtor_label); return finish_goto_stmt (cdtor_label);
} }
} }
......
...@@ -8469,6 +8469,12 @@ modified value and perform any other actions necessary to support the ...@@ -8469,6 +8469,12 @@ modified value and perform any other actions necessary to support the
backend's targeted operating system. backend's targeted operating system.
@end deftypefn @end deftypefn
@deftypefn {Target Hook} bool TARGET_CXX_CDTOR_RETURNS_THIS (void)
This hook should return @code{true} if constructors and destructors return
the address of the object created/destroyed. The default is to return
@code{false}.
@end deftypefn
@node Misc @node Misc
@section Miscellaneous Parameters @section Miscellaneous Parameters
@cindex parameters, miscellaneous @cindex parameters, miscellaneous
......
...@@ -412,13 +412,18 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ...@@ -412,13 +412,18 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define TARGET_CXX_IMPORT_EXPORT_CLASS NULL #define TARGET_CXX_IMPORT_EXPORT_CLASS NULL
#endif #endif
#ifndef TARGET_CXX_CDTOR_RETURNS_THIS
#define TARGET_CXX_CDTOR_RETURNS_THIS hook_bool_void_false
#endif
#define TARGET_CXX \ #define TARGET_CXX \
{ \ { \
TARGET_CXX_GUARD_TYPE, \ TARGET_CXX_GUARD_TYPE, \
TARGET_CXX_GUARD_MASK_BIT, \ TARGET_CXX_GUARD_MASK_BIT, \
TARGET_CXX_GET_COOKIE_SIZE, \ TARGET_CXX_GET_COOKIE_SIZE, \
TARGET_CXX_COOKIE_HAS_SIZE, \ TARGET_CXX_COOKIE_HAS_SIZE, \
TARGET_CXX_IMPORT_EXPORT_CLASS \ TARGET_CXX_IMPORT_EXPORT_CLASS, \
TARGET_CXX_CDTOR_RETURNS_THIS \
} }
/* The whole shebang. */ /* The whole shebang. */
......
...@@ -492,6 +492,8 @@ struct gcc_target ...@@ -492,6 +492,8 @@ struct gcc_target
/* Allows backends to perform additional processing when /* Allows backends to perform additional processing when
deciding if a class should be exported or imported. */ deciding if a class should be exported or imported. */
int (*import_export_class) (tree, int); int (*import_export_class) (tree, int);
/* Returns true if constructors and destructors return "this". */
bool (*cdtor_returns_this) (void);
} cxx; } cxx;
/* Leave the boolean fields at the end. */ /* Leave the boolean fields at the end. */
......
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