1989-02-07 11:04:05 +00:00
|
|
|
/*
|
|
|
|
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
|
|
|
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
|
|
|
*/
|
1994-06-27 08:03:14 +00:00
|
|
|
/* $Id$ */
|
1989-02-07 11:04:05 +00:00
|
|
|
/* Lint evaluation order checking */
|
|
|
|
|
2013-05-12 19:45:55 +00:00
|
|
|
#include "parameters.h"
|
1989-02-07 11:04:05 +00:00
|
|
|
|
|
|
|
#ifdef LINT
|
|
|
|
|
|
|
|
#include <alloc.h> /* for st_free */
|
|
|
|
#include "interface.h"
|
|
|
|
#include "assert.h"
|
1990-12-07 14:42:26 +00:00
|
|
|
#ifdef ANSI
|
1989-09-19 16:13:23 +00:00
|
|
|
#include <flt_arith.h>
|
1991-12-17 13:12:22 +00:00
|
|
|
#endif /* ANSI */
|
1989-02-07 11:04:05 +00:00
|
|
|
#include "arith.h" /* definition arith */
|
|
|
|
#include "label.h" /* definition label */
|
|
|
|
#include "expr.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 "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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1991-12-17 13:12:22 +00:00
|
|
|
#endif /* LINT */
|