Pārlūkot izejas kodu

reorganisation of lint code

dick 36 gadi atpakaļ
vecāks
revīzija
6ac1c9b938

+ 5 - 1
lang/cem/cemcom/Makefile

@@ -418,6 +418,7 @@ ch7bin.o: botch_free.h
 ch7bin.o: expr.h
 ch7bin.o: idf.h
 ch7bin.o: label.h
+ch7bin.o: lint.h
 ch7bin.o: noRoption.h
 ch7bin.o: nobitfield.h
 ch7bin.o: nofloat.h
@@ -891,6 +892,10 @@ l_comment.o: arith.h
 l_comment.o: l_state.h
 l_comment.o: lint.h
 l_comment.o: spec_arith.h
+l_dummy.o: arith.h
+l_dummy.o: label.h
+l_dummy.o: lint.h
+l_dummy.o: spec_arith.h
 tokenfile.o: Lpars.h
 declar.o: LLlex.h
 declar.o: Lpars.h
@@ -946,7 +951,6 @@ expression.o: expr.h
 expression.o: file_info.h
 expression.o: idf.h
 expression.o: label.h
-expression.o: lint.h
 expression.o: noRoption.h
 expression.o: nobitfield.h
 expression.o: nofloat.h

+ 27 - 2
lang/cem/cemcom/ch7bin.c

@@ -8,6 +8,7 @@
 #include	"botch_free.h"
 #include	<alloc.h>
 #include	"nofloat.h"
+#include	"lint.h"
 #include	"idf.h"
 #include	"arith.h"
 #include	"type.h"
@@ -65,6 +66,7 @@ ch7bin(expp, oper, expr)
 		ch7bin(expp, '+', expr);
 		ch7mon('*', expp);
 		break;
+
 	case '(':				/* RM 7.1 */
 		if (	(*expp)->ex_type->tp_fund == POINTER &&
 			(*expp)->ex_type->tp_up->tp_fund == FUNCTION
@@ -86,11 +88,13 @@ ch7bin(expp, oper, expr)
 					*expp, '(', expr);
 		(*expp)->ex_flags |= EX_SIDEEFFECTS;
 		break;
+
 	case PARCOMMA:				/* RM 7.1 */
 		if ((*expp)->ex_type->tp_fund == FUNCTION)
 			function2pointer(*expp);
 		*expp = new_oper(expr->ex_type, *expp, PARCOMMA, expr);
 		break;
+
 	case '%':
 	case MODAB:
 	case ANDAB:
@@ -105,6 +109,7 @@ ch7bin(expp, oper, expr)
 		arithbalance(expp, oper, &expr);
 		non_commutative_binop(expp, oper, expr);
 		break;
+
 	case '&':
 	case '^':
 	case '|':
@@ -115,6 +120,7 @@ ch7bin(expp, oper, expr)
 		arithbalance(expp, oper, &expr);
 		commutative_binop(expp, oper, expr);
 		break;
+
 	case '+':
 		if (expr->ex_type->tp_fund == POINTER)	{ /* swap operands */
 			struct expr *etmp = expr;
@@ -139,6 +145,7 @@ ch7bin(expp, oper, expr)
 				non_commutative_binop(expp, oper, expr);
 		}
 		break;
+
 	case '-':
 	case MINAB:
 	case POSTDECR:
@@ -156,6 +163,7 @@ ch7bin(expp, oper, expr)
 			non_commutative_binop(expp, oper, expr);
 		}
 		break;
+
 	case LEFT:
 	case RIGHT:
 	case LEFTAB:
@@ -166,6 +174,7 @@ ch7bin(expp, oper, expr)
 		ch7cast(&expr, oper, int_type); /* cvt. rightop to int */
 		non_commutative_binop(expp, oper, expr);
 		break;
+
 	case '<':
 	case '>':
 	case LESSEQ:
