Commit efee38a9 by Mark Mitchell Committed by Mark Mitchell

cp-tree.h (check_return_expr): New function.

	* cp-tree.h (check_return_expr): New function.
	* decl.c (finish_constructor_body): New function.
	(pushdecl): Put global friend functions in namespace binding
	level, not the class binding level.
	(finish_destructor_body): Make sure the dtor_label is always
	defined.  Fix typo in comment.
	(finish_function): Move generation of constructor-termination code
	to semantic-analysis time.  Move generation of implicit `main'
	return value to semantic-analysis time.
	* semantics.c (finish_return_stmt): Generate goto's to
	ctor_label/dtor_label here.  Use check_return_expr to do semantic
	analysis on the returned expression.
	* typeck.c (maybe_warn_about_returning_address_of_local): New
	function split out from c_expand_return.
	(check_return_expr): Likewise.
	(c_expand_return): Just generate the RTL for the return.

From-SVN: r29663
parent 5a657fc3
1999-09-25 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (check_return_expr): New function.
* decl.c (finish_constructor_body): New function.
(pushdecl): Put global friend functions in namespace binding
level, not the class binding level.
(finish_destructor_body): Make sure the dtor_label is always
defined. Fix typo in comment.
(finish_function): Move generation of constructor-termination code
to semantic-analysis time. Move generation of implicit `main'
return value to semantic-analysis time.
* semantics.c (finish_return_stmt): Generate goto's to
ctor_label/dtor_label here. Use check_return_expr to do semantic
analysis on the returned expression.
* typeck.c (maybe_warn_about_returning_address_of_local): New
function split out from c_expand_return.
(check_return_expr): Likewise.
(c_expand_return): Just generate the RTL for the return.
1999-09-24 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (CPTI_CLEANUP_TYPE): New macro.
......
......@@ -3949,6 +3949,7 @@ extern tree pfn_from_ptrmemfunc PROTO((tree));
extern tree type_after_usual_arithmetic_conversions PROTO((tree, tree));
extern tree composite_pointer_type PROTO((tree, tree, tree, tree,
const char*));
extern tree check_return_expr PROTO((tree));
/* in typeck2.c */
extern tree error_not_base_type PROTO((tree, tree));
......
......@@ -180,6 +180,7 @@ static void save_function_data PROTO((tree));
static void check_function_type PROTO((tree));
static void destroy_local_static PROTO((tree));
static void destroy_local_var PROTO((tree));
static void finish_constructor_body PROTO((void));
static void finish_destructor_body PROTO((void));
#if defined (DEBUG_CP_BINDING_LEVELS)
......@@ -4064,7 +4065,10 @@ pushdecl (x)
}
if (need_new_binding)
add_decl_to_level (x, current_binding_level);
add_decl_to_level (x,
DECL_NAMESPACE_SCOPE_P (x)
? NAMESPACE_LEVEL (CP_DECL_CONTEXT (x))
: current_binding_level);
return x;
}
......@@ -13329,9 +13333,26 @@ save_function_data (decl)
f->cannot_inline = current_function_cannot_inline;
}
/* At the end of every constructor we generate to code to return
`this'. Do that now. */
static void
finish_constructor_body ()
{
/* Any return from a constructor will end up here. */
add_tree (build_min_nt (LABEL_STMT, ctor_label));
/* Clear CTOR_LABEL so that finish_return_stmt knows to really
generate the return, rather than a goto to CTOR_LABEL. */
ctor_label = NULL_TREE;
/* In check_return_expr we translate an empty return from a
constructor to a return of `this'. */
finish_return_stmt (NULL_TREE);
}
/* At the end of every destructor we generate code to restore virtual
function tables to the values desired by base classes and to call
to base class destructors. Do that now, for DECL. */
to base class destructors. Do that now. */
static void
finish_destructor_body ()
......@@ -13344,6 +13365,9 @@ finish_destructor_body ()
/* Create a block to contain all the extra code. */
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
/* Any return from a destructor will end up here. */
add_tree (build_min_nt (LABEL_STMT, dtor_label));
/* Generate the code to call destructor on base class. If this
destructor belongs to a class with virtual functions, then set
the virtual function table pointer to represent the type of our
......@@ -13372,13 +13396,12 @@ finish_destructor_body ()
|| TREE_OPERAND (exprstmt, 0) != integer_zero_node
|| TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)))
{
add_tree (build_min_nt (LABEL_STMT, dtor_label));
if (exprstmt != void_zero_node)
/* Don't call `expand_expr_stmt' if we're not going to do
anything, since -Wall will give a diagnostic. */
finish_expr_stmt (exprstmt);
/* Run destructor on all virtual baseclasses. */
/* Run destructors for all virtual baseclasses. */
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
{
tree vbases = nreverse (copy_list (CLASSTYPE_VBASECLASSES (current_class_type)));
......@@ -13496,10 +13519,23 @@ finish_function (lineno, flags)
if (building_stmt_tree ())
{
if (DECL_CONSTRUCTOR_P (fndecl) && call_poplevel)
do_poplevel ();
if (DECL_CONSTRUCTOR_P (fndecl))
{
finish_constructor_body ();
if (call_poplevel)
do_poplevel ();
}
else if (DECL_DESTRUCTOR_P (fndecl) && !processing_template_decl)
finish_destructor_body ();
else if (DECL_MAIN_P (fndecl))
{
/* Make it so that `main' always returns 0 by default. */
#ifdef VMS
finish_return_stmt (integer_one_node);
#else
finish_return_stmt (integer_zero_node);
#endif
}
/* Finish dealing with exception specifiers. */
if (flag_exceptions && !processing_template_decl
......@@ -13535,28 +13571,11 @@ finish_function (lineno, flags)
;
else if (DECL_CONSTRUCTOR_P (fndecl))
{
/* This is where the body of the constructor begins. All
subobjects have been fully constructed at this point. */
/* All subobjects have been fully constructed at this point. */
end_protect_partials ();
/* This is where the body of the constructor ends. */
expand_label (ctor_label);
ctor_label = NULL_TREE;
if (call_poplevel)
do_poplevel ();
/* c_expand_return knows to return 'this' from a constructor. */
c_expand_return (NULL_TREE);
}
else if (DECL_MAIN_P (fndecl))
{
/* Make it so that `main' always returns 0 by default. */
#ifdef VMS
c_expand_return (integer_one_node);
#else
c_expand_return (integer_zero_node);
#endif
}
else if (return_label != NULL_RTX
&& flag_this_is_variable <= 0
......
......@@ -371,6 +371,33 @@ void
finish_return_stmt (expr)
tree expr;
{
if (doing_semantic_analysis_p () && !processing_template_decl)
expr = check_return_expr (expr);
if (doing_semantic_analysis_p () && !processing_template_decl)
{
if (DECL_CONSTRUCTOR_P (current_function_decl) && ctor_label)
{
/* Even returns without a value in a constructor must return
`this'. We accomplish this by sending all returns in a
constructor to the CTOR_LABEL; finish_function emits code to
return a value there. When we finally generate the real
return statement, CTOR_LABEL is no longer set, and we fall
through into the normal return-processing code below. */
finish_goto_stmt (ctor_label);
return;
}
else if (DECL_DESTRUCTOR_P (current_function_decl))
{
/* Similarly, all destructors must run destructors for
base-classes before returning. So, all returns in a
destructor get sent to the DTOR_LABEL; finsh_function emits
code to return a value there. */
finish_goto_stmt (dtor_label);
return;
}
}
if (building_stmt_tree ())
add_tree (build_min_nt (RETURN_STMT, expr));
else
......
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