public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* An x86 patch for egcs
@ 1998-03-12 17:24 H.J. Lu
  1998-03-16 19:46 ` Jim Wilson
  0 siblings, 1 reply; 10+ messages in thread
From: H.J. Lu @ 1998-03-12 17:24 UTC (permalink / raw)
  To: egcs

Hi,

This is a partial patch for the PPro bug I reported. It fixed
loading standard x87 constants in conditional move. But it still
leaves an undefined label in one of my test cases. My other test
case still doesn't compile.

Thanks.


-- 
H.J. Lu (hjl@gnu.org)
--
Thu Mar 12 08:25:19 1998  H.J. Lu  (hjl@gnu.org)

	* config/i386/i386.md (movsfcc_1, movdfcc_1, movxfcc_1): Handle
	loading standard x87 constants.

Index: config/i386/i386.md
===================================================================
RCS file: /home/work/cvs/gnu/egcs/gcc/config/i386/i386.md,v
retrieving revision 1.1.1.8
diff -u -r1.1.1.8 i386.md
--- i386.md	1998/03/12 17:19:11	1.1.1.8
+++ i386.md	1998/03/13 00:12:40
@@ -7528,8 +7529,21 @@
 	output_asm_insn (AS1 (fld%z2,%y2), operands);
       else
         {
-	  operands[2] = XEXP (operands[2], 0);
-	  output_asm_insn (AS1 (fld%z2,%y2), operands);
+	  int conval = standard_80387_constant_p (operands[2]);
+
+	  switch (conval)
+	    {
+	    case 1:
+	      fprintf (asm_out_file, \"\\tfldz\\n\");
+	      break;
+	    case 2:
+	      fprintf (asm_out_file, \"\\tfld1\\n\");
+	      break;
+	    default:
+	      operands[2] = XEXP (operands[2], 0);
+	      output_asm_insn (AS1 (fld%z2,%y2), operands);
+	      break;
+	    }
         }
       output_asm_insn (\"jmp %l1\", xops);
       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0]));
@@ -7537,8 +7551,21 @@
 	  output_asm_insn (AS1 (fld%z3,%y3), operands);
       else
 	{
-	  operands[3] = XEXP (operands[3], 0);
-	  output_asm_insn (AS1 (fld%z3,%y3), operands);
+	  int conval = standard_80387_constant_p (operands[3]);
+
+	  switch (conval)
+	    {
+	    case 1:
+	      fprintf (asm_out_file, \"\\tfldz\\n\");
+	      break;
+	    case 2:
+	      fprintf (asm_out_file, \"\\tfld1\\n\");
+	      break;
+	    default:
+	      operands[3] = XEXP (operands[3], 0);
+	      output_asm_insn (AS1 (fld%z3,%y3), operands);
+	      break;
+	   }
 	}
       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1]));
 }
@@ -7584,8 +7611,21 @@
 	output_asm_insn (AS1 (fld%z2,%y2), operands);
       else
         {
-	  operands[2] = XEXP (operands[2], 0);
-	  output_asm_insn (AS1 (fld%z2,%y2), operands);
+	  int conval = standard_80387_constant_p (operands[2]);
+
+	  switch (conval)
+	    {
+	    case 1:
+	      fprintf (asm_out_file, \"\\tfldz\\n\");
+	      break;
+	    case 2:
+	      fprintf (asm_out_file, \"\\tfld1\\n\");
+	      break;
+	    default:
+	      operands[2] = XEXP (operands[2], 0);
+	      output_asm_insn (AS1 (fld%z2,%y2), operands);
+	      break;
+	    }
         }
       output_asm_insn (\"jmp %l1\", xops);
       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0]));
@@ -7593,8 +7633,21 @@
 	  output_asm_insn (AS1 (fld%z3,%y3), operands);
       else
 	{
-	  operands[3] = XEXP (operands[3], 0);
-	  output_asm_insn (AS1 (fld%z3,%y3), operands);
+	  int conval = standard_80387_constant_p (operands[3]);
+
+	  switch (conval)
+	    {
+	    case 1:
+	      fprintf (asm_out_file, \"\\tfldz\\n\");
+	      break;
+	    case 2:
+	      fprintf (asm_out_file, \"\\tfld1\\n\");
+	      break;
+	    default:
+	      operands[3] = XEXP (operands[3], 0);
+	      output_asm_insn (AS1 (fld%z3,%y3), operands);
+	      break;
+	   }
 	}
       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1]));
 }
@@ -7640,8 +7693,21 @@
 	output_asm_insn (AS1 (fld%z2,%y2), operands);
       else
         {
-	  operands[2] = XEXP (operands[2], 0);
-	  output_asm_insn (AS1 (fld%z2,%y2), operands);
+	  int conval = standard_80387_constant_p (operands[2]);
+
+	  switch (conval)
+	    {
+	    case 1:
+	      fprintf (asm_out_file, \"\\tfldz\\n\");
+	      break;
+	    case 2:
+	      fprintf (asm_out_file, \"\\tfld1\\n\");
+	      break;
+	    default:
+	      operands[2] = XEXP (operands[2], 0);
+	      output_asm_insn (AS1 (fld%z2,%y2), operands);
+	      break;
+	    }
         }
       output_asm_insn (\"jmp %l1\", xops);
       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0]));
@@ -7649,8 +7715,21 @@
 	  output_asm_insn (AS1 (fld%z3,%y3), operands);
       else
 	{
-	  operands[3] = XEXP (operands[3], 0);
-	  output_asm_insn (AS1 (fld%z3,%y3), operands);
+	  int conval = standard_80387_constant_p (operands[3]);
+
+	  switch (conval)
+	    {
+	    case 1:
+	      fprintf (asm_out_file, \"\\tfldz\\n\");
+	      break;
+	    case 2:
+	      fprintf (asm_out_file, \"\\tfld1\\n\");
+	      break;
+	    default:
+	      operands[3] = XEXP (operands[3], 0);
+	      output_asm_insn (AS1 (fld%z3,%y3), operands);
+	      break;
+	   }
 	}
       ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1]));
 }

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: An x86 patch for egcs
       [not found] ` <smtp.earthlink.net>