@@ -176,6 +185,7 @@ ch7bin(expp, oper, expr)
 		non_commutative_binop(expp, oper, expr);
 		(*expp)->ex_type = int_type;
 		break;
+
 	case AND:
 	case OR:
 		opnd2test(expp, oper);
@@ -220,6 +230,7 @@ ch7bin(expp, oper, expr)
 			*expp = new_oper(int_type, *expp, oper, expr);
 		(*expp)->ex_flags |= EX_LOGICAL;
 		break;
+
 	case ':':
 		if (	is_struct_or_union((*expp)->ex_type->tp_fund)
 		||	is_struct_or_union(expr->ex_type->tp_fund)
@@ -229,16 +240,30 @@ ch7bin(expp, oper, expr)
 		}
 		else
 			relbalance(expp, oper, &expr);
+#ifdef	LINT
+		if (	(is_cp_cst(*expp) && is_cp_cst(expr))
+		&&	(*expp)->VL_VALUE == expr->VL_VALUE
+		) {
+			hwarning("operands of : are constant and equal");
+		}
+#endif	LINT
 		*expp = new_oper((*expp)->ex_type, *expp, oper, expr);
 		break;
+
 	case '?':
 		opnd2logical(expp, oper);
-		if (is_cp_cst(*expp))
+		if (is_cp_cst(*expp)) {
+#ifdef	LINT
+			hwarning("condition in ?: expression is constant");
+#endif	LINT
 			*expp = (*expp)->VL_VALUE ?
 				expr->OP_LEFT : expr->OP_RIGHT;
-		else
+		}
+		else {
 			*expp = new_oper(expr->ex_type, *expp, oper, expr);
+		}
 		break;
+
 	case ',':
 		if (is_cp_cst(*expp))
 			*expp = expr;

+ 0 - 1
lang/cem/cemcom/declar.g

@@ -225,7 +225,6 @@ initializer(struct idf *idf; int sc;)
 #endif	DEBUG
 #ifdef	LINT
 			change_state(idf, SET);
-			pre_lint_expr(expr, RVAL, USED);
 #endif	LINT
 			code_declaration(idf, expr, level, sc);
 		}

+ 0 - 5
lang/cem/cemcom/expression.g

@@ -6,7 +6,6 @@
 /*	EXPRESSION SYNTAX PARSER	*/
 
 {
-#include	"lint.h"
 #include	"arith.h"
 #include	"LLlex.h"
 #include	"type.h"
@@ -208,10 +207,6 @@ conditional_expression(struct expr **expp;)
 #endif
 			ch7bin(&e1, ':', e2);
 			opnd2test(expp, '?');
-#ifdef	LINT
-			if (is_cp_cst(*expp))
-				hwarning("condition in ?: is constant");
-#endif	LINT
 			ch7bin(expp, '?', e1);
 		}
 	]?

+ 8 - 2
lang/cem/cemcom/l_dummy.c

@@ -1,10 +1,16 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+
 /*
  *The following functions are hacked to null-functions (i.e. they
  * do nothing). This needs another solution in the future.
  */
 #include	"lint.h"
 
-#ifdef LINT
+#ifdef	LINT
 
 #include	"arith.h"
 #include	"label.h"
@@ -65,4 +71,4 @@ CC_psdnam(ps_xxx,s) char *s; {}
 CC_pspnam(ps_xxx,s) char *s; {}
 /* ARGSUSED */
 CC_scon(v,s) char *s; {}
-#endif LINT
+#endif	LINT

+ 216 - 196
lang/cem/cemcom/l_lint.c

@@ -29,7 +29,9 @@
 extern char options[128];
 extern char *symbol2str();
 
-struct expr_state *lint_expr();
+static struct expr_state *lint_expr();
+static struct expr_state *lint_value();
+static struct expr_state *lint_oper();
 
 lint_init()
 {
@@ -44,6 +46,8 @@ lint_init()
 
 pre_lint_expr(expr, val, used)
 	struct expr *expr;
+	int val;			/* LVAL or RVAL */
+	int used;
 {
 /* Introduced to dispose the returned expression states */
 
@@ -65,9 +69,11 @@ free_expr_states(esp)
 	}
 }
 
