l_lint.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  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. /* $Header$ */
  6. /* Lint main routines */
  7. #include "lint.h"
  8. #ifdef LINT
  9. #include <alloc.h> /* for st_free */
  10. #include "arith.h" /* definition arith */
  11. #include "label.h" /* definition label */
  12. #include "expr.h"
  13. #include "idf.h"
  14. #include "def.h"
  15. #include "code.h" /* RVAL etc */
  16. #include "LLlex.h"
  17. #include "Lpars.h"
  18. #include "stack.h"
  19. #include "type.h"
  20. #include "level.h"
  21. #include "nofloat.h"
  22. #include "l_lint.h"
  23. #include "l_state.h"
  24. #include "l_outdef.h"
  25. extern char options[128];
  26. extern char *symbol2str();
  27. static struct expr_state *lint_expr();
  28. static struct expr_state *lint_value();
  29. static struct expr_state *lint_oper();
  30. lint_init()
  31. {
  32. /* Allocate some memory for the global stack_bottom
  33. * and some other initializations
  34. */
  35. extern struct lint_stack_entry stack_bottom;
  36. stack_bottom.ls_current = new_state();
  37. }
  38. pre_lint_expr(expr, val, used)
  39. struct expr *expr;
  40. int val; /* LVAL or RVAL */
  41. int used;
  42. {
  43. /* Introduced to dispose the returned expression states */
  44. register struct expr_state *esp;
  45. esp = lint_expr(expr, val, used);
  46. free_expr_states(esp);
  47. }
  48. free_expr_states(esp)
  49. register struct expr_state *esp;
  50. {
  51. register struct expr_state *esp2;
  52. while (esp) {
  53. esp2 = esp;
  54. esp = esp->next;
  55. free_expr_state(esp2);
  56. }
  57. }
  58. static struct expr_state *
  59. lint_expr(expr, val, used)
  60. register struct expr *expr;
  61. int val;
  62. int used;
  63. {
  64. /* Main function to process an expression tree.
  65. * It returns a structure containing information about which variables
  66. * are set and which are used in the expression.
  67. * In addition it sets 'used' and 'set' fields of the corresponding
  68. * variables in the current state.
  69. * If the value of an operation without side-effects is not used,
  70. * a warning is given.
  71. */
  72. if (used == IGNORED) {
  73. expr_ignored(expr);
  74. }
  75. switch (expr->ex_class) {
  76. case Value:
  77. return lint_value(expr, val);
  78. case Oper:
  79. return lint_oper(expr, val, used);
  80. default: /* String Float Type */
  81. return 0;
  82. }
  83. }
  84. static struct expr_state *
  85. lint_value(expr, val)
  86. register struct expr *expr;
  87. {
  88. switch (expr->VL_CLASS) {
  89. case Const:
  90. case Label:
  91. return 0;
  92. case Name:
  93. {
  94. register struct idf *idf = expr->VL_IDF;
  95. struct expr_state *esp1 = 0;
  96. if (!idf || !idf->id_def)
  97. return 0;
  98. if ( val == LVAL
  99. || ( val == RVAL
  100. && expr->ex_type->tp_fund == POINTER
  101. && !expr->ex_lvalue
  102. )
  103. ) {
  104. change_state(idf, SET);
  105. idf->id_def->df_file =
  106. Salloc(dot.tk_file,
  107. strlen(dot.tk_file) + 1);
  108. idf->id_def->df_line = dot.tk_line;
  109. }
  110. if (val == RVAL) {
  111. change_state(idf, USED);
  112. add_expr_state(expr->EX_VALUE, USED, &esp1);
  113. }
  114. return esp1;
  115. }
  116. default:
  117. crash("(lint_expr) bad value class\n");
  118. /* NOTREACHED */
  119. }
  120. }
  121. static struct expr_state *
  122. lint_oper(expr, val, used)
  123. struct expr *expr;
  124. int val;
  125. int used;
  126. {
  127. register int oper = expr->OP_OPER;
  128. register struct expr *left = expr->OP_LEFT;
  129. register struct expr *right = expr->OP_RIGHT;
  130. struct expr_state *esp1 = 0;
  131. struct expr_state *esp2 = 0;
  132. switch (oper) {
  133. case '=':
  134. case PLUSAB:
  135. case MINAB:
  136. case TIMESAB:
  137. case DIVAB:
  138. case MODAB:
  139. case LEFTAB:
  140. case RIGHTAB:
  141. case ANDAB:
  142. case XORAB:
  143. case ORAB:
  144. lint_conversion(oper, right->ex_type, left->ex_type);
  145. /* for cases like i += l; */
  146. esp1 = lint_expr(right, RVAL, USED);
  147. if (oper != '=') {
  148. /* i += 1; is interpreted as i = i + 1; */
  149. esp2 = lint_expr(left, RVAL, USED);
  150. check_and_merge(&esp1, esp2, oper);
  151. }
  152. esp2 = lint_expr(left, LVAL, USED);
  153. /* for cases like i = i + 1; and i not set, this
  154. ** order is essential
  155. */
  156. check_and_merge(&esp1, esp2, oper);
  157. if ( left->ex_class == Value
  158. && left->VL_CLASS == Name
  159. ) {
  160. add_expr_state(left->EX_VALUE, SET, &esp1);
  161. }
  162. return esp1;
  163. case POSTINCR:
  164. case POSTDECR:
  165. case PLUSPLUS:
  166. case MINMIN:
  167. /* i++; is parsed as i = i + 1;
  168. * This isn't quite correct :
  169. * The first statement doesn't USE i,
  170. * the second does.
  171. */
  172. esp1 = lint_expr(left, RVAL, USED);
  173. esp2 = lint_expr(left, LVAL, USED);
  174. check_and_merge(&esp1, esp2, oper);
  175. if ( left->ex_class == Value
  176. && left->VL_CLASS == Name
  177. ) {
  178. add_expr_state(left->EX_VALUE, SET, &esp1);
  179. add_expr_state(left->EX_VALUE, USED, &esp1);
  180. }
  181. return esp1;
  182. case '-':
  183. case '*':
  184. if (left == 0) /* unary */
  185. return lint_expr(right, RVAL, USED);
  186. esp1 = lint_expr(left, RVAL, USED);
  187. esp2 = lint_expr(right, RVAL, USED);
  188. check_and_merge(&esp1, esp2, oper);
  189. return esp1;
  190. case '(':
  191. if (right != 0) {
  192. /* function call with parameters */
  193. register struct expr *ex = right;
  194. while ( ex->ex_class == Oper
  195. && ex->OP_OPER == PARCOMMA
  196. ) {
  197. esp2 = lint_expr(ex->OP_RIGHT, RVAL,
  198. USED);
  199. check_and_merge(&esp1, esp2, oper);
  200. ex = ex->OP_LEFT;
  201. }
  202. esp2 = lint_expr(ex, RVAL, USED);
  203. check_and_merge(&esp1, esp2, oper);
  204. }
  205. if ( left->ex_class == Value
  206. && left->VL_CLASS == Name
  207. ) {
  208. fill_outcall(expr,
  209. expr->ex_type->tp_fund == VOID ?
  210. VOIDED : used
  211. );
  212. outcall();
  213. left->VL_IDF->id_def->df_used = 1;
  214. }
  215. else {
  216. esp2 = lint_expr(left, val, USED);
  217. check_and_merge(&esp1, esp2, oper);
  218. }
  219. return esp1;
  220. case '.':
  221. return lint_expr(left, val, USED);
  222. case ARROW:
  223. return lint_expr(left, RVAL, USED);
  224. case '~':
  225. case '!':
  226. return lint_expr(right, RVAL, USED);
  227. case '?':
  228. esp1 = lint_expr(left, RVAL, USED);
  229. esp2 = lint_expr(right->OP_LEFT, RVAL, USED);
  230. check_and_merge(&esp1, esp2, 0);
  231. esp2 = lint_expr(right->OP_RIGHT, RVAL, USED);
  232. check_and_merge(&esp1, esp2, 0);
  233. return esp1;
  234. case INT2INT:
  235. case INT2FLOAT:
  236. case FLOAT2INT:
  237. case FLOAT2FLOAT:
  238. lint_conversion(oper, right->ex_type, left->ex_type);
  239. return lint_expr(right, RVAL, USED);
  240. case '<':
  241. case '>':
  242. case LESSEQ:
  243. case GREATEREQ:
  244. case EQUAL:
  245. case NOTEQUAL:
  246. lint_relop(left, right, oper);
  247. lint_relop(right, left,
  248. oper == '<' ? '>' :
  249. oper == '>' ? '<' :
  250. oper == LESSEQ ? GREATEREQ :
  251. oper == GREATEREQ ? LESSEQ :
  252. oper
  253. );
  254. /*FALLTHROUGH*/
  255. case '+':
  256. case '/':
  257. case '%':
  258. case ',':
  259. case LEFT:
  260. case RIGHT:
  261. case '&':
  262. case '|':
  263. case '^':
  264. case OR:
  265. case AND:
  266. esp1 = lint_expr(left, RVAL,
  267. oper == ',' ? IGNORED : USED);
  268. esp2 = lint_expr(right, RVAL,
  269. oper == ',' ? used : USED);
  270. if (oper == OR || oper == AND || oper == ',')
  271. check_and_merge(&esp1, esp2, 0);
  272. else
  273. check_and_merge(&esp1, esp2, oper);
  274. return esp1;
  275. default:
  276. return 0; /* for initcomma */
  277. }
  278. }
  279. expr_ignored(expr)
  280. struct expr *expr;
  281. {
  282. switch (expr->ex_class) {
  283. case Oper:
  284. switch (expr->OP_OPER) {
  285. case '=':
  286. case TIMESAB:
  287. case DIVAB:
  288. case MODAB:
  289. case LEFTAB:
  290. case RIGHTAB:
  291. case ANDAB:
  292. case XORAB:
  293. case ORAB:
  294. case AND: /* doubtful but useful */
  295. case OR: /* doubtful but useful */
  296. case '(':
  297. case '?':
  298. case ',':
  299. break;
  300. case PLUSAB:
  301. case MINAB:
  302. case POSTINCR:
  303. case POSTDECR:
  304. case PLUSPLUS:
  305. case MINMIN:
  306. /* may hide the operator * */
  307. if ( /* operation on a pointer */
  308. expr->OP_TYPE->tp_fund == POINTER
  309. && /* the result is dereferenced, e.g. *p++; */
  310. expr->ex_type == expr->OP_TYPE->tp_up
  311. ) {
  312. hwarning("result of * ignored");
  313. }
  314. break;
  315. default:
  316. hwarning("result of %s ignored",
  317. symbol2str(expr->OP_OPER));
  318. break;
  319. }
  320. break;
  321. case Value:
  322. hwarning("identifier as statement");
  323. break;
  324. default: /* String Float */
  325. hwarning("constant as statement");
  326. break;
  327. }
  328. }
  329. #endif LINT