aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/semantics.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/semantics.c')
-rw-r--r--gcc/cp/semantics.c568
1 files changed, 62 insertions, 506 deletions
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index d93ddd8..c14909d 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -46,7 +46,6 @@
parsing into this file; that will make implementing the new parser
much easier since it will be able to make use of these routines. */
-static tree expand_cond PARAMS ((tree));
static tree maybe_convert_cond PARAMS ((tree));
static tree simplify_aggr_init_exprs_r PARAMS ((tree *, int *, void *));
static void deferred_type_access_control PARAMS ((void));
@@ -88,55 +87,63 @@ static void emit_associated_thunks PARAMS ((tree));
substmt = cond; \
} while (0)
-/* Finish a scope. */
+/* Wrapper since C and C++ expand_expr_stmt are different. */
-tree
-do_poplevel ()
+expand_expr_stmt_fn lang_expand_expr_stmt = cplus_expand_expr_stmt;
+
+/* Wrapper function instead of #define for use with c-common code. */
+
+void
+set_current_function_name_declared (i)
+ int i;
{
- tree block = NULL_TREE;
+ cp_function_chain->name_declared = i;
+}
- if (stmts_are_full_exprs_p)
- {
- tree scope_stmts;
+/* Returns non-zero if the current statement is a full expression,
+ i.e. temporaries created during that statement should be destroyed
+ at the end of the statement. */
- if (!processing_template_decl)
- scope_stmts = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
+int
+stmts_are_full_exprs_p ()
+{
+ return current_stmt_tree->stmts_are_full_exprs_p;
+}
- block = poplevel (kept_level_p (), 1, 0);
- if (block && !processing_template_decl)
- {
- SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block;
- SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block;
- }
- }
+/* One if we have already declared __FUNCTION__ (and related
+ variables) in the current function. Two if we are in the process
+ of doing so. */
- return block;
+int
+current_function_name_declared ()
+{
+ return cp_function_chain->name_declared;
}
-/* Begin a new scope. */
+/* Nonzero if TYPE is an anonymous union or struct type. We have to use a
+ flag for this because "A union for which objects or pointers are
+ declared is not an anonymous union" [class.union]. */
-void
-do_pushlevel ()
+int
+anon_aggr_type_p (node)
+ tree node;
{
- if (stmts_are_full_exprs_p)
- {
- pushlevel (0);
- if (!processing_template_decl)
- add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
- }
+ return (CLASS_TYPE_P (node) && TYPE_LANG_SPECIFIC(node)->anon_aggr);
}
-/* Helper for generating the RTL at the end of a scope. */
+/* Finish a scope. */
tree
-genrtl_do_poplevel ()
+do_poplevel ()
{
tree block = NULL_TREE;
- if (stmts_are_full_exprs_p)
+ if (stmts_are_full_exprs_p ())
{
tree scope_stmts;
- scope_stmts = NULL_TREE;
+
+ if (!processing_template_decl)
+ scope_stmts = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
block = poplevel (kept_level_p (), 1, 0);
if (block && !processing_template_decl)
@@ -149,34 +156,16 @@ genrtl_do_poplevel ()
return block;
}
-/* Helper for generating the RTL at the beginning of a scope. */
-
-void
-genrtl_do_pushlevel ()
-{
- emit_line_note (input_filename, lineno);
- clear_last_expr ();
-
- if (stmts_are_full_exprs_p)
- {
- pushlevel (0); // Try to get rid of me.
- if (!cfun->x_whole_function_mode_p)
- my_friendly_abort (19991129);
- }
-}
-
-/* Helper for generating the RTL. */
+/* Begin a new scope. */
void
-genrtl_clear_out_block ()
+do_pushlevel ()
{
- /* If COND wasn't a declaration, clear out the
- block we made for it and start a new one here so the
- optimization in expand_end_loop will work. */
- if (getdecls () == NULL_TREE)
+ if (stmts_are_full_exprs_p ())
{
- genrtl_do_poplevel ();
- genrtl_do_pushlevel ();
+ pushlevel (0);
+ if (!processing_template_decl)
+ add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
}
}
@@ -191,7 +180,7 @@ add_tree (t)
SET_LAST_STMT (t);
/* When we expand a statement-tree, we must know whether or not the
statements are full-expresions. We record that fact here. */
- STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p;
+ STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p ();
}
/* Finish a goto-statement. */
@@ -220,35 +209,10 @@ finish_goto_stmt (destination)
add_tree (build_min_nt (GOTO_STMT, destination));
}
-/* Generate the RTL for DESTINATION, which is a GOTO_STMT. */
-
-void
-genrtl_goto_stmt (destination)
- tree destination;
-{
- if (TREE_CODE (destination) == IDENTIFIER_NODE)
- destination = lookup_label (destination);
-
- /* We warn about unused labels with -Wunused. That means we have to
- mark the used labels as used. */
- if (TREE_CODE (destination) == LABEL_DECL)
- TREE_USED (destination) = 1;
-
- emit_line_note (input_filename, lineno);
-
- if (TREE_CODE (destination) == LABEL_DECL)
- {
- label_rtx (destination);
- expand_goto (destination);
- }
- else
- expand_computed_goto (destination);
-}
-
/* COND is the condition-expression for an if, while, etc.,
statement. Convert it to a boolean value, if appropriate. */
-static tree
+tree
maybe_convert_cond (cond)
tree cond;
{
@@ -274,13 +238,13 @@ finish_expr_stmt (expr)
if (expr != NULL_TREE)
{
if (!processing_template_decl
- && !stmts_are_full_exprs_p
+ && !(stmts_are_full_exprs_p ())
&& ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
&& lvalue_p (expr))
|| TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE))
expr = default_conversion (expr);
- if (stmts_are_full_exprs_p)
+ if (stmts_are_full_exprs_p ())
expr = convert_to_void (expr, "statement");
if (!processing_template_decl)
@@ -296,92 +260,6 @@ finish_expr_stmt (expr)
last_expr_type = expr ? TREE_TYPE (expr) : NULL_TREE;
}
-/* Generate the RTL for EXPR, which is an EXPR_STMT. */
-
-void
-genrtl_expr_stmt (expr)
- tree expr;
-{
- if (expr != NULL_TREE)
- {
- emit_line_note (input_filename, lineno);
-
- if (stmts_are_full_exprs_p)
- expand_start_target_temps ();
-
- cplus_expand_expr_stmt (expr);
-
- if (stmts_are_full_exprs_p)
- expand_end_target_temps ();
- }
-
- finish_stmt ();
-
- /* This was an expression-statement, so we save the type of the
- expression. */
- last_expr_type = expr ? TREE_TYPE (expr) : NULL_TREE;
-}
-
-/* Generate the RTL for T, which is a DECL_STMT. */
-
-void
-genrtl_decl_stmt (t)
- tree t;
-{
- tree decl;
- emit_line_note (input_filename, lineno);
- decl = DECL_STMT_DECL (t);
- /* If this is a declaration for an automatic local
- variable, initialize it. Note that we might also see a
- declaration for a namespace-scope object (declared with
- `extern'). We don't have to handle the initialization
- of those objects here; they can only be declarations,
- rather than definitions. */
- if (TREE_CODE (decl) == VAR_DECL
- && !TREE_STATIC (decl)
- && !DECL_EXTERNAL (decl))
- {
- /* Let the back-end know about this variable. */
- if (!ANON_AGGR_TYPE_P (TREE_TYPE (decl)))
- emit_local_var (decl);
- else
- expand_anon_union_decl (decl, NULL_TREE,
- DECL_ANON_UNION_ELEMS (decl));
- }
- else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
- {
- if (DECL_ARTIFICIAL (decl) && ! TREE_USED (decl))
- /* Do not emit unused decls. This is not just an
- optimization. We really do not want to emit
- __PRETTY_FUNCTION__ etc, if they're never used. */
- DECL_IGNORED_P (decl) = 1;
- else
- make_rtl_for_local_static (decl);
- }
-}
-
-/* Generate the RTL for T, which is an IF_STMT. */
-
-void
-genrtl_if_stmt (t)
- tree t;
-{
- tree cond;
- genrtl_do_pushlevel ();
- cond = maybe_convert_cond (expand_cond (IF_COND (t)));
- emit_line_note (input_filename, lineno);
- expand_start_cond (cond, 0);
- if (THEN_CLAUSE (t))
- expand_stmt (THEN_CLAUSE (t));
- if (ELSE_CLAUSE (t))
- {
- expand_start_else ();
- expand_stmt (ELSE_CLAUSE (t));
- }
- expand_end_cond ();
- genrtl_do_poplevel ();
- finish_stmt ();
-}
/* Begin an if-statement. Returns a newly created IF_STMT if
appropriate. */
@@ -459,30 +337,6 @@ clear_out_block ()
}
}
-/* Generate the RTL for T, which is a WHILE_STMT. */
-
-void
-genrtl_while_stmt (t)
- tree t;
-{
- tree cond;
- emit_nop ();
- emit_line_note (input_filename, lineno);
- expand_start_loop (1);
- genrtl_do_pushlevel ();
-
- cond = maybe_convert_cond (expand_cond (WHILE_COND (t)));
- emit_line_note (input_filename, lineno);
- expand_exit_loop_if_false (0, cond);
- genrtl_clear_out_block ();
-
- expand_stmt (WHILE_BODY (t));
-
- genrtl_do_poplevel ();
- expand_end_loop ();
- finish_stmt ();
-}
-
/* Begin a while-statement. Returns a newly created WHILE_STMT if
appropriate. */
@@ -520,28 +374,6 @@ finish_while_stmt (while_stmt)
finish_stmt ();
}
-/* Generate the RTL for T, which is a DO_STMT. */
-
-void
-genrtl_do_stmt (t)
- tree t;
-{
- tree cond;
- emit_nop ();
- emit_line_note (input_filename, lineno);
- expand_start_loop_continue_elsewhere (1);
-
- expand_stmt (DO_BODY (t));
-
- expand_loop_continue_here ();
-
- cond = maybe_convert_cond (DO_COND (t));
- emit_line_note (input_filename, lineno);
- expand_exit_loop_if_false (0, cond);
- expand_end_loop ();
- finish_stmt ();
-}
-
/* Begin a do-statement. Returns a newly created DO_STMT if
appropriate. */
@@ -575,17 +407,6 @@ finish_do_stmt (cond, do_stmt)
finish_stmt ();
}
-/* Generate the RTL for EXPR, which is a RETURN_STMT. */
-
-void
-genrtl_return_stmt (expr)
- tree expr;
-{
- emit_line_note (input_filename, lineno);
- c_expand_return (expr);
- finish_stmt ();
-}
-
/* Finish a return-statement. The EXPRESSION returned, if any, is as
indicated. */
@@ -622,47 +443,6 @@ finish_return_stmt (expr)
finish_stmt ();
}
-/* Generate the RTL for T, which is a FOR_STMT. */
-
-void
-genrtl_for_stmt (t)
- tree t;
-{
- tree tmp;
- tree cond;
- if (flag_new_for_scope > 0)
- {
- genrtl_do_pushlevel ();
- note_level_for_for ();
- }
-
- expand_stmt (FOR_INIT_STMT (t));
-
- emit_nop ();
- emit_line_note (input_filename, lineno);
- expand_start_loop_continue_elsewhere (1);
- genrtl_do_pushlevel ();
- cond = maybe_convert_cond (expand_cond (FOR_COND (t)));
- emit_line_note (input_filename, lineno);
- if (cond)
- expand_exit_loop_if_false (0, cond);
- genrtl_clear_out_block ();
- tmp = FOR_EXPR (t);
-
- expand_stmt (FOR_BODY (t));
-
- /* Pop the scope for the body of the loop. */
- genrtl_do_poplevel ();
- emit_line_note (input_filename, lineno);
- expand_loop_continue_here ();
- if (tmp)
- genrtl_expr_stmt (tmp);
- expand_end_loop ();
- if (flag_new_for_scope > 0)
- genrtl_do_poplevel ();
- finish_stmt ();
-}
-
/* Begin a for-statement. Returns a new FOR_STMT if appropriate. */
tree
@@ -672,9 +452,9 @@ begin_for_stmt ()
r = build_min_nt (FOR_STMT, NULL_TREE, NULL_TREE,
NULL_TREE, NULL_TREE);
+ NEW_FOR_SCOPE_P (r) = flag_new_for_scope > 0;
add_tree (r);
-
- if (flag_new_for_scope > 0)
+ if (NEW_FOR_SCOPE_P (r))
{
do_pushlevel ();
note_level_for_for ();
@@ -730,21 +510,11 @@ finish_for_stmt (for_stmt)
/* Pop the scope for the body of the loop. */
do_poplevel ();
RECHAIN_STMTS (for_stmt, FOR_BODY (for_stmt));
- if (flag_new_for_scope > 0)
+ if (NEW_FOR_SCOPE_P (for_stmt))
do_poplevel ();
finish_stmt ();
}
-/* Generate the RTL for a BREAK_STMT. */
-
-void
-genrtl_break_stmt ()
-{
- emit_line_note (input_filename, lineno);
- if ( ! expand_exit_something ())
- cp_error ("break statement not within loop or switch");
-}
-
/* Finish a break-statement. */
void
@@ -754,16 +524,6 @@ finish_break_stmt ()
add_tree (build_min_nt (BREAK_STMT));
}
-/* Generate the RTL for a CONTINUE_STMT. */
-
-void
-genrtl_continue_stmt ()
-{
- emit_line_note (input_filename, lineno);
- if (! expand_continue_loop (0))
- cp_error ("continue statement not within a loop");
-}
-
/* Finish a continue-statement. */
void
@@ -773,60 +533,6 @@ finish_continue_stmt ()
add_tree (build_min_nt (CONTINUE_STMT));
}
-/* Generate the RTL for T, which is a SCOPE_STMT. */
-
-void
-genrtl_scope_stmt (t)
- tree t;
-{
- if (!SCOPE_NO_CLEANUPS_P (t))
- {
- if (SCOPE_BEGIN_P (t))
- expand_start_bindings_and_block (2 * SCOPE_NULLIFIED_P (t),
- SCOPE_STMT_BLOCK (t));
- else if (SCOPE_END_P (t))
- expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t), 0);
- }
- else if (!SCOPE_NULLIFIED_P (t))
- {
- rtx note = emit_note (NULL,
- (SCOPE_BEGIN_P (t)
- ? NOTE_INSN_BLOCK_BEG
- : NOTE_INSN_BLOCK_END));
- NOTE_BLOCK (note) = SCOPE_STMT_BLOCK (t);
- }
-}
-
-/* Generate the RTL for T, which is a SWITCH_STMT. */
-
-void
-genrtl_switch_stmt (t)
- tree t;
-{
- tree cond;
- genrtl_do_pushlevel ();
-
- cond = expand_cond (SWITCH_COND (t));
- if (cond != error_mark_node)
- {
- emit_line_note (input_filename, lineno);
- c_expand_start_case (cond);
- }
- else
- /* The code is in error, but we don't want expand_end_case to
- crash. */
- c_expand_start_case (boolean_false_node);
-
- push_switch ();
-
- expand_stmt (SWITCH_BODY (t));
-
- expand_end_case (cond);
- pop_switch ();
- genrtl_do_poplevel ();
- finish_stmt ();
-}
-
/* Begin a switch-statement. Returns a new SWITCH_STMT if
appropriate. */
@@ -892,16 +598,6 @@ finish_switch_stmt (switch_stmt)
finish_stmt ();
}
-/* Generate the RTL for a CASE_LABEL. */
-
-void
-genrtl_case_label (low_value, high_value)
- tree low_value;
- tree high_value;
-{
- do_case (low_value, high_value);
-}
-
/* Finish a case-label. */
void
@@ -1070,8 +766,6 @@ genrtl_handler (t)
expand_goto (top_label_entry (&caught_return_label_stack));
end_catch_handler ();
}
-
- genrtl_do_poplevel ();
}
/* Begin a handler. Returns a HANDLER if appropriate. */
@@ -1165,79 +859,6 @@ genrtl_ctor_stmt (t)
end_protect_partials ();
}
-/* Generate the RTL for the start of a COMPOUND_STMT. */
-
-tree genrtl_begin_compound_stmt (has_no_scope)
- int has_no_scope;
-{
- tree r;
- int is_try = 0;
-
- r = NULL_TREE;
-
- last_expr_type = NULL_TREE;
-
- if (!has_no_scope)
- {
- genrtl_do_pushlevel ();
- if (is_try)
- note_level_for_eh ();
- }
- else
- /* Normally, we try hard to keep the BLOCK for a
- statement-expression. But, if it's a statement-expression with
- a scopeless block, there's nothing to keep, and we don't want
- to accidentally keep a block *inside* the scopeless block. */
- keep_next_level (0);
-
- /* If this is the outermost block of the function, declare the
- variables __FUNCTION__, __PRETTY_FUNCTION__, and so forth. */
- if (cfun
- && !current_function_name_declared
- && !has_no_scope)
- {
- current_function_name_declared = 1;
- declare_function_name ();
- }
-
- return r;
-}
-
-/* Generate the RTL for the end of a COMPOUND_STMT. */
-
-tree genrtl_finish_compound_stmt (has_no_scope)
- int has_no_scope;
-{
- tree r;
- tree t;
-
- if (!has_no_scope)
- r = genrtl_do_poplevel ();
- else
- r = NULL_TREE;
-
- /* When we call finish_stmt we will lose LAST_EXPR_TYPE. But, since
- the precise purpose of that variable is store the type of the
- last expression statement within the last compound statement, we
- preserve the value. */
- t = last_expr_type;
- finish_stmt ();
- last_expr_type = t;
-
- return r;
-}
-
-/* Generate the RTL for T, which is a COMPOUND_STMT. */
-
-tree
-genrtl_compound_stmt (t)
- tree t;
-{
- genrtl_begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
- expand_stmt (COMPOUND_BODY (t));
- return (genrtl_finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t)));
-}
-
/* Begin a compound-statement. If HAS_NO_SCOPE is non-zero, the
compound-statement does not define a scope. Returns a new
COMPOUND_STMT if appropriate. */
@@ -1276,10 +897,10 @@ begin_compound_stmt (has_no_scope)
/* If this is the outermost block of the function, declare the
variables __FUNCTION__, __PRETTY_FUNCTION__, and so forth. */
if (cfun
- && !current_function_name_declared
+ && !(current_function_name_declared () )
&& !has_no_scope)
{
- current_function_name_declared = 1;
+ cp_function_chain->name_declared = 1;
declare_function_name ();
}
@@ -1316,42 +937,6 @@ finish_compound_stmt (has_no_scope, compound_stmt)
return r;
}
-/* Generate the RTL for an ASM_STMT. */
-
-void
-genrtl_asm_stmt (cv_qualifier, string, output_operands,
- input_operands, clobbers)
- tree cv_qualifier;
- tree string;
- tree output_operands;
- tree input_operands;
- tree clobbers;
-{
- if (TREE_CHAIN (string))
- string = combine_strings (string);
-
- if (cv_qualifier != NULL_TREE
- && cv_qualifier != ridpointers[(int) RID_VOLATILE])
- {
- cp_warning ("%s qualifier ignored on asm",
- IDENTIFIER_POINTER (cv_qualifier));
- cv_qualifier = NULL_TREE;
- }
-
- emit_line_note (input_filename, lineno);
- if (output_operands != NULL_TREE || input_operands != NULL_TREE
- || clobbers != NULL_TREE)
- c_expand_asm_operands (string, output_operands,
- input_operands,
- clobbers,
- cv_qualifier != NULL_TREE,
- input_filename, lineno);
- else
- expand_asm (string);
-
- finish_stmt ();
-}
-
/* Finish an asm-statement, whose components are a CV_QUALIFIER, a
STRING, some OUTPUT_OPERANDS, some INPUT_OPERANDS, and some
CLOBBERS. */
@@ -1446,17 +1031,6 @@ finish_subobject (cleanup)
add_tree (r);
}
-/* Generate the RTL for a DECL_CLEANUP. */
-
-void
-genrtl_decl_cleanup (decl, cleanup)
- tree decl;
- tree cleanup;
-{
- if (!decl || (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node))
- expand_decl_cleanup (decl, cleanup);
-}
-
/* When DECL goes out of scope, make sure that CLEANUP is executed. */
void
@@ -1694,10 +1268,10 @@ setup_vtbl_ptr (member_init_list, base_init_list)
/* Don't declare __PRETTY_FUNCTION__ and friends here when we
open the block for the if-body. */
- saved_cfnd = current_function_name_declared;
- current_function_name_declared = 1;
+ saved_cfnd = current_function_name_declared ();
+ cp_function_chain->name_declared = 1;
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
- current_function_name_declared = saved_cfnd;
+ cp_function_chain->name_declared = saved_cfnd;
/* Make all virtual function table pointers in non-virtual base
classes point to CURRENT_CLASS_TYPE's virtual function
@@ -2722,32 +2296,14 @@ prep_stmt (t)
{
if (!STMT_LINENO_FOR_FN_P (t))
lineno = STMT_LINENO (t);
- stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t);
-}
-
-/* Some statements, like for-statements or if-statements, require a
- condition. This condition can be a declaration. If T is such a
- declaration it is processed, and an expression appropriate to use
- as the condition is returned. Otherwise, T itself is returned. */
-
-static tree
-expand_cond (t)
- tree t;
-{
- if (t && TREE_CODE (t) == TREE_LIST)
- {
- expand_stmt (TREE_PURPOSE (t));
- return TREE_VALUE (t);
- }
- else
- return t;
+ current_stmt_tree->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t);
}
/* Generate RTL for the statement T, and its substatements, and any
other statements at its nesting level. */
tree
-expand_stmt (t)
+lang_expand_stmt (t)
tree t;
{
tree rval = NULL_TREE;
@@ -2760,7 +2316,7 @@ expand_stmt (t)
rval = NULL_TREE;
/* Set up context appropriately for handling this statement. */
- saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p;
+ saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
prep_stmt (t);
switch (TREE_CODE (t))
@@ -2865,7 +2421,7 @@ expand_stmt (t)
}
/* Restore saved state. */
- stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
+ current_stmt_tree->stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
/* Go on to the next statement in this scope. */
t = TREE_CHAIN (t);
@@ -3107,14 +2663,14 @@ expand_body (fn)
/* We don't need to redeclare __FUNCTION__, __PRETTY_FUNCTION__, or
any of the other magic variables we set up when starting a
function body. */
- current_function_name_declared = 1;
+ cp_function_chain->name_declared = 1;
/* Expand the body. */
expand_stmt (DECL_SAVED_TREE (fn));
/* Statements should always be full-expressions at the outermost set
of curly braces for a function. */
- my_friendly_assert (stmts_are_full_exprs_p, 19990831);
+ my_friendly_assert (stmts_are_full_exprs_p (), 19990831);
/* The outermost statement for a function contains the line number
recorded when we finished processing the function. */