Index: compile.c
===================================================================
RCS file: /projects/cvsroot/python/dist/src/Python/compile.c,v
retrieving revision 2.97
diff -c -r2.97 compile.c
*** compile.c	1999/01/28 15:08:09	2.97
--- compile.c	1999/09/04 20:48:05
***************
*** 320,325 ****
--- 320,330 ----
  	int c_stacklevel;	/* Current stack level */
  	int c_maxstacklevel;	/* Maximum stack level */
  	int c_firstlineno;
+ #define R_NORET 1		/* no return */
+ #define R_EXPR 2		/* return expression */
+ #define R_NONE 4		/* return */
+ #define R_RAISE 8		/* raise */
+ 	int c_rettype;		/* how a function is exited */
  	PyObject *c_lnotab;	/* Table mapping address to line number */
  	int c_last_addr, c_last_line, c_lnotab_next;
  #ifdef PRIVATE_NAME_MANGLING
***************
*** 2053,2061 ****
  	if (NCH(n) < 2) {
  		com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
  		com_push(c, 1);
  	}
! 	else
  		com_node(c, CHILD(n, 1));
  	com_addbyte(c, RETURN_VALUE);
  	com_pop(c, 1);
  }
--- 2058,2069 ----
  	if (NCH(n) < 2) {
  		com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
  		com_push(c, 1);
+ 		c->c_rettype = R_NONE;
  	}
! 	else {
  		com_node(c, CHILD(n, 1));
+ 		c->c_rettype = R_EXPR;
+ 	}
  	com_addbyte(c, RETURN_VALUE);
  	com_pop(c, 1);
  }
***************
*** 2078,2083 ****
--- 2086,2092 ----
  	i = NCH(n)/2;
  	com_addoparg(c, RAISE_VARARGS, i);
  	com_pop(c, i);
+ 	c->c_rettype = R_RAISE;
  }
  
  static void
***************
*** 2299,2310 ****
--- 2308,2342 ----
  }
  
  static void
+ com_set_rettype(c, in_rettype, stmt_rettype)
+      struct compiling *c;
+      int in_rettype;
+      int stmt_rettype;
+ {
+ 	/* merge the accumulated return type coming into the statement
+ 	   with the return type generated by the statement */
+ 	if (!(in_rettype & R_NORET))
+ 		/* all branches before this statement led to a return
+ 		   of some type, so the return possibilities of this
+ 		   statement are irrelevant */
+ 		c->c_rettype = in_rettype;
+ 	else
+ 		/* there was at least one path leading to this statement
+ 		   that did not return - merge the return possibilities
+ 		   coming in with the return possibilities from this
+ 		   statement, which might include R_NORET */
+ 		c->c_rettype = (in_rettype & ~R_NORET) | stmt_rettype;
+ }
+ 
+ static void
  com_if_stmt(c, n)
  	struct compiling *c;
  	node *n;
  {
  	int i;
  	int anchor = 0;
+ 	int in_rettype = c->c_rettype;
+ 	int if_rettype = 0;
  	REQ(n, if_stmt);
  	/*'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] */
  	for (i = 0; i+3 < NCH(n); i+=4) {
***************
*** 2318,2331 ****
  		com_addfwref(c, JUMP_IF_FALSE, &a);
  		com_addbyte(c, POP_TOP);
  		com_pop(c, 1);
  		com_node(c, CHILD(n, i+3));
  		com_addfwref(c, JUMP_FORWARD, &anchor);
  		com_backpatch(c, a);
  		/* We jump here with an extra entry which we now pop */
  		com_addbyte(c, POP_TOP);
  	}
! 	if (i+2 < NCH(n))
  		com_node(c, CHILD(n, i+2));
  	if (anchor)
  		com_backpatch(c, anchor);
  }
--- 2350,2373 ----
  		com_addfwref(c, JUMP_IF_FALSE, &a);
  		com_addbyte(c, POP_TOP);
  		com_pop(c, 1);
+ 		c->c_rettype = R_NORET;
  		com_node(c, CHILD(n, i+3));
+ 		if_rettype |= c->c_rettype;
  		com_addfwref(c, JUMP_FORWARD, &anchor);
  		com_backpatch(c, a);
  		/* We jump here with an extra entry which we now pop */
  		com_addbyte(c, POP_TOP);
  	}
