semantics.c: New file, containing routines to perform the semantic phase of parsing.
* 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. From-SVN: r18658
This commit is contained in:
parent
cbe3672526
commit
ad32129310
@ -1,3 +1,15 @@
|
||||
Wed Mar 18 10: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.
|
||||
|
||||
Wed Mar 18 00:24:10 1998 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* pt.c (push_template_decl): Only check primary templates.
|
||||
|
@ -122,7 +122,7 @@ CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)/cp/decl2.c \
|
||||
$(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/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
|
||||
|
@ -166,7 +166,7 @@ INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config
|
||||
|
||||
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
|
||||
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
|
||||
@ -259,6 +259,8 @@ error.o : error.c $(CONFIG_H) $(CXX_TREE_H)
|
||||
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
|
||||
|
||||
#
|
||||
# These exist for maintenance purposes.
|
||||
|
||||
|
@ -200,6 +200,7 @@ DEFTREECODE (BREAK_STMT, "break_stmt", 'e', 0)
|
||||
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)
|
||||
|
@ -1524,6 +1524,37 @@ extern int flag_new_for_scope;
|
||||
#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_COND(NODE) TREE_OPERAND (NODE, 0)
|
||||
#define THEN_CLAUSE(NODE) TREE_OPERAND (NODE, 1)
|
||||
#define ELSE_CLAUSE(NODE) TREE_OPERAND (NODE, 2)
|
||||
#define WHILE_COND(NODE) TREE_OPERAND (NODE, 0)
|
||||
#define WHILE_BODY(NODE) TREE_OPERAND (NODE, 1)
|
||||
#define DO_COND(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_COND(NODE) TREE_OPERAND (NODE, 1)
|
||||
#define FOR_EXPR(NODE) TREE_OPERAND (NODE, 2)
|
||||
#define FOR_BODY(NODE) TREE_OPERAND (NODE, 3)
|
||||
#define SWITCH_COND(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 };
|
||||
@ -2511,6 +2542,42 @@ extern tree current_scope PROTO((void));
|
||||
extern tree lookup_conversions PROTO((tree));
|
||||
extern tree get_template_base PROTO((tree, tree));
|
||||
|
||||
/* in semantics.c */
|
||||
extern void finish_expr_stmt PROTO((tree));
|
||||
extern tree begin_if_stmt PROTO((void));
|
||||
extern void finish_if_stmt_cond 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_stmt PROTO((void));
|
||||
extern tree begin_while_stmt PROTO((void));
|
||||
extern void finish_while_stmt_cond PROTO((tree, tree));
|
||||
extern void finish_while_stmt PROTO((tree));
|
||||
extern tree begin_do_stmt PROTO((void));
|
||||
extern void finish_do_body PROTO((tree));
|
||||
extern void finish_do_stmt PROTO((tree, tree));
|
||||
extern void finish_return_stmt PROTO((tree));
|
||||
extern tree begin_for_stmt PROTO((void));
|
||||
extern void finish_for_init_stmt PROTO((tree));
|
||||
extern void finish_for_cond PROTO((tree, tree));
|
||||
extern void finish_for_expression PROTO((tree, tree));
|
||||
extern void finish_for_stmt PROTO((tree, tree));
|
||||
extern void finish_break_stmt PROTO((void));
|
||||
extern void finish_continue_stmt PROTO((void));
|
||||
extern void begin_switch_stmt PROTO((void));
|
||||
extern tree finish_switch_cond PROTO((tree));
|
||||
extern void finish_switch_stmt PROTO((tree, tree));
|
||||
extern void finish_case_label PROTO((tree, tree));
|
||||
extern void finish_goto_stmt 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_parms PROTO((tree));
|
||||
extern void finish_handler PROTO((tree));
|
||||
extern tree begin_compound_stmt PROTO((int));
|
||||
extern tree finish_compound_stmt PROTO((int, tree));
|
||||
extern void finish_asm_stmt 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));
|
||||
|
6731
gcc/cp/parse.c
6731
gcc/cp/parse.c
File diff suppressed because it is too large
Load Diff
529
gcc/cp/parse.y
529
gcc/cp/parse.y
@ -263,7 +263,7 @@ empty_parms ()
|
||||
%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> 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. */
|
||||
@ -1002,7 +1002,7 @@ paren_expr_or_null:
|
||||
cond_stmt_keyword);
|
||||
$$ = integer_zero_node; }
|
||||
| '(' expr ')'
|
||||
{ $$ = condition_conversion ($2); }
|
||||
{ $$ = $2; }
|
||||
;
|
||||
|
||||
paren_cond_or_null:
|
||||
@ -1011,7 +1011,7 @@ paren_cond_or_null:
|
||||
cond_stmt_keyword);
|
||||
$$ = integer_zero_node; }
|
||||
| '(' condition ')'
|
||||
{ $$ = condition_conversion ($2); }
|
||||
{ $$ = $2; }
|
||||
;
|
||||
|
||||
xcond:
|
||||
@ -1062,24 +1062,9 @@ compstmtend:
|
||||
|
||||
already_scoped_stmt:
|
||||
'{'
|
||||
{
|
||||
if (processing_template_decl)
|
||||
{
|
||||
$<ttype>$ = build_min_nt (COMPOUND_STMT, NULL_TREE);
|
||||
COMPOUND_STMT_NO_SCOPE ($<ttype>$) = 1;
|
||||
add_tree ($<ttype>$);
|
||||
}
|
||||
}
|
||||
{ $<ttype>$ = begin_compound_stmt (1); }
|
||||
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 ();
|
||||
}
|
||||
{ finish_compound_stmt (1, $<ttype>2); }
|
||||
| simple_stmt
|
||||
;
|
||||
|
||||
@ -3437,20 +3422,6 @@ errstmt:
|
||||
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:
|
||||
@ -3487,92 +3458,33 @@ compstmt_or_error:
|
||||
|
||||
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;
|
||||
}
|
||||
{ $<ttype>$ = begin_compound_stmt (0); }
|
||||
compstmtend
|
||||
{ $$ = finish_compound_stmt (0, $<ttype>2); }
|
||||
;
|
||||
|
||||
simple_if:
|
||||
IF
|
||||
{
|
||||
if (processing_template_decl)
|
||||
{
|
||||
$<ttype>$ = build_min_nt (IF_STMT, NULL_TREE, NULL_TREE,
|
||||
NULL_TREE);
|
||||
add_tree ($<ttype>$);
|
||||
}
|
||||
$<ttype>$ = begin_if_stmt ();
|
||||
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);
|
||||
}
|
||||
}
|
||||
paren_cond_or_null
|
||||
{ finish_if_stmt_cond ($3, $<ttype>2); }
|
||||
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;
|
||||
}
|
||||
}
|
||||
{ $<ttype>$ = finish_then_clause ($<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;
|
||||
}
|
||||
| { $<ttype>$ = begin_compound_stmt (0); }
|
||||
simple_stmt
|
||||
{ $$ = finish_compound_stmt (0, $<ttype>1); }
|
||||
;
|
||||
|
||||
stmt:
|
||||
compstmt
|
||||
{ finish_stmt (); }
|
||||
{}
|
||||
| simple_stmt
|
||||
;
|
||||
|
||||
@ -3580,346 +3492,93 @@ simple_stmt:
|
||||
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 (); }
|
||||
{ finish_expr_stmt ($1); }
|
||||
| simple_if ELSE
|
||||
{ if (! processing_template_decl) expand_start_else (); }
|
||||
{ begin_else_clause (); }
|
||||
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;
|
||||
finish_else_clause ($<ttype>1);
|
||||
finish_if_stmt ();
|
||||
}
|
||||
else
|
||||
expand_end_cond ();
|
||||
}
|
||||
.poplevel
|
||||
{ finish_stmt (); }
|
||||
| simple_if %prec IF
|
||||
{ if (! processing_template_decl) expand_end_cond ();
|
||||
do_poplevel ();
|
||||
finish_stmt (); }
|
||||
{ finish_if_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);
|
||||
}
|
||||
$<ttype>$ = begin_while_stmt ();
|
||||
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 ();
|
||||
}
|
||||
paren_cond_or_null
|
||||
{ finish_while_stmt_cond ($3, $<ttype>2); }
|
||||
already_scoped_stmt
|
||||
{ finish_while_stmt ($<ttype>2); }
|
||||
| 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);
|
||||
}
|
||||
}
|
||||
{ $<ttype>$ = begin_do_stmt (); }
|
||||
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 ();
|
||||
finish_do_body ($<ttype>2);
|
||||
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 ();
|
||||
}
|
||||
{ finish_do_stmt ($6, $<ttype>2); }
|
||||
| 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);
|
||||
}
|
||||
}
|
||||
{ $<ttype>$ = begin_for_stmt (); }
|
||||
'(' 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 ();
|
||||
}
|
||||
}
|
||||
{ finish_for_init_stmt ($<ttype>2); }
|
||||
xcond ';'
|
||||
{ finish_for_cond ($6, $<ttype>2); }
|
||||
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 ();
|
||||
}
|
||||
{ finish_for_expr ($9, $<ttype>2); }
|
||||
already_scoped_stmt
|
||||
{ finish_for_stmt ($9, $<ttype>2); }
|
||||
| SWITCH
|
||||
{ begin_switch_stmt (); }
|
||||
'(' condition ')'
|
||||
{ $<ttype>$ = finish_switch_cond ($4); }
|
||||
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 (); }
|
||||
{ finish_switch_stmt ($4, $<ttype>6); }
|
||||
| CASE expr_no_commas ':'
|
||||
{ do_case ($2, NULL_TREE); }
|
||||
{ finish_case_label ($2, NULL_TREE); }
|
||||
stmt
|
||||
| CASE expr_no_commas ELLIPSIS expr_no_commas ':'
|
||||
{ do_case ($2, $4); }
|
||||
{ finish_case_label ($2, $4); }
|
||||
stmt
|
||||
| DEFAULT ':'
|
||||
{ do_case (NULL_TREE, NULL_TREE); }
|
||||
{ finish_case_label (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"); }
|
||||
{ finish_break_stmt (); }
|
||||
| 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"); }
|
||||
{ finish_continue_stmt (); }
|
||||
| RETURN ';'
|
||||
{ emit_line_note (input_filename, lineno);
|
||||
c_expand_return (NULL_TREE); }
|
||||
{ finish_return_stmt (NULL_TREE); }
|
||||
| RETURN expr ';'
|
||||
{ emit_line_note (input_filename, lineno);
|
||||
c_expand_return ($2);
|
||||
finish_stmt ();
|
||||
}
|
||||
{ finish_return_stmt ($2); }
|
||||
| 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 ();
|
||||
{
|
||||
finish_asm_stmt ($2, $4, NULL_TREE, NULL_TREE,
|
||||
NULL_TREE);
|
||||
}
|
||||
/* 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 ();
|
||||
{
|
||||
finish_asm_stmt ($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 ')' ';'
|
||||
{ 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 ();
|
||||
}
|
||||
{ finish_asm_stmt ($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 ')' ';'
|
||||
{ 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 ();
|
||||
}
|
||||
{ finish_asm_stmt ($2, $4, $6, $8, $10); }
|
||||
| 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); }
|
||||
if (pedantic)
|
||||
pedwarn ("ANSI C++ forbids computed gotos");
|
||||
finish_goto_stmt ($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);
|
||||
}
|
||||
}
|
||||
{ finish_goto_stmt ($2); }
|
||||
| label_colon stmt
|
||||
{ finish_stmt (); }
|
||||
| label_colon '}'
|
||||
@ -3951,41 +3610,11 @@ function_try_block:
|
||||
|
||||
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 ();
|
||||
}
|
||||
}
|
||||
{ $<ttype>$ = begin_try_block (); }
|
||||
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 ();
|
||||
}
|
||||
{ finish_try_block ($<ttype>2); }
|
||||
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 ();
|
||||
}
|
||||
{ finish_handler_sequence ($<ttype>2); }
|
||||
;
|
||||
|
||||
handler_seq:
|
||||
@ -3995,35 +3624,11 @@ handler_seq:
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
{ $<ttype>$ = begin_handler(); }
|
||||
handler_args
|
||||
{ finish_handler_parms ($<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
|
||||
{ finish_handler ($<ttype>2); }
|
||||
;
|
||||
|
||||
type_specifier_seq:
|
||||
|
231
gcc/cp/pt.c
231
gcc/cp/pt.c
@ -4690,24 +4690,14 @@ tsubst_expr (t, args, in_decl)
|
||||
{
|
||||
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 ();
|
||||
finish_return_stmt (tsubst_expr (RETURN_EXPR (t),
|
||||
args, in_decl));
|
||||
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 ();
|
||||
finish_expr_stmt (tsubst_expr (EXPR_STMT_EXPR (t),
|
||||
args, in_decl));
|
||||
break;
|
||||
|
||||
case DECL_STMT:
|
||||
@ -4731,184 +4721,117 @@ tsubst_expr (t, args, in_decl)
|
||||
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))
|
||||
|
||||
begin_for_stmt ();
|
||||
for (tmp = FOR_INIT_STMT (t); 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 ();
|
||||
finish_for_init_stmt (NULL_TREE);
|
||||
finish_for_cond (tsubst_expr (FOR_COND (t), args,
|
||||
in_decl),
|
||||
NULL_TREE);
|
||||
tmp = tsubst_expr (FOR_EXPR (t), args, in_decl);
|
||||
finish_for_expr (tmp, NULL_TREE);
|
||||
tsubst_expr (FOR_BODY (t), args, in_decl);
|
||||
finish_for_stmt (tmp, NULL_TREE);
|
||||
}
|
||||
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 ();
|
||||
begin_while_stmt ();
|
||||
finish_while_stmt_cond (tsubst_expr (WHILE_COND (t),
|
||||
args, in_decl),
|
||||
NULL_TREE);
|
||||
tsubst_expr (WHILE_BODY (t), args, in_decl);
|
||||
finish_while_stmt (NULL_TREE);
|
||||
}
|
||||
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 ();
|
||||
begin_do_stmt ();
|
||||
tsubst_expr (DO_BODY (t), args, in_decl);
|
||||
finish_do_body (NULL_TREE);
|
||||
finish_do_stmt (tsubst_expr (DO_COND (t), args,
|
||||
in_decl),
|
||||
NULL_TREE);
|
||||
}
|
||||
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);
|
||||
begin_if_stmt ();
|
||||
finish_if_stmt_cond (tsubst_expr (IF_COND (t),
|
||||
args, in_decl),
|
||||
NULL_TREE);
|
||||
|
||||
if (tmp = TREE_OPERAND (t, 1), tmp)
|
||||
tsubst_expr (tmp, args, in_decl);
|
||||
|
||||
if (tmp = TREE_OPERAND (t, 2), tmp)
|
||||
if (tmp = THEN_CLAUSE (t), tmp)
|
||||
{
|
||||
expand_start_else ();
|
||||
tsubst_expr (tmp, args, in_decl);
|
||||
finish_then_clause (NULL_TREE);
|
||||
}
|
||||
|
||||
expand_end_cond ();
|
||||
if (tmp = ELSE_CLAUSE (t), tmp)
|
||||
{
|
||||
begin_else_clause ();
|
||||
tsubst_expr (tmp, args, in_decl);
|
||||
finish_else_clause (NULL_TREE);
|
||||
}
|
||||
|
||||
if (cond_scope)
|
||||
do_poplevel ();
|
||||
|
||||
finish_stmt ();
|
||||
finish_if_stmt ();
|
||||
}
|
||||
break;
|
||||
|
||||
case COMPOUND_STMT:
|
||||
{
|
||||
tree substmt = TREE_OPERAND (t, 0);
|
||||
tree substmt;
|
||||
|
||||
lineno = TREE_COMPLEXITY (t);
|
||||
|
||||
if (COMPOUND_STMT_NO_SCOPE (t) == 0)
|
||||
do_pushlevel ();
|
||||
|
||||
for (; substmt; substmt = TREE_CHAIN (substmt))
|
||||
begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
|
||||
for (substmt = COMPOUND_BODY (t);
|
||||
substmt != NULL_TREE;
|
||||
substmt = TREE_CHAIN (substmt))
|
||||
tsubst_expr (substmt, args, in_decl);
|
||||
|
||||
if (COMPOUND_STMT_NO_SCOPE (t) == 0)
|
||||
return do_poplevel ();
|
||||
return finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t),
|
||||
NULL_TREE);
|
||||
}
|
||||
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");
|
||||
finish_break_stmt ();
|
||||
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");
|
||||
finish_continue_stmt ();
|
||||
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 ();
|
||||
begin_switch_stmt ();
|
||||
val = tsubst_expr (SWITCH_COND (t), args, in_decl);
|
||||
finish_switch_cond (val);
|
||||
|
||||
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 ();
|
||||
finish_switch_stmt (val, NULL_TREE);
|
||||
}
|
||||
break;
|
||||
|
||||
case CASE_LABEL:
|
||||
do_case (tsubst_expr (TREE_OPERAND (t, 0), args, in_decl),
|
||||
tsubst_expr (TREE_OPERAND (t, 1), args, in_decl));
|
||||
finish_case_label (tsubst_expr (CASE_LOW (t), args, in_decl),
|
||||
tsubst_expr (CASE_HIGH (t), args, in_decl));
|
||||
break;
|
||||
|
||||
case LABEL_DECL:
|
||||
@ -4920,47 +4843,47 @@ tsubst_expr (t, args, in_decl)
|
||||
|
||||
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));
|
||||
finish_goto_stmt (tsubst_expr (GOTO_DESTINATION (t),
|
||||
args, in_decl));
|
||||
break;
|
||||
|
||||
case ASM_STMT:
|
||||
lineno = TREE_COMPLEXITY (t);
|
||||
finish_asm_stmt (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);
|
||||
emit_line_note (input_filename, lineno);
|
||||
expand_start_try_stmts ();
|
||||
tsubst_expr (TREE_OPERAND (t, 0), args, in_decl);
|
||||
expand_start_all_catch ();
|
||||
begin_try_block ();
|
||||
tsubst_expr (TRY_STMTS (t), args, in_decl);
|
||||
finish_try_block (NULL_TREE);
|
||||
{
|
||||
tree handler = TREE_OPERAND (t, 1);
|
||||
tree handler = TRY_HANDLERS (t);
|
||||
for (; handler; handler = TREE_CHAIN (handler))
|
||||
tsubst_expr (handler, args, in_decl);
|
||||
}
|
||||
expand_end_all_catch ();
|
||||
finish_handler_sequence (NULL_TREE);
|
||||
break;
|
||||
|
||||
case HANDLER:
|
||||
lineno = TREE_COMPLEXITY (t);
|
||||
do_pushlevel ();
|
||||
if (TREE_OPERAND (t, 0))
|
||||
begin_handler ();
|
||||
if (HANDLER_PARMS (t))
|
||||
{
|
||||
tree d = TREE_OPERAND (t, 0);
|
||||
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);
|
||||
tsubst_expr (TREE_OPERAND (t, 1), args, in_decl);
|
||||
expand_end_catch_block ();
|
||||
do_poplevel ();
|
||||
finish_handler_parms (NULL_TREE);
|
||||
tsubst_expr (HANDLER_BODY (t), args, in_decl);
|
||||
finish_handler (NULL_TREE);
|
||||
break;
|
||||
|
||||
case TAG_DEFN:
|
||||
|
748
gcc/cp/semantics.c
Normal file
748
gcc/cp/semantics.c
Normal file
@ -0,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_STMTS(stmt, substmt, last) \
|
||||
do { \
|
||||
substmt = last; \
|
||||
TREE_CHAIN (stmt) = NULL_TREE; \
|
||||
last_tree = stmt; \
|
||||
} while (0)
|
||||
|
||||
#define RECHAIN_STMTS_FROM_LAST(stmt, substmt) \
|
||||
RECHAIN_STMTS (stmt, substmt, last_tree)
|
||||
|
||||
#define RECHAIN_STMTS_FROM_CHAIN(stmt, substmt) \
|
||||
RECHAIN_STMTS (stmt, substmt, TREE_CHAIN (stmt))
|
||||
|
||||
/* Finish an expression-statement, whose EXPRESSION is as indicated. */
|
||||
|
||||
void
|
||||
finish_expr_stmt (expr)
|
||||
tree expr;
|
||||
{
|
||||
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 ();
|
||||
}
|
||||
|
||||
/* Begin an if-statement. Returns a newly created IF_STMT if
|
||||
appropriate. */
|
||||
|
||||
tree
|
||||
begin_if_stmt ()
|
||||
{
|
||||
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 COND of an if-statement, which may be given by
|
||||
IF_STMT. */
|
||||
|
||||
void
|
||||
finish_if_stmt_cond (cond, if_stmt)
|
||||
tree cond;
|
||||
tree if_stmt;
|
||||
{
|
||||
if (processing_template_decl)
|
||||
{
|
||||
if (last_tree != if_stmt)
|
||||
RECHAIN_STMTS_FROM_LAST (if_stmt, IF_COND (if_stmt));
|
||||
else
|
||||
IF_COND (if_stmt) = cond;
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_line_note (input_filename, lineno);
|
||||
expand_start_cond (condition_conversion (cond), 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_STMTS_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_STMTS_FROM_CHAIN (if_stmt, ELSE_CLAUSE (if_stmt));
|
||||
}
|
||||
|
||||
/* Finsh an if-statement. */
|
||||
|
||||
void
|
||||
finish_if_stmt ()
|
||||
{
|
||||
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_stmt ()
|
||||
{
|
||||
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 COND of an if-statement, which may be given by
|
||||
WHILE_STMT. */
|
||||
|
||||
void
|
||||
finish_while_stmt_cond (cond, while_stmt)
|
||||
tree cond;
|
||||
tree while_stmt;
|
||||
{
|
||||
if (processing_template_decl)
|
||||
{
|
||||
if (last_tree != while_stmt)
|
||||
RECHAIN_STMTS_FROM_LAST (while_stmt,
|
||||
WHILE_COND (while_stmt));
|
||||
else
|
||||
TREE_OPERAND (while_stmt, 0) = cond;
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_line_note (input_filename, lineno);
|
||||
expand_exit_loop_if_false (0, condition_conversion (cond));
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
do_poplevel ();
|
||||
do_pushlevel ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Finish a while-statement, which may be given by WHILE_STMT. */
|
||||
|
||||
void
|
||||
finish_while_stmt (while_stmt)
|
||||
tree while_stmt;
|
||||
{
|
||||
do_poplevel ();
|
||||
|
||||
if (processing_template_decl)
|
||||
RECHAIN_STMTS_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_stmt ()
|
||||
{
|
||||
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_STMTS_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
|
||||
COND is as indicated. */
|
||||
|
||||
void
|
||||
finish_do_stmt (cond, do_stmt)
|
||||
tree cond;
|
||||
tree do_stmt;
|
||||
{
|
||||
if (processing_template_decl)
|
||||
DO_COND (do_stmt) = cond;
|
||||
else
|
||||
{
|
||||
emit_line_note (input_filename, lineno);
|
||||
expand_exit_loop_if_false (0, condition_conversion (cond));
|
||||
expand_end_loop ();
|
||||
}
|
||||
|
||||
clear_momentary ();
|
||||
finish_stmt ();
|
||||
}
|
||||
|
||||
/* Finish a return-statement. The EXPRESSION returned, if any, is as
|
||||
indicated. */
|
||||
|
||||
void
|
||||
finish_return_stmt (expr)
|
||||
tree expr;
|
||||
{
|
||||
emit_line_note (input_filename, lineno);
|
||||
c_expand_return (expr);
|
||||
finish_stmt ();
|
||||
}
|
||||
|
||||
/* Begin a for-statement. Returns a new FOR_STMT if appropriate. */
|
||||
|
||||
tree
|
||||
begin_for_stmt ()
|
||||
{
|
||||
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_stmt (for_stmt)
|
||||
tree for_stmt;
|
||||
{
|
||||
if (processing_template_decl)
|
||||
{
|
||||
if (last_tree != for_stmt)
|
||||
RECHAIN_STMTS_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 COND of a for-statement, which may be given by
|
||||
FOR_STMT. */
|
||||
|
||||
void
|
||||
finish_for_cond (cond, for_stmt)
|
||||
tree cond;
|
||||
tree for_stmt;
|
||||
{
|
||||
if (processing_template_decl)
|
||||
{
|
||||
if (last_tree != for_stmt)
|
||||
RECHAIN_STMTS_FROM_LAST (for_stmt, FOR_COND (for_stmt));
|
||||
else
|
||||
FOR_COND (for_stmt) = cond;
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_line_note (input_filename, lineno);
|
||||
if (cond)
|
||||
expand_exit_loop_if_false (0, cond);
|
||||
}
|
||||
|
||||
/* If the 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)
|
||||
{
|
||||
do_poplevel ();
|
||||
do_pushlevel ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Finish the increment-EXPRESSION in a for-statement, which may be
|
||||
given by FOR_STMT. */
|
||||
|
||||
void
|
||||
finish_for_expr (expr, for_stmt)
|
||||
tree expr;
|
||||
tree for_stmt;
|
||||
{
|
||||
if (processing_template_decl)
|
||||
FOR_EXPR (for_stmt) = expr;
|
||||
|
||||
/* Don't let the tree nodes for EXPR 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-EXPR for the loop must be
|
||||
provided. */
|
||||
|
||||
void
|
||||
finish_for_stmt (expr, for_stmt)
|
||||
tree expr;
|
||||
tree for_stmt;
|
||||
{
|
||||
/* Pop the scope for the body of the loop. */
|
||||
do_poplevel ();
|
||||
|
||||
if (processing_template_decl)
|
||||
RECHAIN_STMTS_FROM_CHAIN (for_stmt, FOR_BODY (for_stmt));
|
||||
else
|
||||
{
|
||||
emit_line_note (input_filename, lineno);
|
||||
expand_loop_continue_here ();
|
||||
if (expr)
|
||||
cplus_expand_expr_stmt (expr);
|
||||
expand_end_loop ();
|
||||
}
|
||||
|
||||
pop_momentary ();
|
||||
|
||||
if (flag_new_for_scope > 0)
|
||||
do_poplevel ();
|
||||
|
||||
finish_stmt ();
|
||||
}
|
||||
|
||||
/* Finish a break-statement. */
|
||||
|
||||
void
|
||||
finish_break_stmt ()
|
||||
{
|
||||
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_stmt ()
|
||||
{
|
||||
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_stmt ()
|
||||
{
|
||||
do_pushlevel ();
|
||||
}
|
||||
|
||||
/* Finish the cond of a switch-statement. Returns a new
|
||||
SWITCH_STMT if appropriate. */
|
||||
|
||||
tree
|
||||
finish_switch_cond (cond)
|
||||
tree cond;
|
||||
{
|
||||
tree r;
|
||||
|
||||
if (processing_template_decl)
|
||||
{
|
||||
r = build_min_nt (SWITCH_STMT, cond, NULL_TREE);
|
||||
add_tree (r);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit_line_note (input_filename, lineno);
|
||||
c_expand_start_case (cond);
|
||||
r = NULL_TREE;
|
||||
}
|
||||
push_switch ();
|
||||
|
||||
/* Don't let the tree nodes for COND 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 COND to switch on is indicated. */
|
||||
|
||||
void
|
||||
finish_switch_stmt (cond, switch_stmt)
|
||||
tree cond;
|
||||
tree switch_stmt;
|
||||
{
|
||||
if (processing_template_decl)
|
||||
RECHAIN_STMTS_FROM_CHAIN (switch_stmt, SWITCH_BODY (switch_stmt));
|
||||
else
|
||||
expand_end_case (cond);
|
||||
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_stmt (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_STMTS_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_STMTS_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_parms (handler)
|
||||
tree handler;
|
||||
{
|
||||
if (processing_template_decl)
|
||||
RECHAIN_STMTS_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_STMTS_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_stmt (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_stmt (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_STMTS_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_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))
|
||||
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 ();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user