-struct expr_state *
+static struct expr_state *
 lint_expr(expr, val, used)
 	register struct expr *expr;
+	int val;
+	int used;
 {
 /* Main function to process an expression tree.
  * It returns a structure containing information about which variables
@@ -77,217 +83,232 @@ lint_expr(expr, val, used)
  * If the value of an operation without side-effects is not used,
  * a warning is given.
  */
-	struct expr_state *esp1 = 0, *esp2 = 0;
-
 	if (used == IGNORED) {
 		expr_ignored(expr);
 	}
 
 	switch (expr->ex_class) {
 	case Value:
-		switch (expr->VL_CLASS) {
-		case Const:
-		case Label:
-			return(0);
-
-		case Name:
-		{
-			register struct idf *idf = expr->VL_IDF;
-
-			if (!idf || !idf->id_def)
-				return(0);
-
-			if (	val == LVAL
-			||	(	val == RVAL
-				&&	expr->ex_type->tp_fund == POINTER
-				&&	!expr->ex_lvalue
-				)
-			) {
-				change_state(idf, SET);
-				idf->id_def->df_file =
-					Salloc(dot.tk_file,
-						strlen(dot.tk_file) + 1);
-				idf->id_def->df_line = dot.tk_line;
-			}
-			if (val == RVAL) {
-				change_state(idf, USED);
-				add_expr_state(expr->EX_VALUE, USED, &esp1);
-			}
-			return(esp1);
-		}
-
-		default:
-			crash("(lint_expr) bad value class\n");
-			/* NOTREACHED */
-		}
+		return lint_value(expr, val);
 
 	case Oper:
+		return lint_oper(expr, val, used);
+
+	default:			/* String Float Type */
+		return 0;
+	}
+}
+
+static struct expr_state *
+lint_value(expr, val)
+	register struct expr *expr;
+{
+	switch (expr->VL_CLASS) {
+	case Const:
+	case Label:
+		return 0;
+
+	case Name:
 	{
-		register int oper = expr->OP_OPER;
-		register struct expr *left = expr->OP_LEFT;
-		register struct expr *right = expr->OP_RIGHT;
+		register struct idf *idf = expr->VL_IDF;
+		struct expr_state *esp1 = 0;
+
+		if (!idf || !idf->id_def)
+			return 0;
+
+		if (	val == LVAL
+		||	(	val == RVAL
+			&&	expr->ex_type->tp_fund == POINTER
+			&&	!expr->ex_lvalue
+			)
+		) {
+			change_state(idf, SET);
+			idf->id_def->df_file =
+				Salloc(dot.tk_file,
+					strlen(dot.tk_file) + 1);
+			idf->id_def->df_line = dot.tk_line;
+		}
+		if (val == RVAL) {
+			change_state(idf, USED);
+			add_expr_state(expr->EX_VALUE, USED, &esp1);
+		}
+		return esp1;
+	}
 
-		switch (oper) {
-		case '=':
-		case PLUSAB:
-		case MINAB:
-		case TIMESAB:
-		case DIVAB:
-		case MODAB:
-		case LEFTAB:
-		case RIGHTAB:
-		case ANDAB:
-		case XORAB:
-		case ORAB:
-			lint_conversion(oper, right->ex_type, left->ex_type);
-			/* for cases like i += l; */
-			esp1 = lint_expr(right, RVAL, USED);
-			if (oper != '=') {
-				/* i += 1; is interpreted as i = i + 1; */
-				esp2 = lint_expr(left, RVAL, USED);
-				check_and_merge(&esp1, esp2, oper);
-			}
-			esp2 = lint_expr(left, LVAL, USED);
-			/* for cases like i = i + 1; and i not set, this
-			** order is essential
-			*/
-			check_and_merge(&esp1, esp2, oper);
-			if (	left->ex_class == Value
-			&&	left->VL_CLASS == Name
-			) {
-				add_expr_state(left->EX_VALUE, SET, &esp1);
-			}
-			return(esp1);
+	default:
+		crash("(lint_expr) bad value class\n");
+		/* NOTREACHED */
+	}
+}
 
-		case POSTINCR:
-		case POSTDECR:
-		case PLUSPLUS:
-		case MINMIN:
-			/* i++; is parsed as i = i + 1;
-			 * This isn't quite correct :
-			 * The first statement doesn't USE i,
-			 * the second does.
-			 */
-			esp1 = lint_expr(left, RVAL, USED);
-			esp2 = lint_expr(left, LVAL, USED);
-			check_and_merge(&esp1, esp2, oper);
-			if (	left->ex_class == Value
-			&&	left->VL_CLASS == Name
-			) {
-				add_expr_state(left->EX_VALUE, SET, &esp1);
-				add_expr_state(left->EX_VALUE, USED, &esp1);
-			}
-			return(esp1);
-
-		case '-':
-		case '*':
-			if (left == 0)	/* unary */
-				return(lint_expr(right, RVAL, USED));
-			esp1 = lint_expr(left, RVAL, USED);
-			esp2 = lint_expr(right, RVAL, USED);
+static struct expr_state *
+lint_oper(expr, val, used)
+	struct expr *expr;
+	int val;
+	int used;
+{
+	register int oper = expr->OP_OPER;
+	register struct expr *left = expr->OP_LEFT;
+	register struct expr *right = expr->OP_RIGHT;
+	struct expr_state *esp1 = 0;
+	struct expr_state *esp2 = 0;
+
+	switch (oper) {
+	case '=':
+	case PLUSAB:
+	case MINAB:
+	case TIMESAB:
+	case DIVAB:
+	case MODAB:
+	case LEFTAB:
+	case RIGHTAB:
+	case ANDAB:
+	case XORAB:
+	case ORAB:
+		lint_conversion(oper, right->ex_type, left->ex_type);
+		/* for cases like i += l; */
+		esp1 = lint_expr(right, RVAL, USED);
+		if (oper != '=') {
+			/* i += 1; is interpreted as i = i + 1; */
+			esp2 = lint_expr(left, RVAL, USED);
 			check_and_merge(&esp1, esp2, oper);
-			return(esp1);
-
-		case '(':
-			if (right != 0) {
-				/* function call with parameters */
-				register struct expr *ex = right;
-
-				while (	ex->ex_class == Oper
-				&&	ex->OP_OPER == PARCOMMA
-				) {
-					esp2 = lint_expr(ex->OP_RIGHT, RVAL,
-							 USED);
-					check_and_merge(&esp1, esp2, oper);
-					ex = ex->OP_LEFT;
-				}
-				esp2 = lint_expr(ex, RVAL, USED);
-				check_and_merge(&esp1, esp2, oper);
-			}
-			if (	left->ex_class == Value
-			&&	left->VL_CLASS == Name
+		}
+		esp2 = lint_expr(left, LVAL, USED);
+		/* for cases like i = i + 1; and i not set, this
+		** order is essential
+		*/
+		check_and_merge(&esp1, esp2, oper);
+		if (	left->ex_class == Value
+		&&	left->VL_CLASS == Name
+		) {
+			add_expr_state(left->EX_VALUE, SET, &esp1);
+		}
+		return esp1;
+
+	case POSTINCR:
+	case POSTDECR:
+	case PLUSPLUS:
+	case MINMIN:
+		/* i++; is parsed as i = i + 1;
+		 * This isn't quite correct :
+		 * The first statement doesn't USE i,
+		 * the second does.
+		 */
+		esp1 = lint_expr(left, RVAL, USED);
+		esp2 = lint_expr(left, LVAL, USED);
+		check_and_merge(&esp1, esp2, oper);
+		if (	left->ex_class == Value
+		&&	left->VL_CLASS == Name
+		) {
+			add_expr_state(left->EX_VALUE, SET, &esp1);
+			add_expr_state(left->EX_VALUE, USED, &esp1);
+		}
+		return esp1;
+
+	case '-':
+	case '*':
+		if (left == 0)	/* unary */
+			return lint_expr(right, RVAL, USED);
+		esp1 = lint_expr(left, RVAL, USED);
+		esp2 = lint_expr(right, RVAL, USED);
+		check_and_merge(&esp1, esp2, oper);
+		return esp1;
+
+	case '(':
+		if (right != 0) {
+			/* function call with parameters */
+			register struct expr *ex = right;
+
+			while (	ex->ex_class == Oper
+			&&	ex->OP_OPER == PARCOMMA
 			) {
-				fill_outcall(expr,
-					expr->ex_type->tp_fund == VOID ?
-					VOIDED : used
-				);
-				outcall();
-				left->VL_IDF->id_def->df_used = 1;
-			}
-			else {
-				esp2 = lint_expr(left, val, USED);
+				esp2 = lint_expr(ex->OP_RIGHT, RVAL,
+						 USED);
 				check_and_merge(&esp1, esp2, oper);
+				ex = ex->OP_LEFT;
 			}
-			return(esp1);
-
-		case '.':
-			return(lint_expr(left, val, USED));
-
-		case ARROW:
-			return(lint_expr(left, RVAL, USED));
-
-		case '~':
-		case '!':
-			return(lint_expr(right, RVAL, USED));
-
-		case '?':
-			esp1 = lint_expr(left, RVAL, USED);
-			esp2 = lint_expr(right->OP_LEFT, RVAL, USED);
-			check_and_merge(&esp1, esp2, 0);
-			esp2 = lint_expr(right->OP_RIGHT, RVAL, USED);
-			check_and_merge(&esp1, esp2, 0);
-			return(esp1);
-
-		case INT2INT:
-		case INT2FLOAT:
-		case FLOAT2INT:
-		case FLOAT2FLOAT:
-			lint_conversion(oper, right->ex_type, left->ex_type);
-			return(lint_expr(right, RVAL, USED));
-
-		case '<':
-		case '>':
-		case LESSEQ:
-		case GREATEREQ:
-		case EQUAL:
-		case NOTEQUAL:
-			lint_relop(left, right, oper);
-			lint_relop(right, left, 
-				oper == '<' ? '>' :
-				oper == '>' ? '<' :
-				oper == LESSEQ ? GREATEREQ :
-				oper == GREATEREQ ? LESSEQ :
-				oper
+			esp2 = lint_expr(ex, RVAL, USED);
+			check_and_merge(&esp1, esp2, oper);
+		}
+		if (	left->ex_class == Value
+		&&	left->VL_CLASS == Name
+		) {
+			fill_outcall(expr,
+				expr->ex_type->tp_fund == VOID ?
+				VOIDED : used
 			);
-			/*FALLTHROUGH*/
-		case '+':
-		case '/':
-		case '%':
-		case ',':
-		case LEFT:
-		case RIGHT:
-		case '&':
-		case '|':
-		case '^':
-		case OR:
-		case AND:
-			esp1 = lint_expr(left, RVAL,
-						oper == ',' ? IGNORED : USED);
-			esp2 = lint_expr(right, RVAL,
-						oper == ',' ? used : USED);
-			if (oper == OR || oper == AND || oper == ',')
-				check_and_merge(&esp1, esp2, 0);
-			else
-				check_and_merge(&esp1, esp2, oper);
-			return(esp1);
-
-		default:
-			return(0);	/* for initcomma */
+			outcall();
+			left->VL_IDF->id_def->df_used = 1;
 		}
-	}
+		else {
+			esp2 = lint_expr(left, val, USED);
+			check_and_merge(&esp1, esp2, oper);
+		}
+		return esp1;
+
+	case '.':
+		return lint_expr(left, val, USED);
+
+	case ARROW:
+		return lint_expr(left, RVAL, USED);
+
+	case '~':
+	case '!':
+		return lint_expr(right, RVAL, USED);
+
+	case '?':
+		esp1 = lint_expr(left, RVAL, USED);
+		esp2 = lint_expr(right->OP_LEFT, RVAL, USED);
+		check_and_merge(&esp1, esp2, 0);
+		esp2 = lint_expr(right->OP_RIGHT, RVAL, USED);
+		check_and_merge(&esp1, esp2, 0);
+		return esp1;
+
+	case INT2INT:
+	case INT2FLOAT:
+	case FLOAT2INT:
+	case FLOAT2FLOAT:
+		lint_conversion(oper, right->ex_type, left->ex_type);
+		return lint_expr(right, RVAL, USED);
+
+	case '<':
+	case '>':
+	case LESSEQ:
+	case GREATEREQ:
+	case EQUAL:
+	case NOTEQUAL:
+		lint_relop(left, right, oper);
+		lint_relop(right, left, 
+			oper == '<' ? '>' :
+			oper == '>' ? '<' :
+			oper == LESSEQ ? GREATEREQ :
+			oper == GREATEREQ ? LESSEQ :
+			oper
+		);
+		/*FALLTHROUGH*/
+	case '+':
+	case '/':
+	case '%':
+	case ',':
+	case LEFT:
+	case RIGHT:
+	case '&':
+	case '|':
+	case '^':
+	case OR:
+	case AND:
+		esp1 = lint_expr(left, RVAL,
+					oper == ',' ? IGNORED : USED);
+		esp2 = lint_expr(right, RVAL,
+					oper == ',' ? used : USED);
+		if (oper == OR || oper == AND || oper == ',')
+			check_and_merge(&esp1, esp2, 0);
+		else
+			check_and_merge(&esp1, esp2, oper);
+		return esp1;
 
 	default:
-		return(0);
+		return 0;	/* for initcomma */
 	}
 }
 
@@ -340,8 +361,7 @@ expr_ignored(expr)
 		hwarning("identifier as statement");
 		break;
 
-	case String:
-	case Float:
+	default:			/* String Float */
 		hwarning("constant as statement");
 		break;
 	}

+ 29 - 15
lang/cem/cemcom/l_states.c

@@ -365,7 +365,7 @@ copy_st_auto_list(from_al, lvl)
 		from_al = from_al->next;
 	}
 