@ 1998-03-13 18:29   ` H.J. Lu
  1998-03-18 16:14   ` PATCH: add semantics.c Mark Mitchell
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: H.J. Lu @ 1998-03-13 18:29 UTC (permalink / raw)
  To: mmitchell; +Cc: egcs

> This kind of code duplication is a pet peeve of mine; it makes it much
> harder to maintain software, especially software as complex as gcc.
> In general, if you had to change something in several places, then
> there should have been some kind of abstraction (e.g. a macro or a
> function) that would have allowed you to change something in only one
> place.  That might be the fault of the previous author, but it's up to
> us, the current authors, to correct these defects.
> 

Good suggestion. That is also my motivation to cleanup gen*.c. But my
gen*.c patch went nowhere. In the meantime, I have to keep updating my
patch.

I didn't write the original code. I just want to keep my change to
minimum.  Otherwise, it will be a nightmare for me to create a patch
against the egcs CVS since my source tree is quite different from the
official one, especially the 386 backend. Currently my diff against
the egcs CVS is more than 6,000 lines.

BTW, I will see what I can do. There are many more PPro bugs in egcs.


H.J.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: An x86 patch for egcs
       [not found] ` <smtp.earthlink.net>
@ 1998-03-13 18:47 Mark Mitchell
       [not found] ` <smtp.earthlink.net>
  4 siblings, 1 reply; 10+ messages in thread
From: Mark Mitchell @ 1998-03-13 18:47 UTC (permalink / raw)
  To: hjl; +Cc: egcs

    Hi,

    This is a partial patch for the PPro bug I reported. It fixed
    loading standard x87 constants in conditional move. But it still
    leaves an undefined label in one of my test cases. My other test
    case still doesn't compile.

    Thanks.


This is not a commentary on the contents of this patch, merely its
form.  I object strongly to the kind of code-duplication in your
patch.  It appears to me that you replaced each of several similar
pieces of code with some large block of code which is also similar.  I
hope that you did this only because you weren't quite finished with
the patch, and wanted someone to help resolve the remaining problems.

This kind of code duplication is a pet peeve of mine; it makes it much
harder to maintain software, especially software as complex as gcc.
In general, if you had to change something in several places, then
there should have been some kind of abstraction (e.g. a macro or a
function) that would have allowed you to change something in only one
place.  That might be the fault of the previous author, but it's up to
us, the current authors, to correct these defects.

