Commit 3dbc07b6 by Mark Mitchell Committed by Mark Mitchell

Under the new ABI, constructors don't return `this'.

	* cp-tree.h (warn_reorder): Declare.
	(special_function_kind): New enum.
	(global_base_init_list): Remove declaration.
	(emit_base_init): Don't return a value.
	(check_base_init): Don't declare.
	(is_aggr_typedef): Likewise.
	* decl.c (check_special_function_return_type): New function.
	(return_types): Remove.
	(grokdeclarator): Use check_special_function_return_type.
	(start_function): Don't initialize ctor_label under the new ABI.
	(finish_construtor_body): Don't create a corresponding LABEL_STMT.
	* init.c (begin_init_stmts): Move to top of file.
	(finish_init_stmts): Likewise.
	(warn_reorder): Don't declare.
	(emit_base_init): Don't create a STMT_EXPR here.  Don't return a
	value.
	(check_base_init): Remove.
	(is_aggr_typedef): Likewise.
	(build_new_1): Don't use the return value of a constructor.
	* semantics.c (setup_vtbl_ptr): Don't use the return value
	of emit_base_init.
	* typeck.c (check_return_expr): Don't magically convert return
	statements into `return this' in constructors under the new ABI.

From-SVN: r33035
parent 4eaf5996
2000-04-08 Mark Mitchell <mark@codesourcery.com> 2000-04-08 Mark Mitchell <mark@codesourcery.com>
Under the new ABI, constructors don't return `this'.
* cp-tree.h (warn_reorder): Declare.
(special_function_kind): New enum.
(global_base_init_list): Remove declaration.
(emit_base_init): Don't return a value.
(check_base_init): Don't declare.
(is_aggr_typedef): Likewise.
* decl.c (check_special_function_return_type): New function.
(return_types): Remove.
(grokdeclarator): Use check_special_function_return_type.
(start_function): Don't initialize ctor_label under the new ABI.
(finish_construtor_body): Don't create a corresponding LABEL_STMT.
* init.c (begin_init_stmts): Move to top of file.
(finish_init_stmts): Likewise.
(warn_reorder): Don't declare.
(emit_base_init): Don't create a STMT_EXPR here. Don't return a
value.
(check_base_init): Remove.
(is_aggr_typedef): Likewise.
(build_new_1): Don't use the return value of a constructor.
* semantics.c (setup_vtbl_ptr): Don't use the return value
of emit_base_init.
* typeck.c (check_return_expr): Don't magically convert return
statements into `return this' in constructors under the new ABI.
* cp-tree.h (cp_tree_index): Add CPTI_BASE_CTOR_IDENTIFIER, * cp-tree.h (cp_tree_index): Add CPTI_BASE_CTOR_IDENTIFIER,
CPTI_BASE_DTOR_IDENTIFIER, and CPTI_DELETING_DTOR_IDENTIFIER. CPTI_BASE_DTOR_IDENTIFIER, and CPTI_DELETING_DTOR_IDENTIFIER.
(base_ctor_identifier): New macro. (base_ctor_identifier): New macro.
......
...@@ -1102,6 +1102,10 @@ extern int warn_extern_inline; ...@@ -1102,6 +1102,10 @@ extern int warn_extern_inline;
extern int warn_old_style_cast; extern int warn_old_style_cast;
/* Non-zero means warn when the compiler will reorder code. */
extern int warn_reorder;
/* Nonzero means to treat bitfields as unsigned unless they say `signed'. */ /* Nonzero means to treat bitfields as unsigned unless they say `signed'. */
extern int flag_signed_bitfields; extern int flag_signed_bitfields;
...@@ -3098,6 +3102,13 @@ typedef enum access_kind { ...@@ -3098,6 +3102,13 @@ typedef enum access_kind {
ak_private = 3 /* Accessible, as a `private' thing. */ ak_private = 3 /* Accessible, as a `private' thing. */
} access_kind; } access_kind;
typedef enum special_function_kind {
sfk_none, /* Not a special function. */
sfk_constructor, /* A constructor. */
sfk_destructor, /* A destructor. */
sfk_conversion /* A conversion operator. */
} special_function_kind;
/* Zero means prototype weakly, as in ANSI C (no args means nothing). /* Zero means prototype weakly, as in ANSI C (no args means nothing).
Each language context defines how this variable should be set. */ Each language context defines how this variable should be set. */
extern int strict_prototype; extern int strict_prototype;
...@@ -3217,10 +3228,6 @@ extern int current_class_depth; ...@@ -3217,10 +3228,6 @@ extern int current_class_depth;
/* Points to the name of that function. May not be the DECL_NAME /* Points to the name of that function. May not be the DECL_NAME
of CURRENT_FUNCTION_DECL due to overloading */ of CURRENT_FUNCTION_DECL due to overloading */
extern tree original_function_name; extern tree original_function_name;
/* in init.c */
extern tree global_base_init_list;
/* Here's where we control how name mangling takes place. */ /* Here's where we control how name mangling takes place. */
...@@ -3999,11 +4006,9 @@ extern tree do_friend PARAMS ((tree, tree, tree, tree, tree, enum overload_fl ...@@ -3999,11 +4006,9 @@ extern tree do_friend PARAMS ((tree, tree, tree, tree, tree, enum overload_fl
/* in init.c */ /* in init.c */
extern void init_init_processing PARAMS ((void)); extern void init_init_processing PARAMS ((void));
extern tree emit_base_init PARAMS ((tree)); extern void emit_base_init PARAMS ((tree));
extern void check_base_init PARAMS ((tree));
extern void expand_member_init PARAMS ((tree, tree, tree)); extern void expand_member_init PARAMS ((tree, tree, tree));
extern tree build_aggr_init PARAMS ((tree, tree, int)); extern tree build_aggr_init PARAMS ((tree, tree, int));
extern int is_aggr_typedef PARAMS ((tree, int));
extern int is_aggr_type PARAMS ((tree, int)); extern int is_aggr_type PARAMS ((tree, int));
extern tree get_aggr_from_typedef PARAMS ((tree, int)); extern tree get_aggr_from_typedef PARAMS ((tree, int));
extern tree get_type_value PARAMS ((tree)); extern tree get_type_value PARAMS ((tree));
......
...@@ -178,6 +178,8 @@ static tree start_cleanup_fn PARAMS ((void)); ...@@ -178,6 +178,8 @@ static tree start_cleanup_fn PARAMS ((void));
static void end_cleanup_fn PARAMS ((void)); static void end_cleanup_fn PARAMS ((void));
static tree cp_make_fname_decl PARAMS ((tree, const char *, int)); static tree cp_make_fname_decl PARAMS ((tree, const char *, int));
static void initialize_predefined_identifiers PARAMS ((void)); static void initialize_predefined_identifiers PARAMS ((void));
static tree check_special_function_return_type
PARAMS ((special_function_kind, tree, tree, tree));
#if defined (DEBUG_CP_BINDING_LEVELS) #if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PARAMS ((void)); static void indent PARAMS ((void));
...@@ -9298,6 +9300,54 @@ create_array_type_for_decl (name, type, size) ...@@ -9298,6 +9300,54 @@ create_array_type_for_decl (name, type, size)
return build_cplus_array_type (type, itype); return build_cplus_array_type (type, itype);
} }
/* 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. CTYPE is the class of which this function is a
member. OPTYPE is the type given in a conversion operator
declaration. Returns the actual return type of the function; that
may be different than TYPE if an error occurs, or for certain
special functions. */
static tree
check_special_function_return_type (sfk, type, ctype, optype)
special_function_kind sfk;
tree type;
tree ctype;
tree optype;
{
switch (sfk)
{
case sfk_constructor:
if (type)
cp_error ("return type specification for constructor invalid");
/* In the old ABI, we return `this'; in the new ABI we don't
bother. */
type = flag_new_abi ? void_type_node : build_pointer_type (ctype);
break;
case sfk_destructor:
if (type)
cp_error ("return type specification for destructor invalid");
type = void_type_node;
break;
case sfk_conversion:
if (type && !same_type_p (type, optype))
cp_error ("operator `%T' declared to return `%T'", optype, type);
else if (type)
cp_pedwarn ("return type specified for `operator %T'", optype);
type = optype;
break;
default:
my_friendly_abort (20000408);
break;
}
return type;
}
/* Given declspecs and a declarator, /* Given declspecs and a declarator,
determine the name and type of the object declared determine the name and type of the object declared
and construct a ..._DECL node for it. and construct a ..._DECL node for it.
...@@ -9358,8 +9408,6 @@ create_array_type_for_decl (name, type, size) ...@@ -9358,8 +9408,6 @@ create_array_type_for_decl (name, type, size)
May return void_type_node if the declarator turned out to be a friend. May return void_type_node if the declarator turned out to be a friend.
See grokfield for details. */ See grokfield for details. */
enum return_types { return_normal, return_ctor, return_dtor, return_conversion };
tree tree
grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
tree declspecs; tree declspecs;
...@@ -9398,7 +9446,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -9398,7 +9446,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* Keep track of what sort of function is being processed /* Keep track of what sort of function is being processed
so that we can warn about default return values, or explicit so that we can warn about default return values, or explicit
return values which do not match prescribed defaults. */ return values which do not match prescribed defaults. */
enum return_types return_type = return_normal; special_function_kind sfk = sfk_none;
tree dname = NULL_TREE; tree dname = NULL_TREE;
tree ctype = current_class_type; tree ctype = current_class_type;
...@@ -9448,7 +9496,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -9448,7 +9496,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
my_friendly_assert (flags == NO_SPECIAL, 152); my_friendly_assert (flags == NO_SPECIAL, 152);
flags = DTOR_FLAG; flags = DTOR_FLAG;
return_type = return_dtor; sfk = sfk_destructor;
if (TREE_CODE (name) == TYPE_DECL) if (TREE_CODE (name) == TYPE_DECL)
TREE_OPERAND (decl, 0) = name = constructor_name (name); TREE_OPERAND (decl, 0) = name = constructor_name (name);
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 153); my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 153);
...@@ -9547,7 +9595,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -9547,7 +9595,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& decl != NULL_TREE && flags != DTOR_FLAG && decl != NULL_TREE && flags != DTOR_FLAG
&& decl == constructor_name (ctype)) && decl == constructor_name (ctype))
{ {
return_type = return_ctor; sfk = sfk_constructor;
ctor_return_type = ctype; ctor_return_type = ctype;
} }
ctype = NULL_TREE; ctype = NULL_TREE;
...@@ -9595,7 +9643,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -9595,7 +9643,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
my_friendly_assert (flags == NO_SPECIAL, 154); my_friendly_assert (flags == NO_SPECIAL, 154);
flags = TYPENAME_FLAG; flags = TYPENAME_FLAG;
ctor_return_type = TREE_TYPE (dname); ctor_return_type = TREE_TYPE (dname);
return_type = return_conversion; sfk = sfk_conversion;
} }
name = operator_name_string (dname); name = operator_name_string (dname);
} }
...@@ -9659,7 +9707,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -9659,7 +9707,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (TREE_CODE (decl) == IDENTIFIER_NODE if (TREE_CODE (decl) == IDENTIFIER_NODE
&& constructor_name (ctype) == decl) && constructor_name (ctype) == decl)
{ {
return_type = return_ctor; sfk = sfk_constructor;
ctor_return_type = ctype; ctor_return_type = ctype;
} }
else if (TREE_CODE (decl) == BIT_NOT_EXPR else if (TREE_CODE (decl) == BIT_NOT_EXPR
...@@ -9667,7 +9715,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -9667,7 +9715,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& (constructor_name (ctype) == TREE_OPERAND (decl, 0) && (constructor_name (ctype) == TREE_OPERAND (decl, 0)
|| constructor_name_full (ctype) == TREE_OPERAND (decl, 0))) || constructor_name_full (ctype) == TREE_OPERAND (decl, 0)))
{ {
return_type = return_dtor; sfk = sfk_destructor;
ctor_return_type = ctype; ctor_return_type = ctype;
flags = DTOR_FLAG; flags = DTOR_FLAG;
TREE_OPERAND (decl, 0) = constructor_name (ctype); TREE_OPERAND (decl, 0) = constructor_name (ctype);
...@@ -9883,58 +9931,35 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -9883,58 +9931,35 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
defaulted_int = 1; defaulted_int = 1;
} }
if (type == NULL_TREE) if (sfk != sfk_none)
type = check_special_function_return_type (sfk, type,
ctor_return_type,
ctor_return_type);
else if (type == NULL_TREE)
{ {
int is_main;
explicit_int = -1; explicit_int = -1;
if (return_type == return_dtor)
type = void_type_node;
else if (return_type == return_ctor)
type = build_pointer_type (ctor_return_type);
else if (return_type == return_conversion)
type = ctor_return_type;
else
{
/* We handle `main' specially here, because 'main () { }' is so /* We handle `main' specially here, because 'main () { }' is so
common. With no options, it is allowed. With -Wreturn-type, common. With no options, it is allowed. With -Wreturn-type,
it is a warning. It is only an error with -pedantic-errors. */ it is a warning. It is only an error with -pedantic-errors. */
int is_main = (funcdef_flag is_main = (funcdef_flag
&& MAIN_NAME_P (dname) && MAIN_NAME_P (dname)
&& ctype == NULL_TREE && ctype == NULL_TREE
&& in_namespace == NULL_TREE && in_namespace == NULL_TREE
&& current_namespace == global_namespace); && current_namespace == global_namespace);
if (in_system_header || flag_ms_extensions) if (in_system_header || flag_ms_extensions)
/* Allow it, sigh. */; /* Allow it, sigh. */;
else if (pedantic || ! is_main) else if (pedantic || ! is_main)
cp_pedwarn ("ISO C++ forbids declaration of `%s' with no type", cp_pedwarn ("ISO C++ forbids declaration of `%s' with no type",
name); name);
else if (warn_return_type) else if (warn_return_type)
cp_warning ("ISO C++ forbids declaration of `%s' with no type", cp_warning ("ISO C++ forbids declaration of `%s' with no type",
name); name);
type = integer_type_node; type = integer_type_node;
}
}
else if (return_type == return_dtor)
{
error ("return type specification for destructor invalid");
type = void_type_node;
}
else if (return_type == return_ctor)
{
error ("return type specification for constructor invalid");
type = build_pointer_type (ctor_return_type);
}
else if (return_type == return_conversion)
{
if (!same_type_p (type, ctor_return_type))
cp_error ("operator `%T' declared to return `%T'",
ctor_return_type, type);
else
cp_pedwarn ("return type specified for `operator %T'",
ctor_return_type);
type = ctor_return_type;
} }
ctype = NULL_TREE; ctype = NULL_TREE;
...@@ -10079,7 +10104,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -10079,7 +10104,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
type = build_complex_type (type); type = build_complex_type (type);
} }
if (return_type == return_conversion if (sfk == sfk_conversion
&& (RIDBIT_SETP (RID_CONST, specbits) && (RIDBIT_SETP (RID_CONST, specbits)
|| RIDBIT_SETP (RID_VOLATILE, specbits) || RIDBIT_SETP (RID_VOLATILE, specbits)
|| RIDBIT_SETP (RID_RESTRICT, specbits))) || RIDBIT_SETP (RID_RESTRICT, specbits)))
...@@ -10376,7 +10401,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -10376,7 +10401,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
&& (friendp == 0 || dname == current_class_name)) && (friendp == 0 || dname == current_class_name))
ctype = current_class_type; ctype = current_class_type;
if (ctype && return_type == return_conversion) if (ctype && sfk == sfk_conversion)
TYPE_HAS_CONVERSION (ctype) = 1; TYPE_HAS_CONVERSION (ctype) = 1;
if (ctype && constructor_name (ctype) == dname) if (ctype && constructor_name (ctype) == dname)
{ {
...@@ -10435,7 +10460,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -10435,7 +10460,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (RIDBIT_ANY_SET (tmp_bits)) if (RIDBIT_ANY_SET (tmp_bits))
error ("return value type specifier for constructor ignored"); error ("return value type specifier for constructor ignored");
} }
type = build_pointer_type (ctype);
if (decl_context == FIELD) if (decl_context == FIELD)
{ {
if (! member_function_or_else (ctype, if (! member_function_or_else (ctype,
...@@ -10443,7 +10467,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -10443,7 +10467,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
flags)) flags))
return void_type_node; return void_type_node;
TYPE_HAS_CONSTRUCTOR (ctype) = 1; TYPE_HAS_CONSTRUCTOR (ctype) = 1;
if (return_type != return_ctor) if (sfk != sfk_constructor)
return NULL_TREE; return NULL_TREE;
} }
} }
...@@ -13532,7 +13556,12 @@ start_function (declspecs, declarator, attrs, flags) ...@@ -13532,7 +13556,12 @@ start_function (declspecs, declarator, attrs, flags)
dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
DECL_CONTEXT (dtor_label) = current_function_decl; DECL_CONTEXT (dtor_label) = current_function_decl;
} }
else if (DECL_CONSTRUCTOR_P (decl1)) /* Under the old ABI we return `this' from constructors, so we make
ordinary `return' statements in constructors jump to CTOR_LABEL;
from there we return `this'. Under the new ABI, we don't bother
with any of this. By not setting CTOR_LABEL the remainder of the
machinery is automatically disabled. */
else if (!flag_new_abi && DECL_CONSTRUCTOR_P (decl1))
{ {
ctor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); ctor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
DECL_CONTEXT (ctor_label) = current_function_decl; DECL_CONTEXT (ctor_label) = current_function_decl;
...@@ -13764,7 +13793,8 @@ static void ...@@ -13764,7 +13793,8 @@ static void
finish_constructor_body () finish_constructor_body ()
{ {
/* Any return from a constructor will end up here. */ /* Any return from a constructor will end up here. */
add_tree (build_min_nt (LABEL_STMT, ctor_label)); if (ctor_label)
add_tree (build_min_nt (LABEL_STMT, ctor_label));
/* Clear CTOR_LABEL so that finish_return_stmt knows to really /* Clear CTOR_LABEL so that finish_return_stmt knows to really
generate the return, rather than a goto to CTOR_LABEL. */ generate the return, rather than a goto to CTOR_LABEL. */
......
...@@ -79,6 +79,45 @@ void init_init_processing () ...@@ -79,6 +79,45 @@ void init_init_processing ()
ggc_add_tree_root (&BI_header_size, 1); ggc_add_tree_root (&BI_header_size, 1);
} }
/* We are about to generate some complex initialization code.
Conceptually, it is all a single expression. However, we may want
to include conditionals, loops, and other such statement-level
constructs. Therefore, we build the initialization code inside a
statement-expression. This function starts such an expression.
STMT_EXPR_P and COMPOUND_STMT_P are filled in by this function;
pass them back to finish_init_stmts when the expression is
complete. */
void
begin_init_stmts (stmt_expr_p, compound_stmt_p)
tree *stmt_expr_p;
tree *compound_stmt_p;
{
*stmt_expr_p = begin_stmt_expr ();
*compound_stmt_p = begin_compound_stmt (/*has_no_scope=*/1);
}
/* Finish out the statement-expression begun by the previous call to
begin_init_stmts. Returns the statement-expression itself. */
tree
finish_init_stmts (stmt_expr, compound_stmt)
tree stmt_expr;
tree compound_stmt;
{
finish_compound_stmt (/*has_no_scope=*/1, compound_stmt);
stmt_expr = finish_stmt_expr (stmt_expr);
/* To avoid spurious warnings about unused values, we set
TREE_USED. */
if (stmt_expr)
TREE_USED (stmt_expr) = 1;
return stmt_expr;
}
/* Constructors */
/* Called from initialize_vtbl_ptrs via dfs_walk. */ /* Called from initialize_vtbl_ptrs via dfs_walk. */
static tree static tree
...@@ -132,8 +171,6 @@ initialize_vtbl_ptrs (type, addr) ...@@ -132,8 +171,6 @@ initialize_vtbl_ptrs (type, addr)
expand_indirect_vtbls_init (TYPE_BINFO (type), addr); expand_indirect_vtbls_init (TYPE_BINFO (type), addr);
} }
/* 348 - 351 */
/* Subroutine of emit_base_init. */ /* Subroutine of emit_base_init. */
static void static void
...@@ -240,8 +277,6 @@ perform_member_init (member, name, init, explicit) ...@@ -240,8 +277,6 @@ perform_member_init (member, name, init, explicit)
} }
} }
extern int warn_reorder;
/* Subroutine of emit_member_init. */ /* Subroutine of emit_member_init. */
static tree static tree
...@@ -485,7 +520,7 @@ sort_base_init (t, rbase_ptr, vbase_ptr) ...@@ -485,7 +520,7 @@ sort_base_init (t, rbase_ptr, vbase_ptr)
Note that emit_base_init does *not* initialize virtual base Note that emit_base_init does *not* initialize virtual base
classes. That is done specially, elsewhere. */ classes. That is done specially, elsewhere. */
tree void
emit_base_init (t) emit_base_init (t)
tree t; tree t;
{ {
...@@ -494,9 +529,8 @@ emit_base_init (t) ...@@ -494,9 +529,8 @@ emit_base_init (t)
tree rbase_init_list, vbase_init_list; tree rbase_init_list, vbase_init_list;
tree t_binfo = TYPE_BINFO (t); tree t_binfo = TYPE_BINFO (t);
tree binfos = BINFO_BASETYPES (t_binfo); tree binfos = BINFO_BASETYPES (t_binfo);
int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; int i;
tree stmt_expr; int n_baseclasses = BINFO_N_BASETYPES (t_binfo);
tree compound_stmt;
mem_init_list = sort_member_init (t); mem_init_list = sort_member_init (t);
current_member_init_list = NULL_TREE; current_member_init_list = NULL_TREE;
...@@ -504,8 +538,6 @@ emit_base_init (t) ...@@ -504,8 +538,6 @@ emit_base_init (t)
sort_base_init (t, &rbase_init_list, &vbase_init_list); sort_base_init (t, &rbase_init_list, &vbase_init_list);
current_base_init_list = NULL_TREE; current_base_init_list = NULL_TREE;
begin_init_stmts (&stmt_expr, &compound_stmt);
/* First, initialize the virtual base classes, if we are /* First, initialize the virtual base classes, if we are
constructing the most-derived object. */ constructing the most-derived object. */
if (TYPE_USES_VIRTUAL_BASECLASSES (t)) if (TYPE_USES_VIRTUAL_BASECLASSES (t))
...@@ -618,25 +650,6 @@ emit_base_init (t) ...@@ -618,25 +650,6 @@ emit_base_init (t)
} }
mem_init_list = TREE_CHAIN (mem_init_list); mem_init_list = TREE_CHAIN (mem_init_list);
} }
/* All the implicit try blocks we built up will be zapped
when we come to a real binding contour boundary. */
return finish_init_stmts (stmt_expr, compound_stmt);
}
/* Check that all fields are properly initialized after
an assignment to `this'. Called only when such an assignment
is actually noted. */
void
check_base_init (t)
tree t;
{
tree member;
for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
if (DECL_NAME (member) && TREE_USED (member))
cp_error ("field `%D' used before initialized (after assignment to `this')",
member);
} }
/* This code sets up the virtual function tables appropriate for /* This code sets up the virtual function tables appropriate for
...@@ -983,43 +996,6 @@ expand_member_init (exp, name, init) ...@@ -983,43 +996,6 @@ expand_member_init (exp, name, init)
} }
} }
/* We are about to generate some complex initialization code.
Conceptually, it is all a single expression. However, we may want
to include conditionals, loops, and other such statement-level
constructs. Therefore, we build the initialization code inside a
statement-expression. This function starts such an expression.
STMT_EXPR_P and COMPOUND_STMT_P are filled in by this function;
pass them back to finish_init_stmts when the expression is
complete. */
void
begin_init_stmts (stmt_expr_p, compound_stmt_p)
tree *stmt_expr_p;
tree *compound_stmt_p;
{
*stmt_expr_p = begin_stmt_expr ();
*compound_stmt_p = begin_compound_stmt (/*has_no_scope=*/1);
}
/* Finish out the statement-expression begun by the previous call to
begin_init_stmts. Returns the statement-expression itself. */
tree
finish_init_stmts (stmt_expr, compound_stmt)
tree stmt_expr;
tree compound_stmt;
{
finish_compound_stmt (/*has_no_scope=*/1, compound_stmt);
stmt_expr = finish_stmt_expr (stmt_expr);
/* To avoid spurious warnings about unused values, we set
TREE_USED. */
if (stmt_expr)
TREE_USED (stmt_expr) = 1;
return stmt_expr;
}
/* This is like `expand_member_init', only it stores one aggregate /* This is like `expand_member_init', only it stores one aggregate
value into another. value into another.
...@@ -1268,39 +1244,6 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, flags) ...@@ -1268,39 +1244,6 @@ expand_aggr_init_1 (binfo, true_exp, exp, init, flags)
expand_default_init (binfo, true_exp, exp, init, flags); expand_default_init (binfo, true_exp, exp, init, flags);
} }
/* Report an error if NAME is not the name of a user-defined,
aggregate type. If OR_ELSE is nonzero, give an error message. */
int
is_aggr_typedef (name, or_else)
tree name;
int or_else;
{
tree type;
if (name == error_mark_node)
return 0;
if (IDENTIFIER_HAS_TYPE_VALUE (name))
type = IDENTIFIER_TYPE_VALUE (name);
else
{
if (or_else)
cp_error ("`%T' is not an aggregate typedef", name);
return 0;
}
if (! IS_AGGR_TYPE (type)
&& TREE_CODE (type) != TEMPLATE_TYPE_PARM
&& TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM)
{
if (or_else)
cp_error ("`%T' is not an aggregate type", type);
return 0;
}
return 1;
}
/* Report an error if TYPE is not a user-defined, aggregate type. If /* Report an error if TYPE is not a user-defined, aggregate type. If
OR_ELSE is nonzero, give an error message. */ OR_ELSE is nonzero, give an error message. */
...@@ -2413,8 +2356,7 @@ build_new_1 (exp) ...@@ -2413,8 +2356,7 @@ build_new_1 (exp)
flags |= LOOKUP_HAS_IN_CHARGE; flags |= LOOKUP_HAS_IN_CHARGE;
} }
if (use_java_new) rval = save_expr (rval);
rval = save_expr (rval);
newrval = rval; newrval = rval;
if (newrval && TREE_CODE (TREE_TYPE (newrval)) == POINTER_TYPE) if (newrval && TREE_CODE (TREE_TYPE (newrval)) == POINTER_TYPE)
...@@ -2426,10 +2368,7 @@ build_new_1 (exp) ...@@ -2426,10 +2368,7 @@ build_new_1 (exp)
if (newrval == NULL_TREE || newrval == error_mark_node) if (newrval == NULL_TREE || newrval == error_mark_node)
return error_mark_node; return error_mark_node;
/* Java constructors compiled by jc1 do not return this. */ newrval = build (COMPOUND_EXPR, TREE_TYPE (rval), newrval, rval);
if (use_java_new)
newrval = build (COMPOUND_EXPR, TREE_TYPE (newrval),
newrval, rval);
rval = newrval; rval = newrval;
TREE_HAS_CONSTRUCTOR (rval) = 1; TREE_HAS_CONSTRUCTOR (rval) = 1;
} }
......
...@@ -1235,7 +1235,7 @@ setup_vtbl_ptr () ...@@ -1235,7 +1235,7 @@ setup_vtbl_ptr ()
add_tree (ctor_stmt); add_tree (ctor_stmt);
/* And actually initialize the base-classes and members. */ /* And actually initialize the base-classes and members. */
finish_expr_stmt (emit_base_init (current_class_type)); emit_base_init (current_class_type);
} }
} }
else if (DECL_DESTRUCTOR_P (current_function_decl) else if (DECL_DESTRUCTOR_P (current_function_decl)
......
...@@ -6796,9 +6796,9 @@ check_return_expr (retval) ...@@ -6796,9 +6796,9 @@ check_return_expr (retval)
/* You can't return a value from a constructor. */ /* You can't return a value from a constructor. */
error ("returning a value from a constructor"); error ("returning a value from a constructor");
/* Constructors actually always return `this', even though in C++ /* Under the old ABI, constructors actually always return `this',
you can't return a value from a constructor. */ even though in C++ you can't return a value from a constructor. */
if (DECL_CONSTRUCTOR_P (current_function_decl)) if (!flag_new_abi && DECL_CONSTRUCTOR_P (current_function_decl))
retval = current_class_ptr; retval = current_class_ptr;
/* When no explicit return-value is given in a function with a named /* When no explicit return-value is given in a function with a named
......
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