-	return(start);
+	return start;
 }
 
 free_st_auto_list(au)
@@ -392,7 +392,7 @@ copy_state(from_st, lvl)
 	st->st_auto_list = copy_st_auto_list(from_st->st_auto_list, lvl);
 	st->st_notreached = from_st->st_notreached;
 	st->st_warned = from_st->st_warned;
-	return(st);
+	return st;
 }
 
 static
@@ -497,7 +497,7 @@ merge_autos(a1, a2, lvl, mode)
 		crash("(merge_autos) a2 longer than a1");
 		/*NOTREACHED*/
 	}
-	return(a);
+	return a;
 }
 
 merge_states(st1, st2, lvl, mode)
@@ -547,14 +547,15 @@ find_wdf()
 	register struct lint_stack_entry *lse = top_ls;
 
 	while (lse != &stack_bottom) {
-		switch (lse->ls_class)
+		switch (lse->ls_class) {
 		case WHILE:
 		case DO:
 		case FOR:
-			return(lse);
+			return lse;
+		}
 		lse = lse->ls_previous;
 	}
-	return(0);
+	return 0;
 }
 
 struct lint_stack_entry *
@@ -563,15 +564,16 @@ find_wdfc()
 	register struct lint_stack_entry *lse = top_ls;
 
 	while (lse != &stack_bottom) {
-		switch (lse->ls_class)
+		switch (lse->ls_class) {
 		case WHILE:
 		case DO:
 		case FOR:
 		case CASE:
-			return(lse);
+			return lse;
+		}
 		lse = lse->ls_previous;
 	}