! 	if (i+2 < NCH(n)) {
! 		c->c_rettype = R_NORET;
  		com_node(c, CHILD(n, i+2));
+ 		if_rettype |= c->c_rettype;
+ 	}
+ 	else
+ 		/* no else clause - have to consider that we might
+ 		   get here without returning */
+ 		if_rettype |= R_NORET;
+ 	com_set_rettype(c, in_rettype, if_rettype);
  	if (anchor)
  		com_backpatch(c, anchor);
  }
***************
*** 2338,2343 ****
--- 2380,2387 ----
  	int break_anchor = 0;
  	int anchor = 0;
  	int save_begin = c->c_begin;
+ 	int in_rettype = c->c_rettype;
+ 	int while_rettype = 0;
  	REQ(n, while_stmt); /* 'while' test ':' suite ['else' ':' suite] */
  	com_addfwref(c, SETUP_LOOP, &break_anchor);
  	block_push(c, SETUP_LOOP);
***************
*** 2348,2354 ****
--- 2392,2400 ----
  	com_addbyte(c, POP_TOP);
  	com_pop(c, 1);
  	c->c_loops++;
+ 	c->c_rettype = R_NORET;
  	com_node(c, CHILD(n, 3));
+ 	while_rettype = c->c_rettype;
  	c->c_loops--;
  	com_addoparg(c, JUMP_ABSOLUTE, c->c_begin);
  	c->c_begin = save_begin;
***************
*** 2357,2364 ****
  	com_addbyte(c, POP_TOP);
  	com_addbyte(c, POP_BLOCK);
  	block_pop(c, SETUP_LOOP);
! 	if (NCH(n) > 4)
  		com_node(c, CHILD(n, 6));
  	com_backpatch(c, break_anchor);
  }
  
--- 2403,2418 ----
  	com_addbyte(c, POP_TOP);
  	com_addbyte(c, POP_BLOCK);
  	block_pop(c, SETUP_LOOP);
! 	if (NCH(n) > 4) {
! 		c->c_rettype = R_NORET;
  		com_node(c, CHILD(n, 6));
+ 		while_rettype |= c->c_rettype;
+ 	}
+ 	else
+ 		/* no else clause - have to consider that we might
+ 		   never execute the loop body */
+ 		while_rettype |= R_NORET;
+ 	com_set_rettype(c, in_rettype, while_rettype);
  	com_backpatch(c, break_anchor);
  }
  
***************
*** 2371,2376 ****
--- 2425,2432 ----
  	int break_anchor = 0;
  	int anchor = 0;
  	int save_begin = c->c_begin;
+ 	int in_rettype = c->c_rettype;
+ 	int for_rettype = 0;
  	REQ(n, for_stmt);
  	/* 'for' exprlist 'in' exprlist ':' suite ['else' ':' suite] */
  	com_addfwref(c, SETUP_LOOP, &break_anchor);
***************
*** 2388,2394 ****
--- 2444,2452 ----
  	com_push(c, 1);
  	com_assign(c, CHILD(n, 1), OP_ASSIGN);
  	c->c_loops++;
+ 	c->c_rettype = R_NORET;
  	com_node(c, CHILD(n, 5));
+ 	for_rettype = c->c_rettype;
  	c->c_loops--;
  	com_addoparg(c, JUMP_ABSOLUTE, c->c_begin);
  	c->c_begin = save_begin;
***************
*** 2396,2403 ****
  	com_pop(c, 2); /* FOR_LOOP has popped these */
  	com_addbyte(c, POP_BLOCK);
  	block_pop(c, SETUP_LOOP);
! 	if (NCH(n) > 8)
  		com_node(c, CHILD(n, 8));
  	com_backpatch(c, break_anchor);
  }
  
--- 2454,2469 ----
  	com_pop(c, 2); /* FOR_LOOP has popped these */
  	com_addbyte(c, POP_BLOCK);
  	block_pop(c, SETUP_LOOP);
! 	if (NCH(n) > 8) {
! 		c->c_rettype = R_NORET;
  		com_node(c, CHILD(n, 8));
+ 		for_rettype |= c->c_rettype;
+ 	}
+ 	else
+ 		/* no else clause - have to consider that we might
+ 		   never execute the loop body */
+ 		for_rettype |= R_NORET;
+ 	com_set_rettype(c, in_rettype, for_rettype);
  	com_backpatch(c, break_anchor);
  }
  
***************
*** 2477,2486 ****
--- 2543,2557 ----
  	int else_anchor = 0;
  	int i;
  	node *ch;
+ 	int in_rettype = c->c_rettype;
+ 	int try_rettype = 0;
+ 	int tryclause_rettype = 0;
  
  	com_addfwref(c, SETUP_EXCEPT, &except_anchor);
  	block_push(c, SETUP_EXCEPT);
