Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / cemcom.ansi / l_ev_ord.c
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  */
5 /* $Id: l_ev_ord.c,v 1.5 1994/06/27 08:00:49 ceriel Exp $ */
6 /*      Lint evaluation order checking  */
7
8 #include        "lint.h"
9
10 #ifdef  LINT
11
12 #include        <alloc.h>       /* for st_free */
13 #include        "interface.h"
14 #include        "assert.h"
15 #ifdef ANSI
16 #include        <flt_arith.h>
17 #endif /* ANSI */
18 #include        "arith.h"       /* definition arith */
19 #include        "label.h"       /* definition label */
20 #include        "expr.h"
21 #include        "idf.h"
22 #include        "def.h"
23 #include        "code.h"        /* RVAL etc */
24 #include        "LLlex.h"
25 #include        "Lpars.h"
26 #include        "stack.h"
27 #include        "type.h"
28 #include        "level.h"
29 #include        "l_lint.h"
30 #include        "l_state.h"
31
32 extern char *symbol2str();
33
34 PRIVATE check_ev_order();
35
36 check_and_merge(expr, espp, esp)
37         struct expr *expr;
38         struct expr_state **espp, *esp;
39 {
40 /* Checks for undefined evaluation orders in case of a non-sequencing operator.
41  * In addition the sets of used and set variables of both expressions are
42  * united.
43  * *espp will be pointing to this new list. esp is used for this list.
44  */
45         register struct expr_state **pp, *p1, *p2;
46         int oper = expr->OP_OPER;
47         int is_sequencer =
48                 (oper == '?' || oper == OR || oper == AND || oper ==',');
49
50         for (p1 = *espp; p1; p1 = p1->next) {
51                 /* scan the list esp for the same variable */
52                 p2 = esp;
53                 pp = &esp;
54                 while (p2) {
55                         if (    /* p1 and p2 refer to the same location */
56                                 p1->es_idf == p2->es_idf
57                         &&      p1->es_offset == p2->es_offset
58                         ) {
59                                 /* check */
60                                 if (!is_sequencer)
61                                         check_ev_order(p1, p2, expr);
62
63                                 /* merge the info */
64                                 p1->es_used |= p2->es_used;
65                                 p1->es_referred |= p2->es_referred;
66                                 p1->es_set |= p2->es_set;
67
68                                 /* and remove the entry from esp */
69                                 *pp = p2->next;
70                                 free_expr_state(p2);
71                                 p2 = *pp;
72                         }
73                         else {
74                                 /* skip over the entry in esp */
75                                 pp = &p2->next;
76                                 p2 = p2->next;
77                         }
78                 }
79         }
80         /*      If there is anything left in the list esp, this is put in
81                 front of the list *espp is now pointing to, and *espp will be
82                 left pointing to this new list.
83         */
84         if (!esp)
85                 return;
86         p1 = *espp;
87         *espp = esp;
88         while (esp->next)
89                 esp = esp->next;
90         esp->next = p1;
91 }
92
93 PRIVATE
94 check_ev_order(esp1, esp2, expr)
95         struct expr_state *esp1, *esp2;
96         struct expr *expr;
97 {
98         if (    (esp1->es_used && esp2->es_set)
99         ||      (esp1->es_set && esp2->es_used)
100         ||      (esp1->es_set && esp2->es_set)
101         ) {
102                 expr_warning(expr,
103                         "result of %s depends on evaluation order on %s",
104                         symbol2str(expr->OP_OPER),
105                         esp1->es_idf->id_text);
106         }
107 }
108
109 #endif  /* LINT */