This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[c/c++] debugging line numbers
- To: gcc-patches at gcc dot gnu dot org
- Subject: [c/c++] debugging line numbers
- From: Richard Henderson <rth at redhat dot com>
- Date: Wed, 20 Dec 2000 01:56:08 -0800
For a test case like
---
int main(ac, av)
int ac;
char **av;
{
printf("%d %s\n",
ac,
av[0]);
return 0;
}
---
GCC's behaviour has changed since moving to functions-as-trees.
First, the first line of main would be reported to be the "int ac;"
rather than the open brace. Second, multi-line statements are given
the last line number of the statement rather than the first.
Both of these changes cause gdb test failures. and really seem
to be less than intuitive a change.
As it happens, the c front end had grammar rules that appear to
have been designed to address just this problem. But they didn't
actually do anything with the information that they collected.
The c++ front end did not, and I've adjusted it to match.
The patch is conseptually simple. Before parsing a statement,
read the next token and record its line number. After parsing
a statement, set the start line number appropriately. It's the
quantity of small changes required to get statement node and
recorded line number at the same place at the same time that
causes the patch to bulk up.
I'm going to give the C++ folk a chance to examine the patch
before checking this in.
r~
* c-typeck.c (build_asm_stmt): New, broken out from ...
(c_expand_asm_operands): ... here. Just to rtl expansion.
(c_expand_return): Return the new stmt node.
(c_start_case, do_case): Likewise.
* c-common.c (c_expand_expr_stmt): Likewise.
* c-common.h: Update declarations.
* c-tree.h: Likewise.
* c-semantics.c (build_stmt): Use STMT_LINENO not TREE_COMPLEXITY.
* c-parse.in (fndef): Set DECL_SOURCE_LINE to the open brace.
(nested_function, notype_nested_function): Likewise.
(compstmt): Return the compound statement not the binding level.
(lineno_labeled_stmt): Simplify.
(lineno_stmt, lineno_label): Set STMT_LINENO.
(stmt, label): Return the new stmt node.
cp/
* cp-tree.h: Update declarations.
* decl.c (finish_case_label): Return the new stmt node.
* semantics.c (finish_goto_stmt): Likewise.
(finish_expr_stmt, finish_return_stmt): Likewise.
(finish_break_stmt, finish_continue_stmt): Likewise.
(finish_asm_stmt): Likewise.
* parse.y (already_scoped_stmt): Set STMT_LINENO.
(compstmt, implicitly_scoped_stmt, stmt): Likewise.
(simple_if, simple_stmt): Return the new stmt node.
(save_lineno): New.
Index: c-common.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-common.c,v
retrieving revision 1.209
diff -c -p -d -r1.209 c-common.c
*** c-common.c 2000/12/18 23:50:55 1.209
--- c-common.c 2000/12/20 09:30:35
*************** verify_sequence_points (expr)
*** 3950,3956 ****
obstack_free (&tlist_obstack, tlist_firstobj);
}
! void
c_expand_expr_stmt (expr)
tree expr;
{
--- 3950,3956 ----
obstack_free (&tlist_obstack, tlist_firstobj);
}
! tree
c_expand_expr_stmt (expr)
tree expr;
{
*************** c_expand_expr_stmt (expr)
*** 3969,3975 ****
error ("expression statement has incomplete type");
last_expr_type = TREE_TYPE (expr);
! add_stmt (build_stmt (EXPR_STMT, expr));
}
/* Validate the expression after `case' and apply default promotions. */
--- 3969,3975 ----
error ("expression statement has incomplete type");
last_expr_type = TREE_TYPE (expr);
! return add_stmt (build_stmt (EXPR_STMT, expr));
}
/* Validate the expression after `case' and apply default promotions. */
Index: c-common.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-common.h,v
retrieving revision 1.57
diff -c -p -d -r1.57 c-common.h
*** c-common.h 2000/12/18 23:50:55 1.57
--- c-common.h 2000/12/20 09:30:36
*************** extern void c_apply_type_quals_to_decl
*** 467,473 ****
/* Print an error message for invalid operands to arith operation CODE.
NOP_EXPR is used as a special case (see truthvalue_conversion). */
extern void binary_op_error PARAMS ((enum tree_code));
! extern void c_expand_expr_stmt PARAMS ((tree));
extern void c_expand_start_cond PARAMS ((tree, int));
extern void c_finish_then PARAMS ((void));
extern void c_expand_start_else PARAMS ((void));
--- 467,473 ----
/* Print an error message for invalid operands to arith operation CODE.
NOP_EXPR is used as a special case (see truthvalue_conversion). */
extern void binary_op_error PARAMS ((enum tree_code));
! extern tree c_expand_expr_stmt PARAMS ((tree));
extern void c_expand_start_cond PARAMS ((tree, int));
extern void c_finish_then PARAMS ((void));
extern void c_expand_start_else PARAMS ((void));
*************** extern int anon_aggr_type_p
*** 713,720 ****
extern void emit_local_var PARAMS ((tree));
extern void make_rtl_for_local_static PARAMS ((tree));
extern tree expand_cond PARAMS ((tree));
! extern void c_expand_return PARAMS ((tree));
! extern void do_case PARAMS ((tree, tree));
extern tree build_stmt PARAMS ((enum tree_code, ...));
extern tree build_case_label PARAMS ((tree, tree, tree));
extern tree build_continue_stmt PARAMS ((void));
--- 713,720 ----
extern void emit_local_var PARAMS ((tree));
extern void make_rtl_for_local_static PARAMS ((tree));
extern tree expand_cond PARAMS ((tree));
! extern tree c_expand_return PARAMS ((tree));
! extern tree do_case PARAMS ((tree, tree));
extern tree build_stmt PARAMS ((enum tree_code, ...));
extern tree build_case_label PARAMS ((tree, tree, tree));
extern tree build_continue_stmt PARAMS ((void));
Index: c-parse.in
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-parse.in,v
retrieving revision 1.74
diff -c -p -d -r1.74 c-parse.in
*** c-parse.in 2000/11/28 22:52:26 1.74
--- c-parse.in 2000/12/20 09:30:36
*************** end ifc
*** 177,183 ****
%type <ttype> any_word extension
%type <ttype> compstmt compstmt_start compstmt_nostart compstmt_primary_start
! %type <ttype> do_stmt_start poplevel
%type <ttype> c99_block_start c99_block_end
%type <ttype> declarator
--- 177,183 ----
%type <ttype> any_word extension
%type <ttype> compstmt compstmt_start compstmt_nostart compstmt_primary_start
! %type <ttype> do_stmt_start poplevel stmt label
%type <ttype> c99_block_start c99_block_end
%type <ttype> declarator
*************** fndef:
*** 365,372 ****
}
old_style_parm_decls
{ store_parm_decls (); }
! compstmt_or_error
! { finish_function (0);
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack); }
--- 365,374 ----
}
old_style_parm_decls
{ store_parm_decls (); }
! save_filename save_lineno compstmt_or_error
! { DECL_SOURCE_FILE (current_function_decl) = $7;
! DECL_SOURCE_LINE (current_function_decl) = $8;
! finish_function (0);
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack); }
*************** fndef:
*** 381,388 ****
}
old_style_parm_decls
{ store_parm_decls (); }
! compstmt_or_error
! { finish_function (0);
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack); }
--- 383,392 ----
}
old_style_parm_decls
{ store_parm_decls (); }
! save_filename save_lineno compstmt_or_error
! { DECL_SOURCE_FILE (current_function_decl) = $7;
! DECL_SOURCE_LINE (current_function_decl) = $8;
! finish_function (0);
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack); }
*************** fndef:
*** 397,404 ****
}
old_style_parm_decls
{ store_parm_decls (); }
! compstmt_or_error
! { finish_function (0);
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack); }
--- 401,410 ----
}
old_style_parm_decls
{ store_parm_decls (); }
! save_filename save_lineno compstmt_or_error
! { DECL_SOURCE_FILE (current_function_decl) = $6;
! DECL_SOURCE_LINE (current_function_decl) = $7;
! finish_function (0);
current_declspecs = TREE_VALUE (declspec_stack);
prefix_attributes = TREE_PURPOSE (declspec_stack);
declspec_stack = TREE_CHAIN (declspec_stack); }
*************** nested_function:
*** 1192,1199 ****
which then was handled by compstmt_or_error.
There followed a repeated execution of that same rule,
which called YYERROR1 again, and so on. */
! compstmt
{ tree decl = current_function_decl;
finish_function (1);
pop_function_context ();
add_decl_stmt (decl); }
--- 1198,1207 ----
which then was handled by compstmt_or_error.
There followed a repeated execution of that same rule,
which called YYERROR1 again, and so on. */
! save_filename save_lineno compstmt
{ tree decl = current_function_decl;
+ DECL_SOURCE_FILE (decl) = $5;
+ DECL_SOURCE_LINE (decl) = $6;
finish_function (1);
pop_function_context ();
add_decl_stmt (decl); }
*************** notype_nested_function:
*** 1220,1227 ****
which then was handled by compstmt_or_error.
There followed a repeated execution of that same rule,
which called YYERROR1 again, and so on. */
! compstmt
{ tree decl = current_function_decl;
finish_function (1);
pop_function_context ();
add_decl_stmt (decl); }
--- 1228,1237 ----
which then was handled by compstmt_or_error.
There followed a repeated execution of that same rule,
which called YYERROR1 again, and so on. */
! save_filename save_lineno compstmt
{ tree decl = current_function_decl;
+ DECL_SOURCE_FILE (decl) = $5;
+ DECL_SOURCE_LINE (decl) = $6;
finish_function (1);
pop_function_context ();
add_decl_stmt (decl); }
*************** compstmt_primary_start:
*** 1750,1756 ****
compstmt: compstmt_start compstmt_nostart
{ RECHAIN_STMTS ($1, COMPOUND_BODY ($1));
! $$ = $2; }
;
/* Value is number of statements counted as of the closeparen. */
--- 1760,1766 ----
compstmt: compstmt_start compstmt_nostart
{ RECHAIN_STMTS ($1, COMPOUND_BODY ($1));
! $$ = $1; }
;
/* Value is number of statements counted as of the closeparen. */
*************** save_lineno:
*** 1808,1820 ****
;
lineno_labeled_stmt:
! save_filename save_lineno stmt
! { }
! /* | save_filename save_lineno error
! { }
! */
! | save_filename save_lineno label lineno_labeled_stmt
! { }
;
/* Like lineno_labeled_stmt, but a block in C99. */
--- 1818,1825 ----
;
lineno_labeled_stmt:
! lineno_stmt
! | lineno_label lineno_labeled_stmt
;
/* Like lineno_labeled_stmt, but a block in C99. */
*************** c99_block_lineno_labeled_stmt:
*** 1826,1837 ****
lineno_stmt:
save_filename save_lineno stmt
! { }
;
lineno_label:
save_filename save_lineno label
! { }
;
select_or_iter_stmt:
--- 1831,1855 ----
lineno_stmt:
save_filename save_lineno stmt
! { if ($3)
! {
! STMT_LINENO ($3) = $2;
! /* ??? We currently have no way of recording
! the filename for a statement. This probably
! matters little in practice at the moment,
! but I suspect that problems will ocurr when
! doing inlining at the tree level. */
! }
! }
;
lineno_label:
save_filename save_lineno label
! { if ($3)
! {
! STMT_LINENO ($3) = $2;
! }
! }
;
select_or_iter_stmt:
*************** for_init_stmt:
*** 1900,1924 ****
/* Parse a single real statement, not including any labels. */
stmt:
compstmt
! { stmt_count++; }
| expr ';'
{ stmt_count++;
! c_expand_expr_stmt ($1); }
| c99_block_start select_or_iter_stmt c99_block_end
{ if (flag_isoc99)
! RECHAIN_STMTS ($1, COMPOUND_BODY ($1)); }
| BREAK ';'
{ stmt_count++;
! add_stmt (build_break_stmt ()); }
| CONTINUE ';'
{ stmt_count++;
! add_stmt (build_continue_stmt ()); }
| RETURN ';'
{ stmt_count++;
! c_expand_return (NULL_TREE); }
| RETURN expr ';'
{ stmt_count++;
! c_expand_return ($2); }
| ASM_KEYWORD maybe_type_qual '(' expr ')' ';'
{ stmt_count++;
STRIP_NOPS ($4);
--- 1918,1943 ----
/* Parse a single real statement, not including any labels. */
stmt:
compstmt
! { stmt_count++; $$ = $1; }
| expr ';'
{ stmt_count++;
! $$ = c_expand_expr_stmt ($1); }
| c99_block_start select_or_iter_stmt c99_block_end
{ if (flag_isoc99)
! RECHAIN_STMTS ($1, COMPOUND_BODY ($1));
! $$ = NULL_TREE; }
| BREAK ';'
{ stmt_count++;
! $$ = add_stmt (build_break_stmt ()); }
| CONTINUE ';'
{ stmt_count++;
! $$ = add_stmt (build_continue_stmt ()); }
| RETURN ';'
{ stmt_count++;
! $$ = c_expand_return (NULL_TREE); }
| RETURN expr ';'
{ stmt_count++;
! $$ = c_expand_return ($2); }
| ASM_KEYWORD maybe_type_qual '(' expr ')' ';'
{ stmt_count++;
STRIP_NOPS ($4);
*************** stmt:
*** 1930,1959 ****
$4 = TREE_OPERAND ($4, 0);
if (TREE_CHAIN ($4))
$4 = combine_strings ($4);
! add_stmt (build_stmt (ASM_STMT, NULL_TREE, $4,
! NULL_TREE, NULL_TREE, NULL_TREE));
}
else
! error ("argument of `asm' is not a constant string"); }
/* This is the case with just output operands. */
| ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ')' ';'
{ stmt_count++;
! c_expand_asm_operands ($4, $6, NULL_TREE, NULL_TREE,
! $2 == ridpointers[(int)RID_VOLATILE],
! input_filename, lineno); }
/* This is the case with input operands as well. */
! | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':' asm_operands ')' ';'
{ stmt_count++;
! c_expand_asm_operands ($4, $6, $8, NULL_TREE,
! $2 == ridpointers[(int)RID_VOLATILE],
! input_filename, lineno); }
/* This is the case with clobbered registers as well. */
| ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':'
asm_operands ':' asm_clobbers ')' ';'
{ stmt_count++;
! c_expand_asm_operands ($4, $6, $8, $10,
! $2 == ridpointers[(int)RID_VOLATILE],
! input_filename, lineno); }
| GOTO identifier ';'
{ tree decl;
stmt_count++;
--- 1949,1978 ----
$4 = TREE_OPERAND ($4, 0);
if (TREE_CHAIN ($4))
$4 = combine_strings ($4);
! $$ = add_stmt (build_stmt (ASM_STMT, NULL_TREE, $4,
! NULL_TREE, NULL_TREE,
! NULL_TREE));
}
else
! {
! error ("argument of `asm' is not a constant string");
! $$ = NULL_TREE;
! }
! }
/* This is the case with just output operands. */
| ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ')' ';'
{ stmt_count++;
! $$ = build_asm_stmt ($2, $4, $6, NULL_TREE, NULL_TREE); }
/* This is the case with input operands as well. */
! | ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':'
! asm_operands ')' ';'
{ stmt_count++;
! $$ = build_asm_stmt ($2, $4, $6, $8, NULL_TREE); }
/* This is the case with clobbered registers as well. */
| ASM_KEYWORD maybe_type_qual '(' expr ':' asm_operands ':'
asm_operands ':' asm_clobbers ')' ';'
{ stmt_count++;
! $$ = build_asm_stmt ($2, $4, $6, $8, $10); }
| GOTO identifier ';'
{ tree decl;
stmt_count++;
*************** stmt:
*** 1961,1976 ****
if (decl != 0)
{
TREE_USED (decl) = 1;
! add_stmt (build_stmt (GOTO_STMT, decl));
}
}
| GOTO '*' expr ';'
{ if (pedantic)
pedwarn ("ISO C forbids `goto *expr;'");
stmt_count++;
$3 = convert (ptr_type_node, $3);
! add_stmt (build_stmt (GOTO_STMT, $3)); }
| ';'
;
/* Any kind of label, including jump labels and case labels.
--- 1980,1998 ----
if (decl != 0)
{
TREE_USED (decl) = 1;
! $$ = add_stmt (build_stmt (GOTO_STMT, decl));
}
+ else
+ $$ = NULL_TREE;
}
| GOTO '*' expr ';'
{ if (pedantic)
pedwarn ("ISO C forbids `goto *expr;'");
stmt_count++;
$3 = convert (ptr_type_node, $3);
! $$ = add_stmt (build_stmt (GOTO_STMT, $3)); }
| ';'
+ { $$ = NULL_TREE; }
;
/* Any kind of label, including jump labels and case labels.
*************** stmt:
*** 1979,1999 ****
label: CASE expr_no_commas ':'
{ stmt_count++;
! do_case ($2, NULL_TREE); }
| CASE expr_no_commas ELLIPSIS expr_no_commas ':'
{ stmt_count++;
! do_case ($2, $4); }
| DEFAULT ':'
{ stmt_count++;
! do_case (NULL_TREE, NULL_TREE); }
| identifier save_filename save_lineno ':' maybe_attribute
{ tree label = define_label ($2, $3, $1);
stmt_count++;
if (label)
{
decl_attributes (label, $5, NULL_TREE);
! add_stmt (build_stmt (LABEL_STMT, label));
}
}
;
--- 2001,2023 ----
label: CASE expr_no_commas ':'
{ stmt_count++;
! $$ = do_case ($2, NULL_TREE); }
| CASE expr_no_commas ELLIPSIS expr_no_commas ':'
{ stmt_count++;
! $$ = do_case ($2, $4); }
| DEFAULT ':'
{ stmt_count++;
! $$ = do_case (NULL_TREE, NULL_TREE); }
| identifier save_filename save_lineno ':' maybe_attribute
{ tree label = define_label ($2, $3, $1);
stmt_count++;
if (label)
{
decl_attributes (label, $5, NULL_TREE);
! $$ = add_stmt (build_stmt (LABEL_STMT, label));
}
+ else
+ $$ = NULL_TREE;
}
;
Index: c-semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-semantics.c,v
retrieving revision 1.15
diff -c -p -d -r1.15 c-semantics.c
*** c-semantics.c 2000/11/26 00:40:46 1.15
--- c-semantics.c 2000/12/20 09:30:36
*************** finish_stmt_tree (t)
*** 220,226 ****
/* Build a generic statement based on the given type of node and
arguments. Similar to `build_nt', except that we set
! TREE_COMPLEXITY to be the current line number. */
tree
build_stmt VPARAMS ((enum tree_code code, ...))
--- 220,228 ----
/* Build a generic statement based on the given type of node and
arguments. Similar to `build_nt', except that we set
! STMT_LINENO to be the current line number. */
! /* ??? This should be obsolete with the lineno_stmt productions
! in the grammar. */
tree
build_stmt VPARAMS ((enum tree_code code, ...))
*************** build_stmt VPARAMS ((enum tree_code code
*** 241,247 ****
t = make_node (code);
length = TREE_CODE_LENGTH (code);
! TREE_COMPLEXITY (t) = lineno;
for (i = 0; i < length; i++)
TREE_OPERAND (t, i) = va_arg (p, tree);
--- 243,249 ----
t = make_node (code);
length = TREE_CODE_LENGTH (code);
! STMT_LINENO (t) = lineno;
for (i = 0; i < length; i++)
TREE_OPERAND (t, i) = va_arg (p, tree);
Index: c-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-tree.h,v
retrieving revision 1.53
diff -c -p -d -r1.53 c-tree.h
*** c-tree.h 2000/12/18 23:50:55 1.53
--- c-tree.h 2000/12/20 09:30:36
*************** extern void pedwarn_c99 PARAMS ((cons
*** 275,280 ****
--- 275,282 ----
ATTRIBUTE_PRINTF_1;
extern tree c_start_case PARAMS ((tree));
extern void c_finish_case PARAMS ((void));
+ extern tree build_asm_stmt PARAMS ((tree, tree, tree,
+ tree, tree));
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */
Index: c-typeck.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-typeck.c,v
retrieving revision 1.105
diff -c -p -d -r1.105 c-typeck.c
*** c-typeck.c 2000/11/20 19:06:17 1.105
--- c-typeck.c 2000/12/20 09:30:36
*************** process_init_element (value)
*** 6303,6343 ****
}
}
! /* Expand an ASM statement with operands, handling output operands
! that are not variables or INDIRECT_REFS by transforming such
! cases into cases that expand_asm_operands can handle.
!
! Arguments are same as for expand_asm_operands. */
! void
! c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
! tree string, outputs, inputs, clobbers;
! int vol;
! const char *filename;
! int line;
{
! int noutputs = list_length (outputs);
! register int i;
! /* o[I] is the place that output number I should be written. */
! register tree *o = (tree *) alloca (noutputs * sizeof (tree));
! register tree tail;
! if (TREE_CODE (string) == ADDR_EXPR)
! string = TREE_OPERAND (string, 0);
! if (last_tree && TREE_CODE (string) != STRING_CST)
{
error ("asm template is not a string constant");
! return;
}
! /* Record the contents of OUTPUTS before it is modified. */
! for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
{
tree output = TREE_VALUE (tail);
- /* We can remove conversions that just change the type, not the mode. */
STRIP_NOPS (output);
! o[i] = output;
/* Allow conversions as LHS here. build_modify_expr as called below
will do the right thing with them. */
--- 6303,6345 ----
}
}
! /* Build an asm-statement, whose components are a CV_QUALIFIER, a
! STRING, some OUTPUTS, some INPUTS, and some CLOBBERS. */
! tree
! build_asm_stmt (cv_qualifier, string, outputs, inputs, clobbers)
! tree cv_qualifier;
! tree string;
! tree outputs;
! tree inputs;
! tree clobbers;
{
! tree tail;
! if (TREE_CHAIN (string))
! string = combine_strings (string);
! if (TREE_CODE (string) != STRING_CST)
{
error ("asm template is not a string constant");
! return NULL_TREE;
}
! if (cv_qualifier != NULL_TREE
! && cv_qualifier != ridpointers[(int) RID_VOLATILE])
! {
! warning ("%s qualifier ignored on asm",
! IDENTIFIER_POINTER (cv_qualifier));
! cv_qualifier = NULL_TREE;
! }
!
! /* We can remove output conversions that change the type,
! but not the mode. */
! for (tail = outputs; tail; tail = TREE_CHAIN (tail))
{
tree output = TREE_VALUE (tail);
STRIP_NOPS (output);
! TREE_VALUE (tail) = output;
/* Allow conversions as LHS here. build_modify_expr as called below
will do the right thing with them. */
*************** c_expand_asm_operands (string, outputs,
*** 6350,6378 ****
|| TREE_CODE (output) == FIX_CEIL_EXPR)
output = TREE_OPERAND (output, 0);
! if (last_tree)
! lvalue_or_else (o[i], "invalid lvalue in asm statement");
}
! /* Perform default conversions on array and function inputs. */
! /* Don't do this for other types--
! it would screw up operands expected to be in memory. */
! for (i = 0, tail = inputs; tail; tail = TREE_CHAIN (tail), i++)
if (TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == FUNCTION_TYPE)
TREE_VALUE (tail) = default_conversion (TREE_VALUE (tail));
! if (last_tree)
! {
! add_stmt (build_stmt (ASM_STMT,
! vol ? ridpointers[(int) RID_VOLATILE] : NULL_TREE,
! string, outputs, inputs, clobbers));
! return;
! }
! /* Generate the ASM_OPERANDS insn;
! store into the TREE_VALUEs of OUTPUTS some trees for
! where the values were actually stored. */
expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line);
/* Copy all the intermediate outputs into the specified outputs. */
--- 6352,6405 ----
|| TREE_CODE (output) == FIX_CEIL_EXPR)
output = TREE_OPERAND (output, 0);
! lvalue_or_else (TREE_VALUE (tail), "invalid lvalue in asm statement");
}
! /* Remove output conversions that change the type but not the mode. */
! for (tail = outputs; tail; tail = TREE_CHAIN (tail))
! {
! tree output = TREE_VALUE (tail);
! STRIP_NOPS (output);
! TREE_VALUE (tail) = output;
! }
!
! /* Perform default conversions on array and function inputs.
! Don't do this for other types as it would screw up operands
! expected to be in memory. */
! for (tail = inputs; tail; tail = TREE_CHAIN (tail))
if (TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (TREE_VALUE (tail))) == FUNCTION_TYPE)
TREE_VALUE (tail) = default_conversion (TREE_VALUE (tail));
! return add_stmt (build_stmt (ASM_STMT, cv_qualifier, string,
! outputs, inputs, clobbers));
! }
! /* Expand an ASM statement with operands, handling output operands
! that are not variables or INDIRECT_REFS by transforming such
! cases into cases that expand_asm_operands can handle.
!
! Arguments are same as for expand_asm_operands. */
!
! void
! c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line)
! tree string, outputs, inputs, clobbers;
! int vol;
! const char *filename;
! int line;
! {
! int noutputs = list_length (outputs);
! register int i;
! /* o[I] is the place that output number I should be written. */
! register tree *o = (tree *) alloca (noutputs * sizeof (tree));
! register tree tail;
!
! /* Record the contents of OUTPUTS before it is modified. */
! for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
! o[i] = TREE_VALUE (tail);
!
! /* Generate the ASM_OPERANDS insn; store into the TREE_VALUEs of
! OUTPUTS some trees for where the values were actually stored. */
expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line);
/* Copy all the intermediate outputs into the specified outputs. */
*************** c_expand_asm_operands (string, outputs,
*** 6410,6416 ****
RETVAL is the expression for what to return,
or a null pointer for `return;' with no value. */
! void
c_expand_return (retval)
tree retval;
{
--- 6437,6443 ----
RETVAL is the expression for what to return,
or a null pointer for `return;' with no value. */
! tree
c_expand_return (retval)
tree retval;
{
*************** c_expand_return (retval)
*** 6440,6446 ****
tree inner;
if (t == error_mark_node)
! return;
inner = t = convert (TREE_TYPE (res), t);
--- 6467,6473 ----
tree inner;
if (t == error_mark_node)
! return NULL_TREE;
inner = t = convert (TREE_TYPE (res), t);
*************** c_expand_return (retval)
*** 6499,6505 ****
current_function_returns_value = 1;
}
! add_stmt (build_return_stmt (retval));
}
struct c_switch {
--- 6526,6532 ----
current_function_returns_value = 1;
}
! return add_stmt (build_return_stmt (retval));
}
struct c_switch {
*************** c_start_case (exp)
*** 6581,6600 ****
/* Process a case label. */
! void
do_case (low_value, high_value)
tree low_value;
tree high_value;
{
if (switch_stack)
! c_add_case_label (switch_stack->cases,
! SWITCH_COND (switch_stack->switch_stmt),
! low_value,
! high_value);
else if (low_value)
error ("case label not within a switch statement");
else
error ("`default' label not within a switch statement");
}
/* Finish the switch statement. */
--- 6608,6634 ----
/* Process a case label. */
! tree
do_case (low_value, high_value)
tree low_value;
tree high_value;
{
+ tree label = NULL_TREE;
+
if (switch_stack)
! {
! label = c_add_case_label (switch_stack->cases,
! SWITCH_COND (switch_stack->switch_stmt),
! low_value, high_value);
! if (label == error_mark_node)
! label = NULL_TREE;
! }
else if (low_value)
error ("case label not within a switch statement");
else
error ("`default' label not within a switch statement");
+
+ return label;
}
/* Finish the switch statement. */
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.547
diff -c -p -d -r1.547 cp-tree.h
*** cp-tree.h 2000/12/18 23:50:57 1.547
--- cp-tree.h 2000/12/20 09:30:36
*************** extern void check_function_format PARAM
*** 3200,3206 ****
NOP_EXPR is used as a special case (see truthvalue_conversion). */
extern void binary_op_error PARAMS ((enum tree_code));
extern tree canonical_type_variant PARAMS ((tree));
- extern void c_expand_expr_stmt PARAMS ((tree));
/* Validate the expression after `case' and apply default promotions. */
extern tree check_case_value PARAMS ((tree));
/* Concatenate a list of STRING_CST nodes into one STRING_CST. */
--- 3200,3205 ----
*************** extern void fixup_all_virtual_upcast_off
*** 4291,4297 ****
/* in semantics.c */
extern void init_cp_semantics PARAMS ((void));
! extern void finish_expr_stmt PARAMS ((tree));
extern tree begin_if_stmt PARAMS ((void));
extern void finish_if_stmt_cond PARAMS ((tree, tree));
extern tree finish_then_clause PARAMS ((tree));
--- 4290,4296 ----
/* in semantics.c */
extern void init_cp_semantics PARAMS ((void));
! extern tree finish_expr_stmt PARAMS ((tree));
extern tree begin_if_stmt PARAMS ((void));
extern void finish_if_stmt_cond PARAMS ((tree, tree));
extern tree finish_then_clause PARAMS ((tree));
*************** extern void finish_while_stmt
*** 4304,4322 ****
extern tree begin_do_stmt PARAMS ((void));
extern void finish_do_body PARAMS ((tree));
extern void finish_do_stmt PARAMS ((tree, tree));
! extern void finish_return_stmt PARAMS ((tree));
extern tree begin_for_stmt PARAMS ((void));
extern void finish_for_init_stmt PARAMS ((tree));
extern void finish_for_cond PARAMS ((tree, tree));
extern void finish_for_expr PARAMS ((tree, tree));
extern void finish_for_stmt PARAMS ((tree));
! extern void finish_break_stmt PARAMS ((void));
! extern void finish_continue_stmt PARAMS ((void));
extern tree begin_switch_stmt PARAMS ((void));
extern void finish_switch_cond PARAMS ((tree, tree));
extern void finish_switch_stmt PARAMS ((tree));
! extern void finish_case_label PARAMS ((tree, tree));
! extern void finish_goto_stmt PARAMS ((tree));
extern tree begin_try_block PARAMS ((void));
extern void finish_try_block PARAMS ((tree));
extern void finish_handler_sequence PARAMS ((tree));
--- 4303,4321 ----
extern tree begin_do_stmt PARAMS ((void));
extern void finish_do_body PARAMS ((tree));
extern void finish_do_stmt PARAMS ((tree, tree));
! extern tree finish_return_stmt PARAMS ((tree));
extern tree begin_for_stmt PARAMS ((void));
extern void finish_for_init_stmt PARAMS ((tree));
extern void finish_for_cond PARAMS ((tree, tree));
extern void finish_for_expr PARAMS ((tree, tree));
extern void finish_for_stmt PARAMS ((tree));
! extern tree finish_break_stmt PARAMS ((void));
! extern tree finish_continue_stmt PARAMS ((void));
extern tree begin_switch_stmt PARAMS ((void));
extern void finish_switch_cond PARAMS ((tree, tree));
extern void finish_switch_stmt PARAMS ((tree));
! extern tree finish_case_label PARAMS ((tree, tree));
! extern tree finish_goto_stmt PARAMS ((tree));
extern tree begin_try_block PARAMS ((void));
extern void finish_try_block PARAMS ((tree));
extern void finish_handler_sequence PARAMS ((tree));
*************** extern void finish_handler
*** 4331,4337 ****
extern void finish_cleanup PARAMS ((tree, tree));
extern tree begin_compound_stmt PARAMS ((int));
extern tree finish_compound_stmt PARAMS ((int, tree));
! extern void finish_asm_stmt PARAMS ((tree, tree, tree, tree, tree));
extern void finish_label_stmt PARAMS ((tree));
extern void finish_label_decl PARAMS ((tree));
extern void finish_subobject PARAMS ((tree));
--- 4330,4336 ----
extern void finish_cleanup PARAMS ((tree, tree));
extern tree begin_compound_stmt PARAMS ((int));
extern tree finish_compound_stmt PARAMS ((int, tree));
! extern tree finish_asm_stmt PARAMS ((tree, tree, tree, tree, tree));
extern void finish_label_stmt PARAMS ((tree));
extern void finish_label_decl PARAMS ((tree));
extern void finish_subobject PARAMS ((tree));
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.725
diff -c -p -d -r1.725 decl.c
*** decl.c 2000/12/15 16:15:52 1.725
--- decl.c 2000/12/20 09:30:37
*************** pop_switch ()
*** 5158,5169 ****
/* Note that we've seen a definition of a case label, and complain if this
is a bad place for one. */
! void
finish_case_label (low_value, high_value)
tree low_value;
tree high_value;
{
! tree cond;
register struct binding_level *p;
if (! switch_stack)
--- 5158,5169 ----
/* Note that we've seen a definition of a case label, and complain if this
is a bad place for one. */
! tree
finish_case_label (low_value, high_value)
tree low_value;
tree high_value;
{
! tree cond, r;
register struct binding_level *p;
if (! switch_stack)
*************** finish_case_label (low_value, high_value
*** 5175,5181 ****
low_value);
else
error ("`default' label not within a switch statement");
! return;
}
if (processing_template_decl)
--- 5175,5181 ----
low_value);
else
error ("`default' label not within a switch statement");
! return NULL_TREE;
}
if (processing_template_decl)
*************** finish_case_label (low_value, high_value
*** 5185,5192 ****
/* For templates, just add the case label; we'll do semantic
analysis at instantiation-time. */
label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
! add_stmt (build_case_label (low_value, high_value, label));
! return;
}
/* Find the condition on which this switch statement depends. */
--- 5185,5191 ----
/* For templates, just add the case label; we'll do semantic
analysis at instantiation-time. */
label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
! return add_stmt (build_case_label (low_value, high_value, label));
}
/* Find the condition on which this switch statement depends. */
*************** finish_case_label (low_value, high_value
*** 5194,5200 ****
if (cond && TREE_CODE (cond) == TREE_LIST)
cond = TREE_VALUE (cond);
! c_add_case_label (switch_stack->cases, cond, low_value, high_value);
check_switch_goto (switch_stack->level);
--- 5193,5201 ----
if (cond && TREE_CODE (cond) == TREE_LIST)
cond = TREE_VALUE (cond);
! r = c_add_case_label (switch_stack->cases, cond, low_value, high_value);
! if (r == error_mark_node)
! r = NULL_TREE;
check_switch_goto (switch_stack->level);
*************** finish_case_label (low_value, high_value
*** 5203,5208 ****
--- 5204,5211 ----
for (p = current_binding_level; !(p->parm_flag); p = p->level_chain)
p->more_cleanups_ok = 0;
current_function_return_value = NULL_TREE;
+
+ return r;
}
/* Return the list of declarations of the current level.
Index: cp/parse.y
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/parse.y,v
retrieving revision 1.203
diff -c -p -d -r1.203 parse.y
*** parse.y 2000/11/28 10:31:06 1.203
--- parse.y 2000/12/20 09:30:37
*************** cp_parse_init ()
*** 338,344 ****
%type <ttype> maybe_attribute attributes attribute attribute_list attrib
%type <ttype> any_word
! %type <ttype> compstmt implicitly_scoped_stmt
%type <ttype> declarator notype_declarator after_type_declarator
%type <ttype> notype_declarator_intern absdcl_intern
--- 338,345 ----
%type <ttype> maybe_attribute attributes attribute attribute_list attrib
%type <ttype> any_word
! %type <itype> save_lineno
! %type <ttype> simple_stmt simple_if
%type <ttype> declarator notype_declarator after_type_declarator
%type <ttype> notype_declarator_intern absdcl_intern
*************** compstmtend:
*** 1151,1164 ****
;
already_scoped_stmt:
! '{'
! { $<ttype>$ = begin_compound_stmt (1); }
compstmtend
! { finish_compound_stmt (1, $<ttype>2); }
! | simple_stmt
;
-
nontrivial_exprlist:
expr_no_commas ',' expr_no_commas
{ $$ = tree_cons (NULL_TREE, $$,
--- 1152,1166 ----
;
already_scoped_stmt:
! save_lineno '{'
! { $<ttype>$ = begin_compound_stmt (1); }
compstmtend
! { STMT_LINENO ($<ttype>3) = $1;
! finish_compound_stmt (1, $<ttype>3); }
! | save_lineno simple_stmt
! { if ($2) STMT_LINENO ($2) = $1; }
;
nontrivial_exprlist:
expr_no_commas ',' expr_no_commas
{ $$ = tree_cons (NULL_TREE, $$,
*************** label_decl:
*** 3277,3332 ****
It causes syntax errors to ignore to the next openbrace. */
compstmt_or_error:
compstmt
- {}
| error compstmt
;
compstmt:
! '{'
{ $<ttype>$ = begin_compound_stmt (0); }
compstmtend
! { $$ = finish_compound_stmt (0, $<ttype>2); }
;
simple_if:
IF
! {
! $<ttype>$ = begin_if_stmt ();
! cond_stmt_keyword = "if";
! }
paren_cond_or_null
{ finish_if_stmt_cond ($3, $<ttype>2); }
implicitly_scoped_stmt
! { $<ttype>$ = finish_then_clause ($<ttype>2); }
;
implicitly_scoped_stmt:
compstmt
! | { $<ttype>$ = begin_compound_stmt (0); }
! simple_stmt
! { $$ = finish_compound_stmt (0, $<ttype>1); }
;
stmt:
compstmt
! {}
! | simple_stmt
;
simple_stmt:
decl
! { finish_stmt (); }
| expr ';'
! { finish_expr_stmt ($1); }
| simple_if ELSE
{ begin_else_clause (); }
implicitly_scoped_stmt
{
! finish_else_clause ($<ttype>1);
finish_if_stmt ();
}
| simple_if %prec IF
! { finish_if_stmt (); }
| WHILE
{
$<ttype>$ = begin_while_stmt ();
--- 3279,3339 ----
It causes syntax errors to ignore to the next openbrace. */
compstmt_or_error:
compstmt
| error compstmt
;
compstmt:
! save_lineno '{'
{ $<ttype>$ = begin_compound_stmt (0); }
compstmtend
! { STMT_LINENO ($<ttype>3) = $1;
! finish_compound_stmt (0, $<ttype>3); }
;
simple_if:
IF
! { $<ttype>$ = begin_if_stmt ();
! cond_stmt_keyword = "if"; }
paren_cond_or_null
{ finish_if_stmt_cond ($3, $<ttype>2); }
implicitly_scoped_stmt
! { $$ = $<ttype>2;
! finish_then_clause ($<ttype>2); }
;
implicitly_scoped_stmt:
compstmt
! |
! { $<ttype>$ = begin_compound_stmt (0); }
! save_lineno simple_stmt
! { STMT_LINENO ($<ttype>1) = $2;
! if ($3) STMT_LINENO ($3) = $2;
! finish_compound_stmt (0, $<ttype>1); }
;
stmt:
compstmt
! | save_lineno simple_stmt
! { if ($2) STMT_LINENO ($2) = $1; }
;
simple_stmt:
decl
! { finish_stmt ();
! $$ = NULL_TREE; }
| expr ';'
! { $$ = finish_expr_stmt ($1); }
| simple_if ELSE
{ begin_else_clause (); }
implicitly_scoped_stmt
{
! $$ = $1;
! finish_else_clause ($1);
finish_if_stmt ();
}
| simple_if %prec IF
! { $$ = $1;
! finish_if_stmt (); }
| WHILE
{
$<ttype>$ = begin_while_stmt ();
*************** simple_stmt:
*** 3335,3341 ****
paren_cond_or_null
{ finish_while_stmt_cond ($3, $<ttype>2); }
already_scoped_stmt
! { finish_while_stmt ($<ttype>2); }
| DO
{ $<ttype>$ = begin_do_stmt (); }
implicitly_scoped_stmt WHILE
--- 3342,3349 ----
paren_cond_or_null
{ finish_while_stmt_cond ($3, $<ttype>2); }
already_scoped_stmt
! { $$ = $<ttype>2;
! finish_while_stmt ($<ttype>2); }
| DO
{ $<ttype>$ = begin_do_stmt (); }
implicitly_scoped_stmt WHILE
*************** simple_stmt:
*** 3344,3350 ****
cond_stmt_keyword = "do";
}
paren_expr_or_null ';'
! { finish_do_stmt ($6, $<ttype>2); }
| FOR
{ $<ttype>$ = begin_for_stmt (); }
'(' for.init.statement
--- 3352,3359 ----
cond_stmt_keyword = "do";
}
paren_expr_or_null ';'
! { $$ = $<ttype>2;
! finish_do_stmt ($6, $<ttype>2); }
| FOR
{ $<ttype>$ = begin_for_stmt (); }
'(' for.init.statement
*************** simple_stmt:
*** 3354,3428 ****
xexpr ')'
{ finish_for_expr ($9, $<ttype>2); }
already_scoped_stmt
! { finish_for_stmt ($<ttype>2); }
| SWITCH
{ $<ttype>$ = begin_switch_stmt (); }
'(' condition ')'
{ finish_switch_cond ($4, $<ttype>2); }
implicitly_scoped_stmt
! { finish_switch_stmt ($<ttype>2); }
| 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_stmt (); }
| CONTINUE ';'
! { finish_continue_stmt (); }
| RETURN_KEYWORD ';'
! { finish_return_stmt (NULL_TREE); }
| RETURN_KEYWORD expr ';'
! { finish_return_stmt ($2); }
| asm_keyword maybe_cv_qualifier '(' string ')' ';'
! {
! 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 ')' ';'
! {
! 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 ')' ';'
! { finish_asm_stmt ($2, $4, $6, $8, NULL_TREE); }
| asm_keyword maybe_cv_qualifier '(' string SCOPE asm_operands ')' ';'
! { finish_asm_stmt ($2, $4, NULL_TREE, $6, 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_stmt ($2, $4, $6, $8, $10); }
| asm_keyword maybe_cv_qualifier '(' string SCOPE asm_operands ':'
asm_clobbers ')' ';'
! { finish_asm_stmt ($2, $4, NULL_TREE, $6, $8); }
| asm_keyword maybe_cv_qualifier '(' string ':' asm_operands SCOPE
asm_clobbers ')' ';'
! { finish_asm_stmt ($2, $4, $6, NULL_TREE, $8); }
| GOTO '*' expr ';'
{
if (pedantic)
pedwarn ("ISO C++ forbids computed gotos");
! finish_goto_stmt ($3);
}
| GOTO identifier ';'
! { finish_goto_stmt ($2); }
| label_colon stmt
| label_colon '}'
{ error ("label must be followed by statement");
! yyungetc ('}', 0); }
| ';'
! { finish_stmt (); }
| try_block
| using_directive
| namespace_using_decl
! { do_local_using_decl ($1); }
| namespace_alias
;
function_try_block:
--- 3363,3445 ----
xexpr ')'
{ finish_for_expr ($9, $<ttype>2); }
already_scoped_stmt
! { $$ = $<ttype>2;
! finish_for_stmt ($<ttype>2); }
| SWITCH
{ $<ttype>$ = begin_switch_stmt (); }
'(' condition ')'
{ finish_switch_cond ($4, $<ttype>2); }
implicitly_scoped_stmt
! { $$ = $<ttype>2;
! finish_switch_stmt ($<ttype>2); }
| CASE expr_no_commas ':'
! { $<ttype>$ = finish_case_label ($2, NULL_TREE); }
stmt
+ { $$ = $<ttype>4; }
| CASE expr_no_commas ELLIPSIS expr_no_commas ':'
! { $<ttype>$ = finish_case_label ($2, $4); }
stmt
+ { $$ = $<ttype>6; }
| DEFAULT ':'
! { $<ttype>$ = finish_case_label (NULL_TREE, NULL_TREE); }
stmt
+ { $$ = $<ttype>3; }
| BREAK ';'
! { $$ = finish_break_stmt (); }
| CONTINUE ';'
! { $$ = finish_continue_stmt (); }
| RETURN_KEYWORD ';'
! { $$ = finish_return_stmt (NULL_TREE); }
| RETURN_KEYWORD expr ';'
! { $$ = finish_return_stmt ($2); }
| asm_keyword maybe_cv_qualifier '(' string ')' ';'
! { $$ = 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 ')' ';'
! { $$ = 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 ')' ';'
! { $$ = finish_asm_stmt ($2, $4, $6, $8, NULL_TREE); }
| asm_keyword maybe_cv_qualifier '(' string SCOPE asm_operands ')' ';'
! { $$ = finish_asm_stmt ($2, $4, NULL_TREE, $6, 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_stmt ($2, $4, $6, $8, $10); }
| asm_keyword maybe_cv_qualifier '(' string SCOPE asm_operands ':'
asm_clobbers ')' ';'
! { $$ = finish_asm_stmt ($2, $4, NULL_TREE, $6, $8); }
| asm_keyword maybe_cv_qualifier '(' string ':' asm_operands SCOPE
asm_clobbers ')' ';'
! { $$ = finish_asm_stmt ($2, $4, $6, NULL_TREE, $8); }
| GOTO '*' expr ';'
{
if (pedantic)
pedwarn ("ISO C++ forbids computed gotos");
! $$ = finish_goto_stmt ($3);
}
| GOTO identifier ';'
! { $$ = finish_goto_stmt ($2); }
| label_colon stmt
+ { $$ = NULL_TREE; }
| label_colon '}'
{ error ("label must be followed by statement");
! yyungetc ('}', 0);
! $$ = NULL_TREE; }
| ';'
! { finish_stmt ();
! $$ = NULL_TREE; }
| try_block
+ { $$ = NULL_TREE; }
| using_directive
+ { $$ = NULL_TREE; }
| namespace_using_decl
! { do_local_using_decl ($1);
! $$ = NULL_TREE; }
| namespace_alias
+ { $$ = NULL_TREE; }
;
function_try_block:
*************** operator_name:
*** 3842,3847 ****
--- 3859,3872 ----
{ $$ = frob_opname (ansi_opname (ERROR_MARK)); }
;
+ /* The forced readahead in here is because we might be at the end of a
+ line, and lineno won't be bumped until yylex absorbs the first token
+ on the next line. */
+ save_lineno:
+ { if (yychar == YYEMPTY)
+ yychar = YYLEX;
+ $$ = lineno; }
+ ;
%%
#ifdef SPEW_DEBUG
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/semantics.c,v
retrieving revision 1.181
diff -c -p -d -r1.181 semantics.c
*** semantics.c 2000/11/28 10:31:06 1.181
--- semantics.c 2000/12/20 09:30:37
*************** do_pushlevel ()
*** 150,156 ****
/* Finish a goto-statement. */
! void
finish_goto_stmt (destination)
tree destination;
{
--- 150,156 ----
/* Finish a goto-statement. */
! tree
finish_goto_stmt (destination)
tree destination;
{
*************** finish_goto_stmt (destination)
*** 171,177 ****
check_goto (destination);
! add_stmt (build_stmt (GOTO_STMT, destination));
}
/* COND is the condition-expression for an if, while, etc.,
--- 171,177 ----
check_goto (destination);
! return add_stmt (build_stmt (GOTO_STMT, destination));
}
/* COND is the condition-expression for an if, while, etc.,
*************** maybe_convert_cond (cond)
*** 196,205 ****
/* Finish an expression-statement, whose EXPRESSION is as indicated. */
! void
finish_expr_stmt (expr)
tree expr;
{
if (expr != NULL_TREE)
{
if (!processing_template_decl
--- 196,207 ----
/* Finish an expression-statement, whose EXPRESSION is as indicated. */
! tree
finish_expr_stmt (expr)
tree expr;
{
+ tree r = NULL_TREE;
+
if (expr != NULL_TREE)
{
if (!processing_template_decl
*************** finish_expr_stmt (expr)
*** 215,221 ****
if (!processing_template_decl)
expr = break_out_cleanups (expr);
! add_stmt (build_stmt (EXPR_STMT, expr));
}
finish_stmt ();
--- 217,223 ----
if (!processing_template_decl)
expr = break_out_cleanups (expr);
! r = add_stmt (build_stmt (EXPR_STMT, expr));
}
finish_stmt ();
*************** finish_expr_stmt (expr)
*** 223,228 ****
--- 225,232 ----
/* This was an expression-statement, so we save the type of the
expression. */
last_expr_type = expr ? TREE_TYPE (expr) : NULL_TREE;
+
+ return r;
}
*************** finish_do_stmt (cond, do_stmt)
*** 375,384 ****
/* Finish a return-statement. The EXPRESSION returned, if any, is as
indicated. */
! void
finish_return_stmt (expr)
tree expr;
{
if (!processing_template_decl)
expr = check_return_expr (expr);
if (!processing_template_decl)
--- 379,390 ----
/* Finish a return-statement. The EXPRESSION returned, if any, is as
indicated. */
! tree
finish_return_stmt (expr)
tree expr;
{
+ tree r;
+
if (!processing_template_decl)
expr = check_return_expr (expr);
if (!processing_template_decl)
*************** finish_return_stmt (expr)
*** 391,398 ****
return a value there. When we finally generate the real
return statement, CTOR_LABEL is no longer set, and we fall
through into the normal return-processing code below. */
! finish_goto_stmt (ctor_label);
! return;
}
else if (DECL_DESTRUCTOR_P (current_function_decl))
{
--- 397,403 ----
return a value there. When we finally generate the real
return statement, CTOR_LABEL is no longer set, and we fall
through into the normal return-processing code below. */
! return finish_goto_stmt (ctor_label);
}
else if (DECL_DESTRUCTOR_P (current_function_decl))
{
*************** finish_return_stmt (expr)
*** 400,411 ****
base-classes before returning. So, all returns in a
destructor get sent to the DTOR_LABEL; finsh_function emits
code to return a value there. */
! finish_goto_stmt (dtor_label);
! return;
}
}
! add_stmt (build_stmt (RETURN_STMT, expr));
finish_stmt ();
}
/* Begin a for-statement. Returns a new FOR_STMT if appropriate. */
--- 405,417 ----
base-classes before returning. So, all returns in a
destructor get sent to the DTOR_LABEL; finsh_function emits
code to return a value there. */
! return finish_goto_stmt (dtor_label);
}
}
! r = add_stmt (build_stmt (RETURN_STMT, expr));
finish_stmt ();
+
+ return r;
}
/* Begin a for-statement. Returns a new FOR_STMT if appropriate. */
*************** finish_for_stmt (for_stmt)
*** 482,499 ****
/* Finish a break-statement. */
! void
finish_break_stmt ()
{
! add_stmt (build_break_stmt ());
}
/* Finish a continue-statement. */
! void
finish_continue_stmt ()
{
! add_stmt (build_continue_stmt ());
}
/* Begin a switch-statement. Returns a new SWITCH_STMT if
--- 488,505 ----
/* Finish a break-statement. */
! tree
finish_break_stmt ()
{
! return add_stmt (build_break_stmt ());
}
/* Finish a continue-statement. */
! tree
finish_continue_stmt ()
{
! return add_stmt (build_continue_stmt ());
}
/* Begin a switch-statement. Returns a new SWITCH_STMT if
*************** finish_compound_stmt (has_no_scope, comp
*** 884,890 ****
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;
--- 890,896 ----
STRING, some OUTPUT_OPERANDS, some INPUT_OPERANDS, and some
CLOBBERS. */
! tree
finish_asm_stmt (cv_qualifier, string, output_operands,
input_operands, clobbers)
tree cv_qualifier;
*************** finish_asm_stmt (cv_qualifier, string, o
*** 914,920 ****
r = build_stmt (ASM_STMT, cv_qualifier, string,
output_operands, input_operands,
clobbers);
! add_stmt (r);
}
/* Finish a label with the indicated NAME. */
--- 920,926 ----
r = build_stmt (ASM_STMT, cv_qualifier, string,
output_operands, input_operands,
clobbers);
! return add_stmt (r);
}
/* Finish a label with the indicated NAME. */