-	return(0);
+	return 0;
 }
 
 struct lint_stack_entry *
@@ -580,24 +582,28 @@ find_cs()
 	register struct lint_stack_entry *lse = top_ls;
 
 	while (lse != &stack_bottom) {
-		switch (lse->ls_class)
+		switch (lse->ls_class) {
 		case CASE:
 		case SWITCH:
-			return(lse);
+			return lse;
+		}
 		lse = lse->ls_previous;
 	}
-	return(0);
+	return 0;
 }
 
 /******** A C T I O N S ********/
 
-start_if_part()
+start_if_part(const)
 {
 /* Push a new stack entry on the lint_stack with class == IF
  * copy the ls_current to the top of this stack
  */
 	register struct lint_stack_entry *lse = new_lint_stack_entry();
 
+	if (const)
+		hwarning("condition in if statement is constant");
+
 	lse->ls_class = IF;
 	lse->ls_current = copy_state(top_ls->ls_current, level);
 	lse->ls_level = level;
@@ -685,7 +691,7 @@ end_do_stmt(const, cond)
 {
 	end_loop_stmt();
 	if (const)
-		hwarning("constant do condition");
+		hwarning("condition in do-while statement is constant");
 	if (const && cond && top_ls->ls_current->st_notreached) {
 		/* no break met; this is really an endless loop */
 	}
@@ -718,7 +724,8 @@ lint_continue_stmt()
 	top_ls->ls_current->st_notreached = 1;
 }
 
-start_switch_part()
+start_switch_part(expr)
+	struct expr *expr;
 {
 /* ls_current of a SWITCH entry has different meaning from ls_current of
  * other entries. It keeps track of which variables are used in all
@@ -727,6 +734,13 @@ start_switch_part()
  */
 	register struct lint_stack_entry *lse = new_lint_stack_entry();
 
+	/* the following is a trick to detect a constant
+	 * expression in a switch
+	 */
+	opnd2test(&expr, SWITCH);
+	if (is_cp_cst(expr))
+		hwarning("value in switch statement is constant");
+
 	lse->ls_class = SWITCH;
 	lse->ls_current = copy_state(top_ls->ls_current, level);
 	lse->ls_level = level;

+ 7 - 13
lang/cem/cemcom/statement.g

@@ -144,22 +144,22 @@ if_statement
 				/*	The comparison has been optimized
 					to a 0 or 1.
 				*/
-#ifdef	LINT
-				hwarning("condition in if is constant");
-#endif	LINT
 				if (expr->VL_VALUE == (arith)0)	{
 					C_bra(l_false);
 				}
 				/* else fall through */
+#ifdef	LINT
+				start_if_part(1);
+#endif	LINT
 			}
 			else	{
 				code_expr(expr, RVAL, TRUE, l_true, l_false);
 				C_df_ilb(l_true);
-			}
-			free_expression(expr);
 #ifdef	LINT
-			start_if_part();
+				start_if_part(0);
 #endif	LINT
+			}
+			free_expression(expr);
 		}
 	')'
 	statement
@@ -363,13 +363,7 @@ switch_statement
 		{
 			code_startswitch(&expr);
 #ifdef	LINT
-			start_switch_part();
-			/* the following is a trick to detect a constant
-			 * expression in a switch
-			 */
-			opnd2test(&expr, SWITCH);
-			if (is_cp_cst(expr))
-				hwarning("switch value is constant");
+			start_switch_part(expr);
 #endif	LINT
 		}
 	')'