From 44d10c10029bc5bec8fb352c6270b07f0d4d82e8 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Wed, 4 Aug 2004 15:33:51 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 9 ++++++ gcc/config/arm/arm.c | 14 ++++++++ gcc/cp/ChangeLog | 21 ++++++++++++ gcc/cp/Make-lang.in | 4 +-- gcc/cp/cp-tree.h | 10 +++--- gcc/cp/decl.c | 77 +++++++++++++++++++++++++++++++------------- gcc/cp/method.c | 13 +++++++- gcc/cp/optimize.c | 8 +++++ gcc/cp/semantics.c | 7 ++-- gcc/doc/tm.texi | 6 ++++ gcc/target-def.h | 7 +++- gcc/target.h | 2 ++ 12 files changed, 146 insertions(+), 32 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 81b43147a36..64fff1d6140 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2004-08-04 Paul Brook + + * 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 * c-lex.c (narrowest_unsigned_type, narrowest_signed_type): Take diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 66fc8f88735..8b1ae87f757 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -168,6 +168,7 @@ static tree arm_cxx_guard_type (void); static bool arm_cxx_guard_mask_bit (void); static tree arm_get_cookie_size (tree); static bool arm_cookie_has_size (void); +static bool arm_cxx_cdtor_returns_this (void); /* Initialize the GCC target structure. */ @@ -282,6 +283,9 @@ static bool arm_cookie_has_size (void); #undef TARGET_CXX_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; /* Obstack for minipool constant handling. */ @@ -14578,3 +14582,13 @@ arm_cookie_has_size (void) { 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; +} diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e82e5005d00..81ac4397627 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,24 @@ +2004-08-04 Paul Brook + + * 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 * class.c (build_vtable): Do not set DECL_VISIBILITY here. diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index 1ce05dac03c..52337392d0b 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -260,10 +260,10 @@ cp/repo.o: cp/repo.c $(CXX_TREE_H) $(TM_H) toplev.h diagnostic.h \ gt-cp-repo.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) \ - 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/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 \ $(TARGET_H) $(TM_P_H) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 5b499256238..e2c94f25ed2 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -708,7 +708,7 @@ struct language_function GTY(()) { struct c_language_function base; - tree x_dtor_label; + tree x_cdtor_label; tree x_current_class_ptr; tree x_current_class_ref; tree x_eh_spec_block; @@ -735,10 +735,12 @@ struct language_function GTY(()) #define cp_function_chain (cfun->language) -/* In a destructor, the point at which all derived class destroying - has been done, just before any base class destroying will be done. */ +/* In a constructor destructor, the point at which all derived class + 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 PARM_DECL for the `this' pointer. The current_class_ref is an diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 8c85e71003d..0f489976a63 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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 save_function_data (tree); static void check_function_type (tree, tree); -static void begin_constructor_body (void); static void finish_constructor_body (void); static void begin_destructor_body (void); static void finish_destructor_body (void); @@ -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. SFK indicates the kind of special function (if any) that this 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 special functions. */ @@ -6197,13 +6197,23 @@ check_special_function_return_type (special_function_kind sfk, if (type) 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; case sfk_destructor: if (type) 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; case sfk_conversion: @@ -6589,6 +6599,9 @@ grokdeclarator (const cp_declarator *declarator, typedef_type = type; + if (sfk != sfk_conversion) + ctor_return_type = ctype; + if (sfk != sfk_none) type = check_special_function_return_type (sfk, type, ctor_return_type); @@ -9879,10 +9892,12 @@ start_preparsed_function (tree decl1, tree attrs, int flags) ++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); - DECL_CONTEXT (dtor_label) = current_function_decl; + cdtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); + DECL_CONTEXT (cdtor_label) = current_function_decl; } start_fname_decls (); @@ -10050,22 +10065,27 @@ save_function_data (tree decl) 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 -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. */ +/* Set the return value of the constructor (if present). */ static 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 @@ -10125,7 +10145,7 @@ finish_destructor_body (void) /* Any return from a destructor will end up here; that way all base 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. */ if (DECL_VIRTUAL_P (current_function_decl)) @@ -10152,6 +10172,18 @@ finish_destructor_body (void) finish_then_clause (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 @@ -10177,8 +10209,6 @@ begin_function_body (void) if (processing_template_decl) /* Do nothing now. */; - else if (DECL_CONSTRUCTOR_P (current_function_decl)) - begin_constructor_body (); else if (DECL_DESTRUCTOR_P (current_function_decl)) begin_destructor_body (); @@ -10363,7 +10393,10 @@ finish_function (int flags) && !DECL_NAME (DECL_RESULT (fndecl)) /* Normally, with -Wreturn-type, flow will complain. Unless we're an 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"); /* Store the end of the function, so that we get good line number diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 7a2a7624fd8..317790e877f 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -929,7 +929,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) { tree fn; tree parameter_types = void_list_node; - tree return_type = void_type_node; + tree return_type; tree fn_type; tree raises = empty_except_spec; tree rhs_parm_type = NULL_TREE; @@ -937,6 +937,17 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) 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) { case sfk_destructor: diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index b94270eabd6..7ccfaffbf0d 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -34,6 +34,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "varray.h" #include "params.h" #include "hashtab.h" +#include "target.h" #include "debug.h" #include "tree-inline.h" #include "flags.h" @@ -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_body (clone, fn, decl_map); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 606fe5fc3f6..cf61c221e72 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -45,6 +45,7 @@ #include "cgraph.h" #include "tree-iterator.h" #include "vec.h" +#include "target.h" /* There routines provide a modular interface to perform many parsing operations. They may therefore be used during actual parsing, or @@ -703,13 +704,15 @@ finish_return_stmt (tree expr) expr = check_return_expr (expr); 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 base-classes before returning. So, all returns in a destructor get sent to the DTOR_LABEL; finish_function emits code to return a value there. */ - return finish_goto_stmt (dtor_label); + return finish_goto_stmt (cdtor_label); } } diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 76fd3871f19..cc3cfeebee4 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -8469,6 +8469,12 @@ modified value and perform any other actions necessary to support the backend's targeted operating system. @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 @section Miscellaneous Parameters @cindex parameters, miscellaneous diff --git a/gcc/target-def.h b/gcc/target-def.h index a3edb019a14..fe06c8c702a 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -412,13 +412,18 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define TARGET_CXX_IMPORT_EXPORT_CLASS NULL #endif +#ifndef TARGET_CXX_CDTOR_RETURNS_THIS +#define TARGET_CXX_CDTOR_RETURNS_THIS hook_bool_void_false +#endif + #define TARGET_CXX \ { \ TARGET_CXX_GUARD_TYPE, \ TARGET_CXX_GUARD_MASK_BIT, \ TARGET_CXX_GET_COOKIE_SIZE, \ TARGET_CXX_COOKIE_HAS_SIZE, \ - TARGET_CXX_IMPORT_EXPORT_CLASS \ + TARGET_CXX_IMPORT_EXPORT_CLASS, \ + TARGET_CXX_CDTOR_RETURNS_THIS \ } /* The whole shebang. */ diff --git a/gcc/target.h b/gcc/target.h index cdcaa18acd9..44562da3964 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -492,6 +492,8 @@ struct gcc_target /* Allows backends to perform additional processing when deciding if a class should be exported or imported. */ int (*import_export_class) (tree, int); + /* Returns true if constructors and destructors return "this". */ + bool (*cdtor_returns_this) (void); } cxx; /* Leave the boolean fields at the end. */ -- 2.30.2