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".
|
|
|
|
*/
|
|
|
|
/* $Header$ */
|
|
|
|
/* Lint state stack */
|
|
|
|
|
|
|
|
/* These datastructures are used to implement a stack on which the
|
|
|
|
* state of automatic variables (including register variables) is
|
|
|
|
* kept.
|
|
|
|
* In this way it is possible to account for the flow of
|
|
|
|
* control of the program.
|
|
|
|
*/
|
|
|
|
|
1990-12-07 14:42:26 +00:00
|
|
|
#define TEST_VAR 0 /* not a constant */
|
|
|
|
#define TEST_TRUE 1 /* always true */
|
|
|
|
#define TEST_FALSE 2 /* always false */
|
1989-02-07 11:04:05 +00:00
|
|
|
|
1990-12-07 14:42:26 +00:00
|
|
|
struct loop_state { /* used in lint_end_state only */
|
|
|
|
int lps_test; /* is the test a constant? */
|
|
|
|
struct state *lps_body;
|
|
|
|
struct state *lps_loop;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct switch_state { /* used in lint_end_state only */
|
1989-02-07 11:04:05 +00:00
|
|
|
struct state *sws_case;
|
|
|
|
struct state *sws_break;
|
|
|
|
int sws_default_met;
|
|
|
|
};
|
|
|
|
|
1990-12-07 14:42:26 +00:00
|
|
|
/* This union describes the (possibly incomplete) state at the end of the
|
|
|
|
mentioned construct.
|
|
|
|
*/
|
|
|
|
union lint_end_state { /* used in lint_stack_entry only */
|
|
|
|
struct state *ule_if;
|
|
|
|
struct loop_state ule_loop;
|
|
|
|
struct switch_state ule_switch;
|
|
|
|
};
|
|
|
|
|
1989-02-07 11:04:05 +00:00
|
|
|
struct lint_stack_entry {
|
|
|
|
struct lint_stack_entry *next;
|
|
|
|
struct lint_stack_entry *ls_previous;
|
|
|
|
int ls_level;
|
1990-12-07 14:42:26 +00:00
|
|
|
struct state *ls_current; /* used by all classes */
|
|
|
|
short ls_class; /* IF, WHILE, DO, FOR, SWITCH, CASE */
|
|
|
|
union lint_end_state ls_end;
|
1989-02-07 11:04:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* ALLOCDEF "lint_stack_entry" 10 */
|
|
|
|
|
1990-12-07 14:42:26 +00:00
|
|
|
/* macros to access the union */
|
|
|
|
#define LS_IF ls_end.ule_if
|
|
|
|
#define LS_TEST ls_end.ule_loop.lps_test
|
|
|
|
#define LS_BODY ls_end.ule_loop.lps_body
|
|
|
|
#define LS_LOOP ls_end.ule_loop.lps_loop
|
|
|
|
#define LS_CASE ls_end.ule_switch.sws_case
|
|
|
|
#define LS_BREAK ls_end.ule_switch.sws_break
|
|
|
|
#define LS_DEFAULT_MET ls_end.ule_switch.sws_default_met
|
|
|
|
|
|
|
|
/* describes a branch in the program, with its local idfs */
|
1989-02-07 11:04:05 +00:00
|
|
|
struct state {
|
|
|
|
struct state *next; /* only used by memory allocator */
|
|
|
|
struct auto_def *st_auto_list;
|
|
|
|
int st_notreached; /* set if not reached */
|
|
|
|
int st_warned; /* set if warning issued */
|
|
|
|
};
|
|
|
|
|
|
|
|
/* ALLOCDEF "state" 15 */
|
|
|
|
|
1990-12-07 14:42:26 +00:00
|
|
|
/* describes the state of a local idf in a given branch of the program */
|
1989-02-07 11:04:05 +00:00
|
|
|
struct auto_def {
|
|
|
|
struct auto_def *next;
|
|
|
|
struct idf *ad_idf;
|
|
|
|
struct def *ad_def;
|
|
|
|
int ad_used;
|
|
|
|
int ad_set;
|
|
|
|
int ad_maybe_set;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* ALLOCDEF "auto_def" 20 */
|
|
|
|
|
1990-12-07 14:42:26 +00:00
|
|
|
/* describes the state of an idf during expression evaluation */
|
|
|
|
struct expr_state { /*actually concerns idfs only */
|
1989-02-07 11:04:05 +00:00
|
|
|
struct expr_state *next;
|
1990-12-07 14:42:26 +00:00
|
|
|
struct idf *es_idf; /* the idf with its offset */
|
1989-02-07 11:04:05 +00:00
|
|
|
arith es_offset;
|
1990-12-07 14:42:26 +00:00
|
|
|
int es_used; /* value has been used */
|
|
|
|
int es_referred; /* address has been taken */
|
|
|
|
int es_set; /* has been assigned to */
|
1989-02-07 11:04:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* ALLOCDEF "expr_state" 20 */
|
|
|
|
|