+ 	c->c_rettype = R_NORET;
  	com_node(c, CHILD(n, 2));
+ 	tryclause_rettype = c->c_rettype;
  	com_addbyte(c, POP_BLOCK);
  	block_pop(c, SETUP_EXCEPT);
  	com_addfwref(c, JUMP_FORWARD, &else_anchor);
***************
*** 2517,2523 ****
--- 2588,2596 ----
  		}
  		com_addbyte(c, POP_TOP);
  		com_pop(c, 1);
+ 		c->c_rettype = R_NORET;
  		com_node(c, CHILD(n, i+2));
+ 		try_rettype |= c->c_rettype;
  		com_addfwref(c, JUMP_FORWARD, &end_anchor);
  		if (except_anchor) {
  			com_backpatch(c, except_anchor);
***************
*** 2533,2540 ****
  	   anything. */
  	com_addbyte(c, END_FINALLY);
  	com_backpatch(c, else_anchor);
! 	if (i < NCH(n))
  		com_node(c, CHILD(n, i+2));
  	com_backpatch(c, end_anchor);
  }
  
--- 2606,2622 ----
  	   anything. */
  	com_addbyte(c, END_FINALLY);
  	com_backpatch(c, else_anchor);
! 	if (i < NCH(n)) {
! 		/* pick up with the return stuff where the try clause ended */
! 		c->c_rettype = tryclause_rettype;
  		com_node(c, CHILD(n, i+2));
+ 		try_rettype |= c->c_rettype;
+ 	}
+ 	else
+ 		/* no else clause - just merge try clause return info
+ 		   with return info from all the except clauses */
+ 		try_rettype |= tryclause_rettype;
+ 	com_set_rettype(c, in_rettype, try_rettype);
  	com_backpatch(c, end_anchor);
  }
  
***************
*** 2545,2554 ****
--- 2627,2640 ----
  {
  	int finally_anchor = 0;
  	node *ch;
+ 	int in_rettype = c->c_rettype;
+ 	int try_rettype = 0;
  
  	com_addfwref(c, SETUP_FINALLY, &finally_anchor);
  	block_push(c, SETUP_FINALLY);
+ 	c->c_rettype = R_NORET;
  	com_node(c, CHILD(n, 2));
+ 	try_rettype = c->c_rettype;
  	com_addbyte(c, POP_BLOCK);
  	block_pop(c, SETUP_FINALLY);
  	block_push(c, END_FINALLY);
***************
*** 2561,2570 ****
--- 2647,2661 ----
  	com_backpatch(c, finally_anchor);
  	ch = CHILD(n, NCH(n)-1);
  	com_addoparg(c, SET_LINENO, ch->n_lineno);
+ 	/* shouldn't start with R_NORET, because it's essentially
+ 	   the tail end of the try clause */
+ 	c->c_rettype = 0;
  	com_node(c, ch);
+ 	try_rettype |= c->c_rettype;
  	com_addbyte(c, END_FINALLY);
  	block_pop(c, END_FINALLY);
  	com_pop(c, 3); /* Matches the com_push above */
+ 	com_set_rettype(c, in_rettype, try_rettype);
  }
  
  static void
***************
*** 2886,2891 ****
--- 2977,2984 ----
  				  "'break' outside loop");
  		}
  		com_addbyte(c, BREAK_LOOP);
+ 		/* else clause wouldn't get executed, so R_NORET is possible */
+ 		c->c_rettype = R_NORET;
  		break;
  	case continue_stmt:
  		com_continue_stmt(c, n);
***************
*** 3156,3167 ****
--- 3249,3267 ----
  	if (TYPE(ch) == varargslist)
  		com_arglist(c, ch);
  	c->c_infunction = 1;
+ 	c->c_rettype = R_NORET;
  	com_node(c, CHILD(n, 4));
  	c->c_infunction = 0;
  	com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
  	com_push(c, 1);
  	com_addbyte(c, RETURN_VALUE);
  	com_pop(c, 1);
+ 	com_set_rettype(c, c->c_rettype, R_NONE);
+ 	if ((c->c_rettype & R_NONE) && (c->c_rettype & R_EXPR)) {
+ 		PySys_WriteStderr("warning: File \"%s\", line %d: %s",
+ 				  c->c_filename, c->c_lineno, c->c_name);
+ 		PySys_WriteStderr(" has \"return\" and \"return expr\"\n");
+ 	}
  }
  
  static void
