l_lint.c 7.1 KB

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