I hereby encourage the maintainers to reject patches that contain
unnecessary duplication, including mine.

    -- 
    H.J. Lu (hjl@gnu.org)
    --
    Thu Mar 12 08:25:19 1998  H.J. Lu  (hjl@gnu.org)

	    * config/i386/i386.md (movsfcc_1, movdfcc_1, movxfcc_1): Handle
	    loading standard x87 constants.

    Index: config/i386/i386.md
    ===================================================================
    RCS file: /home/work/cvs/gnu/egcs/gcc/config/i386/i386.md,v
    retrieving revision 1.1.1.8
    diff -u -r1.1.1.8 i386.md
    --- i386.md	1998/03/12 17:19:11	1.1.1.8
    +++ i386.md	1998/03/13 00:12:40
    @@ -7528,8 +7529,21 @@
	    output_asm_insn (AS1 (fld%z2,%y2), operands);
	   else
	     {
    -	  operands[2] = XEXP (operands[2], 0);
    -	  output_asm_insn (AS1 (fld%z2,%y2), operands);
    +	  int conval = standard_80387_constant_p (operands[2]);
    +
    +	  switch (conval)
    +	    {
    +	    case 1:
    +	      fprintf (asm_out_file, \"\\tfldz\\n\");
    +	      break;
    +	    case 2:
    +	      fprintf (asm_out_file, \"\\tfld1\\n\");
    +	      break;
    +	    default:
    +	      operands[2] = XEXP (operands[2], 0);
    +	      output_asm_insn (AS1 (fld%z2,%y2), operands);
    +	      break;
    +	    }
	     }
	   output_asm_insn (\"jmp %l1\", xops);
	   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0]));
    @@ -7537,8 +7551,21 @@
	      output_asm_insn (AS1 (fld%z3,%y3), operands);
	   else
	    {
    -	  operands[3] = XEXP (operands[3], 0);
    -	  output_asm_insn (AS1 (fld%z3,%y3), operands);
    +	  int conval = standard_80387_constant_p (operands[3]);
    +
    +	  switch (conval)
    +	    {
    +	    case 1:
    +	      fprintf (asm_out_file, \"\\tfldz\\n\");
    +	      break;
    +	    case 2:
    +	      fprintf (asm_out_file, \"\\tfld1\\n\");
    +	      break;
    +	    default:
    +	      operands[3] = XEXP (operands[3], 0);
    +	      output_asm_insn (AS1 (fld%z3,%y3), operands);
    +	      break;
    +	   }

<more deleted>

-- 
Mark Mitchell <mmitchell@usa.net>
http://home.earthlink.net/~mbmitchell
Consulting Services Available

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: An x86 patch for egcs
  1998-03-12 17:24 An x86 patch for egcs H.J. Lu
@ 1998-03-16 19:46 ` Jim Wilson
  0 siblings, 0 replies; 10+ messages in thread
From: Jim Wilson @ 1998-03-16 19:46 UTC (permalink / raw)
  To: H.J. Lu; +Cc: egcs

This patch is wrong as indicated in other mail.

You can not use CONST_DOUBLE_MEM in a md file.

Jim

^ permalink raw reply	[flat|nested] 10+ messages in thread

* PATCH: add semantics.c
       [not found] ` <smtp.earthlink.net>
  1998-03-13 18:29   ` H.J. Lu
@ 1998-03-18 16:14   ` Mark Mitchell
  1998-03-19 21:47   ` PATCH for Re: cp/semantics.c is broken Mark Mitchell
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Mark Mitchell @ 1998-03-18 16:14 UTC (permalink / raw)
  To: Jason Merrill; +Cc: egcs

Jason --

  I've begun the process of separating the process of parsing tokens
from the process of building up semantic information.  As we discussed
before, this has several benefits, including:

  o Making it easier to implement a new parser, whether hand-written
    or machine-generated, since it will be able to use the same
    interface as the current parser.

  o Reducing code duplication (and accompanying inconsistencies!)
    between template instantiation and parsing.

  I've done this work for statements.  As a side-benefit, I've added
the (somewhat frightening) ability to use asm-statements in templates.
(They used to cause a crash.)

  Is this OK?

-- 
Mark Mitchell <mmitchell@usa.net>
http://home.earthlink.net/~mbmitchell
Consulting Services Available

Tue Mar 17 15:09:51 1998  Mark Mitchell  <mmitchell@usa.net>

	* semantics.c: New file, containing routines to perform the
	semantic phase of parsing.
	* parse.y: Use it.
	* pt.c (tsubst_expr): Likewise.
	* cp-tree.h: Declare the various functions in semantics.c.
	Provide macros to access _STMT tree nodes.
	* cp-tree.def: Add ASM_STMT tree node.
	* Makefile.in, Make-lang.in: Add dependencies on and for
	semantics.c.

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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* cp/semantics.c is broken.
@ 1998-03-19 12:55 H.J. Lu
  0 siblings, 0 replies; 10+ messages in thread
From: H.J. Lu @ 1998-03-19 12:55 UTC (permalink / raw)
  To: mmitchell; +Cc: egcs

Hi,

On x86,

# g++ -O2 -B/home/work/gnu/bin/egcs/gcc/    -c cw.cc -o cw.o
cw.cc: In function `double floor(double)':
cw.cc:9: warning: volatile qualifier ignored on asm
cw.cc:11: warning: volatile qualifier ignored on asm
cw.cc: In function `double ceil(double)':
cw.cc:21: warning: volatile qualifier ignored on asm
cw.cc:23: warning: volatile qualifier ignored on asm
/tmp/cca30122.s: Assembler messages:
/tmp/cca30122.s:31: Error: bad register name ('%0')
/tmp/cca30122.s:33: Error: bad register name ('%0')

It is from cp/semantics.c.

Thanks.


-- 
H.J. Lu (hjl@gnu.org)
---cw.cc--
extern "C" { 
__inline  double
floor (double __x)
{
  register double __value;
  __volatile unsigned short int __cw, __cwtmp;
  __asm __volatile ("fnstcw %0" : "=m" (__cw));
  __cwtmp = (__cw & 0xf3ff) | 0x0400;  
  __asm __volatile ("fldcw %0" : : "m" (__cwtmp));
  __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));
  __asm __volatile ("fldcw %0" : : "m" (__cw));
  return __value;
}
__inline  double
ceil (double __x)
{
  register double __value;
  __volatile unsigned short int __cw, __cwtmp;
  __asm __volatile ("fnstcw %0" : "=m" (__cw));
  __cwtmp = (__cw & 0xf3ff) | 0x0800;  
  __asm __volatile ("fldcw %0" : : "m" (__cwtmp));
  __asm __volatile ("frndint" : "=t" (__value) : "0" (__x));
  __asm __volatile ("fldcw %0" : : "m" (__cw));
  return __value;
}
} 
class DiscreteUniform {
    long pLow;
    double delta;
public:
    virtual double operator()();
};
double DiscreteUniform::operator()()
{
    long tmp = long(floor(delta * 2.5));
    return( double(pLow + tmp) );
}

^ permalink raw reply	[flat|nested] 10+ messages in thread

* egcs-1.0.2, egcs-980315 and templates
@ 1998-03-19 12:55 Andrew Pollard
  0 siblings, 0 replies; 10+ messages in thread
From: Andrew Pollard @ 1998-03-19 12:55 UTC (permalink / raw)
  To: egcs

Hi,

 I'm not sure if this is an egcs specific thing or just my
misunderstanding of the latest C++ spec, but the following code
snippet (which was created from a much larger bit of our source code)
has problems with egcs-980315..

-------------------------------------------------------------------------------
template<class K>
struct A {
	int foo(const K&);
	int bar(const K&);
};

template<class K>
int
A<K>::bar(const K& k)
{
#if PROBLEM
	return(foo(k));
#else
	return(0);
#endif
}

#if (__GNUC__ == 2) && (__GNUC_MINOR__ >= 90)
template<>
#endif
int
A<const char*>::foo(const char*const& k)
{
        return((int)k);
}
-------------------------------------------------------------------------------

It compiles fine with egcs-1.0.2 and gcc-2.7.2.2, but with

% gcc -v
Reading specs from /usr/egcs/usr/lib/gcc-lib/i586-pc-linux-gnulibc1/egcs-2.91.14/specs
gcc version egcs-2.91.14 980315 (gcc-2.8.0 release)
% g++ -DPROBLEM -c f.cc
f.cc:23: specialization of A<const char *>::foo<const char *>(const char *const &) after instantiation
f.cc:23: explicit specialization of A<const char *>::foo<const char *>(const char *const &) after first use

but without the -DPROBLEM it compiles

(It compiles with both in egcs-1.0.2 and gcc-2.7.2.2 as well).

From what I could understand from the draft C++ spec, I can't see why
the call to foo(k) in A::bar should instantiate the template and hence
make the specialization invalid.

Can someone tell me what I am missing here?

Cheers,
 Andrew.
--
   Andrew Pollard, Auto Simulations Ltd. UK.    | home: andrew@odie.demon.co.uk
   2 Milbanke Court, Milbanke Way, Bracknell    | work: andrewp@autosim.com
Tel:+44(0)1344 426486x103 Fax:+44(0)1344 426615 | http://www.odie.demon.co.uk



^ permalink raw reply	[flat|nested] 10+ messages in thread

* PATCH for Re: cp/semantics.c is broken.
       [not found] ` <smtp.earthlink.net>
  1998-03-13 18:29   ` H.J. Lu
  1998-03-18 16:14   ` PATCH: add semantics.c Mark Mitchell
@ 1998-03-19 21:47   ` Mark Mitchell
  1998-03-23 15:35   ` PATCH for Re: egcs-1.0.2, egcs-980315 and templates Andrew Pollard
  1998-03-23 19:24   ` Mark Mitchell
  4 siblings, 0 replies; 10+ messages in thread
From: Mark Mitchell @ 1998-03-19 21:47 UTC (permalink / raw)
  To: hjl; +Cc: egcs

Here's a patch.  Jason, is this OK?

-- 
Mark Mitchell <mmitchell@usa.net>
http://home.earthlink.net/~mbmitchell
Consulting Services Available

Thu Mar 19 18:52:38 1998  Mark Mitchell  <mmitchell@usa.net>

	* semantics.c (finish_asm_stmt): Correct mishandling of asm's with
	some omitted fields.

Index: semantics.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/semantics.c,v
retrieving revision 1.1
diff -c -p -r1.1 semantics.c
*** semantics.c	1998/03/18 10:51:59	1.1
--- semantics.c	1998/03/20 02:50:43
*************** finish_asm_stmt (cv_qualifier, string, o
*** 721,727 ****
    else
      {
        emit_line_note (input_filename, lineno);
!       if (output_operands != NULL_TREE)
  	{
  	  if (cv_qualifier != NULL_TREE
  	      && cv_qualifier != ridpointers[(int) RID_VOLATILE])
--- 721,729 ----
    else
      {
        emit_line_note (input_filename, lineno);
!       if (output_operands != NULL_TREE
! 	  || input_operands != NULL_TREE
! 	  || clobbers != NULL_TREE)
  	{
  	  if (cv_qualifier != NULL_TREE
  	      && cv_qualifier != ridpointers[(int) RID_VOLATILE])

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: PATCH for Re: egcs-1.0.2, egcs-980315 and templates
       [not found] ` <smtp.earthlink.net>
                     ` (2 preceding siblings ...)
  1998-03-19 21:47   ` PATCH for Re: cp/semantics.c is broken Mark Mitchell
@ 1998-03-23 15:35   ` Andrew Pollard
  1998-03-23 19:24   ` Mark Mitchell
  4 siblings, 0 replies; 10+ messages in thread
From: Andrew Pollard @ 1998-03-23 15:35 UTC (permalink / raw)
  To: mmitchell; +Cc: egcs

Mark Mitchell <mmitchell@usa.net> wrote:

>Andrew --
>
>  Here's a patch for your problem.  Jason?
>

Just to let you know that this worked fine for me (under egcs-980321).

>From what I could understand from the draft C++ spec, I can't see why
>>the call to foo(k) in A::bar should instantiate the template and hence
>>make the specialization invalid.

Glad to see that I did understand the C++ spec correctly :-)

Cheers,
 Andrew.

>
>Sat Mar 21 19:00:03 1998  Mark Mitchell  <mmitchell@usa.net>
>
>	* pt.c (tsubst): Clear TREE_USED for new FUNCTION_DECLs.
>
>Index: pt.c
>===================================================================
>RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
>retrieving revision 1.101
>diff -c -p -r1.101 pt.c
>*** pt.c	1998/03/20 10:44:05	1.101
>--- pt.c	1998/03/22 02:57:30
>*************** tsubst (t, args, in_decl)
>*** 4063,4068 ****
>--- 4197,4203 ----
>  	TREE_CHAIN (r) = NULL_TREE;
>  	DECL_CHAIN (r) = NULL_TREE;
>  	DECL_PENDING_INLINE_INFO (r) = 0;
>+ 	TREE_USED (r) = 0;
>  
>  	if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
>  	  grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
>Index: spec16.C
>===================================================================
>RCS file: spec16.C
>diff -N spec16.C
>*** /dev/null	Mon Dec 31 20:00:00 1979
>--- spec16.C	Sat Mar 21 19:00:01 1998
>***************
>*** 0 ****
>--- 1,21 ----
>+ // Build don't link:
>+ 
>+ template<class K>
>+ struct A {
>+ 	int foo(const K&);
>+ 	int bar(const K&);
>+ };
>+ 
>+ template<class K>
>+ int
>+ A<K>::bar(const K& k)
>+ {
>+ 	return(foo(k));
>+ }
>+ 
>+ template<>
>+ int
>+ A<const char*>::foo(const char*const& k)
>+ {
>+         return((int)k);
>+ }


^ permalink raw reply	[flat|nested] 10+ messages in thread

* PATCH for Re: egcs-1.0.2, egcs-980315 and templates
       [not found] ` <smtp.earthlink.net>
                     ` (3 preceding siblings ...)
  1998-03-23 15:35   ` PATCH for Re: egcs-1.0.2, egcs-980315 and templates Andrew Pollard
@ 1998-03-23 19:24   ` Mark Mitchell
  4 siblings, 0 replies; 10+ messages in thread
From: Mark Mitchell @ 1998-03-23 19:24 UTC (permalink / raw)
  To: andrew; +Cc: egcs

Andrew --

  Here's a patch for your problem.  Jason?

-- 
Mark Mitchell <mmitchell@usa.net>
http://home.earthlink.net/~mbmitchell
Consulting Services Available

Sat Mar 21 19:00:03 1998  Mark Mitchell  <mmitchell@usa.net>

	* pt.c (tsubst): Clear TREE_USED for new FUNCTION_DECLs.

Index: pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.101
diff -c -p -r1.101 pt.c
*** pt.c	1998/03/20 10:44:05	1.101
--- pt.c	1998/03/22 02:57:30
*************** tsubst (t, args, in_decl)
*** 4063,4068 ****
--- 4197,4203 ----
  	TREE_CHAIN (r) = NULL_TREE;
  	DECL_CHAIN (r) = NULL_TREE;
  	DECL_PENDING_INLINE_INFO (r) = 0;
+ 	TREE_USED (r) = 0;
  
  	if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
  	  grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
Index: spec16.C
===================================================================
RCS file: spec16.C
diff -N spec16.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- spec16.C	Sat Mar 21 19:00:01 1998
***************
*** 0 ****
--- 1,21 ----
+ // Build don't link:
+ 
+ template<class K>
+ struct A {
+ 	int foo(const K&);
+ 	int bar(const K&);
+ };
+ 
+ template<class K>
+ int
+ A<K>::bar(const K& k)
+ {
+ 	return(foo(k));
+ }
+ 
+ template<>
+ int
+ A<const char*>::foo(const char*const& k)
+ {
+         return((int)k);
+ }

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~1998-03-23 19:24 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-03-12 17:24 An x86 patch for egcs H.J. Lu
1998-03-16 19:46 ` Jim Wilson
1998-03-13 18:47 Mark Mitchell
     [not found] ` <smtp.earthlink.net>
1998-03-13 18:29   ` H.J. Lu
1998-03-18 16:14   ` PATCH: add semantics.c Mark Mitchell
1998-03-19 21:47   ` PATCH for Re: cp/semantics.c is broken Mark Mitchell
1998-03-23 15:35   ` PATCH for Re: egcs-1.0.2, egcs-980315 and templates Andrew Pollard
1998-03-23 19:24   ` Mark Mitchell
1998-03-19 12:55 Andrew Pollard
1998-03-19 12:55 cp/semantics.c is broken H.J. Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).