* PATCH: add semantics.c
[not found] ` <smtp.earthlink.net>
1998-03-13 18:29 ` H.J. Lu
@ 1998-03-18 16:14 ` Mark Mitchell
1998-03-19 21:47 ` PATCH for Re: cp/semantics.c is broken Mark Mitchell
` (2 subsequent siblings)
4 siblings, 0 replies; 10+ messages in thread
From: Mark Mitchell @ 1998-03-18 16:14 UTC (permalink / raw)
To: Jason Merrill; +Cc: egcs
Jason --
I've begun the process of separating the process of parsing tokens
from the process of building up semantic information. As we discussed
before, this has several benefits, including:
o Making it easier to implement a new parser, whether hand-written
or machine-generated, since it will be able to use the same
interface as the current parser.
o Reducing code duplication (and accompanying inconsistencies!)
between template instantiation and parsing.
I've done this work for statements. As a side-benefit, I've added
the (somewhat frightening) ability to use asm-statements in templates.
(They used to cause a crash.)
Is this OK?
--
Mark Mitchell <mmitchell@usa.net>
http://home.earthlink.net/~mbmitchell
Consulting Services Available
Tue Mar 17 15:09:51 1998 Mark Mitchell <mmitchell@usa.net>
* semantics.c: New file, containing routines to perform the
semantic phase of parsing.
* parse.y: Use it.
* pt.c (tsubst_expr): Likewise.
* cp-tree.h: Declare the various functions in semantics.c.
Provide macros to access _STMT tree nodes.
* cp-tree.def: Add ASM_STMT tree node.
* Makefile.in, Make-lang.in: Add dependencies on and for
semantics.c.
Index: cp-tree.def
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.def,v
retrieving revision 1.10
diff -c -p -r1.10 cp-tree.def
*** cp-tree.def 1998/02/25 00:49:40 1.10
--- cp-tree.def 1998/03/17 23:10:42
*************** DEFTREECODE (BREAK_STMT, "break_stmt", '
*** 200,205 ****
--- 200,206 ----
DEFTREECODE (CONTINUE_STMT, "continue_stmt", 'e', 0)
DEFTREECODE (SWITCH_STMT, "switch_stmt", 'e', 2)
DEFTREECODE (GOTO_STMT, "goto_stmt", 'e', 1)
+ DEFTREECODE (ASM_STMT, "asm_stmt", 'e', 5)
DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 2)
DEFTREECODE (CASE_LABEL, "case_label", 'e', 2)
Index: parse.y
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/parse.y,v
retrieving revision 1.42
diff -c -p -r1.42 parse.y
*** parse.y 1998/03/17 00:03:42 1.42
--- parse.y 1998/03/17 23:20:09
*************** empty_parms ()
*** 263,269 ****
%type <ttype> complete_type_name notype_identifier nonnested_type
%type <ttype> complex_type_name nested_name_specifier_1
%type <ttype> new_initializer new_placement
! %type <ttype> using_decl .poplevel
%type <ttype> typename_sub typename_sub0 typename_sub1 typename_sub2
%type <ttype> explicit_template_type
/* in order to recognize aggr tags as defining and thus shadowing. */
--- 263,269 ----
%type <ttype> complete_type_name notype_identifier nonnested_type
%type <ttype> complex_type_name nested_name_specifier_1
%type <ttype> new_initializer new_placement
! %type <ttype> using_decl
%type <ttype> typename_sub typename_sub0 typename_sub1 typename_sub2
%type <ttype> explicit_template_type
/* in order to recognize aggr tags as defining and thus shadowing. */
*************** paren_expr_or_null:
*** 1002,1008 ****
cond_stmt_keyword);
$$ = integer_zero_node; }
| '(' expr ')'
! { $$ = condition_conversion ($2); }
;
paren_cond_or_null:
--- 1002,1008 ----
cond_stmt_keyword);
$$ = integer_zero_node; }
| '(' expr ')'
! { $$ = $2; }
;
paren_cond_or_null:
*************** paren_cond_or_null:
*** 1011,1017 ****
cond_stmt_keyword);
$$ = integer_zero_node; }
| '(' condition ')'
! { $$ = condition_conversion ($2); }
;
xcond:
--- 1011,1017 ----
cond_stmt_keyword);
$$ = integer_zero_node; }
| '(' condition ')'
! { $$ = $2; }
;
xcond:
*************** compstmtend:
*** 1062,1085 ****
already_scoped_stmt:
'{'
! {
! if (processing_template_decl)
! {
! $<ttype>$ = build_min_nt (COMPOUND_STMT, NULL_TREE);
! COMPOUND_STMT_NO_SCOPE ($<ttype>$) = 1;
! add_tree ($<ttype>$);
! }
! }
compstmtend
! {
! if (processing_template_decl)
! {
! TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2);
! TREE_CHAIN ($<ttype>2) = NULL_TREE;
! last_tree = $<ttype>2;
! }
! finish_stmt ();
! }
| simple_stmt
;
--- 1062,1070 ----
already_scoped_stmt:
'{'
! { $<ttype>$ = begin_compound_statement (1); }
compstmtend
! { finish_compound_statement (1, $<ttype>2); }
| simple_stmt
;
*************** errstmt:
*** 3436,3455 ****
error ';'
;
- /* build the LET_STMT node before parsing its contents,
- so that any LET_STMTs within the context can have their display pointers
- set up to point at this one. */
-
- .pushlevel:
- /* empty */
- { do_pushlevel (); }
- ;
-
- .poplevel:
- /* empty */
- { $$ = do_poplevel (); }
- ;
-
/* Read zero or more forward-declarations for labels
that nested functions can jump to. */
maybe_label_decls:
--- 3421,3426 ----
*************** compstmt_or_error:
*** 3486,3577 ****
compstmt:
'{'
! {
! if (processing_template_decl)
! {
! $<ttype>$ = build_min_nt (COMPOUND_STMT, NULL_TREE);
! add_tree ($<ttype>$);
! }
! }
! .pushlevel compstmtend .poplevel
! {
! if (processing_template_decl)
! {
! TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2);
! TREE_CHAIN ($<ttype>2) = NULL_TREE;
! last_tree = $<ttype>2;
! }
! $$ = $5;
! }
;
simple_if:
IF
- {
- if (processing_template_decl)
- {
- $<ttype>$ = build_min_nt (IF_STMT, NULL_TREE, NULL_TREE,
- NULL_TREE);
- add_tree ($<ttype>$);
- }
- cond_stmt_keyword = "if";
- }
- .pushlevel paren_cond_or_null
{
! if (processing_template_decl)
! {
! if (last_tree != $<ttype>2)
! {
! TREE_OPERAND ($<ttype>2, 0) = last_tree;
! TREE_CHAIN ($<ttype>2) = NULL_TREE;
! last_tree = $<ttype>2;
! }
! else
! TREE_OPERAND ($<ttype>2, 0) = $4;
! }
! else
! {
! emit_line_note (input_filename, lineno);
! expand_start_cond ($4, 0);
! }
}
! implicitly_scoped_stmt
! {
! if (processing_template_decl)
! {
! TREE_OPERAND ($<ttype>2, 1) = TREE_CHAIN ($<ttype>2);
! TREE_CHAIN ($<ttype>2) = NULL_TREE;
! $<ttype>$ = last_tree = $<ttype>2;
! }
! }
;
implicitly_scoped_stmt:
compstmt
! { finish_stmt (); }
! | .pushlevel
! {
! if (processing_template_decl)
! {
! $<ttype>$ = build_min_nt (COMPOUND_STMT, NULL_TREE);
! add_tree ($<ttype>$);
! }
! }
! simple_stmt .poplevel
! {
! if (processing_template_decl)
! {
! TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2);
! TREE_CHAIN ($<ttype>2) = NULL_TREE;
! last_tree = $<ttype>2;
! }
! $$ = $4;
! }
;
stmt:
compstmt
! { finish_stmt (); }
| simple_stmt
;
--- 3457,3489 ----
compstmt:
'{'
! { $<ttype>$ = begin_compound_statement (0); }
! compstmtend
! { $$ = finish_compound_statement (0, $<ttype>2); }
;
simple_if:
IF
{
! $<ttype>$ = begin_if_statement ();
! cond_stmt_keyword = "if";
}
! paren_cond_or_null
! { finish_if_statement_condition ($3, $<ttype>2); }
! implicitly_scoped_stmt
! { $<ttype>$ = finish_then_clause ($<ttype>2); }
;
implicitly_scoped_stmt:
compstmt
! | { $<ttype>$ = begin_compound_statement (0); }
! simple_stmt
! { $$ = finish_compound_statement (0, $<ttype>1); }
;
stmt:
compstmt
! {}
| simple_stmt
;
*************** simple_stmt:
*** 3579,3924 ****
decl
{ finish_stmt (); }
| expr ';'
! {
! tree expr = $1;
! if (! processing_template_decl)
! {
! emit_line_note (input_filename, lineno);
! /* Do default conversion if safe and possibly important,
! in case within ({...}). */
! if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
! && lvalue_p (expr))
! || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
! expr = default_conversion (expr);
! }
! cplus_expand_expr_stmt (expr);
! clear_momentary ();
! finish_stmt (); }
| simple_if ELSE
! { if (! processing_template_decl) expand_start_else (); }
implicitly_scoped_stmt
! {
! if (processing_template_decl)
! {
! TREE_OPERAND ($<ttype>1, 2) = TREE_CHAIN ($<ttype>1);
! TREE_CHAIN ($<ttype>1) = NULL_TREE;
! last_tree = $<ttype>1;
! }
! else
! expand_end_cond ();
}
- .poplevel
- { finish_stmt (); }
| simple_if %prec IF
! { if (! processing_template_decl) expand_end_cond ();
! do_poplevel ();
! finish_stmt (); }
| WHILE
{
! if (processing_template_decl)
! {
! $<ttype>$ = build_min_nt (WHILE_STMT, NULL_TREE, NULL_TREE);
! add_tree ($<ttype>$);
! }
! else
! {
! emit_nop ();
! emit_line_note (input_filename, lineno);
! expand_start_loop (1);
! }
cond_stmt_keyword = "while";
}
! .pushlevel paren_cond_or_null
! {
! if (processing_template_decl)
! {
! if (last_tree != $<ttype>2)
! {
! TREE_OPERAND ($<ttype>2, 0) = last_tree;
! TREE_CHAIN ($<ttype>2) = NULL_TREE;
! last_tree = $<ttype>2;
! }
! else
! TREE_OPERAND ($<ttype>2, 0) = $4;
! }
! else
! {
! emit_line_note (input_filename, lineno);
! expand_exit_loop_if_false (0, $4);
! }
!
! /* If the condition 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)
! {
! do_poplevel ();
! do_pushlevel ();
! }
! }
! already_scoped_stmt .poplevel
! {
! if (processing_template_decl)
! {
! TREE_OPERAND ($<ttype>2, 1) = TREE_CHAIN ($<ttype>2);
! TREE_CHAIN ($<ttype>2) = NULL_TREE;
! last_tree = $<ttype>2;
! }
! else
! expand_end_loop ();
! finish_stmt ();
! }
| DO
! {
! if (processing_template_decl)
! {
! $<ttype>$ = build_min_nt (DO_STMT, NULL_TREE, NULL_TREE);
! add_tree ($<ttype>$);
! }
! else
! {
! emit_nop ();
! emit_line_note (input_filename, lineno);
! expand_start_loop_continue_elsewhere (1);
! }
! }
implicitly_scoped_stmt WHILE
{
! if (processing_template_decl)
! {
! TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2);
! TREE_CHAIN ($<ttype>2) = NULL_TREE;
! last_tree = $<ttype>2;
! }
! else
! {
! expand_loop_continue_here ();
! cond_stmt_keyword = "do";
! }
}
paren_expr_or_null ';'
! {
! if (processing_template_decl)
! TREE_OPERAND ($<ttype>2, 1) = $6;
! else
! {
! emit_line_note (input_filename, lineno);
! expand_exit_loop_if_false (0, $6);
! expand_end_loop ();
! }
! clear_momentary ();
! finish_stmt ();
! }
| FOR
! { if (processing_template_decl)
! {
! $<ttype>$ = build_min_nt (FOR_STMT, NULL_TREE, NULL_TREE,
! NULL_TREE, NULL_TREE);
! add_tree ($<ttype>$);
! }
! else
! emit_line_note (input_filename, lineno);
! if (flag_new_for_scope > 0)
! {
! /* Conditionalize .pushlevel */
! pushlevel (0);
! note_level_for_for ();
! clear_last_expr ();
! push_momentary ();
! expand_start_bindings (0);
! }
! }
'(' for.init.statement
! {
! if (processing_template_decl)
! {
! if (last_tree != $<ttype>2)
! {
! TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2);
! TREE_CHAIN ($<ttype>2) = NULL_TREE;
! last_tree = $<ttype>2;
! }
! }
! else
! {
! emit_nop ();
! emit_line_note (input_filename, lineno);
! expand_start_loop_continue_elsewhere (1);
! }
! }
! .pushlevel xcond ';'
! {
! if (processing_template_decl)
! {
! if (last_tree != $<ttype>2)
! {
! TREE_OPERAND ($<ttype>2, 1) = last_tree;
! TREE_CHAIN ($<ttype>2) = NULL_TREE;
! last_tree = $<ttype>2;
! }
! else
! TREE_OPERAND ($<ttype>2, 1) = $7;
! }
! else
! {
! emit_line_note (input_filename, lineno);
! if ($7) expand_exit_loop_if_false (0, $7);
! }
!
! /* If the condition 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)
! {
! do_poplevel ();
! do_pushlevel ();
! }
! }
xexpr ')'
! /* Don't let the tree nodes for $10 be discarded
! by clear_momentary during the parsing of the next stmt. */
! {
! if (processing_template_decl)
! TREE_OPERAND ($<ttype>2, 2) = $10;
! push_momentary ();
! }
! already_scoped_stmt .poplevel
! {
! if (processing_template_decl)
! {
! TREE_OPERAND ($<ttype>2, 3) = TREE_CHAIN ($<ttype>2);
! TREE_CHAIN ($<ttype>2) = NULL_TREE;
! last_tree = $<ttype>2;
! }
! else
! {
! emit_line_note (input_filename, lineno);
! expand_loop_continue_here ();
! if ($10) cplus_expand_expr_stmt ($10);
! expand_end_loop ();
! }
! pop_momentary ();
! if (flag_new_for_scope > 0)
! {
! do_poplevel ();
! }
! finish_stmt (); }
! | SWITCH .pushlevel '(' condition ')'
! {
! if (processing_template_decl)
! {
! $<ttype>$ = build_min_nt (SWITCH_STMT, $4, NULL_TREE);
! add_tree ($<ttype>$);
! }
! else
! {
! emit_line_note (input_filename, lineno);
! c_expand_start_case ($4);
! }
! push_switch ();
! /* Don't let the tree nodes for $4 be discarded by
! clear_momentary during the parsing of the next stmt. */
! push_momentary ();
! }
implicitly_scoped_stmt
! {
! if (processing_template_decl)
! {
! TREE_OPERAND ($<ttype>6, 1) = TREE_CHAIN ($<ttype>6);
! TREE_CHAIN ($<ttype>6) = NULL_TREE;
! last_tree = $<ttype>6;
! }
! else
! expand_end_case ($4);
! pop_momentary ();
! pop_switch ();
! }
! .poplevel
! { finish_stmt (); }
| CASE expr_no_commas ':'
! { do_case ($2, NULL_TREE); }
stmt
| CASE expr_no_commas ELLIPSIS expr_no_commas ':'
! { do_case ($2, $4); }
stmt
| DEFAULT ':'
! { do_case (NULL_TREE, NULL_TREE); }
stmt
| BREAK ';'
! { emit_line_note (input_filename, lineno);
! if (processing_template_decl)
! add_tree (build_min_nt (BREAK_STMT));
! else if ( ! expand_exit_something ())
! error ("break statement not within loop or switch"); }
| CONTINUE ';'
! { emit_line_note (input_filename, lineno);
! if (processing_template_decl)
! add_tree (build_min_nt (CONTINUE_STMT));
! else if (! expand_continue_loop (0))
! error ("continue statement not within a loop"); }
| RETURN ';'
! { emit_line_note (input_filename, lineno);
! c_expand_return (NULL_TREE); }
| RETURN expr ';'
! { emit_line_note (input_filename, lineno);
! c_expand_return ($2);
! finish_stmt ();
! }
| asm_keyword maybe_cv_qualifier '(' string ')' ';'
! { if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
! emit_line_note (input_filename, lineno);
! expand_asm ($4);
! finish_stmt ();
}
/* This is the case with just output operands. */
| asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ')' ';'
! { if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
! emit_line_note (input_filename, lineno);
! c_expand_asm_operands ($4, $6, NULL_TREE, NULL_TREE,
! $2 == ridpointers[(int)RID_VOLATILE],
! input_filename, lineno);
! finish_stmt ();
}
/* This is the case with input operands as well. */
| asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ':' asm_operands ')' ';'
! { if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
! emit_line_note (input_filename, lineno);
! c_expand_asm_operands ($4, $6, $8, NULL_TREE,
! $2 == ridpointers[(int)RID_VOLATILE],
! input_filename, lineno);
! finish_stmt ();
! }
/* This is the case with clobbered registers as well. */
| asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ':'
asm_operands ':' asm_clobbers ')' ';'
! { if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
! emit_line_note (input_filename, lineno);
! c_expand_asm_operands ($4, $6, $8, $10,
! $2 == ridpointers[(int)RID_VOLATILE],
! input_filename, lineno);
! finish_stmt ();
! }
| GOTO '*' expr ';'
! {
! if (processing_template_decl)
! add_tree (build_min_nt (GOTO_STMT, $3));
! else
! { emit_line_note (input_filename, lineno);
! expand_computed_goto ($3); }
}
| GOTO identifier ';'
! {
! if (processing_template_decl)
! add_tree (build_min_nt (GOTO_STMT, $2));
! else
! {
! tree decl;
! emit_line_note (input_filename, lineno);
! decl = lookup_label ($2);
! TREE_USED (decl) = 1;
! expand_goto (decl);
! }
! }
| label_colon stmt
{ finish_stmt (); }
| label_colon '}'
--- 3491,3583 ----
decl
{ finish_stmt (); }
| expr ';'
! { finish_expression_statement ($1); }
| simple_if ELSE
! { begin_else_clause (); }
implicitly_scoped_stmt
! {
! finish_else_clause ($<ttype>1);
! finish_if_statement ();
}
| simple_if %prec IF
! { finish_if_statement (); }
| WHILE
{
! $<ttype>$ = begin_while_statement ();
cond_stmt_keyword = "while";
}
! paren_cond_or_null
! { finish_while_statement_condition ($3, $<ttype>2); }
! already_scoped_stmt
! { finish_while_statement ($<ttype>2); }
| DO
! { $<ttype>$ = begin_do_statement (); }
implicitly_scoped_stmt WHILE
{
! finish_do_body ($<ttype>2);
! cond_stmt_keyword = "do";
}
paren_expr_or_null ';'
! { finish_do_statement ($6, $<ttype>2); }
| FOR
! { $<ttype>$ = begin_for_statement (); }
'(' for.init.statement
! { finish_for_init_statement ($<ttype>2); }
! xcond ';'
! { finish_for_condition ($6, $<ttype>2); }
xexpr ')'
! { finish_for_expression ($9, $<ttype>2); }
! already_scoped_stmt
! { finish_for_statement ($9, $<ttype>2); }
! | SWITCH
! { begin_switch_statement (); }
! '(' condition ')'
! { $<ttype>$ = finish_switch_condition ($4); }
implicitly_scoped_stmt
! { finish_switch_statement ($4, $<ttype>6); }
| CASE expr_no_commas ':'
! { finish_case_label ($2, NULL_TREE); }
stmt
| CASE expr_no_commas ELLIPSIS expr_no_commas ':'
! { finish_case_label ($2, $4); }
stmt
| DEFAULT ':'
! { finish_case_label (NULL_TREE, NULL_TREE); }
stmt
| BREAK ';'
! { finish_break_statement (); }
| CONTINUE ';'
! { finish_continue_statement (); }
| RETURN ';'
! { finish_return_statement (NULL_TREE); }
| RETURN expr ';'
! { finish_return_statement ($2); }
| asm_keyword maybe_cv_qualifier '(' string ')' ';'
! {
! finish_asm_statement ($2, $4, NULL_TREE, NULL_TREE,
! NULL_TREE);
}
/* This is the case with just output operands. */
| asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ')' ';'
! {
! finish_asm_statement ($2, $4, $6, NULL_TREE,
! NULL_TREE);
}
/* This is the case with input operands as well. */
| asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ':' asm_operands ')' ';'
! { finish_asm_statement ($2, $4, $6, $8, NULL_TREE); }
/* This is the case with clobbered registers as well. */
| asm_keyword maybe_cv_qualifier '(' string ':' asm_operands ':'
asm_operands ':' asm_clobbers ')' ';'
! { finish_asm_statement ($2, $4, $6, $8, $10); }
| GOTO '*' expr ';'
! {
! if (pedantic)
! pedwarn ("ANSI C++ forbids computed gotos");
! finish_goto_statement ($3);
}
| GOTO identifier ';'
! { finish_goto_statement ($2); }
| label_colon stmt
{ finish_stmt (); }
| label_colon '}'
*************** function_try_block:
*** 3950,3990 ****
try_block:
TRY
! {
! if (processing_template_decl)
! {
! $<ttype>$ = build_min_nt (TRY_BLOCK, NULL_TREE,
! NULL_TREE);
! add_tree ($<ttype>$);
! }
! else
! {
! emit_line_note (input_filename, lineno);
! expand_start_try_stmts ();
! }
! }
compstmt
! {
! if (processing_template_decl)
! {
! TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2);
! TREE_CHAIN ($<ttype>2) = NULL_TREE;
! last_tree = $<ttype>2;
! }
! else
! expand_start_all_catch ();
! }
handler_seq
! {
! if (processing_template_decl)
! {
! TREE_OPERAND ($<ttype>2, 1) = TREE_CHAIN ($<ttype>2);
! TREE_CHAIN ($<ttype>2) = NULL_TREE;
! last_tree = $<ttype>2;
! }
! else
! expand_end_all_catch ();
! }
;
handler_seq:
--- 3609,3619 ----
try_block:
TRY
! { $<ttype>$ = begin_try_block (); }
compstmt
! { finish_try_block ($<ttype>2); }
handler_seq
! { finish_handler_sequence ($<ttype>2); }
;
handler_seq:
*************** handler_seq:
*** 3994,4028 ****
handler:
CATCH
! {
! if (processing_template_decl)
! {
! $<ttype>$ = build_min_nt (HANDLER, NULL_TREE,
! NULL_TREE);
! add_tree ($<ttype>$);
! }
! }
! .pushlevel handler_args
! {
! if (processing_template_decl)
! {
! TREE_OPERAND ($<ttype>2, 0) = TREE_CHAIN ($<ttype>2);
! TREE_CHAIN ($<ttype>2) = NULL_TREE;
! last_tree = $<ttype>2;
! }
! }
compstmt
! {
! if (processing_template_decl)
! {
! TREE_OPERAND ($<ttype>2, 1) = TREE_CHAIN ($<ttype>2);
! TREE_CHAIN ($<ttype>2) = NULL_TREE;
! last_tree = $<ttype>2;
! }
! else
! expand_end_catch_block ();
! }
! .poplevel
;
type_specifier_seq:
--- 3623,3633 ----
handler:
CATCH
! { $<ttype>$ = begin_handler(); }
! handler_args
! { finish_handler_parameters ($<ttype>2); }
compstmt
! { finish_handler ($<ttype>2); }
;
type_specifier_seq:
Index: pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.93
diff -c -p -r1.93 pt.c
*** pt.c 1998/03/17 12:20:38 1.93
--- pt.c 1998/03/17 23:06:38
*************** tsubst_expr (t, args, in_decl)
*** 4675,4698 ****
{
case RETURN_STMT:
lineno = TREE_COMPLEXITY (t);
! emit_line_note (input_filename, lineno);
! c_expand_return
! (tsubst_expr (TREE_OPERAND (t, 0), args, in_decl));
! finish_stmt ();
break;
case EXPR_STMT:
lineno = TREE_COMPLEXITY (t);
! emit_line_note (input_filename, lineno);
! t = tsubst_expr (TREE_OPERAND (t, 0), args, in_decl);
! /* Do default conversion if safe and possibly important,
! in case within ({...}). */
! if ((TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE && lvalue_p (t))
! || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
! t = default_conversion (t);
! cplus_expand_expr_stmt (t);
! clear_momentary ();
! finish_stmt ();
break;
case DECL_STMT:
--- 4675,4688 ----
{
case RETURN_STMT:
lineno = TREE_COMPLEXITY (t);
! finish_return_statement (tsubst_expr (RETURN_EXPR (t),
! args, in_decl));
break;
case EXPR_STMT:
lineno = TREE_COMPLEXITY (t);
! finish_expression_statement (tsubst_expr (EXPR_STMT_EXPR (t),
! args, in_decl));
break;
case DECL_STMT:
*************** tsubst_expr (t, args, in_decl)
*** 4716,4899 ****
case FOR_STMT:
{
tree tmp;
- int init_scope = (flag_new_for_scope > 0 && TREE_OPERAND (t, 0)
- && TREE_CODE (TREE_OPERAND (t, 0)) == DECL_STMT);
- int cond_scope = (TREE_OPERAND (t, 1)
- && TREE_CODE (TREE_OPERAND (t, 1)) == DECL_STMT);
-
lineno = TREE_COMPLEXITY (t);
- emit_line_note (input_filename, lineno);
- if (init_scope)
- do_pushlevel ();
- for (tmp = TREE_OPERAND (t, 0); tmp; tmp = TREE_CHAIN (tmp))
- tsubst_expr (tmp, args, in_decl);
- emit_nop ();
- emit_line_note (input_filename, lineno);
- expand_start_loop_continue_elsewhere (1);
-
- if (cond_scope)
- do_pushlevel ();
- tmp = tsubst_expr (TREE_OPERAND (t, 1), args, in_decl);
- emit_line_note (input_filename, lineno);
- if (tmp)
- expand_exit_loop_if_false (0, condition_conversion (tmp));
! if (! cond_scope)
! do_pushlevel ();
! tsubst_expr (TREE_OPERAND (t, 3), args, in_decl);
! do_poplevel ();
!
! emit_line_note (input_filename, lineno);
! expand_loop_continue_here ();
! tmp = tsubst_expr (TREE_OPERAND (t, 2), args, in_decl);
! if (tmp)
! cplus_expand_expr_stmt (tmp);
!
! expand_end_loop ();
! if (init_scope)
! do_poplevel ();
! finish_stmt ();
}
break;
case WHILE_STMT:
{
- tree cond;
-
lineno = TREE_COMPLEXITY (t);
! emit_nop ();
! emit_line_note (input_filename, lineno);
! expand_start_loop (1);
!
! cond = TREE_OPERAND (t, 0);
! if (TREE_CODE (cond) == DECL_STMT)
! do_pushlevel ();
! cond = tsubst_expr (cond, args, in_decl);
! emit_line_note (input_filename, lineno);
! expand_exit_loop_if_false (0, condition_conversion (cond));
!
! if (TREE_CODE (TREE_OPERAND (t, 0)) != DECL_STMT)
! do_pushlevel ();
! tsubst_expr (TREE_OPERAND (t, 1), args, in_decl);
! do_poplevel ();
!
! expand_end_loop ();
! finish_stmt ();
}
break;
case DO_STMT:
{
- tree cond;
-
lineno = TREE_COMPLEXITY (t);
! emit_nop ();
! emit_line_note (input_filename, lineno);
! expand_start_loop_continue_elsewhere (1);
!
! tsubst_expr (TREE_OPERAND (t, 0), args, in_decl);
! expand_loop_continue_here ();
!
! cond = tsubst_expr (TREE_OPERAND (t, 1), args, in_decl);
! emit_line_note (input_filename, lineno);
! expand_exit_loop_if_false (0, condition_conversion (cond));
! expand_end_loop ();
!
! clear_momentary ();
! finish_stmt ();
}
break;
case IF_STMT:
{
tree tmp;
- int cond_scope = (TREE_CODE (TREE_OPERAND (t, 0)) == DECL_STMT);
lineno = TREE_COMPLEXITY (t);
! if (cond_scope)
! do_pushlevel ();
! tmp = tsubst_expr (TREE_OPERAND (t, 0), args, in_decl);
! emit_line_note (input_filename, lineno);
! expand_start_cond (condition_conversion (tmp), 0);
!
! if (tmp = TREE_OPERAND (t, 1), tmp)
! tsubst_expr (tmp, args, in_decl);
! if (tmp = TREE_OPERAND (t, 2), tmp)
{
- expand_start_else ();
tsubst_expr (tmp, args, in_decl);
}
-
- expand_end_cond ();
! if (cond_scope)
! do_poplevel ();
! finish_stmt ();
}
break;
case COMPOUND_STMT:
{
! tree substmt = TREE_OPERAND (t, 0);
lineno = TREE_COMPLEXITY (t);
!
! if (COMPOUND_STMT_NO_SCOPE (t) == 0)
! do_pushlevel ();
!
! for (; substmt; substmt = TREE_CHAIN (substmt))
tsubst_expr (substmt, args, in_decl);
!
! if (COMPOUND_STMT_NO_SCOPE (t) == 0)
! return do_poplevel ();
}
break;
case BREAK_STMT:
lineno = TREE_COMPLEXITY (t);
! emit_line_note (input_filename, lineno);
! if (! expand_exit_something ())
! error ("break statement not within loop or switch");
break;
case CONTINUE_STMT:
lineno = TREE_COMPLEXITY (t);
! emit_line_note (input_filename, lineno);
! if (! expand_continue_loop (0))
! error ("continue statement not within a loop");
break;
case SWITCH_STMT:
{
tree val, tmp;
- int cond_scope = (TREE_CODE (TREE_OPERAND (t, 0)) == DECL_STMT);
lineno = TREE_COMPLEXITY (t);
! if (cond_scope)
! do_pushlevel ();
! val = tsubst_expr (TREE_OPERAND (t, 0), args, in_decl);
! emit_line_note (input_filename, lineno);
! c_expand_start_case (val);
! push_switch ();
if (tmp = TREE_OPERAND (t, 1), tmp)
tsubst_expr (tmp, args, in_decl);
-
- expand_end_case (val);
- pop_switch ();
! if (cond_scope)
! do_poplevel ();
!
! finish_stmt ();
}
break;
case CASE_LABEL:
! do_case (tsubst_expr (TREE_OPERAND (t, 0), args, in_decl),
! tsubst_expr (TREE_OPERAND (t, 1), args, in_decl));
break;
case LABEL_DECL:
--- 4706,4822 ----
case FOR_STMT:
{
tree tmp;
lineno = TREE_COMPLEXITY (t);
! begin_for_statement ();
! for (tmp = FOR_INIT_STMT (t); tmp; tmp = TREE_CHAIN (tmp))
! tsubst_expr (tmp, args, in_decl);
! finish_for_init_statement (NULL_TREE);
! finish_for_condition (tsubst_expr (FOR_CONDITION (t), args,
! in_decl),
! NULL_TREE);
! tmp = tsubst_expr (FOR_EXPRESSION (t), args, in_decl);
! finish_for_expression (tmp, NULL_TREE);
! tsubst_expr (FOR_BODY (t), args, in_decl);
! finish_for_statement (tmp, NULL_TREE);
}
break;
case WHILE_STMT:
{
lineno = TREE_COMPLEXITY (t);
! begin_while_statement ();
! finish_while_statement_condition (tsubst_expr (WHILE_CONDITION (t),
! args, in_decl),
! NULL_TREE);
! tsubst_expr (WHILE_BODY (t), args, in_decl);
! finish_while_statement (NULL_TREE);
}
break;
case DO_STMT:
{
lineno = TREE_COMPLEXITY (t);
! begin_do_statement ();
! tsubst_expr (DO_BODY (t), args, in_decl);
! finish_do_body (NULL_TREE);
! finish_do_statement (tsubst_expr (DO_CONDITION (t), args,
! in_decl),
! NULL_TREE);
}
break;
case IF_STMT:
{
tree tmp;
lineno = TREE_COMPLEXITY (t);
! begin_if_statement ();
! finish_if_statement_condition (tsubst_expr (IF_CONDITION (t),
! args, in_decl),
! NULL_TREE);
! if (tmp = THEN_CLAUSE (t), tmp)
{
tsubst_expr (tmp, args, in_decl);
+ finish_then_clause (NULL_TREE);
}
! if (tmp = ELSE_CLAUSE (t), tmp)
! {
! begin_else_clause ();
! tsubst_expr (tmp, args, in_decl);
! finish_else_clause (NULL_TREE);
! }
! finish_if_statement ();
}
break;
case COMPOUND_STMT:
{
! tree substmt;
lineno = TREE_COMPLEXITY (t);
! begin_compound_statement (COMPOUND_STMT_NO_SCOPE (t));
! for (substmt = COMPOUND_BODY (t);
! substmt != NULL_TREE;
! substmt = TREE_CHAIN (substmt))
tsubst_expr (substmt, args, in_decl);
! return finish_compound_statement (COMPOUND_STMT_NO_SCOPE (t),
! NULL_TREE);
}
break;
case BREAK_STMT:
lineno = TREE_COMPLEXITY (t);
! finish_break_statement ();
break;
case CONTINUE_STMT:
lineno = TREE_COMPLEXITY (t);
! finish_continue_statement ();
break;
case SWITCH_STMT:
{
tree val, tmp;
lineno = TREE_COMPLEXITY (t);
! begin_switch_statement ();
! val = tsubst_expr (SWITCH_CONDITION (t), args, in_decl);
! finish_switch_condition (val);
if (tmp = TREE_OPERAND (t, 1), tmp)
tsubst_expr (tmp, args, in_decl);
! finish_switch_statement (val, NULL_TREE);
}
break;
case CASE_LABEL:
! finish_case_label (tsubst_expr (CASE_LOW (t), args, in_decl),
! tsubst_expr (CASE_HIGH (t), args, in_decl));
break;
case LABEL_DECL:
*************** tsubst_expr (t, args, in_decl)
*** 4905,4951 ****
case GOTO_STMT:
lineno = TREE_COMPLEXITY (t);
! emit_line_note (input_filename, lineno);
! if (TREE_CODE (TREE_OPERAND (t, 0)) == IDENTIFIER_NODE)
! {
! tree decl = lookup_label (TREE_OPERAND (t, 0));
! TREE_USED (decl) = 1;
! expand_goto (decl);
! }
! else
! expand_computed_goto
! (tsubst_expr (TREE_OPERAND (t, 0), args, in_decl));
break;
case TRY_BLOCK:
lineno = TREE_COMPLEXITY (t);
! emit_line_note (input_filename, lineno);
! expand_start_try_stmts ();
! tsubst_expr (TREE_OPERAND (t, 0), args, in_decl);
! expand_start_all_catch ();
{
! tree handler = TREE_OPERAND (t, 1);
for (; handler; handler = TREE_CHAIN (handler))
tsubst_expr (handler, args, in_decl);
}
! expand_end_all_catch ();
break;
case HANDLER:
lineno = TREE_COMPLEXITY (t);
! do_pushlevel ();
! if (TREE_OPERAND (t, 0))
{
! tree d = TREE_OPERAND (t, 0);
expand_start_catch_block
(tsubst (TREE_OPERAND (d, 1), args, in_decl),
tsubst (TREE_OPERAND (d, 0), args, in_decl));
}
else
expand_start_catch_block (NULL_TREE, NULL_TREE);
! tsubst_expr (TREE_OPERAND (t, 1), args, in_decl);
! expand_end_catch_block ();
! do_poplevel ();
break;
case TAG_DEFN:
--- 4828,4877 ----
case GOTO_STMT:
lineno = TREE_COMPLEXITY (t);
! finish_goto_statement (tsubst_expr (GOTO_DESTINATION (t),
! args, in_decl));
! break;
!
! case ASM_STMT:
! lineno = TREE_COMPLEXITY (t);
! finish_asm_statement (tsubst_expr (ASM_CV_QUAL (t), args, in_decl),
! tsubst_expr (ASM_STRING (t), args, in_decl),
! tsubst_expr (ASM_OUTPUTS (t), args,
! in_decl),
! tsubst_expr (ASM_INPUTS (t), args,
! in_decl),
! tsubst_expr (ASM_CLOBBERS (t), args,
! in_decl));
break;
case TRY_BLOCK:
lineno = TREE_COMPLEXITY (t);
! begin_try_block ();
! tsubst_expr (TRY_STMTS (t), args, in_decl);
! finish_try_block (NULL_TREE);
{
! tree handler = TRY_HANDLERS (t);
for (; handler; handler = TREE_CHAIN (handler))
tsubst_expr (handler, args, in_decl);
}
! finish_handler_sequence (NULL_TREE);
break;
case HANDLER:
lineno = TREE_COMPLEXITY (t);
! begin_handler ();
! if (HANDLER_PARMS (t))
{
! tree d = HANDLER_PARMS (t);
expand_start_catch_block
(tsubst (TREE_OPERAND (d, 1), args, in_decl),
tsubst (TREE_OPERAND (d, 0), args, in_decl));
}
else
expand_start_catch_block (NULL_TREE, NULL_TREE);
! finish_handler_parameters (NULL_TREE);
! tsubst_expr (HANDLER_BODY (t), args, in_decl);
! finish_handler (NULL_TREE);
break;
case TAG_DEFN:
Index: semantics.c
===================================================================
RCS file: semantics.c
diff -N semantics.c
*** /dev/null Mon Dec 31 20:00:00 1979
--- semantics.c Tue Mar 17 15:06:39 1998
***************
*** 0 ****
--- 1,748 ----
+ /* Perform the semantic phase of parsing, i.e., the process of
+ building tree structure, checking semantic consistency, and
+ building RTL. These routines are used both during actual parsing
+ and during the instantiation of template functions.
+
+ Copyright (C) 1998 Free Software Foundation, Inc.
+ Written by Mark Mitchell (mmitchell@usa.net) based on code found
+ formerly in parse.y and pt.c.
+
+ This file is part of GNU CC.
+
+ GNU CC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU CC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU CC; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+ #include "config.h"
+ #include <stdio.h>
+ #include "tree.h"
+ #include "cp-tree.h"
+ #include "except.h"
+ #include "lex.h"
+
+ /* There routines provide a modular interface to perform many parsing
+ operations. They may therefore be used during actual parsing, or
+ during template instantiation, which may be regarded as a
+ degenerate form of parsing. Since the current g++ parser is
+ lacking in several respects, and will be reimplemented, we are
+ attempting to move most code that is not directly related to
+ parsing into this file; that will make implementing the new parser
+ much easier since it will be able to make use of these routines. */
+
+ /* When parsing a template, LAST_TREE contains the last statement
+ parsed. These are chained together through the TREE_CHAIN field,
+ but often need to be re-organized since the parse is performed
+ bottom-up. This macro makes LAST_TREE the indicated SUBSTMT of
+ STMT. */
+
+ #define RECHAIN_STATEMENTS(stmt, substmt, last) \
+ do { \
+ substmt = last; \
+ TREE_CHAIN (stmt) = NULL_TREE; \
+ last_tree = stmt; \
+ } while (0)
+
+ #define RECHAIN_STATEMENTS_FROM_LAST(stmt, substmt) \
+ RECHAIN_STATEMENTS (stmt, substmt, last_tree)
+
+ #define RECHAIN_STATEMENTS_FROM_CHAIN(stmt, substmt) \
+ RECHAIN_STATEMENTS (stmt, substmt, TREE_CHAIN (stmt))
+
+ /* Finish an expression-statement, whose EXPRESSION is as indicated. */
+
+ void
+ finish_expression_statement (expression)
+ tree expression;
+ {
+ if (!processing_template_decl)
+ {
+ emit_line_note (input_filename, lineno);
+ /* Do default conversion if safe and possibly important,
+ in case within ({...}). */
+ if ((TREE_CODE (TREE_TYPE (expression)) == ARRAY_TYPE
+ && lvalue_p (expression))
+ || TREE_CODE (TREE_TYPE (expression)) == FUNCTION_TYPE)
+ expression = default_conversion (expression);
+ }
+
+ cplus_expand_expr_stmt (expression);
+ clear_momentary ();
+ finish_stmt ();
+ }
+
+ /* Begin an if-statement. Returns a newly created IF_STMT if
+ appropriate. */
+
+ tree
+ begin_if_statement ()
+ {
+ tree r;
+
+ if (processing_template_decl)
+ {
+ r = build_min_nt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
+ add_tree (r);
+ }
+ else
+ r = NULL_TREE;
+
+ do_pushlevel ();
+
+ return r;
+ }
+
+ /* Process the CONDITION of an if-statement, which may be given by
+ IF_STMT. */
+
+ void
+ finish_if_statement_condition (condition, if_stmt)
+ tree condition;
+ tree if_stmt;
+ {
+ if (processing_template_decl)
+ {
+ if (last_tree != if_stmt)
+ RECHAIN_STATEMENTS_FROM_LAST (if_stmt, IF_CONDITION (if_stmt));
+ else
+ IF_CONDITION (if_stmt) = condition;
+ }
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ expand_start_cond (condition_conversion (condition), 0);
+ }
+ }
+
+ /* Finish the then-clause of an if-statement, which may be given by
+ IF_STMT. */
+
+ tree
+ finish_then_clause (if_stmt)
+ tree if_stmt;
+ {
+ if (processing_template_decl)
+ {
+ RECHAIN_STATEMENTS_FROM_CHAIN (if_stmt,
+ THEN_CLAUSE (if_stmt));
+ last_tree = if_stmt;
+ return if_stmt;
+ }
+ else
+ return NULL_TREE;
+ }
+
+ /* Begin the else-clause of an if-statement. */
+
+ void
+ begin_else_clause ()
+ {
+ if (!processing_template_decl)
+ expand_start_else ();
+ }
+
+ /* Finish the else-clause of an if-statement, which may be given by
+ IF_STMT. */
+
+ void
+ finish_else_clause (if_stmt)
+ tree if_stmt;
+ {
+ if (processing_template_decl)
+ RECHAIN_STATEMENTS_FROM_CHAIN (if_stmt, ELSE_CLAUSE (if_stmt));
+ }
+
+ /* Finsh an if-statement. */
+
+ void
+ finish_if_statement ()
+ {
+ if (!processing_template_decl)
+ expand_end_cond ();
+
+ do_poplevel ();
+ finish_stmt ();
+ }
+
+ /* Begin a while-statement. Returns a newly created WHILE_STMT if
+ appropriate. */
+
+ tree
+ begin_while_statement ()
+ {
+ tree r;
+
+ if (processing_template_decl)
+ {
+ r = build_min_nt (WHILE_STMT, NULL_TREE, NULL_TREE);
+ add_tree (r);
+ }
+ else
+ {
+ emit_nop ();
+ emit_line_note (input_filename, lineno);
+ expand_start_loop (1);
+ r = NULL_TREE;
+ }
+
+ do_pushlevel ();
+
+ return r;
+ }
+
+ /* Process the CONDITION of an if-statement, which may be given by
+ WHILE_STMT. */
+
+ void
+ finish_while_statement_condition (condition, while_stmt)
+ tree condition;
+ tree while_stmt;
+ {
+ if (processing_template_decl)
+ {
+ if (last_tree != while_stmt)
+ RECHAIN_STATEMENTS_FROM_LAST (while_stmt,
+ WHILE_CONDITION (while_stmt));
+ else
+ TREE_OPERAND (while_stmt, 0) = condition;
+ }
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ expand_exit_loop_if_false (0, condition_conversion (condition));
+ }
+
+ /* If the condition 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)
+ {
+ do_poplevel ();
+ do_pushlevel ();
+ }
+ }
+
+ /* Finish a while-statement, which may be given by WHILE_STMT. */
+
+ void
+ finish_while_statement (while_stmt)
+ tree while_stmt;
+ {
+ do_poplevel ();
+
+ if (processing_template_decl)
+ RECHAIN_STATEMENTS_FROM_CHAIN (while_stmt, WHILE_BODY (while_stmt));
+ else
+ expand_end_loop ();
+ finish_stmt ();
+ }
+
+ /* Begin a do-statement. Returns a newly created DO_STMT if
+ appropriate. */
+
+ tree
+ begin_do_statement ()
+ {
+ if (processing_template_decl)
+ {
+ tree r = build_min_nt (DO_STMT, NULL_TREE, NULL_TREE);
+ add_tree (r);
+ return r;
+ }
+ else
+ {
+ emit_nop ();
+ emit_line_note (input_filename, lineno);
+ expand_start_loop_continue_elsewhere (1);
+ return NULL_TREE;
+ }
+ }
+
+ /* Finish the body of a do-statement, which may be given by DO_STMT. */
+
+ void
+ finish_do_body (do_stmt)
+ tree do_stmt;
+ {
+ if (processing_template_decl)
+ RECHAIN_STATEMENTS_FROM_CHAIN (do_stmt, DO_BODY (do_stmt));
+ else
+ expand_loop_continue_here ();
+ }
+
+ /* Finish a do-statement, which may be given by DO_STMT, and whose
+ CONDITION is as indicated. */
+
+ void
+ finish_do_statement (condition, do_stmt)
+ tree condition;
+ tree do_stmt;
+ {
+ if (processing_template_decl)
+ DO_CONDITION (do_stmt) = condition;
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ expand_exit_loop_if_false (0, condition_conversion (condition));
+ expand_end_loop ();
+ }
+
+ clear_momentary ();
+ finish_stmt ();
+ }
+
+ /* Finish a return-statement. The EXPRESSION returned, if any, is as
+ indicated. */
+
+ void
+ finish_return_statement (expression)
+ tree expression;
+ {
+ emit_line_note (input_filename, lineno);
+ c_expand_return (expression);
+ finish_stmt ();
+ }
+
+ /* Begin a for-statement. Returns a new FOR_STMT if appropriate. */
+
+ tree
+ begin_for_statement ()
+ {
+ tree r;
+
+ if (processing_template_decl)
+ {
+ r = build_min_nt (FOR_STMT, NULL_TREE, NULL_TREE,
+ NULL_TREE, NULL_TREE);
+ add_tree (r);
+ }
+ else
+ r = NULL_TREE;
+
+ if (flag_new_for_scope > 0)
+ {
+ do_pushlevel ();
+ note_level_for_for ();
+ }
+
+ return r;
+ }
+
+ /* Finish the for-init-statement of a for-statement, which may be
+ given by FOR_STMT. */
+
+ void
+ finish_for_init_statement (for_stmt)
+ tree for_stmt;
+ {
+ if (processing_template_decl)
+ {
+ if (last_tree != for_stmt)
+ RECHAIN_STATEMENTS_FROM_CHAIN (for_stmt, FOR_INIT_STMT (for_stmt));
+ }
+ else
+ {
+ emit_nop ();
+ emit_line_note (input_filename, lineno);
+ expand_start_loop_continue_elsewhere (1);
+ }
+
+ do_pushlevel ();
+ }
+
+ /* Finish the CONDITION of a for-statement, which may be given by
+ FOR_STMT. */
+
+ void
+ finish_for_condition (condition, for_stmt)
+ tree condition;
+ tree for_stmt;
+ {
+ if (processing_template_decl)
+ {
+ if (last_tree != for_stmt)
+ RECHAIN_STATEMENTS_FROM_LAST (for_stmt, FOR_CONDITION (for_stmt));
+ else
+ FOR_CONDITION (for_stmt) = condition;
+ }
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ if (condition)
+ expand_exit_loop_if_false (0, condition);
+ }
+
+ /* If the condition 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)
+ {
+ do_poplevel ();
+ do_pushlevel ();
+ }
+ }
+
+ /* Finish the increment-EXPRESSION in a for-statement, which may be
+ given by FOR_STMT. */
+
+ void
+ finish_for_expression (expression, for_stmt)
+ tree expression;
+ tree for_stmt;
+ {
+ if (processing_template_decl)
+ FOR_EXPRESSION (for_stmt) = expression;
+
+ /* Don't let the tree nodes for EXPRESSION be discarded
+ by clear_momentary during the parsing of the next stmt. */
+ push_momentary ();
+ }
+
+ /* Finish the body of a for-statement, which may be given by
+ FOR_STMT. The increment-EXPRESSION for the loop must be
+ provided. */
+
+ void
+ finish_for_statement (expression, for_stmt)
+ tree expression;
+ tree for_stmt;
+ {
+ /* Pop the scope for the body of the loop. */
+ do_poplevel ();
+
+ if (processing_template_decl)
+ RECHAIN_STATEMENTS_FROM_CHAIN (for_stmt, FOR_BODY (for_stmt));
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ expand_loop_continue_here ();
+ if (expression)
+ cplus_expand_expr_stmt (expression);
+ expand_end_loop ();
+ }
+
+ pop_momentary ();
+
+ if (flag_new_for_scope > 0)
+ do_poplevel ();
+
+ finish_stmt ();
+ }
+
+ /* Finish a break-statement. */
+
+ void
+ finish_break_statement ()
+ {
+ emit_line_note (input_filename, lineno);
+ if (processing_template_decl)
+ add_tree (build_min_nt (BREAK_STMT));
+ else if ( ! expand_exit_something ())
+ cp_error ("break statement not within loop or switch");
+ }
+
+ /* Finish a continue-statement. */
+
+ void
+ finish_continue_statement ()
+ {
+ emit_line_note (input_filename, lineno);
+ if (processing_template_decl)
+ add_tree (build_min_nt (CONTINUE_STMT));
+ else if (! expand_continue_loop (0))
+ cp_error ("continue statement not within a loop");
+ }
+
+ /* Begin a switch-statement. */
+
+ void
+ begin_switch_statement ()
+ {
+ do_pushlevel ();
+ }
+
+ /* Finish the condition of a switch-statement. Returns a new
+ SWITCH_STMT if appropriate. */
+
+ tree
+ finish_switch_condition (condition)
+ tree condition;
+ {
+ tree r;
+
+ if (processing_template_decl)
+ {
+ r = build_min_nt (SWITCH_STMT, condition, NULL_TREE);
+ add_tree (r);
+ }
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ c_expand_start_case (condition);
+ r = NULL_TREE;
+ }
+ push_switch ();
+
+ /* Don't let the tree nodes for CONDITION be discarded by
+ clear_momentary during the parsing of the next stmt. */
+ push_momentary ();
+
+ return r;
+ }
+
+ /* Finish the body of a switch-statement, which may be given by
+ SWITCH_STMT. The CONDITION to switch on is indicated. */
+
+ void
+ finish_switch_statement (condition, switch_stmt)
+ tree condition;
+ tree switch_stmt;
+ {
+ if (processing_template_decl)
+ RECHAIN_STATEMENTS_FROM_CHAIN (switch_stmt, SWITCH_BODY (switch_stmt));
+ else
+ expand_end_case (condition);
+ pop_momentary ();
+ pop_switch ();
+ do_poplevel ();
+ finish_stmt ();
+ }
+
+ /* Finish a case-label. */
+
+ void
+ finish_case_label (low_value, high_value)
+ tree low_value;
+ tree high_value;
+ {
+ do_case (low_value, high_value);
+ }
+
+
+ /* Finish a goto-statement. */
+
+ void
+ finish_goto_statement (destination)
+ tree destination;
+ {
+ if (processing_template_decl)
+ add_tree (build_min_nt (GOTO_STMT, destination));
+ else
+ {
+ emit_line_note (input_filename, lineno);
+
+ if (TREE_CODE (destination) == IDENTIFIER_NODE)
+ {
+ tree decl = lookup_label (destination);
+ TREE_USED (decl) = 1;
+ expand_goto (decl);
+ }
+ else
+ expand_computed_goto (destination);
+ }
+ }
+
+ /* Begin a try-block. Returns a newly-created TRY_BLOCK if
+ appropriate. */
+
+ tree
+ begin_try_block ()
+ {
+ if (processing_template_decl)
+ {
+ tree r = build_min_nt (TRY_BLOCK, NULL_TREE,
+ NULL_TREE);
+ add_tree (r);
+ return r;
+ }
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ expand_start_try_stmts ();
+ return NULL_TREE;
+ }
+ }
+
+ /* Finish a try-block, which may be given by TRY_BLOCK. */
+
+ void
+ finish_try_block (try_block)
+ tree try_block;
+ {
+ if (processing_template_decl)
+ RECHAIN_STATEMENTS_FROM_LAST (try_block, TRY_STMTS (try_block));
+ else
+ expand_start_all_catch ();
+ }
+
+ /* Finish a handler-sequence for a try-block, which may be given by
+ TRY_BLOCK. */
+
+ void
+ finish_handler_sequence (try_block)
+ tree try_block;
+ {
+ if (processing_template_decl)
+ RECHAIN_STATEMENTS_FROM_CHAIN (try_block, TRY_HANDLERS (try_block));
+ else
+ expand_end_all_catch ();
+ }
+
+ /* Begin a handler. Returns a HANDLER if appropriate. */
+
+ tree
+ begin_handler ()
+ {
+ tree r;
+
+ if (processing_template_decl)
+ {
+ r = build_min_nt (HANDLER, NULL_TREE, NULL_TREE);
+ add_tree (r);
+ }
+ else
+ r = NULL_TREE;
+
+ do_pushlevel ();
+
+ return r;
+ }
+
+ /* Finish the handler-parameters for a handler, which may be given by
+ HANDLER. */
+
+ void
+ finish_handler_parameters (handler)
+ tree handler;
+ {
+ if (processing_template_decl)
+ RECHAIN_STATEMENTS_FROM_CHAIN (handler, HANDLER_PARMS (handler));
+ }
+
+ /* Finish a handler, which may be given by HANDLER. */
+
+ void
+ finish_handler (handler)
+ tree handler;
+ {
+ if (processing_template_decl)
+ RECHAIN_STATEMENTS_FROM_CHAIN (handler, HANDLER_BODY (handler));
+ else
+ expand_end_catch_block ();
+
+ do_poplevel ();
+ }
+
+ /* 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. */
+
+ tree
+ begin_compound_statement (has_no_scope)
+ int has_no_scope;
+ {
+ tree r;
+
+ if (processing_template_decl)
+ {
+ r = build_min_nt (COMPOUND_STMT, NULL_TREE);
+ add_tree (r);
+ if (has_no_scope)
+ COMPOUND_STMT_NO_SCOPE (r) = 1;
+ }
+ else
+ r = NULL_TREE;
+
+ if (!has_no_scope)
+ do_pushlevel ();
+
+ return r;
+ }
+
+
+ /* Finish a compound-statement, which may be given by COMPOUND_STMT.
+ If HAS_NO_SCOPE is non-zero, the compound statement does not define
+ a scope. */
+
+ tree
+ finish_compound_statement (has_no_scope, compound_stmt)
+ int has_no_scope;
+ tree compound_stmt;
+ {
+ tree r;
+
+ if (!has_no_scope)
+ r = do_poplevel ();
+ else
+ r = NULL_TREE;
+
+ if (processing_template_decl)
+ RECHAIN_STATEMENTS_FROM_CHAIN (compound_stmt,
+ COMPOUND_BODY (compound_stmt));
+
+ finish_stmt ();
+
+ return r;
+ }
+
+ /* Finish an asm-statement, whose components are a CV_QUALIFIER, a
+ STRING, some OUTPUT_OPERANDS, some INPUT_OPERANDS, and some
+ CLOBBERS. */
+
+ void
+ finish_asm_statement (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))
+ combine_strings (string);
+
+ if (processing_template_decl)
+ {
+ tree r = build_min_nt (ASM_STMT, cv_qualifier, string,
+ output_operands, input_operands,
+ clobbers);
+ add_tree (r);
+ }
+ else
+ {
+ emit_line_note (input_filename, lineno);
+ if (output_operands != NULL_TREE)
+ {
+ if (cv_qualifier != NULL_TREE
+ && cv_qualifier != ridpointers[(int) RID_VOLATILE])
+ cp_warning ("%s qualifier ignored on asm",
+ IDENTIFIER_POINTER (cv_qualifier));
+
+ c_expand_asm_operands (string, output_operands,
+ input_operands,
+ clobbers,
+ cv_qualifier
+ == ridpointers[(int) RID_VOLATILE],
+ input_filename, lineno);
+ }
+ else
+ {
+ if (cv_qualifier != NULL_TREE)
+ cp_warning ("%s qualifier ignored on asm",
+ IDENTIFIER_POINTER (cv_qualifier));
+ expand_asm (string);
+ }
+
+ finish_stmt ();
+ }
+ }
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.42
diff -c -p -r1.42 cp-tree.h
*** cp-tree.h 1998/03/15 19:53:06 1.42
--- cp-tree.h 1998/03/17 23:06:58
*************** extern int flag_new_for_scope;
*** 1524,1529 ****
--- 1524,1560 ----
#define builtin_function(NAME, TYPE, CODE, LIBNAME) \
define_function (NAME, TYPE, CODE, (void (*) PROTO((tree)))pushdecl, LIBNAME)
+ /* These macros provide convenient access to the various _STMT nodes
+ created when parsing template declarations. */
+ #define IF_CONDITION(NODE) TREE_OPERAND (NODE, 0)
+ #define THEN_CLAUSE(NODE) TREE_OPERAND (NODE, 1)
+ #define ELSE_CLAUSE(NODE) TREE_OPERAND (NODE, 2)
+ #define WHILE_CONDITION(NODE) TREE_OPERAND (NODE, 0)
+ #define WHILE_BODY(NODE) TREE_OPERAND (NODE, 1)
+ #define DO_CONDITION(NODE) TREE_OPERAND (NODE, 0)
+ #define DO_BODY(NODE) TREE_OPERAND (NODE, 1)
+ #define RETURN_EXPR(NODE) TREE_OPERAND (NODE, 0)
+ #define EXPR_STMT_EXPR(NODE) TREE_OPERAND (NODE, 0)
+ #define FOR_INIT_STMT(NODE) TREE_OPERAND (NODE, 0)
+ #define FOR_CONDITION(NODE) TREE_OPERAND (NODE, 1)
+ #define FOR_EXPRESSION(NODE) TREE_OPERAND (NODE, 2)
+ #define FOR_BODY(NODE) TREE_OPERAND (NODE, 3)
+ #define SWITCH_CONDITION(NODE) TREE_OPERAND (NODE, 0)
+ #define SWITCH_BODY(NODE) TREE_OPERAND (NODE, 1)
+ #define CASE_LOW(NODE) TREE_OPERAND (NODE, 0)
+ #define CASE_HIGH(NODE) TREE_OPERAND (NODE, 1)
+ #define GOTO_DESTINATION(NODE) TREE_OPERAND (NODE, 0)
+ #define TRY_STMTS(NODE) TREE_OPERAND (NODE, 0)
+ #define TRY_HANDLERS(NODE) TREE_OPERAND (NODE, 1)
+ #define HANDLER_PARMS(NODE) TREE_OPERAND (NODE, 0)
+ #define HANDLER_BODY(NODE) TREE_OPERAND (NODE, 1)
+ #define COMPOUND_BODY(NODE) TREE_OPERAND (NODE, 0)
+ #define ASM_CV_QUAL(NODE) TREE_OPERAND (NODE, 0)
+ #define ASM_STRING(NODE) TREE_OPERAND (NODE, 1)
+ #define ASM_OUTPUTS(NODE) TREE_OPERAND (NODE, 2)
+ #define ASM_INPUTS(NODE) TREE_OPERAND (NODE, 3)
+ #define ASM_CLOBBERS(NODE) TREE_OPERAND (NODE, 4)
+
/* An enumeration of the kind of tags that C++ accepts. */
enum tag_types { record_type, class_type, union_type, enum_type,
signature_type };
*************** extern tree current_scope PROTO((void)
*** 2511,2516 ****
--- 2542,2583 ----
extern tree lookup_conversions PROTO((tree));
extern tree get_template_base PROTO((tree, tree));
+ /* in semantics.c */
+ extern void finish_expression_statement PROTO((tree));
+ extern tree begin_if_statement PROTO((void));
+ extern void finish_if_statement_condition PROTO((tree, tree));
+ extern tree finish_then_clause PROTO((tree));
+ extern void begin_else_clause PROTO((void));
+ extern void finish_else_clause PROTO((tree));
+ extern void finish_if_statement PROTO((void));
+ extern tree begin_while_statement PROTO((void));
+ extern void finish_while_statement_condition PROTO((tree, tree));
+ extern void finish_while_statement PROTO((tree));
+ extern tree begin_do_statement PROTO((void));
+ extern void finish_do_body PROTO((tree));
+ extern void finish_do_statement PROTO((tree, tree));
+ extern void finish_return_statement PROTO((tree));
+ extern tree begin_for_statement PROTO((void));
+ extern void finish_for_init_statement PROTO((tree));
+ extern void finish_for_condition PROTO((tree, tree));
+ extern void finish_for_expression PROTO((tree, tree));
+ extern void finish_for_statement PROTO((tree, tree));
+ extern void finish_break_statement PROTO((void));
+ extern void finish_continue_statement PROTO((void));
+ extern void begin_switch_statement PROTO((void));
+ extern tree finish_switch_condition PROTO((tree));
+ extern void finish_switch_statement PROTO((tree, tree));
+ extern void finish_case_label PROTO((tree, tree));
+ extern void finish_goto_statement PROTO((tree));
+ extern tree begin_try_block PROTO((void));
+ extern void finish_try_block PROTO((tree));
+ extern void finish_handler_sequence PROTO((tree));
+ extern tree begin_handler PROTO((void));
+ extern void finish_handler_parameters PROTO((tree));
+ extern void finish_handler PROTO((tree));
+ extern tree begin_compound_statement PROTO((int));
+ extern tree finish_compound_statement PROTO((int, tree));
+ extern void finish_asm_statement PROTO((tree, tree, tree, tree, tree));
/* in sig.c */
extern tree build_signature_pointer_type PROTO((tree, int, int));
extern tree build_signature_reference_type PROTO((tree, int, int));
Index: Makefile.in
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/Makefile.in,v
retrieving revision 1.8
diff -c -p -r1.8 Makefile.in
*** Makefile.in 1998/03/06 07:11:29 1.8
--- Makefile.in 1998/03/17 23:10:06
*************** INCLUDES = -I. -I.. -I$(srcdir) -I$(srcd
*** 166,172 ****
CXX_OBJS = call.o decl.o errfn.o expr.o pt.o sig.o typeck2.o \
class.o decl2.o error.o lex.o parse.o ptree.o rtti.o spew.o typeck.o cvt.o \
! except.o friend.o init.o method.o search.o tree.o xref.o repo.o
# Language-independent object files.
OBJS = `cat ../stamp-objlist` ../c-common.o ../c-pragma.o
--- 166,172 ----
CXX_OBJS = call.o decl.o errfn.o expr.o pt.o sig.o typeck2.o \
class.o decl2.o error.o lex.o parse.o ptree.o rtti.o spew.o typeck.o cvt.o \
! except.o friend.o init.o method.o search.o semantics.o tree.o xref.o repo.o
# Language-independent object files.
OBJS = `cat ../stamp-objlist` ../c-common.o ../c-pragma.o
*************** error.o : error.c $(CONFIG_H) $(CXX_TREE
*** 259,264 ****
--- 259,266 ----
errfn.o : errfn.c $(CONFIG_H) $(CXX_TREE_H)
sig.o : sig.c $(CONFIG_H) $(CXX_TREE_H) $(srcdir)/../flags.h
repo.o : repo.c $(CONFIG_H) $(CXX_TREE_H)
+ semantics.o: semantics.c $(CONFIG_H) $(CXX_TREE_H) lex.h $(srcdir)/../except.h
+
#\f
# These exist for maintenance purposes.
Index: Make-lang.in
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/Make-lang.in,v
retrieving revision 1.10
diff -c -p -r1.10 Make-lang.in
*** Make-lang.in 1998/02/23 03:17:26 1.10
--- Make-lang.in 1998/03/17 23:10:06
*************** CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)
*** 122,128 ****
$(srcdir)/cp/search.c $(srcdir)/cp/typeck.c $(srcdir)/cp/decl.c \
$(srcdir)/cp/error.c $(srcdir)/cp/friend.c $(srcdir)/cp/init.c \
$(srcdir)/cp/parse.y $(srcdir)/cp/sig.c $(srcdir)/cp/typeck2.c \
! $(srcdir)/cp/repo.c
cc1plus: $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o \
$(srcdir)/cp/cp-tree.h $(srcdir)/cp/cp-tree.def
--- 122,128 ----
$(srcdir)/cp/search.c $(srcdir)/cp/typeck.c $(srcdir)/cp/decl.c \
$(srcdir)/cp/error.c $(srcdir)/cp/friend.c $(srcdir)/cp/init.c \
$(srcdir)/cp/parse.y $(srcdir)/cp/sig.c $(srcdir)/cp/typeck2.c \
! $(srcdir)/cp/repo.c $(srcdir)/cp/semantics.c
cc1plus: $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o \
$(srcdir)/cp/cp-tree.h $(srcdir)/cp/cp-tree.def
^ permalink raw reply [flat|nested] 10+ messages in thread