107 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			107 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | |
|  * See the copyright notice in the ACK home directory, in the file "Copyright".
 | |
|  */
 | |
| /* $Header$ */
 | |
| /*	Lint evaluation order checking	*/
 | |
| 
 | |
| #include	"lint.h"
 | |
| 
 | |
| #ifdef	LINT
 | |
| 
 | |
| #include	<alloc.h>	/* for st_free */
 | |
| #include	"interface.h"
 | |
| #include	"assert.h"
 | |
| #include	"arith.h"	/* definition arith */
 | |
| #include	"label.h"	/* definition label */
 | |
| #include	"expr.h"
 | |
| #include	"idf.h"
 | |
| #include	"def.h"
 | |
| #include	"code.h"	/* RVAL etc */
 | |
| #include	"LLlex.h"
 | |
| #include	"Lpars.h"
 | |
| #include	"stack.h"
 | |
| #include	"type.h"
 | |
| #include	"level.h"
 | |
| #include	"nofloat.h"
 | |
| #include	"l_lint.h"
 | |
| #include	"l_state.h"
 | |
| 
 | |
| extern char *symbol2str();
 | |
| 
 | |
| PRIVATE check_ev_order();
 | |
| 
 | |
| check_and_merge(expr, espp, esp)
 | |
| 	struct expr *expr;
 | |
| 	struct expr_state **espp, *esp;
 | |
| {
 | |
| /* Checks for undefined evaluation orders in case of a non-sequencing operator.
 | |
|  * In addition the sets of used and set variables of both expressions are
 | |
|  * united.
 | |
|  * *espp will be pointing to this new list. esp is used for this list.
 | |
|  */
 | |
| 	register struct expr_state **pp, *p1, *p2;
 | |
| 	int oper = expr->OP_OPER;
 | |
| 	int is_sequencer =
 | |
| 		(oper == '?' || oper == OR || oper == AND || oper ==',');
 | |
| 
 | |
| 	for (p1 = *espp; p1; p1 = p1->next) {
 | |
| 		/* scan the list esp for the same variable */
 | |
| 		p2 = esp;
 | |
| 		pp = &esp;
 | |
| 		while (p2) {
 | |
| 			if (	/* p1 and p2 refer to the same location */
 | |
| 				p1->es_idf == p2->es_idf
 | |
| 			&&	p1->es_offset == p2->es_offset
 | |
| 			) {
 | |
| 				/* check */
 | |
| 				if (!is_sequencer)
 | |
| 					check_ev_order(p1, p2, expr);
 | |
| 
 | |
| 				/* merge the info */
 | |
| 				p1->es_used |= p2->es_used;
 | |
| 				p1->es_referred |= p2->es_referred;
 | |
| 				p1->es_set |= p2->es_set;
 | |
| 
 | |
| 				/* and remove the entry from esp */
 | |
| 				*pp = p2->next;
 | |
| 				free_expr_state(p2);
 | |
| 				p2 = *pp;
 | |
| 			}
 | |
| 			else {
 | |
| 				/* skip over the entry in esp */
 | |
| 				pp = &p2->next;
 | |
| 				p2 = p2->next;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	/*	If there is anything left in the list esp, this is put in
 | |
| 		front of the list *espp is now pointing to, and *espp will be
 | |
| 		left pointing to this new list.
 | |
| 	*/
 | |
| 	if (!esp)
 | |
| 		return;
 | |
| 	p1 = *espp;
 | |
| 	*espp = esp;
 | |
| 	while (esp->next)
 | |
| 		esp = esp->next;
 | |
| 	esp->next = p1;
 | |
| }
 | |
| 
 | |
| PRIVATE
 | |
| check_ev_order(esp1, esp2, expr)
 | |
| 	struct expr_state *esp1, *esp2;
 | |
| 	struct expr *expr;
 | |
| {
 | |
| 	if (	(esp1->es_used && esp2->es_set)
 | |
| 	||	(esp1->es_set && esp2->es_used)
 | |
| 	||	(esp1->es_set && esp2->es_set)
 | |
| 	) {
 | |
| 		expr_warning(expr,
 | |
| 			"result of %s depends on evaluation order on %s",
 | |
| 			symbol2str(expr->OP_OPER),
 | |
| 			esp1->es_idf->id_text);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| #endif	LINT
 |