aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog13
-rw-r--r--gcc/cp/cp-tree.h15
-rw-r--r--gcc/cp/decl.c15
-rw-r--r--gcc/cp/parse.y131
-rw-r--r--gcc/cp/semantics.c38
5 files changed, 129 insertions, 83 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9804092..fc473fb 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,16 @@
+2000-12-20 Richard Henderson <rth@redhat.com>
+
+ * 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.
+
2000-12-18 Joseph S. Myers <jsm28@cam.ac.uk>
* cp-tree.h: Don't declare warn_long_long.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d7ede4e..f6d0b82 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3200,7 +3200,6 @@ extern void check_function_format PARAMS ((int *, tree, tree, tree));
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. */
@@ -4291,7 +4290,7 @@ extern void fixup_all_virtual_upcast_offsets PARAMS ((tree));
/* in semantics.c */
extern void init_cp_semantics PARAMS ((void));
-extern void finish_expr_stmt PARAMS ((tree));
+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));
@@ -4304,19 +4303,19 @@ extern void finish_while_stmt PARAMS ((tree));
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 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 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 void finish_case_label PARAMS ((tree, tree));
-extern void finish_goto_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));
@@ -4331,7 +4330,7 @@ extern void finish_handler PARAMS ((tree, tree));
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 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));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 924447f..ab05842 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5158,12 +5158,12 @@ pop_switch ()
/* Note that we've seen a definition of a case label, and complain if this
is a bad place for one. */
-void
+tree
finish_case_label (low_value, high_value)
tree low_value;
tree high_value;
{
- tree cond;
+ tree cond, r;
register struct binding_level *p;
if (! switch_stack)
@@ -5175,7 +5175,7 @@ finish_case_label (low_value, high_value)
low_value);
else
error ("`default' label not within a switch statement");
- return;
+ return NULL_TREE;
}
if (processing_template_decl)
@@ -5185,8 +5185,7 @@ finish_case_label (low_value, high_value)
/* 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;
+ return add_stmt (build_case_label (low_value, high_value, label));
}
/* Find the condition on which this switch statement depends. */
@@ -5194,7 +5193,9 @@ finish_case_label (low_value, high_value)
if (cond && TREE_CODE (cond) == TREE_LIST)
cond = TREE_VALUE (cond);
- c_add_case_label (switch_stack->cases, cond, low_value, high_value);
+ 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);
@@ -5203,6 +5204,8 @@ finish_case_label (low_value, high_value)
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.
diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y
index 4c03dc7..15cf725 100644
--- a/gcc/cp/parse.y
+++ b/gcc/cp/parse.y
@@ -338,7 +338,8 @@ cp_parse_init ()
%type <ttype> maybe_attribute attributes attribute attribute_list attrib
%type <ttype> any_word
-%type <ttype> compstmt implicitly_scoped_stmt
+%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
@@ -1151,14 +1152,15 @@ compstmtend:
;
already_scoped_stmt:
- '{'
- { $<ttype>$ = begin_compound_stmt (1); }
+ save_lineno '{'
+ { $<ttype>$ = begin_compound_stmt (1); }
compstmtend
- { finish_compound_stmt (1, $<ttype>2); }
- | simple_stmt
+ { 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, $$,
@@ -3277,56 +3279,61 @@ label_decl:
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
- { $$ = finish_compound_stmt (0, $<ttype>2); }
+ { STMT_LINENO ($<ttype>3) = $1;
+ finish_compound_stmt (0, $<ttype>3); }
;
simple_if:
IF
- {
- $<ttype>$ = begin_if_stmt ();
- cond_stmt_keyword = "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); }
+ { $$ = $<ttype>2;
+ finish_then_clause ($<ttype>2); }
;
implicitly_scoped_stmt:
compstmt
- | { $<ttype>$ = begin_compound_stmt (0); }
- simple_stmt
- { $$ = finish_compound_stmt (0, $<ttype>1); }
+ |
+ { $<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
- {}
- | simple_stmt
+ | save_lineno simple_stmt
+ { if ($2) STMT_LINENO ($2) = $1; }
;
simple_stmt:
decl
- { finish_stmt (); }
+ { finish_stmt ();
+ $$ = NULL_TREE; }
| expr ';'
- { finish_expr_stmt ($1); }
+ { $$ = finish_expr_stmt ($1); }
| simple_if ELSE
{ begin_else_clause (); }
implicitly_scoped_stmt
{
- finish_else_clause ($<ttype>1);
+ $$ = $1;
+ finish_else_clause ($1);
finish_if_stmt ();
}
| simple_if %prec IF
- { finish_if_stmt (); }
+ { $$ = $1;
+ finish_if_stmt (); }
| WHILE
{
$<ttype>$ = begin_while_stmt ();
@@ -3335,7 +3342,8 @@ simple_stmt:
paren_cond_or_null
{ finish_while_stmt_cond ($3, $<ttype>2); }
already_scoped_stmt
- { finish_while_stmt ($<ttype>2); }
+ { $$ = $<ttype>2;
+ finish_while_stmt ($<ttype>2); }
| DO
{ $<ttype>$ = begin_do_stmt (); }
implicitly_scoped_stmt WHILE
@@ -3344,7 +3352,8 @@ simple_stmt:
cond_stmt_keyword = "do";
}
paren_expr_or_null ';'
- { finish_do_stmt ($6, $<ttype>2); }
+ { $$ = $<ttype>2;
+ finish_do_stmt ($6, $<ttype>2); }
| FOR
{ $<ttype>$ = begin_for_stmt (); }
'(' for.init.statement
@@ -3354,75 +3363,83 @@ simple_stmt:
xexpr ')'
{ finish_for_expr ($9, $<ttype>2); }
already_scoped_stmt
- { finish_for_stmt ($<ttype>2); }
+ { $$ = $<ttype>2;
+ 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); }
+ { $$ = $<ttype>2;
+ finish_switch_stmt ($<ttype>2); }
| CASE expr_no_commas ':'
- { finish_case_label ($2, NULL_TREE); }
+ { $<ttype>$ = finish_case_label ($2, NULL_TREE); }
stmt
+ { $$ = $<ttype>4; }
| CASE expr_no_commas ELLIPSIS expr_no_commas ':'
- { finish_case_label ($2, $4); }
+ { $<ttype>$ = finish_case_label ($2, $4); }
stmt
+ { $$ = $<ttype>6; }
| DEFAULT ':'
- { finish_case_label (NULL_TREE, NULL_TREE); }
+ { $<ttype>$ = finish_case_label (NULL_TREE, NULL_TREE); }
stmt
+ { $$ = $<ttype>3; }
| BREAK ';'
- { finish_break_stmt (); }
+ { $$ = finish_break_stmt (); }
| CONTINUE ';'
- { finish_continue_stmt (); }
+ { $$ = finish_continue_stmt (); }
| RETURN_KEYWORD ';'
- { finish_return_stmt (NULL_TREE); }
+ { $$ = finish_return_stmt (NULL_TREE); }
| RETURN_KEYWORD expr ';'
- { finish_return_stmt ($2); }
+ { $$ = finish_return_stmt ($2); }
| asm_keyword maybe_cv_qualifier '(' string ')' ';'
- {
- finish_asm_stmt ($2, $4, NULL_TREE, NULL_TREE,
- NULL_TREE);
- }
+ { $$ = 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);
- }
+ { $$ = 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 ':' 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); }
+ { $$ = 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); }
+ { $$ = 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); }
+ { $$ = 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); }
+ { $$ = finish_asm_stmt ($2, $4, $6, NULL_TREE, $8); }
| GOTO '*' expr ';'
{
if (pedantic)
pedwarn ("ISO C++ forbids computed gotos");
- finish_goto_stmt ($3);
+ $$ = finish_goto_stmt ($3);
}
| GOTO identifier ';'
- { finish_goto_stmt ($2); }
+ { $$ = finish_goto_stmt ($2); }
| label_colon stmt
+ { $$ = NULL_TREE; }
| label_colon '}'
{ error ("label must be followed by statement");
- yyungetc ('}', 0); }
+ yyungetc ('}', 0);
+ $$ = NULL_TREE; }
| ';'
- { finish_stmt (); }
+ { finish_stmt ();
+ $$ = NULL_TREE; }
| try_block
+ { $$ = NULL_TREE; }
| using_directive
+ { $$ = NULL_TREE; }
| namespace_using_decl
- { do_local_using_decl ($1); }
+ { do_local_using_decl ($1);
+ $$ = NULL_TREE; }
| namespace_alias
+ { $$ = NULL_TREE; }
;
function_try_block:
@@ -3842,6 +3859,14 @@ operator_name:
{ $$ = 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
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 8502eef..856f4ae 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -150,7 +150,7 @@ do_pushlevel ()
/* Finish a goto-statement. */
-void
+tree
finish_goto_stmt (destination)
tree destination;
{
@@ -171,7 +171,7 @@ finish_goto_stmt (destination)
check_goto (destination);
- add_stmt (build_stmt (GOTO_STMT, destination));
+ return add_stmt (build_stmt (GOTO_STMT, destination));
}
/* COND is the condition-expression for an if, while, etc.,
@@ -196,10 +196,12 @@ maybe_convert_cond (cond)
/* Finish an expression-statement, whose EXPRESSION is as indicated. */
-void
+tree
finish_expr_stmt (expr)
tree expr;
{
+ tree r = NULL_TREE;
+
if (expr != NULL_TREE)
{
if (!processing_template_decl
@@ -215,7 +217,7 @@ finish_expr_stmt (expr)
if (!processing_template_decl)
expr = break_out_cleanups (expr);
- add_stmt (build_stmt (EXPR_STMT, expr));
+ r = add_stmt (build_stmt (EXPR_STMT, expr));
}
finish_stmt ();
@@ -223,6 +225,8 @@ finish_expr_stmt (expr)
/* This was an expression-statement, so we save the type of the
expression. */
last_expr_type = expr ? TREE_TYPE (expr) : NULL_TREE;
+
+ return r;
}
@@ -375,10 +379,12 @@ finish_do_stmt (cond, do_stmt)
/* Finish a return-statement. The EXPRESSION returned, if any, is as
indicated. */
-void
+tree
finish_return_stmt (expr)
tree expr;
{
+ tree r;
+
if (!processing_template_decl)
expr = check_return_expr (expr);
if (!processing_template_decl)
@@ -391,8 +397,7 @@ finish_return_stmt (expr)
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;
+ return finish_goto_stmt (ctor_label);
}
else if (DECL_DESTRUCTOR_P (current_function_decl))
{
@@ -400,12 +405,13 @@ finish_return_stmt (expr)
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;
+ return finish_goto_stmt (dtor_label);
}
}
- add_stmt (build_stmt (RETURN_STMT, expr));
+ r = add_stmt (build_stmt (RETURN_STMT, expr));
finish_stmt ();
+
+ return r;
}
/* Begin a for-statement. Returns a new FOR_STMT if appropriate. */
@@ -482,18 +488,18 @@ finish_for_stmt (for_stmt)
/* Finish a break-statement. */
-void
+tree
finish_break_stmt ()
{
- add_stmt (build_break_stmt ());
+ return add_stmt (build_break_stmt ());
}
/* Finish a continue-statement. */
-void
+tree
finish_continue_stmt ()
{
- add_stmt (build_continue_stmt ());
+ return add_stmt (build_continue_stmt ());
}
/* Begin a switch-statement. Returns a new SWITCH_STMT if
@@ -884,7 +890,7 @@ finish_compound_stmt (has_no_scope, compound_stmt)
STRING, some OUTPUT_OPERANDS, some INPUT_OPERANDS, and some
CLOBBERS. */
-void
+tree
finish_asm_stmt (cv_qualifier, string, output_operands,
input_operands, clobbers)
tree cv_qualifier;
@@ -914,7 +920,7 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
r = build_stmt (ASM_STMT, cv_qualifier, string,
output_operands, input_operands,
clobbers);
- add_stmt (r);
+ return add_stmt (r);
}
/* Finish a label with the indicated NAME. */