]> andersk Git - splint.git/blame - src/exprNode.c
Lots of changes. Code is mostly annotated. Still lots of breaken stuff though.
[splint.git] / src / exprNode.c
CommitLineData
616915dd 1/*
2** LCLint - annotation-assisted static program checker
3** Copyright (C) 1994-2000 University of Virginia,
4** Massachusetts Institute of Technology
5**
6** This program is free software; you can redistribute it and/or modify it
7** under the terms of the GNU General Public License as published by the
8** Free Software Foundation; either version 2 of the License, or (at your
9** option) any later version.
10**
11** This program is distributed in the hope that it will be useful, but
12** WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14** General Public License for more details.
15**
16** The GNU General Public License is available from http://www.gnu.org/ or
17** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18** MA 02111-1307, USA.
19**
20** For information on lclint: lclint-request@cs.virginia.edu
21** To report a bug: lclint-bug@cs.virginia.edu
22** For more information: http://lclint.cs.virginia.edu
23*/
24/*
25** exprNode.c
26*/
27
28# include <ctype.h> /* for isdigit */
29# include "lclintMacros.nf"
30# include "basic.h"
31# include "cgrammar.h"
32# include "cgrammar_tokens.h"
33
34# include "exprChecks.h"
35# include "aliasChecks.h"
36# include "exprNodeSList.h"
37# include "exprData.i"
38
39static bool exprNode_isEmptyStatement (exprNode p_e);
40static /*@exposed@*/ exprNode exprNode_firstStatement (/*@returned@*/ exprNode p_e);
41static bool exprNode_isFalseConstant (exprNode p_e) /*@*/ ;
42static bool exprNode_isBlock (exprNode p_e);
43static void checkGlobUse (uentry p_glob, bool p_isCall, /*@notnull@*/ exprNode p_e);
44static void exprNode_addUse (exprNode p_e, sRef p_s);
45static bool exprNode_matchArgType (ctype p_ct, exprNode p_e);
84c9ffbf 46
616915dd 47static exprNode exprNode_statementError (/*@only@*/ exprNode p_e, /*@only@*/ lltok p_t);
48static bool exprNode_matchTypes (exprNode p_e1, exprNode p_e2);
49static void checkUniqueParams (exprNode p_fcn,
50 /*@notnull@*/ exprNode p_current, exprNodeList p_args,
51 int p_paramno, uentry p_ucurrent);
52static void updateAliases (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2);
53static void abstractOpError (ctype p_tr1, ctype p_tr2, lltok p_op,
54 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2,
55 fileloc p_loc1, fileloc p_loc2);
56static ctype checkNumerics (ctype p_tr1, ctype p_tr2, ctype p_te1, ctype p_te2,
57 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, lltok p_op);
58static void doAssign (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, bool p_isInit);
59static void checkSafeUse (exprNode p_e, sRef p_s);
60static void reflectNullTest (/*@notnull@*/ exprNode p_e, bool p_isnull);
61static void checkMacroParen (exprNode p_e);
62static exprNodeSList exprNode_flatten (/*@dependent@*/ exprNode p_e);
63static void exprNode_checkSetAny (exprNode p_e, /*@dependent@*/ cstring p_name);
64static void exprNode_checkUse (exprNode p_e, sRef p_s, fileloc p_loc);
65static void exprNode_mergeUSs (exprNode p_res, exprNode p_other);
66static void exprNode_mergeCondUSs (exprNode p_res, exprNode p_other1, exprNode p_other2);
67static /*@only@*/ /*@notnull@*/ exprNode exprNode_fromIdentifierAux (/*@observer@*/ uentry p_c);
68static void checkAnyCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn,
69 /*@dependent@*/ cstring p_fname,
70 uentryList p_pn, exprNodeList p_args,
71 bool p_hasMods, sRefSet p_mods, bool p_isSpec,
72 int p_specialArgs);
73static void checkOneArg (uentry p_ucurrent, /*@notnull@*/ exprNode p_current,
74 /*@dependent@*/ exprNode p_fcn, bool p_isSpec, int p_argno, int p_totargs);
75static void
76 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn, uentryList p_params, exprNodeList p_args);
77
78static /*@only@*/ exprNode exprNode_effect (exprNode p_e)
79 /*@globals internalState@*/ ;
80static /*@only@*/ cstring exprNode_doUnparse (exprNode p_e);
81static /*@observer@*/ cstring exprNode_rootVarName (exprNode p_e);
82static /*@exposed@*/ exprNode
83 exprNode_lastStatement (/*@returned@*/ exprNode p_e);
84
85static /*@null@*/ sRef defref = sRef_undefined;
86static /*@only@*/ exprNode mustExitNode = exprNode_undefined;
87
88static int checkArgsReal (uentry p_fcn, /*@dependent@*/ exprNode p_f,
89 uentryList p_cl,
90 exprNodeList p_args, bool p_isIter, exprNode p_ret);
91
92static bool inEffect = FALSE;
93static int nowalloc = 0;
94static int totalloc = 0;
95static int maxalloc = 0;
96
97static /*@only@*/ uentry regArg;
98static /*@only@*/ uentry outArg;
99static /*@only@*/ uentry outStringArg;
100static /*@exposed@*/ sRef stdinRef;
101static /*@exposed@*/ sRef stdoutRef;
102static /*@only@*/ uentry csArg;
103static /*@only@*/ uentry csOnlyArg;
104static ctype cstringType;
105static ctype ctypeType;
106static ctype filelocType;
107static bool initMod = FALSE;
108
8ac07c2e 109# define exprNode_defineConstraints(e) { \
84c9ffbf 110 (e)->requiresConstraints = constraintList_makeNew(); \
111 (e)->ensuresConstraints = constraintList_makeNew(); \
112 (e)->trueEnsuresConstraints = constraintList_makeNew(); \
113 (e)->falseEnsuresConstraints = constraintList_makeNew(); }
114
616915dd 115/*
116** must occur after library has been read
117*/
118
119void exprNode_initMod (void)
120 /*@globals undef regArg, undef outArg, undef outStringArg,
121 undef csOnlyArg, undef csArg;
122 @*/
123{
124 uentry ue;
125 idDecl tmp;
126
127 initMod = TRUE;
128 cstringType = ctype_unknown;
129 ctypeType = ctype_unknown;
130 filelocType = ctype_unknown;
131
132 defref = sRef_undefined;
133
134 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
135 {
136 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
137 }
138
139 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
140 {
141 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
142 }
143
144 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
145 {
146 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
147 }
148
149 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdin")))
150 {
151 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdin"));
152 }
153 else /* define stdin */
154 {
155 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdin"),
156 ctype_unknown,
157 fileloc_getBuiltin (),
158 FALSE);
159 uentry_setHasNameError (ue);
160 ue = usymtab_supGlobalEntryReturn (ue);
161 }
162
163 stdinRef = sRef_makePointer (uentry_getSref (ue));
164
165 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdout")))
166 {
167 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdout"));
168 }
169 else
170 {
171 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdout"),
172 ctype_unknown,
173 fileloc_getBuiltin (),
174 FALSE);
175 uentry_setHasNameError (ue);
176 ue = usymtab_supGlobalEntryReturn (ue);
177 }
178
179 stdoutRef = sRef_makePointer (uentry_getSref (ue));
180
181 tmp = idDecl_create (cstring_undefined, qtype_create (ctype_unknown));
182
183 regArg = uentry_makeParam (tmp, PARAMUNKNOWN);
184
185 idDecl_setTyp (tmp,
186 qtype_addQual (qtype_create (ctype_makePointer (ctype_unknown)),
187 qual_createOut ()));
188
189 outArg = uentry_makeParam (tmp, PARAMUNKNOWN);
190
191 idDecl_setTyp (tmp, qtype_addQual (qtype_create (ctype_string),
192 qual_createOut ()));
193
194 outStringArg = uentry_makeParam (tmp, PARAMUNKNOWN);
195
196 idDecl_setTyp (tmp, qtype_addQual (qtype_addQual (qtype_create (cstringType),
197 qual_createOnly ()),
198 qual_createNull ()));
199
200 csOnlyArg = uentry_makeParam (tmp, PARAMUNKNOWN);
201
202 idDecl_setTyp (tmp, qtype_addQual (qtype_create (cstringType), qual_createNull ()));
203 csArg = uentry_makeParam (tmp, PARAMUNKNOWN);
204
205 idDecl_free (tmp);
206}
207
208void
209exprNode_destroyMod (void)
210 /*@globals killed regArg, killed outArg, killed outStringArg,
211 killed mustExitNode, initMod @*/
212{
213 if (initMod)
214 {
215 uentry_free (regArg);
216 uentry_free (outArg);
217 uentry_free (outStringArg);
218
219 exprNode_free (mustExitNode);
220 initMod = FALSE;
221 /*@-branchstate@*/
222 }
223 /*@=branchstate@*/
224}
225
226static void exprNode_resetSref (/*@notnull@*/ exprNode e)
227{
228 e->sref = defref;
229}
230
616915dd 231static bool isFlagKey (char key)
232{
233 return (key == '-' || key == '+' || key == ' ' || key == '#');
234}
235
236static void exprNode_combineControl (/*@notnull@*/ exprNode ret,
237 /*@notnull@*/ exprNode ifclause,
238 /*@notnull@*/ exprNode elseclause)
239{
240 ret->canBreak = ifclause->canBreak || elseclause->canBreak;
241
242 ret->mustBreak =
243 (ifclause->mustBreak || exprNode_mustEscape (ifclause))
244 && (elseclause->mustBreak || exprNode_mustEscape (elseclause));
245
246 ret->exitCode = exitkind_combine (ifclause->exitCode,
247 elseclause->exitCode);
248
249}
250
251/*
252** For exprNode's returned by exprNode_effect.
253*/
254
255static bool shallowKind (exprKind kind)
256{
257 return (kind == XPR_STRINGLITERAL
258 || kind == XPR_NUMLIT
259 || kind == XPR_EMPTY
260 || kind == XPR_BODY
261 || kind == XPR_NODE);
262}
263
264static void
265exprNode_freeIniter (/*@only@*/ exprNode e)
266{
267 if (!exprNode_isError (e))
268 {
269 switch (e->kind)
270 {
271 case XPR_FACCESS:
272 sfree (e->edata->field);
273 sfree (e->edata);
274 break;
275 case XPR_FETCH:
276 exprNode_free (e->edata->op->b);
277 /*@-compdestroy@*/ sfree (e->edata->op); /*@=compdestroy@*/
278 sfree (e->edata);
279 break;
280 default:
281 llbug (message ("other: %s", exprNode_unparse (e)));
282 }
283
284 multiVal_free (e->val);
285 cstring_free (e->etext);
286 fileloc_free (e->loc);
287 sRefSet_free (e->uses);
288 sRefSet_free (e->sets);
289 sRefSet_free (e->msets);
290 guardSet_free (e->guards);
291 sfree (e);
292 }
293}
294
295void
296exprNode_freeShallow (/*@only@*/ exprNode e)
297{
298 if (!exprNode_isError (e))
299 {
300 if (shallowKind (e->kind))
301 {
302 }
303 else
304 {
305 if (!inEffect)
306 {
307 if (e->kind == XPR_EMPTY
308 || e->kind == XPR_BODY
309 || e->kind == XPR_STRINGLITERAL
310 || e->kind == XPR_NUMLIT
311 || e->kind == XPR_NODE
312 || e->kind == XPR_OFFSETOF
313 || e->kind == XPR_ALIGNOFT
314 || e->kind == XPR_ALIGNOF
315 || e->kind == XPR_SIZEOFT
316 || e->kind == XPR_SIZEOF)
317 {
318 /* don't free anything */
319 }
320 else
321 {
322 /* multiVal_free (e->val); */
323 cstring_free (e->etext);
324 fileloc_free (e->loc);
325 sRefSet_free (e->uses);
326 sRefSet_free (e->sets);
327 sRefSet_free (e->msets);
328 guardSet_free (e->guards);
329 exprData_freeShallow (e->edata, e->kind);
330 nowalloc--;
331 /*@-compdestroy@*/ sfree (e); /*@=compdestroy@*/
332 /*@-branchstate@*/
333 }
334 }
335 } /*@=branchstate@*/
336 }
337 }
338
339void
340exprNode_free (exprNode e)
341{
342 if (!exprNode_isError (e))
343 {
344 if (!inEffect)
345 {
346 multiVal_free (e->val);
347 cstring_free (e->etext);
348 fileloc_free (e->loc);
349 sRefSet_free (e->uses);
350 sRefSet_free (e->sets);
351 sRefSet_free (e->msets);
352 guardSet_free (e->guards);
353 exprData_free (e->edata, e->kind);
354
355 nowalloc--;
356 sfree (e);
357 /*@-branchstate@*/
358 } /*@=branchstate@*/
359 }
360}
361
362exprNode
363exprNode_makeError ()
364{
365 return exprNode_undefined;
366}
367
368static /*@out@*/ /*@only@*/ /*@notnull@*/ exprNode
369exprNode_new (void)
370{
371 exprNode ret = (exprNode) dmalloc (sizeof (*ret));
372 /* static int lastexpnodes = 0; */
373
374 nowalloc++;
375 totalloc++;
376
377 if (nowalloc > maxalloc)
378 {
379 maxalloc = nowalloc;
380 }
381
382 return ret;
383}
384
385static /*@notnull@*/ /*@special@*/ exprNode
386 exprNode_createPlain (ctype c)
387 /*@defines result@*/
388 /*@post:isnull result->edata, result->loc, result->val, result->guards,
389 result->uses, result->sets, result->msets, result->etext @*/
390 /*@*/
391{
392 exprNode e = exprNode_new ();
393
394 e->typ = c;
395 e->kind = XPR_EMPTY;
396 e->val = multiVal_undefined;
397 e->sref = defref;
398 e->etext = cstring_undefined;
399 e->loc = fileloc_undefined;
400 e->guards = guardSet_undefined;
401 e->uses = sRefSet_undefined;
402 e->sets = sRefSet_undefined;
403 e->msets = sRefSet_undefined;
404 e->edata = exprData_undefined;
405 e->exitCode = XK_NEVERESCAPE;
406 e->canBreak = FALSE;
407 e->mustBreak = FALSE;
408 e->isJumpPoint = FALSE;
8ac07c2e 409
410 exprNode_defineConstraints(e);
411
616915dd 412 return (e);
413}
414
415/*@observer@*/ exprNode exprNode_makeMustExit (void)
416{
417 if (exprNode_isUndefined (mustExitNode))
418 {
419 mustExitNode = exprNode_createPlain (ctype_unknown);
420 mustExitNode->exitCode = XK_MUSTEXIT;
421 }
422
423 return mustExitNode;
424}
425
426
427static /*@notnull@*/ /*@special@*/ exprNode exprNode_create (ctype c)
428 /*@defines result@*/
429 /*@post:isnull result->edata, result->guards, result->val,
430 result->uses, result->sets, result->msets@*/
431 /*@*/
432{
433 exprNode e = exprNode_createPlain (c);
434 e->loc = fileloc_copy (g_currentloc);
435 return (e);
436}
437
438static /*@notnull@*/ /*@special@*/ exprNode exprNode_createUnknown (void)
439 /*@defines result@*/
440 /*@post:isnull result->edata, result->guards,
441 result->uses, result->sets, result->msets@*/
442 /*@*/
443{
444 return (exprNode_create (ctype_unknown));
445}
446
447static /*@notnull@*/ /*@special@*/ exprNode
448 exprNode_createLoc (ctype c, /*@keep@*/ fileloc loc)
449 /*@defines result@*/
450 /*@post:isnull result->edata, result->guards, result->val,
451 result->uses, result->sets, result->msets@*/
452 /*@*/
453{
454 exprNode e = exprNode_createPlain (c);
455 e->loc = loc;
456 return (e);
457}
458
459static void
460 exprNode_copySets (/*@special@*/ /*@notnull@*/ exprNode ret, exprNode e)
461 /*@defines ret->guards, ret->uses, ret->sets, ret->msets@*/
462{
463 if (exprNode_isDefined (e))
464 {
465 ret->guards = guardSet_copy (e->guards);
466 ret->uses = sRefSet_newCopy (e->uses);
467 ret->sets = sRefSet_newCopy (e->sets);
468 ret->msets = sRefSet_newCopy (e->msets);
469 }
470 else
471 {
472 ret->guards = guardSet_undefined;
473 ret->uses = sRefSet_undefined;
474 ret->sets = sRefSet_undefined;
475 ret->msets = sRefSet_undefined;
476 }
477}
478
479static /*@notnull@*/ /*@special@*/ exprNode
480 exprNode_createPartialLocCopy (exprNode e, /*@only@*/ fileloc loc)
481 /*@defines result@*/
482 /*@post:isnull result->edata, result->etext@*/
483 /*@*/
484{
485 exprNode ret = exprNode_new ();
486
487 if (exprNode_isError (e))
488 {
489 ret->typ = ctype_unknown;
490 ret->val = multiVal_undefined;
491 ret->loc = loc;
492 ret->guards = guardSet_undefined;
493 ret->uses = sRefSet_undefined;
494 ret->sets = sRefSet_undefined;
495 ret->msets = sRefSet_undefined;
496 }
497 else
498 {
499 ret->typ = e->typ;
500 ret->val = multiVal_copy (e->val);
501 ret->loc = loc;
502 ret->guards = guardSet_copy (e->guards);
503 ret->uses = sRefSet_newCopy (e->uses);
504 ret->sets = sRefSet_newCopy (e->sets);
505 ret->msets = sRefSet_newCopy (e->msets);
506 }
507
508 ret->kind = XPR_EMPTY;
509 ret->sref = defref;
510 ret->etext = cstring_undefined;
511 ret->exitCode = XK_NEVERESCAPE;
512 ret->canBreak = FALSE;
513 ret->mustBreak = FALSE;
514 ret->isJumpPoint = FALSE;
515 ret->edata = exprData_undefined;
516
517 return (ret);
518}
519
520
521static /*@notnull@*/ /*@special@*/ exprNode
522 exprNode_createPartialCopy (exprNode e)
523 /*@defines result@*/
524 /*@post:isnull result->edata, result->etext@*/
525 /*@*/
526{
527 return (exprNode_createPartialLocCopy (e, fileloc_copy (exprNode_loc (e))));
528}
529
530static /*@notnull@*/ /*@special@*/ exprNode
531 exprNode_createPartialNVCopy (exprNode e)
532 /*@defines result@*/
533 /*@post:isnull result->edata, result->etext, result->val @*/
534 /*@*/
535{
536 exprNode ret = exprNode_new ();
537
538 if (exprNode_isError (e))
539 {
540 ret->typ = ctype_unknown;
541 ret->loc = fileloc_undefined;
542 ret->guards = guardSet_undefined;
543 ret->uses = sRefSet_undefined;
544 ret->sets = sRefSet_undefined;
545 ret->msets = sRefSet_undefined;
546 }
547 else
548 {
549 ret->typ = e->typ;
550 ret->loc = fileloc_copy (e->loc);
551 ret->guards = guardSet_copy (e->guards);
552 ret->uses = sRefSet_newCopy (e->uses);
553 ret->sets = sRefSet_newCopy (e->sets);
554 ret->msets = sRefSet_newCopy (e->msets);
555 }
556
557 ret->val = multiVal_undefined;
558 ret->kind = XPR_EMPTY;
559 ret->sref = defref;
560 ret->etext = cstring_undefined;
561 ret->exitCode = XK_NEVERESCAPE;
562 ret->canBreak = FALSE;
563 ret->mustBreak = FALSE;
564 ret->isJumpPoint = FALSE;
565 ret->edata = exprData_undefined;
566
567 return (ret);
568}
569
570static /*@notnull@*/ /*@special@*/ exprNode
571 exprNode_createSemiCopy (exprNode e)
572 /*@defines result@*/
573 /*@post:isnull result->edata, result->etext, result->sets,
574 result->msets, result->uses, result->guards@*/
575 /*@*/
576{
577 if (exprNode_isError (e))
578 {
579 return exprNode_createPlain (ctype_unknown);
580 }
581 else
582 {
583 exprNode ret = exprNode_new ();
584
585 ret->typ = e->typ;
586 ret->val = multiVal_copy (e->val);
587 ret->loc = fileloc_copy (e->loc);
588 ret->guards = guardSet_undefined;
589 ret->uses = sRefSet_undefined;
590 ret->sets = sRefSet_undefined;
591 ret->msets = sRefSet_undefined;
592
593 ret->kind = XPR_EMPTY;
594 ret->sref = defref;
595 ret->etext = cstring_undefined;
596 ret->exitCode = XK_NEVERESCAPE;
597 ret->canBreak = FALSE;
598 ret->mustBreak = FALSE;
599 ret->isJumpPoint = FALSE;
600 ret->edata = exprData_undefined;
601
602 return (ret);
603 }
604}
605
606bool
607exprNode_isNullValue (exprNode e)
608{
609 if (exprNode_isDefined (e))
610 {
611 multiVal m = exprNode_getValue (e);
612
613 if (multiVal_isInt (m))
614 {
615 return (multiVal_forceInt (m) == 0);
616 }
617 }
618
619 return FALSE;
620}
621
622static bool
623exprNode_isUnknownConstant (/*@notnull@*/ exprNode e)
624{
625 while (e->kind == XPR_PARENS)
626 {
627 e = exprData_getUopNode (e->edata);
628 llassert (exprNode_isDefined (e));
629 }
630
631 if (e->kind == XPR_CONST)
632 {
633 multiVal m = exprNode_getValue (e);
634
635 if (multiVal_isUnknown (m))
636 {
637 return TRUE;
638 }
639 }
640
641 return FALSE;
642}
643
644/*@only@*/ exprNode
645 exprNode_numLiteral (ctype c, /*@temp@*/ cstring t,
646 /*@only@*/ fileloc loc, long val)
647{
648 exprNode e = exprNode_createLoc (c, loc);
649
650 e->kind = XPR_NUMLIT;
651
652 llassert (multiVal_isUndefined (e->val));
653 e->val = multiVal_makeInt (val);
654 e->edata = exprData_makeLiteral (cstring_copy (t));
655
656 if (val == 0)
657 {
658 e->sref = sRef_makeUnknown ();
659 sRef_setDefNull (e->sref, e->loc);
660 }
661
662 DPRINTF (("Num lit: %s / %s", exprNode_unparse (e), ctype_unparse (exprNode_getType (e))));
663 return (e);
664}
665
666/*@only@*/ exprNode
667exprNode_charLiteral (char c, cstring text, /*@only@*/ fileloc loc)
668{
669 exprNode e = exprNode_createLoc (ctype_char, loc);
670
671 if (context_getFlag (FLG_CHARINTLITERAL))
672 {
673 e->typ = ctype_makeConj (ctype_char, ctype_int);
674 }
675
676 e->kind = XPR_NUMLIT;
677 e->val = multiVal_makeChar (c);
678
679 e->edata = exprData_makeLiteral (cstring_copy (text));
680 return (e);
681}
682
683/*@only@*/ exprNode
684exprNode_floatLiteral (double d, ctype ct, cstring text, /*@only@*/ fileloc loc)
685{
686 exprNode e = exprNode_createLoc (ct, loc);
687
688 e->kind = XPR_NUMLIT;
689 e->val = multiVal_makeDouble (d);
690 e->edata = exprData_makeLiteral (cstring_copy (text));
691 return (e);
692}
693
694multiVal exprNode_getValue (exprNode e)
695{
696 while (exprNode_isInParens (e)) {
697 if (e->edata != NULL) {
698 e = exprData_getUopNode (e->edata);
699 } else {
700 break;
701 }
702 }
703
704 if (exprNode_isDefined (e)) {
705 return e->val;
706 } else {
707 return multiVal_undefined;
708 }
709}
710
711/*@only@*/ exprNode
712exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
713{
714 exprNode e = exprNode_createLoc (ctype_string, loc);
715 int len = cstring_length (t) - 2;
716 char *ts = cstring_toCharsSafe (t);
717 char *s = cstring_toCharsSafe (cstring_create (len + 1));
718
719 if (context_getFlag (FLG_STRINGLITERALLEN))
720 {
721 if (len > context_getValue (FLG_STRINGLITERALLEN))
722 {
723 voptgenerror (FLG_STRINGLITERALLEN,
724 message
725 ("String literal length (%d) exceeds maximum "
726 "length (%d): %s",
727 len,
728 context_getValue (FLG_STRINGLITERALLEN),
729 t),
730 e->loc);
731 }
732 }
733
734 strncpy (s, ts+1, size_fromInt (len));
735 *(s + len) = '\0';
736
737
738 e->kind = XPR_STRINGLITERAL;
739 e->val = multiVal_makeString (cstring_fromCharsO (s));
740 e->edata = exprData_makeLiteral (t);
741 e->sref = sRef_makeType (ctype_string);
742 /* Start modifications */
743 /* This expr is null terminated, so we set the len and size */
744 sRef_setNullTerminatedState(e->sref);
745 /*
470b7798 746 DPRINTF("Len is set to : %d\n\n", strlen((char *)multiVal_forceString(e->val)));
747 DPRINTF("Size is set to : %d\n\n", strlen((char *)multiVal_forceString(e->val)));
748 DPRINTF("State is set to: %d\n\n", e->sref->bufinfo.bufstate);
616915dd 749 */
84c9ffbf 750 sRef_setLen(e->sref, (int) strlen((char *)multiVal_forceString(e->val)));
751 sRef_setSize(e->sref, (int) strlen((char *)multiVal_forceString(e->val)));
616915dd 752
753 if (context_getFlag (FLG_READONLYSTRINGS))
754 {
755 sRef_setAliasKind (e->sref, AK_STATIC, fileloc_undefined);
756 sRef_setExKind (e->sref, XO_OBSERVER, loc);
757 }
758 else
759 {
760 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
761 }
762
763 return (e); /* s released */
764}
765
766exprNode exprNode_fromUIO (cstring c)
767{
768 fileloc loc = context_getSaveLocation ();
769 exprNode e = exprNode_createPlain (ctype_unknown);
770
771 e->kind = XPR_VAR;
772
773 if (fileloc_isUndefined (loc))
774 {
775 loc = fileloc_copy (g_currentloc);
776 }
777
778 e->loc = loc; /* save loc was mangled */
779 e->sref = defref;
780
781 if (usymtab_exists (c))
782 {
783 uentry ue = usymtab_lookupEither (c);
784
785 if (uentry_isDatatype (ue)
786 && uentry_isSpecified (ue))
787 {
788 llfatalerror
789 (message ("%q: Specified datatype %s used in code, but not defined. "
790 "(Cannot continue reasonably from this error.)",
791 fileloc_unparse (e->loc), c));
792 }
793 else
794 {
795 BADBRANCH;
796 }
797 }
798
799 llassertprint (!usymtab_exists (c), ("Entry exists: %s", c));
800
801 /*
802 ** was supercedeGlobalEntry...is this better?
803 */
804
805 if (!context_inIterEnd ())
806 {
807 if (context_inMacro ())
808 {
809 if (context_getFlag (FLG_UNRECOG))
810 {
811 voptgenerror
812 (FLG_MACROUNDEF,
813 message ("Unrecognized identifier in macro definition: %s", c), e->loc);
814 }
815 else
816 {
817 flagcode_recordSuppressed (FLG_UNRECOG);
818 }
819 }
820 else
821 {
822 voptgenerror
823 (FLG_UNRECOG, message ("Unrecognized identifier: %s", c),
824 e->loc);
825 }
826 }
827
828 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
829
830 /* No alias errors for unrecognized identifiers */
831 sRef_setAliasKind (e->sref, AK_ERROR, loc);
832
833 return (e);
834}
835
836exprNode exprNode_createId (/*@observer@*/ uentry c)
837{
838 if (uentry_isValid (c))
839 {
840 exprNode e = exprNode_new ();
841
842 e->typ = uentry_getType (c);
843
844 if (uentry_isFunction (c)
845 && !sRef_isLocalVar (uentry_getSref (c)))
846 {
847 e->sref = sRef_undefined;
848 }
849 else
850 {
851 e->sref = uentry_getSref (c);
852 }
853
854 if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
855 {
856 sRef_setDefined (e->sref, fileloc_undefined);
857 }
858
859 /*
860 ** yoikes! leaving this out was a heinous bug...that would have been
861 ** caught if i had lclint working first. gag!
862 */
863
864 e->etext = cstring_undefined;
865
866 if (uentry_isEitherConstant (c))
867 {
868 e->kind = XPR_CONST;
869 e->val = multiVal_copy (uentry_getConstantValue (c));
870 }
871 else
872 {
873 e->kind = XPR_VAR;
874 e->val = multiVal_unknown ();
875 }
876
877 e->edata = exprData_makeId (c);
878 e->loc = context_getSaveLocation ();
879
880 if (fileloc_isUndefined (e->loc))
881 {
882 fileloc_free (e->loc);
883 e->loc = fileloc_copy (g_currentloc);
884 }
885
886 e->guards = guardSet_new ();
887 e->sets = sRefSet_new ();
888 e->msets = sRefSet_new ();
889 e->uses = sRefSet_new ();
890
891 /*> missing fields, detected by lclint <*/
892 e->exitCode = XK_NEVERESCAPE;
893 e->isJumpPoint = FALSE;
894 e->canBreak = FALSE;
895 e->mustBreak = FALSE;
896
84c9ffbf 897 exprNode_defineConstraints(e);
898
616915dd 899 return e;
900 }
901 else
902 {
903 return exprNode_createUnknown ();
904 }
905}
906
907/*@notnull@*/ exprNode
908exprNode_fromIdentifier (/*@observer@*/ uentry c)
909{
910 exprNode ret;
911
912 if (context_justPopped ()) /* watch out! c could be dead */
913 {
914 uentry ce = usymtab_lookupSafe (LastIdentifier ());
915
916 if (uentry_isValid (ce))
917 {
918 c = ce;
919 }
920 else
921 {
922 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
923 }
924 }
925
926 ret = exprNode_fromIdentifierAux (c);
927
928 return ret;
929}
930
931
932static /*@only@*/ /*@notnull@*/ exprNode
933exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
934{
935 exprNode e = exprNode_createId (c);
936 sRef sr = e->sref;
937
938 uentry_setUsed (c, e->loc);
939
940 if (uentry_isVar (c) && sRef_isGlobal (sr))
941 {
942 checkGlobUse (c, FALSE, e);
943 }
944
945 return (e);
946}
947
948static bool
949exprNode_isZero (exprNode e)
950{
951 if (exprNode_isDefined (e))
952 {
953 multiVal m = exprNode_getValue (e);
954
955 if (multiVal_isInt (m))
956 {
957 return (multiVal_forceInt (m) == 0);
958 }
959 }
960
961 return FALSE;
962}
963
964static bool
965exprNode_isNonNegative (exprNode e)
966{
967 if (exprNode_isDefined (e))
968 {
969 multiVal m = exprNode_getValue (e);
970
971 if (multiVal_isInt (m))
972 {
973 return (multiVal_forceInt (m) >= 0);
974 }
975 }
976
977 return FALSE;
978}
979
980/*
981** a[x] - uses a but NOT a[]
982** result sref = a[] (set/use in assignment)
983**
984** The syntax x[a] is also legal in C, and has the same
985** semantics. If ind is an array, and arr is an int, flip
986** the arguments.
987*/
988
989/*@only@*/ exprNode
990exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
991{
992 /*
993 ** error in arr, error propagates (no new messages)
994 ** error in ind, assume valid and continue
995 */
996
997 if (exprNode_isError (e1))
998 {
999 exprNode_free (e2);
1000 return (exprNode_makeError ());
1001 }
1002 else
1003 {
1004 exprNode arr;
1005 exprNode ind;
1006 ctype carr = exprNode_getType (e1);
1007 ctype crarr = ctype_realType (carr);
1008
1009 /*
1010 ** this sets up funny aliasing, that leads to spurious
1011 ** lclint errors. Hence, the i2 comments.
1012 */
1013
1014 if (!ctype_isRealArray (crarr)
1015 && ctype_isRealNumeric (crarr)
1016 && !exprNode_isError (e2)
1017 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1018 {
1019 arr = e2;
1020 ind = e1;
1021
1022 carr = exprNode_getType (arr);
1023 crarr = ctype_realType (carr);
1024 }
1025 else
1026 {
1027 arr = e1;
1028 ind = e2;
1029 }
1030
1031 if (sRef_possiblyNull (arr->sref))
1032 {
1033 if (!usymtab_isGuarded (arr->sref))
1034 {
1035 if (optgenerror (FLG_NULLDEREF,
1036 message ("Index of %s pointer %q: %s",
1037 sRef_nullMessage (arr->sref),
1038 sRef_unparse (arr->sref),
1039 exprNode_unparse (arr)),
1040 arr->loc))
1041 {
1042 sRef_showNullInfo (arr->sref);
1043
1044 /* suppress future messages */
1045 sRef_setNullError (arr->sref);
1046 }
1047 }
1048 }
1049
1050 if (exprNode_isError (ind))
1051 {
1052 if ((ctype_isArrayPtr (crarr)
1053 && !ctype_isFunction (crarr))
1054 || ctype_isUnknown (carr))
1055 {
1056 exprNode ret = exprNode_createPartialCopy (arr);
1057
1058 if (ctype_isKnown (carr))
1059 {
1060 ret->typ = ctype_baseArrayPtr (crarr);
1061 }
1062 else
1063 {
1064 ret->typ = ctype_unknown;
1065 }
1066
1067 ret->sref = sRef_makeArrayFetch (arr->sref);
1068
1069 ret->kind = XPR_FETCH;
1070
1071 /*
1072 ** Because of funny aliasing (when arr and ind are
1073 ** flipped) spurious errors would be reported here.
1074 */
1075
1076 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1077 checkSafeUse (ret, arr->sref);
1078 return (ret);
1079 }
1080 else
1081 {
1082 voptgenerror (FLG_TYPE,
1083 message ("Array fetch from non-array (%t): %s[%s]", carr,
1084 exprNode_unparse (e1), exprNode_unparse (e2)),
1085 arr->loc);
1086 exprNode_free (arr);
1087 return (exprNode_makeError ());
1088 }
1089 }
1090 else
1091 {
1092 if (!ctype_isForceRealInt (&(ind->typ)))
1093 {
1094 ctype rt = ctype_realType (ind->typ);
1095
1096 if (ctype_isChar (rt))
1097 {
1098 vnoptgenerror
1099 (FLG_CHARINDEX,
1100 message ("Array fetch using non-integer, %t: %s[%s]",
1101 ind->typ,
1102 exprNode_unparse (e1), exprNode_unparse (e2)),
1103 arr->loc);
1104 }
1105 else if (ctype_isEnum (rt))
1106 {
1107 vnoptgenerror
1108 (FLG_ENUMINDEX,
1109 message ("Array fetch using non-integer, %t: %s[%s]",
1110 ind->typ,
1111 exprNode_unparse (e1), exprNode_unparse (e2)),
1112 arr->loc);
1113 }
1114 else
1115 {
1116 voptgenerror
1117 (FLG_TYPE,
1118 message ("Array fetch using non-integer, %t: %s[%s]",
1119 ind->typ,
1120 exprNode_unparse (e1), exprNode_unparse (e2)),
1121 arr->loc);
1122 }
1123
1124 multiVal_free (ind->val);
1125 ind->val = multiVal_unknown ();
1126 }
1127
1128 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1129 {
1130 exprNode ret = exprNode_createSemiCopy (arr);
1131 multiVal m = exprNode_getValue (ind);
1132
1133 ret->typ = ctype_baseArrayPtr (crarr);
1134 ret->kind = XPR_FETCH;
1135
1136 if (multiVal_isInt (m))
1137 {
1138 int i = (int) multiVal_forceInt (m);
1139
1140 if (sRef_isValid (arr->sref)) {
1141 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1142 } else {
1143 ret->sref = sRef_undefined;
1144 }
1145 }
1146 else
1147 {
1148 ret->sref = sRef_makeArrayFetch (arr->sref);
1149 }
1150
1151 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1152 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1153 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1154
1155 /* (see comment on spurious errors above) */
1156 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1157
1158 exprNode_checkUse (ret, ind->sref, ind->loc);
1159 exprNode_checkUse (ret, arr->sref, arr->loc);
1160
1161 return (ret);
1162 }
1163 else
1164 {
1165 if (ctype_isUnknown (carr))
1166 {
1167 exprNode ret = exprNode_createPartialCopy (arr);
1168
1169 ret->kind = XPR_FETCH;
1170 ret->typ = ctype_unknown;
1171 ret->sets = sRefSet_union (ret->sets, ind->sets);
1172 ret->msets = sRefSet_union (ret->msets, ind->msets);
1173 ret->uses = sRefSet_union (ret->uses, ind->uses);
1174
1175 /* (see comment on spurious errors above) */
1176 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1177
1178 exprNode_checkUse (ret, ind->sref, ind->loc);
1179 exprNode_checkUse (ret, arr->sref, arr->loc);
1180 return (ret);
1181 }
1182 else
1183 {
1184 voptgenerror
1185 (FLG_TYPE,
1186 message ("Array fetch from non-array (%t): %s[%s]", carr,
1187 exprNode_unparse (e1), exprNode_unparse (e2)),
1188 arr->loc);
1189
1190 exprNode_free (arr);
1191 exprNode_free (ind);
1192
1193 return (exprNode_makeError ());
1194 }
1195 }
1196 }
1197 }
1198 BADEXIT;
1199}
1200
1201
1202static int
1203checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1204 exprNodeList args, exprNode ret)
1205{
1206 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1207}
1208
1209/*
1210** checkPrintfArgs --- checks arguments for printf-like functions
1211** Arguments before ... have already been checked.
1212** The argument before the ... is a char *.
1213** argno is the format string argument.
1214*/
1215
1216static void
1217checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1218 exprNodeList args, exprNode ret, int argno)
1219{
1220 /*
1221 ** the last argument before the elips is the format string
1222 */
1223
1224 int i = argno;
1225 fileloc formatloc;
1226 int nargs = exprNodeList_size (args);
1227 uentryList params = uentry_getParams (fcn);
1228 exprNode a;
1229
1230 /*
1231 ** These should be ensured by checkSpecialFunction
1232 */
1233
1234 llassert (uentryList_size (params) == argno + 1);
1235 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1236
1237 a = exprNodeList_getN (args, argno - 1);
1238 formatloc = fileloc_copy (exprNode_loc (a));
1239
1240 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1241 && exprNode_knownStringValue (a))
1242 {
1243 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1244 char *code = format;
1245 char *ocode = code;
1246
1247 nargs = exprNodeList_size (args);
1248
1249 while ((code = strchr (code, '%')) != NULL)
1250 {
1251 char *origcode = code;
1252 char key = *(++code);
1253 ctype modtype = ctype_int;
1254 bool modified = FALSE;
1255
1256 fileloc_addColumn (formatloc, code - ocode);
1257
1258 /* ignore flags */
1259 while (isFlagKey (key))
1260 {
1261 key = *(++code);
1262 fileloc_incColumn (formatloc);
1263 }
1264
1265 if (key == 'm') /* skipped in syslog */
1266 {
1267 continue;
1268 }
1269
1270 /* ignore field width */
1271 while (isdigit ((int) key) != 0)
1272 {
1273 key = *(++code);
1274 fileloc_incColumn (formatloc);
1275 }
1276
1277 /* ignore precision */
1278 if (key == '.')
1279 {
1280 key = *(++code);
1281 fileloc_incColumn (formatloc);
1282
1283 /*
1284 ** In printf, '*' means: read the next arg as an int for the
1285 ** field width. This seems to be missing from my copy of the
1286 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1287 ** later) but never does.
1288 */
1289
1290 if (key == '*')
1291 {
1292 ; /* don't do anything --- handle later */
1293 }
1294 else
1295 {
1296 while (isdigit ((int) key) != 0)
1297 {
1298 key = *(++code);
1299 fileloc_incColumn (formatloc);
1300 }
1301 }
1302 }
1303
1304 if (key == 'h')
1305 {
1306 modtype = ctype_sint; /* short */
1307 key = *(++code);
1308 fileloc_incColumn (formatloc);
1309 }
1310 else if (key == 'l' || key == 'L')
1311 {
1312 modtype = ctype_lint; /* long */
1313 key = *(++code);
1314 fileloc_incColumn (formatloc);
1315
1316 if (key == 'l' || key == 'L') {
1317 modtype = ctype_llint; /* long long */
1318 key = *(++code);
1319 fileloc_incColumn (formatloc);
1320 }
1321 }
1322 else
1323 {
1324 ; /* no modifier */
1325 }
1326
1327 /* now, key = type of conversion to apply */
1328 ++code;
1329 fileloc_incColumn (formatloc);
1330
1331 if (key != '%')
1332 {
1333 if (i >= nargs)
1334 {
1335 if (optgenerror
1336 (FLG_TYPE,
1337 message ("No argument corresponding to %q format "
1338 "code %d (%%%h): \"%s\"",
1339 uentry_getName (fcn),
1340 i, key,
1341 cstring_fromChars (format)),
1342 f->loc))
1343 {
1344 if (fileloc_isDefined (formatloc)
1345 && context_getFlag (FLG_SHOWCOL))
1346 {
1347 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1348 formatloc);
1349 }
1350 }
1351 i++;
1352 }
1353 else
1354 {
1355 a = exprNodeList_getN (args, i);
1356 i++;
1357
1358 if (!exprNode_isError (a))
1359 {
1360 ctype expecttype;
1361
1362 switch (key)
1363 {
1364 case '*': /* int argument for fieldwidth */
1365 expecttype = ctype_int;
1366 *(--code) = '%'; /* convert it for next code */
1367 fileloc_subColumn (formatloc, 1);
1368 /*@switchbreak@*/ break;
1369 case 'u':
1370 case 'o':
1371 expecttype = ctype_combine (ctype_uint, modtype);
1372 /*@switchbreak@*/ break;
1373
1374 case 'i': /* int argument */
1375 case 'd':
1376 expecttype = ctype_combine (ctype_int, modtype);
1377 /*@switchbreak@*/ break;
1378
1379 case 'x': /* unsigned int */
1380 case 'X':
1381 expecttype = ctype_combine (ctype_uint, modtype);
1382 /*@switchbreak@*/ break;
1383
1384 case 'e':
1385 case 'E':
1386 case 'g':
1387 case 'G':
1388 case 'f': /* double */
1389 expecttype = ctype_combine (ctype_double, modtype);
1390 /*@switchbreak@*/ break;
1391
1392 case 'c': /* int converted to char (check its a char?) */
1393 expecttype = ctype_makeConj (ctype_char, ctype_uchar);
1394 /*@switchbreak@*/ break;
1395
1396 case 's': /* string */
1397 expecttype = ctype_string;
1398 /*@switchbreak@*/ break;
1399 case '[':
1400 /* skip to ']' */
1401 while (((key = *(++code)) != ']')
1402 && (key != '\0'))
1403 {
1404 fileloc_incColumn (formatloc);
1405 }
1406
1407 if (key == '\0')
1408 {
1409 llfatalerrorLoc
1410 (message ("Bad character set format: %s",
1411 cstring_fromChars (origcode)));
1412 }
1413
1414 expecttype = ctype_string;
1415 /*@switchbreak@*/ break;
1416
1417 case 'p': /* pointer */
1418 expecttype = ctype_makePointer (ctype_void);
1419 /* really! */
1420 /*@switchbreak@*/ break;
1421
1422 case 'n': /* pointer to int, modified by call! */
1423 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1424 modified = TRUE;
1425 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1426 /*@switchbreak@*/ break;
1427
1428 case 'm': /* in a syslog, it doesn't consume an argument */
1429 /* should check we're really doing syslog */
1430
1431 /*@switchbreak@*/ break;
1432
1433
1434 default:
1435 expecttype = ctype_unknown;
1436
1437 voptgenerror
1438 (FLG_FORMATCODE,
1439 message ("Unrecognized format code: %s",
1440 cstring_fromChars (origcode)),
1441 fileloc_isDefined (formatloc)
1442 ? formatloc : g_currentloc);
1443
1444 /*@switchbreak@*/ break;
1445 }
1446
1447 if (!(exprNode_matchArgType (expecttype, a)))
1448 {
1449 if (ctype_isVoidPointer (expecttype)
1450 && ctype_isRealAbstract (a->typ)
1451 && (context_getFlag (FLG_ABSTVOIDP)))
1452 {
1453 ;
1454 }
1455 else
1456 {
1457 if (llgenformattypeerror
1458 (expecttype, exprNode_undefined,
1459 a->typ, a,
1460 message ("Format argument %d to %q (%%%h) expects "
1461 "%t gets %t: %s",
1462 i - argno,
1463 uentry_getName (fcn),
1464 key, expecttype,
1465 a->typ, exprNode_unparse (a)),
1466 a->loc))
1467 {
1468 if (fileloc_isDefined (formatloc)
1469 && context_getFlag (FLG_SHOWCOL))
1470 {
1471 llgenindentmsg
1472 (cstring_makeLiteral
1473 ("Corresponding format code"),
1474 formatloc);
1475 }
1476 }
1477 }
1478 }
1479
1480 uentry_setType (regArg, expecttype);
1481 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1482
1483 if (ctype_equal (expecttype, ctype_string))
1484 {
1485 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1486 }
1487
1488 uentry_setType (regArg, ctype_unknown);
1489 uentry_fixupSref (regArg);
1490
1491 if (modified)
1492 {
1493 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1494 }
1495 }
1496 else
1497 {
1498 ;
1499 }
1500 }
1501 }
1502 ocode = code;
1503 }
1504
1505 if (i < nargs)
1506 {
1507 voptgenerror (FLG_TYPE,
1508 message ("Format string for %q has %d arg%p, given %d",
1509 uentry_getName (fcn), i - argno, nargs - argno),
1510 f->loc);
1511 }
1512 }
1513 else
1514 {
1515 /* no checking possible for compile-time unknown format strings */
1516 }
1517
1518 fileloc_free (formatloc);
1519}
1520
1521static void
1522checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1523 exprNodeList args, exprNode ret, int argno)
1524{
1525 int i = argno;
1526 fileloc formatloc;
1527 int nargs = exprNodeList_size (args);
1528 uentryList params = uentry_getParams (fcn);
1529 exprNode a;
1530
1531 /*
1532 ** These should be ensured by checkSpecialFunction
1533 */
1534
1535 llassert (uentryList_size (params) == argno + 1);
1536 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1537
1538 a = exprNodeList_getN (args, argno - 1);
1539 formatloc = fileloc_copy (exprNode_loc (a));
1540
1541 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1542 && exprNode_knownStringValue (a))
1543 {
1544 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1545 char *code = format;
1546 char *ocode = code;
1547
1548 nargs = exprNodeList_size (args);
1549
1550 while ((code = strchr (code, '%')) != NULL)
1551 {
1552 char *origcode = code;
1553 char key = *(++code);
1554 ctype modtype = ctype_int;
1555 char modifier = '\0';
1556 bool modified = TRUE;
1557 bool ignore = FALSE;
1558
1559 fileloc_addColumn (formatloc, code - ocode);
1560
1561 /*
1562 ** this is based on ANSI standard library description of fscanf
1563 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1564 */
1565
1566 /* '*' suppresses assignment (does not need match argument) */
1567
1568 if (key == '*')
1569 {
1570 key = *(++code);
1571 modified = FALSE;
1572 ignore = TRUE;
1573 fileloc_incColumn (formatloc);
1574 }
1575
1576 /* ignore field width */
1577 while (isdigit ((int) key) != 0)
1578 {
1579 key = *(++code);
1580 fileloc_incColumn (formatloc);
1581 }
1582
1583 if (key == 'h')
1584 {
1585 modtype = ctype_sint; /* short */
1586 key = *(++code);
1587 fileloc_incColumn (formatloc);
1588 }
1589 else if (key == 'l' || key == 'L')
1590 {
1591 modtype = ctype_lint; /* long */
1592 modifier = key;
1593
1594 key = *(++code);
1595 fileloc_incColumn (formatloc);
1596
1597 if (key == 'l' || key == 'L') {
1598 modtype = ctype_llint; /* long long */
1599 key = *(++code);
1600 fileloc_incColumn (formatloc);
1601 }
1602 }
1603 else
1604 {
1605 ; /* no modifier */
1606 }
1607
1608 /* now, key = type of conversion to apply */
1609 ++code;
1610 fileloc_incColumn (formatloc);
1611
1612 if (key != '%')
1613 {
1614 if (ignore)
1615 {
1616 ;
1617 }
1618 else
1619 {
1620 if (i >= nargs)
1621 {
1622 if (optgenerror
1623 (FLG_TYPE,
1624 message ("No argument corresponding to %q format "
1625 "code %d (%%%h): \"%s\"",
1626 uentry_getName (fcn),
1627 i, key,
1628 cstring_fromChars (format)),
1629 f->loc))
1630 {
1631 if (fileloc_isDefined (formatloc)
1632 && context_getFlag (FLG_SHOWCOL))
1633 {
1634 llgenindentmsg
1635 (cstring_makeLiteral ("Corresponding format code"),
1636 formatloc);
1637 }
1638 }
1639 i++;
1640 }
1641 else
1642 {
1643 a = exprNodeList_getN (args, i);
1644 i++;
1645
1646 if (!exprNode_isError (a))
1647 {
1648 ctype expecttype;
1649
1650 switch (key)
1651 {
1652 case '*': /* int argument for fieldwidth */
1653 expecttype = ctype_makePointer (ctype_int);
1654 *(--code) = '%'; /* convert it for next code */
1655 fileloc_subColumn (formatloc, 1);
1656 /*@switchbreak@*/ break;
1657 case 'u':
1658 case 'o':
1659 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1660 /*@switchbreak@*/ break;
1661
1662 case 'i':
1663 case 'd':
1664 case 'x':
1665 case 'X': /* unsigned int */
1666 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1667 /*@switchbreak@*/ break;
1668
1669 case 'e':
1670 case 'E':
1671 case 'g':
1672 case 'G':
1673 case 'f':
1674 /* printf is double, scanf is float! */
1675
1676 if (modifier == 'l')
1677 {
1678 expecttype = ctype_makePointer (ctype_double);
1679 }
1680 else if (modifier == 'L')
1681 {
1682 expecttype = ctype_makePointer (ctype_ldouble);
1683 }
1684 else
1685 {
1686 llassert (modifier == '\0');
1687 expecttype = ctype_makePointer (ctype_float);
1688 }
1689 /*@switchbreak@*/ break;
1690
1691 case 'c': /* int converted to char (check its a char?) */
1692 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1693 /*@switchbreak@*/ break;
1694
1695 case 's': /* string */
1696 expecttype = ctype_string;
1697 /*@switchbreak@*/ break;
1698
1699 case '[':
1700 /* skip to ']' */
1701 while (((key = *(++code)) != ']')
1702 && (key != '\0'))
1703 {
1704 fileloc_incColumn (formatloc);
1705 }
1706
1707 if (key == '\0')
1708 {
1709 llfatalerrorLoc
1710 (message ("Bad character set format: %s",
1711 cstring_fromChars (origcode)));
1712 }
1713
1714 expecttype = ctype_string;
1715 /*@switchbreak@*/ break;
1716
1717 case 'p': /* pointer */
1718 expecttype = ctype_unknown;
1719 /* really! */
1720 /*@switchbreak@*/ break;
1721
1722 case 'n': /* pointer to int, modified by call! */
1723 expecttype = ctype_makePointer (ctype_int);
1724 /*@switchbreak@*/ break;
1725
1726 default:
1727 expecttype = ctype_unknown;
1728
1729 voptgenerror
1730 (FLG_FORMATCODE,
1731 message ("Unrecognized format code: %s",
1732 cstring_fromChars (origcode)),
1733 fileloc_isDefined (formatloc)
1734 ? formatloc : g_currentloc);
1735
1736 /*@switchbreak@*/ break;
1737 }
1738
1739 if (!(exprNode_matchArgType (expecttype, a)))
1740 {
1741 if (ctype_isVoidPointer (expecttype)
1742 && ctype_isRealAbstract (a->typ)
1743 && (context_getFlag (FLG_ABSTVOIDP)))
1744 {
1745 ;
1746 }
1747 else
1748 {
1749 if (modifier != '\0')
1750 {
1751 if (llgenformattypeerror
1752 (expecttype, exprNode_undefined,
1753 a->typ, a,
1754 message ("Format argument %d to %q (%%%h%h) expects "
1755 "%t gets %t: %s",
1756 i - argno,
1757 uentry_getName (fcn),
1758 modifier,
1759 key, expecttype,
1760 a->typ, exprNode_unparse (a)),
1761 a->loc))
1762 {
1763 if (fileloc_isDefined (formatloc)
1764 && context_getFlag (FLG_SHOWCOL))
1765 {
1766 llgenindentmsg
1767 (cstring_makeLiteral
1768 ("Corresponding format code"),
1769 formatloc);
1770 }
1771 }
1772
1773 }
1774 else
1775 {
1776 if (llgenformattypeerror
1777 (expecttype, exprNode_undefined,
1778 a->typ, a,
1779 message ("Format argument %d to %q (%%%h) expects "
1780 "%t gets %t: %s",
1781 i - argno,
1782 uentry_getName (fcn),
1783 key, expecttype,
1784 a->typ, exprNode_unparse (a)),
1785 a->loc))
1786 {
1787 if (fileloc_isDefined (formatloc)
1788 && context_getFlag (FLG_SHOWCOL))
1789 {
1790 llgenindentmsg
1791 (cstring_makeLiteral
1792 ("Corresponding format code"),
1793 formatloc);
1794 }
1795 }
1796 }
1797 }
1798 }
1799
1800 uentry_setType (outArg, expecttype);
1801 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
1802 uentry_setType (outArg, ctype_unknown);
1803 uentry_fixupSref (outArg);
1804
1805 if (modified)
1806 {
1807 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1808 }
1809 }
1810 else
1811 {
1812 /* a->sref = defref; */
1813 }
1814 }
1815 }
1816 }
1817 ocode = code;
1818 }
1819
1820 if (i < nargs)
1821 {
1822 voptgenerror (FLG_TYPE,
1823 message ("Format string for %q has %d arg%p, given %d",
1824 uentry_getName (fcn), i - argno, nargs - argno),
1825 f->loc);
1826 }
1827 }
1828 else
1829 {
1830 /* no checking possible for compile-time unknown format strings */
1831 }
1832
1833 fileloc_free (formatloc);
1834}
1835
1836static void
1837checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
1838 uentry fcn,
1839 exprNodeList args,
1840 /*@unused@*/ int argno)
1841{
1842 /*
1843 ** the last argument before the elips is the format string
1844 */
1845
1846 int nargs = exprNodeList_size (args);
1847 int i = argno;
1848 fileloc formatloc;
1849 exprNode a;
1850
1851 a = exprNodeList_getN (args, argno - 1);
1852 formatloc = fileloc_copy (exprNode_loc (a));
1853
1854 if (ctype_isUnknown (cstringType)) {
1855 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
1856 {
1857 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
1858 }
1859 }
1860
1861 if (ctype_isUnknown (ctypeType)) {
1862 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
1863 {
1864 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
1865 }
1866 }
1867
1868 if (ctype_isUnknown (filelocType)) {
1869 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
1870 {
1871 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
1872 }
1873 }
1874
1875 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1876 && exprNode_knownStringValue (a))
1877 {
1878 cstring format = multiVal_forceString (exprNode_getValue (a));
1879 char *code = cstring_toCharsSafe (format);
1880 char *ocode = code;
1881
1882 nargs = exprNodeList_size (args);
1883
1884 while ((code = strchr (code, '%')) != NULL)
1885 {
1886 char *origcode = code;
1887 char key = *(++code);
1888 bool isOnly = FALSE;
1889
1890 fileloc_addColumn (formatloc, code - ocode);
1891
1892 while (key >= '0' && key <= '9')
1893 {
1894 key = *(++code);
1895 fileloc_incColumn (formatloc);
1896 }
1897
1898 ++code;
1899 fileloc_incColumn (formatloc);
1900
1901 if (key != '%')
1902 {
1903 if (key == 'p')
1904 {
1905 goto nextKey;
1906 }
1907
1908 if (i >= nargs)
1909 {
1910 voptgenerror
1911 (FLG_TYPE,
1912 message ("Message missing format arg %d (%%%h): \"%s\"",
1913 i + 1, key, format),
1914 f->loc);
1915 i++;
1916 }
1917 else
1918 {
1919 a = exprNodeList_getN (args, i);
1920 i++;
1921
1922 nextKey:
1923 if (!exprNode_isError (a))
1924 {
1925 ctype expecttype;
1926
1927 /*@-loopswitchbreak@*/
1928
1929 switch (key)
1930 {
1931 case 'c':
1932 case 'h':
1933 expecttype = ctype_char; break;
1934 case 's':
1935 expecttype = cstringType; break;
1936 case 'q':
1937 expecttype = cstringType; isOnly = TRUE; break;
1938 case 'x':
1939 expecttype = cstringType; isOnly = TRUE; break;
1940 case 'd': expecttype = ctype_int; break;
1941 case 'u': expecttype = ctype_uint; break;
1942 case 'w': expecttype = ctype_ulint; break;
1943 case 'f': expecttype = ctype_float; break;
1944 case 'b': expecttype = ctype_bool; break;
1945 case 't': expecttype = ctypeType; break;
1946 case 'l': expecttype = filelocType; break;
1947 case 'p': /* a wee bit of a hack methinks */
1948 expecttype = ctype_int;
1949 break;
1950 case 'r': expecttype = ctype_bool; break;
1951 default:
1952 expecttype = ctype_unknown;
1953 voptgenerror
1954 (FLG_FORMATCODE,
1955 message ("Unrecognized format code: %s",
1956 cstring_fromChars (origcode)),
1957 fileloc_isDefined (formatloc)
1958 ? formatloc : g_currentloc);
1959 break;
1960 }
1961 /*@=loopswitchbreak@*/
1962
1963 if (!(exprNode_matchArgType (expecttype, a)))
1964 {
1965 if (ctype_isVoidPointer (expecttype)
1966 && ctype_isRealAbstract (a->typ)
1967 && (context_getFlag (FLG_ABSTVOIDP)))
1968 {
1969 ;
1970 }
1971 else
1972 {
1973 if (llgenformattypeerror
1974 (expecttype, exprNode_undefined,
1975 a->typ, a,
1976 message ("Format argument %d to %q (%%%h) expects "
1977 "%t gets %t: %s",
1978 i - argno,
1979 uentry_getName (fcn),
1980 key, expecttype,
1981 a->typ, exprNode_unparse (a)),
1982 a->loc))
1983 {
1984 if (fileloc_isDefined (formatloc)
1985 && context_getFlag (FLG_SHOWCOL))
1986 {
1987 llgenindentmsg
1988 (cstring_makeLiteral
1989 ("Corresponding format code"),
1990 formatloc);
1991 }
1992 }
1993 }
1994 }
1995
1996 if (ctype_equal (expecttype, cstringType))
1997 {
1998 if (isOnly)
1999 {
2000 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2001 uentry_fixupSref (csOnlyArg);
2002 }
2003 else
2004 {
2005 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2006 uentry_fixupSref (csArg);
2007 }
2008 }
2009 else
2010 {
2011 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2012 uentry_fixupSref (regArg);
2013 }
2014 }
2015 }
2016 }
2017 }
2018
2019 if (i < nargs)
2020 {
2021 voptgenerror (FLG_TYPE,
2022 message ("Format string for %q has %d arg%p, given %d",
2023 uentry_getName (fcn), i - argno, nargs -argno),
2024 f->loc);
2025 }
2026 }
2027 else
2028 {
2029 /* no checking possible for compile-time unknown format strings */
2030 }
2031
2032 fileloc_free (formatloc);
2033}
2034
2035static void
2036 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2037 /*@notnull@*/ exprNode e2,
2038 sRefSet sets1,
2039 sRefSet sets2,
2040 lltok op,
2041 flagcode flag)
2042{
2043 bool hadUncon = FALSE;
2044
2045 if (sRef_isGlobal (sRef_getRootBase (e1->sref)) &&
2046 sRefSet_hasUnconstrained (sets2))
2047 {
2048 voptgenerror
2049 (FLG_EVALORDERUNCON,
2050 message
2051 ("Expression may have undefined behavior (%q used in right operand "
2052 "may set global variable %q used in left operand): %s %s %s",
2053 sRefSet_unparseUnconstrained (sets2),
2054 sRef_unparse (sRef_getRootBase (e1->sref)),
2055 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2056 e2->loc);
2057 }
2058
2059 if (sRef_isGlobal (sRef_getRootBase (e2->sref)) &&
2060 sRefSet_hasUnconstrained (sets1))
2061 {
2062 voptgenerror
2063 (FLG_EVALORDERUNCON,
2064 message
2065 ("Expression has undefined behavior (%q used in left operand "
2066 "may set global variable %q used in right operand): %s %s %s",
2067 sRefSet_unparseUnconstrained (sets1),
2068 sRef_unparse (e2->sref),
2069 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2070 e2->loc);
2071 }
2072
2073 sRefSet_realElements (e1->uses, sr)
2074 {
2075 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2076 {
2077 voptgenerror
2078 (FLG_EVALORDER,
2079 message
2080 ("Expression has undefined behavior (left operand uses %q, "
2081 "modified by right operand): %s %s %s",
2082 sRef_unparse (sr),
2083 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2084 e2->loc);
2085 }
2086 } end_sRefSet_realElements;
2087
2088 sRefSet_realElements (sets1, sr)
2089 {
2090 if (sRef_isMeaningful (sr))
2091 {
2092 if (sRef_same (sr, e2->sref))
2093 {
2094 voptgenerror
2095 (flag,
2096 message
2097 ("Expression has undefined behavior (value of right operand "
2098 "modified by left operand): %s %s %s",
2099 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2100 e2->loc);
2101 }
2102 else if (sRefSet_member (e2->uses, sr))
2103 {
2104 voptgenerror
2105 (flag,
2106 message
2107 ("Expression has undefined behavior (left operand modifies %q, "
2108 "used by right operand): %s %s %s",
2109 sRef_unparse (sr),
2110 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2111 e2->loc);
2112 }
2113 else
2114 {
2115 if (sRefSet_member (sets2, sr))
2116 {
2117 if (sRef_isUnconstrained (sr))
2118 {
2119 if (hadUncon)
2120 {
2121 ;
2122 }
2123 else
2124 {
2125 hadUncon = optgenerror
2126 (FLG_EVALORDERUNCON,
2127 message
2128 ("Expression may have undefined behavior. Left operand "
2129 "calls %q; right operand calls %q. The unconstrained "
2130 "functions may modify global state used by "
2131 "the other operand): %s %s %s",
2132 sRefSet_unparseUnconstrained (sets1),
2133 sRefSet_unparseUnconstrained (sets2),
2134 exprNode_unparse (e1), lltok_unparse (op),
2135 exprNode_unparse (e2)),
2136 e2->loc);
2137 }
2138 }
2139 else
2140 {
2141 voptgenerror
2142 (flag,
2143 message
2144 ("Expression has undefined behavior (both "
2145 "operands modify %q): %s %s %s",
2146 sRef_unparse (sr),
2147 exprNode_unparse (e1),
2148 lltok_unparse (op), exprNode_unparse (e2)),
2149 e2->loc);
2150 }
2151 }
2152 }
2153 }
2154 } end_sRefSet_realElements;
2155}
2156
2157static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2158{
2159 bool hasError = FALSE;
2160
2161 if (exprNode_isError (e1) || exprNode_isError (e2))
2162 {
2163 return;
2164 }
2165
2166 if (sRefSet_member (e2->sets, e1->sref))
2167 {
2168 if (e2->kind == XPR_CALL)
2169 {
2170 ;
2171 }
2172 else
2173 {
2174 hasError = optgenerror
2175 (FLG_EVALORDER,
2176 message ("Expression has undefined behavior "
2177 "(value of left operand is modified "
2178 "by right operand): %s %s %s",
2179 exprNode_unparse (e1), lltok_unparse (op),
2180 exprNode_unparse (e2)),
2181 e2->loc);
2182 }
2183 }
2184
2185 if (context_getFlag (FLG_EVALORDERUNCON))
2186 {
2187 if (sRefSet_member (e2->msets, e1->sref))
2188 {
2189 if (e2->kind == XPR_CALL)
2190 {
2191 ;
2192 }
2193 else
2194 {
2195 hasError = optgenerror
2196 (FLG_EVALORDER,
2197 message
2198 ("Expression has undefined behavior (value of left "
2199 "operand may be modified by right operand): %s %s %s",
2200 exprNode_unparse (e1), lltok_unparse (op),
2201 exprNode_unparse (e2)),
2202 e2->loc);
2203 }
2204 }
2205 }
2206
2207 if (!hasError)
2208 {
2209 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2210
2211 if (context_maybeSet (FLG_EVALORDERUNCON))
2212 {
2213 checkExpressionDefinedAux (e1, e2, e1->msets,
2214 e2->msets, op, FLG_EVALORDERUNCON);
2215 }
2216 }
2217}
2218
2219static void checkSequencing (exprNode p_f, exprNodeList p_args);
2220
2221static int
2222 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2223 exprNodeList args, bool isIter, exprNode ret)
2224{
2225 int special = 0;
2226
2227 if (!exprNode_isError (f))
2228 {
2229 if (!uentryList_isMissingParams (cl))
2230 {
2231 int nargs = exprNodeList_size (args);
2232 int expectargs = uentryList_size (cl);
2233 ctype last;
2234 int i = 0;
2235
2236 if (expectargs == 0)
2237 {
2238 if (nargs != 0)
2239 {
2240 if (isIter)
2241 {
2242 voptgenerror
2243 (FLG_TYPE,
2244 message ("Iter %q invoked with %d args, "
2245 "declared void",
2246 uentry_getName (fcn),
2247 nargs),
2248 f->loc);
2249 }
2250 else
2251 {
2252 voptgenerror
2253 (FLG_TYPE,
2254 message ("Function %s called with %d args, "
2255 "declared void",
2256 exprNode_unparse (f), nargs),
2257 f->loc);
2258 }
2259 }
2260 return special;
2261 }
2262
2263 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2264
2265 exprNodeList_reset (args);
2266
2267 uentryList_elements (cl, current)
2268 {
2269 ctype ct = uentry_getType (current);
2270 exprNode a;
2271
2272 if (ctype_isElips (ct))
2273 {
2274 /*
2275 ** do special checking for printf/scanf library functions
2276 **
2277 ** this is kludgey code, just for handling the special case
2278 **
2279 */
2280
2281 if (uentry_isPrintfLike (fcn))
2282 {
2283 checkPrintfArgs (f, fcn, args, ret, i);
2284 special = i;
2285 }
2286 else if (uentry_isScanfLike (fcn))
2287 {
2288 checkScanfArgs (f, fcn, args, ret, i);
2289 special = i;
2290 }
2291 else if (uentry_isMessageLike (fcn))
2292 {
2293 checkMessageArgs (f, fcn, args, i);
2294 special = i;
2295 }
2296 else
2297 {
2298 llassert (!uentry_isSpecialFunction (fcn));
2299 }
2300
2301 nargs = expectargs; /* avoid errors */
2302 break;
2303 }
2304 else
2305 {
2306 if (i >= nargs) break;
2307
2308 a = exprNodeList_current (args);
2309 exprNodeList_advance (args);
2310
2311 i++;
2312
2313 if (exprNode_isError (a))
2314 {
2315 ;
2316 }
2317 else
2318 {
2319 /*
2320 probably necessary? I'm not sure about this one
2321 checkMacroParen (a);
2322 */
2323
2324 f->guards = guardSet_union (f->guards, a->guards);
2325
2326 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2327
2328 if (!(exprNode_matchArgType (ct, a)))
2329 {
2330 DPRINTF (("Args mismatch!"));
2331
2332 if (ctype_isVoidPointer (ct)
2333 && (ctype_isPointer (a->typ)
2334 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2335 {
2336 vnoptgenerror
2337 (FLG_ABSTVOIDP,
2338 message
2339 ("Pointer to abstract type (%t) used "
2340 "as void pointer "
2341 "(arg %d to %q): %s",
2342 a->typ, i,
2343 uentry_getName (fcn),
2344 exprNode_unparse (a)),
2345 a->loc);
2346 }
2347 else
2348 {
2349 if (isIter)
2350 {
2351 (void) gentypeerror
2352 (ct, exprNode_undefined,
2353 a->typ, a,
2354 message
2355 ("Iter %q expects arg %d to "
2356 "be %t gets %t: %s",
2357 uentry_getName (fcn),
2358 i, ct, a->typ, exprNode_unparse (a)),
2359 a->loc);
2360 }
2361 else
2362 {
2363 if (gentypeerror
2364 (ct,
2365 exprNode_undefined,
2366 a->typ,
2367 a,
2368 message
2369 ("Function %q expects arg %d to be %t gets %t: %s",
2370 uentry_getName (fcn),
2371 i, ct, a->typ, exprNode_unparse (a)),
2372 a->loc))
2373 {
2374 DPRINTF (("Types: %s / %s",
2375 ctype_unparse (ct),
2376 ctype_unparse (a->typ)));
2377 }
2378
2379 /*
2380 ** Clear null marker for abstract types.
2381 ** (It is not revealed, so suppress future messages.)
2382 */
2383
2384 if (ctype_isAbstract (a->typ))
2385 {
2386 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2387 }
2388 }
2389 }
2390 }
2391 }
2392 }
2393 } end_uentryList_elements ;
2394
2395
2396 if (expectargs != nargs) /* note: not != since we may have ... */
2397 {
2398 if (ctype_isElips (last))
2399 {
2400 voptgenerror
2401 (FLG_TYPE,
2402 message ("Function %s called with %d args, expects at least %d",
2403 exprNode_unparse (f),
2404 nargs, expectargs - 1),
2405 f->loc);
2406 }
2407 else
2408 {
2409 if (isIter)
2410 {
2411 voptgenerror
2412 (FLG_TYPE,
2413 message ("Iter %q invoked with %d args, expects %d",
2414 uentry_getName (fcn), nargs, expectargs),
2415 f->loc);
2416 }
2417 else
2418 {
2419 voptgenerror
2420 (FLG_TYPE,
2421 message ("Function %s called with %d args, expects %d",
2422 exprNode_unparse (f),
2423 nargs, expectargs),
2424 f->loc);
2425 }
2426 }
2427 }
2428 }
2429 }
2430
2431 return special;
2432}
2433
2434/*
2435** Check for undefined code sequences in function arguments:
2436**
2437** one parameter sets something used by another parameter
2438** one parameter sets something set by another parameter
2439*/
2440
2441static void
2442checkSequencingOne (exprNode f, exprNodeList args,
2443 /*@notnull@*/ exprNode el, int argno)
2444{
2445 /*
2446 ** Do second loop, iff +undefunspec
2447 */
2448
2449 int checkloop;
2450 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2451
2452 for (checkloop = 0; checkloop < numloops; checkloop++)
2453 {
2454 sRefSet thissets;
2455
2456 if (checkloop == 0)
2457 {
2458 thissets = el->sets;
2459 }
2460 else
2461 {
2462 llassert (checkloop == 1);
2463 thissets = el->msets;
2464 }
2465
2466 sRefSet_realElements (thissets, thisset)
2467 {
2468 int j;
2469
2470 /*@access exprNodeList@*/
2471 for (j = 0; j < args->nelements; j++)
2472 {
2473 exprNode jl = args->elements[j];
2474 int thisargno = j + 1;
2475
2476 if (thisargno != argno && exprNode_isDefined (jl))
2477 {
2478 sRefSet otheruses = jl->uses;
2479
2480 if (sRef_isGlobal (sRef_getRootBase (jl->sref)) &&
2481 sRefSet_hasUnconstrained (thissets))
2482 {
2483 voptgenerror
2484 (FLG_EVALORDERUNCON,
2485 /*@-sefparams@*/
2486 message
2487 ("%q used in argument %d may set "
2488 "global variable %q used by argument %d: %s(%q)",
2489 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2490 /*@=sefparams@*/
2491 argno,
2492 sRef_unparse (sRef_getRootBase (jl->sref)),
2493 thisargno,
2494 exprNode_unparse (f), exprNodeList_unparse (args)),
2495 el->loc);
2496 }
2497
2498 if (sRefSet_member (otheruses, thisset))
2499 {
2500 if (sRef_isUnconstrained (thisset))
2501 {
2502 voptgenerror
2503 (FLG_EVALORDERUNCON,
2504 message
2505 ("Unconstrained functions used in arguments %d (%q) "
2506 "and %d (%s) may modify "
2507 "or use global state in undefined way: %s(%q)",
2508 argno,
2509 sRefSet_unparseUnconstrainedPlain (otheruses),
2510 thisargno,
2511 sRef_unconstrainedName (thisset),
2512 exprNode_unparse (f),
2513 exprNodeList_unparse (args)),
2514 el->loc);
2515 }
2516 else
2517 {
2518 voptgenerror
2519 (FLG_EVALORDER,
2520 message
2521 ("Argument %d modifies %q, used by argument %d "
2522 "(order of evaluation of actual parameters is "
2523 "undefined): %s(%q)",
2524 argno, sRef_unparse (thisset), thisargno,
2525 exprNode_unparse (f), exprNodeList_unparse (args)),
2526 el->loc);
2527 }
2528 }
2529 else
2530 {
2531 sRefSet othersets = jl->sets;
2532
2533 if (sRefSet_member (othersets, thisset))
2534 {
2535 if (sRef_isUnconstrained (thisset))
2536 {
2537 voptgenerror
2538 (FLG_EVALORDERUNCON,
2539 message
2540 ("Unconstrained functions used in "
2541 "arguments %d (%q) and %d (%s) may modify "
2542 "or use global state in undefined way: %s(%q)",
2543 argno,
2544 sRefSet_unparseUnconstrainedPlain (othersets),
2545 thisargno,
2546 sRef_unconstrainedName (thisset),
2547 exprNode_unparse (f), exprNodeList_unparse (args)),
2548 el->loc);
2549 }
2550 else
2551 {
2552 voptgenerror
2553 (FLG_EVALORDER,
2554 message
2555 ("Argument %d modifies %q, set by argument %d (order of"
2556 " evaluation of actual parameters is undefined): %s(%q)",
2557 argno, sRef_unparse (thisset), thisargno,
2558 exprNode_unparse (f), exprNodeList_unparse (args)),
2559 el->loc);
2560 }
2561 }
2562 }
2563 }
2564 }
2565 /*@noaccess exprNodeList@*/
2566 } end_sRefSet_realElements;
2567 }
2568}
2569
2570static void
2571checkSequencing (exprNode f, exprNodeList args)
2572{
2573 if (exprNodeList_size (args) > 1)
2574 {
2575 int i;
2576 exprNode el;
2577
2578 /*@access exprNodeList*/
2579
2580 for (i = 0; i < args->nelements; i++)
2581 {
2582 el = args->elements[i];
2583
2584 if (!exprNode_isError (el))
2585 {
2586 checkSequencingOne (f, args, el, i + 1);
2587 }
2588 }
2589 /*@noaccess exprNodeList*/
2590 }
2591}
2592
2593/*
2594** requires le = exprNode_getUentry (f)
2595*/
2596
2597static void
2598checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2599 uentry le, exprNodeList args,
2600 /*@notnull@*/ exprNode ret, int specialArgs)
2601{
2602 bool isSpec = FALSE;
2603 bool hasMods = FALSE;
2604 cstring fname;
2605 globSet usesGlobs = globSet_undefined;
2606 sRefSet mods = sRefSet_undefined;
2607 bool freshMods = FALSE;
2608 uentryList params = uentryList_undefined;
2609
2610 /*
2611 ** check globals and modifies
2612 */
2613
2614 setCodePoint ();
2615
2616 if (!uentry_isValid (le))
2617 {
2618 ctype fr = ctype_realType (f->typ);
2619
2620 if (ctype_isFunction (fr))
2621 {
2622 params = ctype_argsFunction (fr);
2623 }
2624 else
2625 {
2626 params = uentryList_missingParams;
2627 }
2628
2629 if (!context_getFlag (FLG_MODNOMODS)
2630 && !context_getFlag (FLG_GLOBUNSPEC))
2631 {
2632 checkUnspecCall (f, params, args);
2633 }
2634
2635 return;
2636 }
2637
2638 fname = uentry_rawName (le);
2639
2640 setCodePoint ();
2641
2642 if (uentry_isFunction (le))
2643 {
2644 params = uentry_getParams (le);
2645 mods = uentry_getMods (le);
2646 hasMods = uentry_hasMods (le);
2647 usesGlobs = uentry_getGlobs (le);
2648 isSpec = uentry_isSpecified (le);
2649 }
2650 else /* not a function */
2651 {
2652 ctype ct = ctype_realType (uentry_getType (le));
2653
2654 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2655 ("checkModGlobs: uentry not a function: %s",
2656 uentry_unparse (le)));
2657
2658 params = ctype_argsFunction (ct);
2659 }
2660
2661 /*
2662 ** check globals
2663 */
2664
2665 setCodePoint ();
2666
2667
2668 globSet_allElements (usesGlobs, el)
2669 {
2670 if (sRef_isValid (el))
2671 {
2672 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2673 {
2674 context_usedGlobal (el);
2675 exprNode_checkUse (f, el, f->loc);
2676
2677 if (context_checkInternalUse ())
2678 {
2679 if (!context_globAccess (el))
2680 {
2681 if (sRef_isSystemState (el)
2682 && !context_getFlag (FLG_MODFILESYSTEM))
2683 {
2684 ;
2685 }
2686 else
2687 {
2688 voptgenerror
2689 (FLG_INTERNALGLOBS,
2690 message
2691 ("Called procedure %s may access %q, but "
2692 "globals list does not include globals %s",
2693 exprNode_unparse (f),
2694 sRef_unparse (el),
2695 cstring_makeLiteralTemp (sRef_isInternalState (el)
2696 ? "internalState"
2697 : "fileSystem")),
2698 f->loc);
2699 }
2700 }
2701 }
2702 }
2703 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2704 {
2705 ;
2706 }
2707 else
2708 {
2709 uentry gle = sRef_getUentry (el);
2710 sRef sr = sRef_updateSref (el);
2711
2712 if (sRef_isUndefGlob (el))
2713 {
2714 sRef_setDefined (sr, f->loc);
2715 exprNode_checkSet (f, sr);
2716 }
2717 else
2718 {
2719 /*
2720 ** check definition
2721 */
2722
2723 if (sRef_isAllocated (el))
2724 {
2725 exprNode_checkSet (f, sr);
2726 }
2727 else
2728 {
2729 if (sRef_isStateUndefined (sr))
2730 {
2731 voptgenerror
2732 (FLG_GLOBSTATE,
2733 message
2734 ("%s %q used by function undefined before call: %s",
2735 sRef_getScopeName (sr),
2736 sRef_unparse (sr),
2737 exprNode_unparse (f)),
2738 f->loc);
2739 sRef_setDefined (sr, f->loc);
2740 }
2741 exprNode_checkUse (f, sr, f->loc);
2742 }
2743
2744 checkGlobUse (gle, TRUE, f);
2745 }
2746
2747 if (sRef_isKilledGlob (el))
2748 {
2749 sRef_kill (sr, f->loc);
2750 context_usedGlobal (sr);
2751 }
2752 }
2753 }
2754 } end_globSet_allElements;
2755
2756 /*
2757 ** check modifies
2758 */
2759
2760 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
2761 {
2762 sRefSet smods = sRefSet_undefined;
2763
2764 /*
2765 ** NEED to check for modifies anything
2766 */
2767
2768 /*
2769 ** check each sRef that called function modifies (ml), is
2770 ** modifiable by tl
2771 */
2772
2773 setCodePoint ();
2774
2775 sRefSet_allElements (mods, s) /* s is something which may be modified */
2776 {
2777 if (sRef_isKindSpecial (s))
2778 {
2779 if (sRef_isSpecInternalState (s))
2780 {
2781 if (context_getFlag (FLG_MODINTERNALSTRICT))
2782 {
2783 exprNode_checkCallModifyVal (s, args, f, ret);
2784 }
2785 else
2786 {
2787 sRefSet mmods = context_modList ();
2788
2789 sRefSet_allElements (mmods, el)
2790 {
2791 if (sRef_isInternalState (el))
2792 {
2793 sRef_setModified (el);
2794 }
2795 } end_sRefSet_allElements ;
2796 }
2797 }
2798 else
2799 {
2800 exprNode_checkCallModifyVal (s, args, f, ret);
2801 }
2802 }
2803 else
2804 {
2805 sRef rb = sRef_getRootBase (s);
2806
2807 if (sRef_isGlobal (rb))
2808 {
2809 context_usedGlobal (rb);
2810 }
2811
2812 if (sRef_isFileStatic (s)
2813 && !fileId_equal (fileloc_fileId (f->loc),
2814 fileloc_fileId (uentry_whereDefined (le))))
2815 {
2816 smods = sRefSet_insert (smods, s);
2817 }
2818 else
2819 {
2820 exprNode_checkCallModifyVal (s, args, f, ret);
2821 }
2822 }
2823 } end_sRefSet_allElements;
2824
2825 setCodePoint ();
2826
2827 /*
2828 ** Static elements in modifies set can have nasty consequences.
2829 ** (I think...have not been able to reproduce a possible bug.)
2830 */
2831
2832 if (!sRefSet_isDefined (smods))
2833 {
2834 mods = sRefSet_newCopy (mods);
2835 freshMods = TRUE;
2836
2837 sRefSet_allElements (smods, el)
2838 {
2839 bool res = sRefSet_delete (mods, el);
2840
2841 llassert (res);
2842 } end_sRefSet_allElements;
2843
2844 sRefSet_free (smods);
2845 /*@-branchstate@*/
2846 }
2847 /*@=branchstate@*/
2848 }
2849 else if (sRefSet_isDefined (mods))
2850 { /* just check observers */
2851 setCodePoint ();
2852
2853 sRefSet_allElements (mods, s) /* s is something which may be modified */
2854 {
2855 sRef rb = sRef_getRootBase (s);
2856
2857 setCodePoint ();
2858
2859 if (sRef_isParam (rb))
2860 {
2861 sRef b = sRef_fixBaseParam (s, args);
2862
2863 if (sRef_isObserver (b))
2864 {
2865 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
2866
2867 if (optgenerror
2868 (FLG_MODOBSERVER,
2869 message ("Function call may modify observer%q: %s",
2870 sRef_unparsePreOpt (b), exprNode_unparse (e)),
2871 exprNode_loc (e)))
2872 {
2873 sRef_showExpInfo (b);
2874 }
2875 }
2876 }
2877 } end_sRefSet_allElements;
2878 }
2879 else
2880 {
2881 if (!hasMods) /* no specified modifications */
2882 {
2883 if (context_getFlag (FLG_MODOBSERVERUNCON))
2884 {
2885 exprNodeList_elements (args, e)
2886 {
2887 if (exprNode_isDefined (e))
2888 {
2889 sRef s = exprNode_getSref (e);
2890
2891 if (sRef_isObserver (s)
2892 && ctype_isMutable (sRef_getType (s)))
2893 {
2894 if (optgenerror
2895 (FLG_MODOBSERVERUNCON,
2896 message
2897 ("Call to unconstrained function %s may modify observer%q: %s",
2898 exprNode_unparse (f),
2899 sRef_unparsePreOpt (s), exprNode_unparse (e)),
2900 exprNode_loc (e)))
2901 {
2902 sRef_showExpInfo (s);
2903 }
2904 }
2905 }
2906 } end_exprNodeList_elements;
2907 }
2908 }
2909 }
2910
2911 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
2912
2913 ret->uses = sRefSet_union (ret->uses, f->uses);
2914 ret->sets = sRefSet_union (ret->sets, f->sets);
2915 ret->msets = sRefSet_union (ret->msets, f->msets);
2916
2917 if (freshMods)
2918 {
2919 /*
2920 ** Spurious errors reported, because lclint can't tell
2921 ** mods must be fresh if freshMods is true.
2922 */
2923
2924 /*@i@*/ sRefSet_free (mods);
2925 }
2926
2927 setCodePoint ();
2928}
2929
2930void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
2931{
2932 if (uentry_isVar (glob))
2933 {
2934 if (context_inFunctionLike ())
2935 {
2936 sRef sr = uentry_getSref (glob);
2937
2938 context_usedGlobal (sr);
2939
2940 if (context_checkGlobUse (glob))
2941 {
2942 if (!context_globAccess (sr))
2943 {
2944 if (isCall)
2945 {
2946 voptgenerror
2947 (FLG_GLOBALS,
2948 message ("Called procedure %s may access %s %q",
2949 exprNode_unparse (e),
2950 sRef_unparseScope (sr),
2951 uentry_getName (glob)),
2952 e->loc);
2953 }
2954 else
2955 {
2956 voptgenerror
2957 (FLG_GLOBALS,
2958 message ("Undocumented use of %s %s",
2959 sRef_unparseScope (sr),
2960 exprNode_unparse (e)),
2961 e->loc);
2962 }
2963 }
2964 }
2965 }
2966 }
2967 else
2968 {
2969 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
2970 }
2971}
2972
2973static /*@only@*/ exprNode
2974functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
2975 ctype t, /*@keep@*/ exprNodeList args)
2976{
2977 /* requires f is a non-error exprNode, with type function */
2978 cstring fname = exprNode_unparse (f);
2979 uentry le = exprNode_getUentry (f);
2980 exprNode ret = exprNode_createPartialCopy (f);
2981 int special;
2982
2983 setCodePoint ();
2984
2985 ret->typ = ctype_returnValue (t);
2986 ret->kind = XPR_CALL;
2987
2988 ret->edata = exprData_makeCall (f, args);
2989
2990 /*
2991 ** Order of these steps is very important!
2992 **
2993 ** Must check for argument dependencies before messing up uses and sets.
2994 */
2995
2996 if (context_getFlag (FLG_EVALORDER))
2997 {
2998 exprNodeList_elements (args, current)
2999 {
3000 if (exprNode_isDefined (current))
3001 {
3002 exprNode_addUse (current, current->sref);
3003 }
3004 } end_exprNodeList_elements;
3005
3006 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3007 {
3008 checkSequencing (f, args);
3009 }
3010
3011 exprNodeList_elements (args, current)
3012 {
3013 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3014 {
3015 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3016 }
3017 } end_exprNodeList_elements ;
3018 }
3019
3020 special = checkArgs (le, f, t, args, ret);
3021 checkGlobMods (f, le, args, ret, special);
3022
3023 setCodePoint ();
3024
3025 if (uentry_isValid (le)
3026 && (uentry_isFunction (le)
3027 || (uentry_isVariable (le)
3028 && ctype_isFunction (uentry_getType (le)))))
3029 {
3030 exitkind exk = uentry_getExitCode (le);
3031
3032 /* f->typ is already set to the return type */
3033
3034 ret->sref = uentry_returnedRef (le, args);
3035
3036 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3037 {
3038 qual nullPred = uentry_nullPred (le);
3039
3040 if (qual_isTrueNull (nullPred))
3041 {
3042 exprNode arg = exprNodeList_head (args);
3043
3044 if (exprNode_isDefined (arg))
3045 {
3046 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3047 }
3048 }
3049 else if (qual_isFalseNull (nullPred))
3050 {
3051 exprNode arg = exprNodeList_head (args);
3052
3053 if (exprNode_isDefined (arg))
3054 {
3055 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3056 }
3057 }
3058 else
3059 {
3060 llassert (qual_isUnknown (nullPred));
3061 }
3062 }
3063
3064 if (exitkind_isConditionalExit (exk))
3065 {
3066 /*
3067 ** True exit is:
3068 ** if (arg0) then { exit! } else { ; }
3069 ** False exit is:
3070 ** if (arg0) then { ; } else { exit! }
3071 */
3072
3073 exprNode firstArg;
3074
3075 llassert (!exprNodeList_isEmpty (args));
3076 firstArg = exprNodeList_head (args);
3077
3078 if (exprNode_isDefined (firstArg)
3079 && !guardSet_isEmpty (firstArg->guards))
3080 {
3081 usymtab_trueBranch (guardSet_undefined);
3082 usymtab_altBranch (guardSet_undefined);
3083
3084 if (exitkind_isTrueExit (exk))
3085 {
3086 usymtab_popBranches (firstArg,
3087 exprNode_makeMustExit (),
3088 exprNode_undefined,
3089 TRUE, TRUEEXITCLAUSE);
3090 }
3091 else
3092 {
3093 usymtab_popBranches (firstArg,
3094 exprNode_undefined,
3095 exprNode_makeMustExit (),
3096 TRUE, FALSEEXITCLAUSE);
3097 }
3098 }
3099
3100 ret->exitCode = XK_MAYEXIT;
3101 }
3102 else if (exitkind_mustExit (exk))
3103 {
3104 ret->exitCode = XK_MUSTEXIT;
3105 }
3106 else if (exitkind_couldExit (exk))
3107 {
3108 ret->exitCode = XK_MAYEXIT;
3109 }
3110 else
3111 {
3112 ;
3113 }
3114
3115 if (cstring_equalLit (fname, "exit"))
3116 {
3117 if (exprNodeList_size (args) == 1)
3118 {
3119 exprNode arg = exprNodeList_head (args);
3120
3121 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3122 {
3123 long int val = multiVal_forceInt (exprNode_getValue (arg));
3124
3125 if (val != 0)
3126 {
3127 voptgenerror
3128 (FLG_EXITARG,
3129 message
3130 ("Argument to exit has implementation defined behavior: %s",
3131 exprNode_unparse (arg)),
3132 exprNode_loc (arg));
3133 }
3134 }
3135 }
3136 }
3137 }
3138 else
3139 {
3140 ret->sref = defref;
3141 exprNode_checkSetAny (ret, uentry_rawName (le));
3142 }
3143
3144 return (ret);
3145}
3146
3147/*
3148** this is yucky! should keep the uentry as part of exprNode!
3149*/
3150
3151/*@observer@*/ uentry
3152exprNode_getUentry (exprNode e)
3153{
3154 if (exprNode_isError (e))
3155 {
3156 return uentry_undefined;
3157 }
3158 else
3159 {
3160 cstring s = exprNode_rootVarName (e);
3161 uentry ue = usymtab_lookupSafe (s);
3162
3163 return ue;
3164 }
3165}
3166
3167exprNode
3168exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3169{
3170 exprNode ret = exprNode_createPlain (ctype_unknown);
3171
3172 ret->kind = XPR_INITBLOCK;
3173 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3174 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3175
3176 return (ret);
3177}
3178
3179exprNode
3180exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3181{
3182 ctype t;
3183
3184 setCodePoint ();
3185
3186 if (exprNode_isUndefined (f))
3187 {
3188 exprNode_free (f);
3189 exprNodeList_free (args);
3190 return exprNode_undefined;
3191 }
3192
3193 t = exprNode_getType (f);
3194
3195 if (sRef_isLocalVar (f->sref))
3196 {
3197 exprNode_checkUse (f, f->sref, f->loc);
3198
3199 if (sRef_possiblyNull (f->sref))
3200 {
3201 if (!usymtab_isGuarded (f->sref))
3202 {
3203 if (optgenerror (FLG_NULLDEREF,
3204 message ("Function call using %s pointer %q",
3205 sRef_nullMessage (f->sref),
3206 sRef_unparse (f->sref)),
3207 f->loc))
3208 {
3209 sRef_showNullInfo (f->sref);
3210 sRef_setNullError (f->sref);
3211 }
3212 }
3213 }
3214 }
3215
3216 setCodePoint ();
3217
3218 if (ctype_isRealFunction (t))
3219 {
3220 exprNode ret = functionCallSafe (f, t, args);
3221 setCodePoint ();
3222 return ret;
3223 }
3224 else if (ctype_isUnknown (t))
3225 {
3226 exprNode ret = exprNode_createPartialCopy (f);
3227 cstring tstring;
3228
3229 setCodePoint ();
3230
3231 ret->typ = t;
3232 exprNodeList_elements (args, current)
3233 {
3234 if (exprNode_isDefined (current))
3235 {
3236 exprNode_checkUse (ret, current->sref, ret->loc);
3237
3238 /*
3239 ** also, anything derivable from current->sref may be used
3240 */
3241
3242 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3243 exprNode_mergeUSs (ret, current);
3244 }
3245 } end_exprNodeList_elements;
3246
3247 ret->edata = exprData_makeCall (f, args);
3248 ret->kind = XPR_CALL;
3249
3250 tstring = cstring_copy (exprNode_unparse (f));
3251
3252 cstring_markOwned (tstring);
3253 exprNode_checkSetAny (ret, tstring);
3254
3255 return (ret);
3256 }
3257 else
3258 {
3259 voptgenerror (FLG_TYPE,
3260 message ("Call to non-function (type %t): %s", t,
3261 exprNode_unparse (f)),
3262 f->loc);
3263 exprNode_free (f);
3264 exprNodeList_free (args);
3265
3266 return (exprNode_makeError ());
3267 }
3268}
3269
3270exprNode
3271exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ cstring f)
3272{
3273 exprNode ret = exprNode_createPartialCopy (s);
3274
3275 ret->kind = XPR_FACCESS;
3276
3277 if (exprNode_isError (s))
3278 {
3279 ret->edata = exprData_makeField (s, f);
3280 return ret;
3281 }
3282 else
3283 {
3284 ctype t = exprNode_getType (s);
3285 ctype tr = ctype_realType (t);
3286
3287 checkMacroParen (s);
3288
3289 ret->edata = exprData_makeField (s, f);
3290
3291 if (ctype_isStructorUnion (tr))
3292 {
3293 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
3294
3295 if (uentry_isUndefined (tf))
3296 {
3297 voptgenerror (FLG_TYPE,
3298 message ("Access non-existent field %s of %t: %s", f, t,
3299 exprNode_unparse (ret)),
3300 s->loc);
3301
3302 return (ret);
3303 }
3304 else
3305 {
3306 uentry_setUsed (tf, exprNode_loc (ret));
3307
3308 ret->typ = uentry_getType (tf);
3309 checkSafeUse (ret, s->sref);
3310
3311 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
3312 return (ret);
3313 }
3314 }
3315 else /* isStructorUnion */
3316 {
3317 if (ctype_isRealAbstract (tr))
3318 {
3319 voptgenerror
3320 (FLG_ABSTRACT,
3321 message ("Access field of abstract type (%t): %s.%s",
3322 t, exprNode_unparse (s), f),
3323 s->loc);
3324 ret->typ = ctype_unknown;
3325 }
3326 else
3327 {
3328 if (ctype_isKnown (tr))
3329 {
3330 voptgenerror
3331 (FLG_TYPE,
3332 message
3333 ("Access field of non-struct or union (%t): %s.%s",
3334 t, exprNode_unparse (s), f),
3335 s->loc);
3336
3337 ret->typ = ctype_unknown;
3338 }
3339 else
3340 {
3341 cstring sn = cstring_copy (f);
3342
3343 checkSafeUse (ret, s->sref);
3344 cstring_markOwned (sn);
3345 ret->sref = sRef_makeField (s->sref, sn);
3346
3347 return (ret);
3348 }
3349 }
3350 return (ret);
3351 }
3352 }
3353 BADEXIT;
3354}
3355
3356exprNode
3357exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
3358{
3359 exprNode ret = exprNode_createPartialCopy (e);
3360
3361 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
3362 ret->kind = XPR_PARENS;
3363 ret->edata = exprData_makeUop (e, lpar);
3364
3365 if (!exprNode_isError (e))
3366 {
3367 ret->exitCode = e->exitCode;
3368 ret->canBreak = e->canBreak;
3369 ret->mustBreak = e->mustBreak;
3370 ret->isJumpPoint = e->isJumpPoint;
3371 ret->sref = e->sref;
3372 }
3373
3374 return ret;
3375}
3376
3377exprNode
3378exprNode_arrowAccess (/*@only@*/ exprNode s, /*@only@*/ cstring f)
3379{
3380 exprNode ret = exprNode_createPartialCopy (s);
3381
3382 ret->edata = exprData_makeField (s, f);
3383 ret->kind = XPR_ARROW;
3384
3385 if (exprNode_isError (s))
3386 {
3387 return (ret);
3388 }
3389 else
3390 {
3391 ctype t = exprNode_getType (s);
3392 ctype tr = ctype_realType (t);
3393
3394 checkMacroParen (s);
3395
3396 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
3397
3398 if (ctype_isRealPointer (tr))
3399 {
3400 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
3401
3402 if (ctype_isStructorUnion (b))
3403 {
3404 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
3405
3406 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
3407 {
3408 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
3409 {
3410 if (optgenerror
3411 (FLG_NULLDEREF,
3412 message ("Arrow access from %s pointer%q: %s",
3413 sRef_nullMessage (s->sref),
3414 sRef_unparsePreOpt (s->sref),
3415 exprNode_unparse (ret)),
3416 s->loc))
3417 {
3418 sRef_showNullInfo (s->sref);
3419 sRef_setNullError (s->sref);
3420 }
3421 }
3422 }
3423
3424 if (uentry_isUndefined (fentry))
3425 {
3426 voptgenerror
3427 (FLG_TYPE,
3428 message ("Access non-existent field %s of %t: %s",
3429 f, t, exprNode_unparse (ret)),
3430 s->loc);
3431 ret->typ = ctype_unknown;
3432
3433 return (ret);
3434 }
3435 else
3436 {
3437 /*
3438 ** was safeUse: shouldn't be safe!
3439 **
3440 ** to do rec->field
3441 ** rec must be defined,
3442 ** *rec must be allocated
3443 ** rec->field need only be defined it if is an rvalue
3444 */
3445
3446 uentry_setUsed (fentry, exprNode_loc (ret));
3447 ret->typ = uentry_getType (fentry);
3448
3449 exprNode_checkUse (ret, s->sref, s->loc);
3450
3451 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
3452 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
3453 return (ret);
3454 }
3455 }
3456 else /* Pointer to something that is not a struct or union*/
3457 {
3458 if (ctype_isRealAbstract (tr))
3459 {
3460 ctype xrt = ctype_forceRealType (tr);
3461
3462 voptgenerror
3463 (FLG_ABSTRACT,
3464 message ("Arrow access field of abstract type (%t): %s->%s",
3465 t, exprNode_unparse (s), f),
3466 s->loc);
3467
3468 /*
3469 ** Set the state correctly, as if the abstraction is broken.
3470 */
3471
3472 if (ctype_isRealPointer (xrt) &&
3473 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
3474 ctype_isStructorUnion (b)))
3475 {
3476 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
3477 ret->typ = uentry_getType (fentry);
3478 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
3479 }
3480 else
3481 {
3482 ret->typ = ctype_unknown;
3483 ret->sref = sRef_undefined;
3484 }
3485 }
3486 else /* not a struct, union or abstract */
3487 {
3488 if (ctype_isUnknown (tr)) {
3489 cstring sn = cstring_copy (f);
3490
3491 DPRINTF (("Here: %s", exprNode_unparse (s)));
3492
3493 exprNode_checkUse (ret, s->sref, s->loc);
3494 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
3495
3496 cstring_markOwned (sn);
3497 ret->sref = sRef_makeArrow (s->sref, sn);
3498
3499 ret->kind = XPR_ARROW;
3500 return (ret);
3501 } else {
3502 voptgenerror
3503 (FLG_TYPE,
3504 message ("Arrow access field of non-struct or union "
3505 "pointer (%t): %s->%s",
3506 t, exprNode_unparse (s), f),
3507 s->loc);
3508
3509 ret->typ = ctype_unknown;
3510 ret->sref = sRef_undefined;
3511 }
3512 }
3513 }
3514 }
3515 else /* its not a pointer */
3516 {
3517 if (!ctype_isUnknown (tr))
3518 {
3519 voptgenerror
3520 (FLG_TYPE,
3521 message ("Arrow access of non-pointer (%t): %s->%s",
3522 t, exprNode_unparse (s), f),
3523 s->loc);
3524
3525 ret->typ = ctype_unknown;
3526 ret->sref = sRef_undefined;
3527 }
3528 else
3529 {
3530 cstring sn = cstring_copy (f);
3531
3532 DPRINTF (("Here: %s", exprNode_unparse (s)));
3533
3534 exprNode_checkUse (ret, s->sref, s->loc);
3535 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
3536
3537 cstring_markOwned (sn);
3538 ret->sref = sRef_makeArrow (s->sref, sn);
3539
3540 ret->kind = XPR_ARROW;
3541 return (ret);
3542 }
3543 }
3544
3545 return (ret);
3546 }
3547 BADEXIT;
3548}
3549
3550/*
3551** only postOp's in C: i++ and i--
3552*/
3553
3554exprNode
3555exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
3556{
3557 /* check modification also */
3558 /* cstring opname = lltok_unparse (op);*/
3559 ctype t;
3560 exprNode ret = exprNode_createPartialCopy (e);
3561
3562 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
3563 ret->kind = XPR_POSTOP;
3564 ret->edata = exprData_makeUop (e, op);
3565
3566 if (!exprNode_isDefined (e))
3567 {
3568 return ret;
3569 }
3570
3571 checkMacroParen (e);
3572
3573 exprNode_checkUse (ret, e->sref, e->loc);
3574 exprNode_checkSet (ret, e->sref);
3575
3576 t = exprNode_getType (e);
3577
3578 if (sRef_isUnsafe (e->sref))
3579 {
3580 voptgenerror (FLG_MACROPARAMS,
3581 message ("Operand of %s is macro parameter (non-functional): %s%s",
3582 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
3583 e->loc);
3584 sRef_makeSafe (e->sref);
3585 sRef_makeSafe (ret->sref);
3586 }
3587
3588 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
3589 {
3590 ret->typ = e->typ;
3591 }
3592 else
3593 {
3594 if (ctype_isRealAbstract (t))
3595 {
3596 voptgenerror
3597 (FLG_ABSTRACT,
3598 message ("Operand of %s is abstract type (%t): %s",
3599 lltok_unparse (op), t, exprNode_unparse (e)),
3600 e->loc);
3601 }
3602 else
3603 {
3604 voptgenerror
3605 (FLG_TYPE,
3606 message ("Operand of %s is non-numeric (%t): %s",
3607 lltok_unparse (op), t, exprNode_unparse (e)),
3608 e->loc);
3609 }
3610 ret->typ = ctype_unknown;
3611 }
3612
3613 /* if (ctype_isZero (t)) e->typ = ctype_int; */
3614
3615 exprNode_checkModify (e, ret);
3616
3617 /* added 7/11/2000 D.L */
84c9ffbf 3618 /*@i223*/
3619 /*DRL 6/8/01 I decided to disable all LCLint Warning here since the code
3620 probably needs a rewrite any way */
3621
3622 /*@ignore@*/
3623
dc92450f 3624 // updateEnvironmentForPostOp (e);
616915dd 3625
3626 /* start modifications */
3627 /* added by Seejo on 4/16/2000 */
3628
3629 /* Arithmetic operations on pointers wil modify the size/len/null terminated
3630 status */
3631 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
3632
3633 ret->sref = sRef_copy (e->sref);
3634
3635 /* Operator : ++ */
3636 if (lltok_getTok (op) == INC_OP) {
3637 if (sRef_getSize(e->sref) > 0) {
3638
3639 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
3640
3641 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
3642 /* Assumption: there is only 1 \0 in the buffer */
3643 /* This will not be correct if there are 2 \0's in the buffer */
3644 sRef_setNotNullTerminatedState(ret->sref);
3645 sRef_resetLen(ret->sref);
3646 } else {
3647 sRef_setNullTerminatedState(ret->sref);
3648 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
3649 }
3650 if (sRef_isNullTerminated (ret->sref))
3651 printf ("ret->sref is Null Terminated\n");
3652 else if (sRef_isPossiblyNullTerminated (ret->sref))
3653 printf ("ret->sref is Possibly Null Terminated\n");
3654 else if (sRef_isNotNullTerminated (ret->sref))
3655 printf ("ret->sref is Not Null Terminated\n");
3656 }
3657 }
3658
3659 /* Operator : -- */
3660 if (lltok_getTok (op) == DEC_OP) {
3661 if (sRef_getSize(e->sref) >= 0) {
3662 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
3663 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
3664 }
3665 }
3666 }
84c9ffbf 3667 /*@end@*/
616915dd 3668 /* end modifications */
3669
3670 return ret;
3671}
3672
3673exprNode
3674exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
3675{
3676 bool checkMod = FALSE;
3677 ctype te, tr;
3678 int opid = lltok_getTok (op);
3679 exprNode ret = exprNode_createSemiCopy (e);
3680
3681 exprNode_copySets (ret, e);
3682
3683 multiVal_free (ret->val);
3684 ret->val = multiVal_undefined;
3685 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
3686 ret->kind = XPR_PREOP;
3687 ret->edata = exprData_makeUop (e, op);
3688
3689 if (exprNode_isError (e))
3690 {
3691 return ret;
3692 }
3693
3694 checkMacroParen (e);
3695
3696 te = exprNode_getType (e);
3697 tr = ctype_realType (te);
3698
3699 if (opid != TAMPERSAND)
3700 {
3701 exprNode_checkUse (ret, e->sref, e->loc);
3702
3703 if (ctype_isRealAbstract (tr)
3704 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
3705 {
3706 if (optgenerror (FLG_ABSTRACT,
3707 message ("Operand of %s is abstract type (%t): %s",
3708 lltok_unparse (op), tr,
3709 exprNode_unparse (ret)),
3710 e->loc))
3711 {
3712 tr = te = ctype_unknown;
3713 ret->typ = ctype_unknown;
3714 sRef_setNullError (e->sref);
3715 }
3716 }
3717 }
3718
3719 switch (opid)
3720 {
3721 case INC_OP:
3722 case DEC_OP: /* should also check modification! */
3723
3724 if (sRef_isMacroParamRef (e->sref))
3725 {
3726 voptgenerror
3727 (FLG_MACROPARAMS,
3728 message ("Operand of %s is macro parameter (non-functional): %s",
3729 lltok_unparse (op), exprNode_unparse (ret)),
3730 e->loc);
3731 }
3732 else
3733 {
3734 exprNode_checkSet (ret, e->sref);
3735 }
3736
3737 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
3738 {
3739 }
3740 else
3741 {
3742 if (context_msgStrictOps ())
3743 {
3744 voptgenerror
3745 (FLG_STRICTOPS,
3746 message ("Operand of %s is non-numeric (%t): %s",
3747 lltok_unparse (op), te, exprNode_unparse (ret)),
3748 e->loc);
3749 }
3750 ret->typ = ctype_int;
3751 }
3752
3753 /* start modifications */
3754 /* added by Seejo on 4/16/2000 */
3755
3756 /* Arithmetic operations on pointers wil modify the size/len/null terminated
3757 status */
3758 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
3759
3760 ret->sref = sRef_copy (e->sref);
3761
3762 /* Operator : ++ */
3763 if (lltok_getTok (op) == INC_OP) {
3764 if (sRef_getSize(e->sref) > 0) {
3765
3766 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
3767
3768 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
3769 /* Assumption: there is only 1 \0 in the buffer */
3770 /* This will not be correct if there are 2 \0's in the buffer */
3771 sRef_setNotNullTerminatedState(ret->sref);
3772 sRef_resetLen (ret->sref);
3773 } else {
3774 sRef_setNullTerminatedState(ret->sref);
3775 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
3776 }
3777 }
3778 }
3779
3780 /* Operator : -- */
3781 if (lltok_getTok (op) == DEC_OP) {
3782 if (sRef_getSize(e->sref) >= 0) {
3783 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
3784 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
3785 }
3786 }
3787 }
3788
3789 /* end modifications */
3790
3791 checkMod = TRUE;
3792 break;
3793
3794 case TMINUS:
3795 case TPLUS:
3796 if (ctype_isForceRealNumeric (&tr))
3797 {
3798 if (opid == TMINUS)
3799 {
3800 ret->val = multiVal_invert (exprNode_getValue (e));
3801 }
3802 else
3803 {
3804 ret->val = multiVal_copy (exprNode_getValue (e));
3805 }
3806 }
3807 else
3808 {
3809 if (context_msgStrictOps ())
3810 {
3811 voptgenerror
3812 (FLG_STRICTOPS,
3813 message ("Operand of %s is non-numeric (%t): %s",
3814 lltok_unparse (op), te, exprNode_unparse (ret)),
3815 e->loc);
3816 }
3817
3818 ret->typ = ctype_int;
3819 }
3820 break;
3821
3822 case TEXCL: /* maybe this should be restricted */
3823 guardSet_flip (ret->guards);
3824
3825 if (ctype_isRealBool (te))
3826 {
3827 ;
3828 }
3829 else
3830 {
3831 if (ctype_isRealPointer (tr))
3832 {
3833 if (sRef_isKnown (e->sref))
3834 {
3835 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
3836 }
3837
3838 voptgenerror2n
3839 (FLG_BOOLOPS, FLG_PTRNEGATE,
3840 message ("Operand of %s is non-boolean (%t): %s",
3841 lltok_unparse (op), te, exprNode_unparse (ret)),
3842 e->loc);
3843 }
3844 else
3845 {
3846 voptgenerror
3847 (FLG_BOOLOPS,
3848 message ("Operand of %s is non-boolean (%t): %s",
3849 lltok_unparse (op), te, exprNode_unparse (ret)),
3850 e->loc);
3851 }
3852
3853 ret->typ = ctype_bool;
3854 }
3855 break;
3856
3857 case TTILDE:
3858 if (ctype_isForceRealInt (&tr))
3859 {
3860 }
3861 else
3862 {
3863 if (context_msgStrictOps ())
3864 {
3865 voptgenerror
3866 (FLG_STRICTOPS,
3867 message ("Operand of %s is non-integer (%t): %s",
3868 lltok_unparse (op), te, exprNode_unparse (ret)),
3869 e->loc);
3870 }
3871
3872 if (ctype_isInt (e->typ))
3873 {
3874 ret->typ = e->typ;
3875 }
3876 else
3877 {
3878 ret->typ = ctype_int;
3879 }
3880 }
3881 break;
3882
3883 case TAMPERSAND:
3884 ret->typ = ctype_makePointer (e->typ);
3885
3886 if (sRef_isKnown (e->sref))
3887 {
3888 ret->sref = sRef_makeAddress (e->sref);
3889 }
3890
3891 break;
3892
3893 case TMULT:
3894
3895 if (ctype_isAP (tr))
3896 {
3897 ret->typ = ctype_baseArrayPtr (e->typ);
3898 }
3899 else
3900 {
3901 if (ctype_isKnown (te))
3902 {
3903 if (ctype_isFunction (te))
3904 {
3905 ret->typ = e->typ;
3906
3907 voptgenerror
3908 (FLG_FCNDEREF,
3909 message ("Dereference of function type (%t): %s",
3910 te, exprNode_unparse (ret)),
3911 e->loc);
3912 }
3913 else
3914 {
3915 voptgenerror (FLG_TYPE,
3916 message ("Dereference of non-pointer (%t): %s",
3917 te, exprNode_unparse (ret)),
3918 e->loc);
3919 ret->typ = ctype_unknown;
3920 }
3921 }
3922 else
3923 {
3924 ret->typ = ctype_unknown;
3925 }
3926
3927 }
3928
3929 if (sRef_isKnown (e->sref))
3930 {
3931 if (sRef_possiblyNull (e->sref))
3932 {
3933 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
3934 {
3935 if (optgenerror
3936 (FLG_NULLDEREF,
3937 message ("Dereference of %s pointer %q: %s",
3938 sRef_nullMessage (e->sref),
3939 sRef_unparse (e->sref),
3940 exprNode_unparse (ret)),
3941 e->loc))
3942 {
3943 sRef_showNullInfo (e->sref);
3944 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
3945 }
3946 }
3947 }
3948
3949 ret->sref = sRef_makePointer (e->sref);
3950 }
3951 break;
3952
3953 default:
3954 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
3955 }
3956
3957 if (checkMod)
3958 {
3959 exprNode_checkModify (e, ret);
3960 }
3961
3962 return ret;
3963}
3964
3965/*
3966** any reason to disallow sizeof (abstract type) ?
3967*/
3968
3969/*
3970** used by both sizeof
3971*/
3972
3973static
3974ctype sizeof_resultType (void)
3975{
3976 static ctype sizet = ctype_unknown;
3977
3978 if (ctype_isUnknown (sizet))
3979 {
3980 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
3981 {
3982 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
3983 }
3984 else
3985 {
3986 sizet = ctype_ulint;
3987 }
3988 }
3989 return sizet;
3990}
3991
3992exprNode
3993exprNode_sizeofType (/*@only@*/ qtype qt)
3994{
3995 exprNode ret = exprNode_create (sizeof_resultType ());
3996 ctype ct = qtype_getType (qt);
3997
3998 ret->kind = XPR_SIZEOFT;
3999 ret->edata = exprData_makeSizeofType (qt);
4000
4001 voptgenerror (FLG_SIZEOFTYPE,
4002 message ("Parameter to sizeof is type %s: %s",
4003 ctype_unparse (ct),
4004 exprNode_unparse (ret)),
4005 ret->loc);
4006
4007 return (ret);
4008}
4009
4010exprNode
4011exprNode_alignofType (/*@only@*/ qtype qt)
4012{
4013 exprNode ret = exprNode_create (sizeof_resultType ());
4014 ctype ct = qtype_getType (qt);
4015
4016 ret->kind = XPR_ALIGNOFT;
4017 ret->edata = exprData_makeSizeofType (qt);
4018
4019 voptgenerror (FLG_SIZEOFTYPE,
4020 message ("Parameter to alignof is type %s: %s",
4021 ctype_unparse (ct),
4022 exprNode_unparse (ret)),
4023 ret->loc);
4024
4025 return (ret);
4026}
4027
4028exprNode exprNode_offsetof (qtype qt, cstringList s)
4029{
4030 exprNode ret = exprNode_create (sizeof_resultType ());
4031 ctype ct = qtype_getType (qt);
4032
4033 ret->kind = XPR_OFFSETOF;
4034 ret->edata = exprData_makeOffsetof (qt, s);
4035
4036 if (!ctype_isRealSU (ct))
4037 {
4038 voptgenerror (FLG_TYPE,
4039 message ("First parameter to offsetof is not a "
4040 "struct or union type (type %s): %s",
4041 ctype_unparse (ct),
4042 exprNode_unparse (ret)),
4043 ret->loc);
4044 }
4045 else
4046 {
4047 ctype lt = ct;
4048
4049 cstringList_elements (s, el) {
4050 uentryList fields;
4051 uentry fld;
4052
4053 if (ctype_isUndefined (lt))
4054 {
4055 break;
4056 }
4057 else if (!ctype_isRealSU (lt))
4058 {
4059 voptgenerror (FLG_TYPE,
4060 message ("Inner offsetof type is not a "
4061 "struct or union type (type %s before field %s): %s",
4062 ctype_unparse (lt), el,
4063 exprNode_unparse (ret)),
4064 ret->loc);
4065 break;
4066 }
4067 else
4068 {
4069 fields = ctype_getFields (ctype_realType (lt));
4070 fld = uentryList_lookupField (fields, el);
4071 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4072
4073 if (uentry_isUndefined (fld))
4074 {
4075 if (ctype_equal (lt, ct)) {
4076 voptgenerror (FLG_TYPE,
4077 message ("Field %s in offsetof is not the "
4078 "name of a field of %s: %s",
4079 el,
4080 ctype_unparse (ct),
4081 exprNode_unparse (ret)),
4082 ret->loc);
4083 } else {
4084 voptgenerror (FLG_TYPE,
4085 message ("Deep field %s in offsetof is not the "
4086 "name of a field of %s: %s",
4087 el,
4088 ctype_unparse (lt),
4089 exprNode_unparse (ret)),
4090 ret->loc);
4091 }
4092 }
4093 else
4094 {
4095 lt = uentry_getType (fld);
4096 }
4097 }
4098 } end_cstringList_elements;
4099
4100 /* Should report error if its a bit field - behavior is undefined! */
4101 }
4102
4103 return (ret);
4104}
4105
4106/*@only@*/ exprNode
4107exprNode_sizeofExpr (/*@only@*/ exprNode e)
4108{
4109 exprNode ret;
4110
4111 if (exprNode_isUndefined (e))
4112 {
4113 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4114 ret->edata = exprData_makeSingle (e);
4115 ret->typ = sizeof_resultType ();
4116 ret->kind = XPR_SIZEOF;
4117 }
4118 else
4119 {
4120 uentry u = exprNode_getUentry (e);
4121
4122 ret = exprNode_createPartialCopy (e);
4123 ret->edata = exprData_makeSingle (e);
4124
4125 ret->typ = sizeof_resultType ();
4126 ret->kind = XPR_SIZEOF;
4127
4128 if (uentry_isValid (u)
4129 && uentry_isRefParam (u)
4130 && ctype_isRealArray (uentry_getType (u)))
4131 {
4132 voptgenerror
4133 (FLG_SIZEOFFORMALARRAY,
4134 message ("Parameter to sizeof is an array-type function parameter: %s",
4135 exprNode_unparse (ret)),
4136 ret->loc);
4137 }
4138 }
4139
4140 /*
4141 ** sizeof (x) doesn't "really" use x
4142 */
4143
4144 return (ret);
4145}
4146
4147/*@only@*/ exprNode
4148exprNode_alignofExpr (/*@only@*/ exprNode e)
4149{
4150 exprNode ret;
4151
4152 if (exprNode_isUndefined (e))
4153 {
4154 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4155 }
4156 else
4157 {
4158 ret = exprNode_createPartialCopy (e);
4159 }
4160
4161 ret->edata = exprData_makeSingle (e);
4162 ret->typ = sizeof_resultType ();
4163 ret->kind = XPR_ALIGNOF;
4164
4165 /*
4166 ** sizeof (x) doesn't "really" use x
4167 */
4168
4169 return (ret);
4170}
4171
4172/*@only@*/ exprNode
4173exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4174{
4175 ctype c;
4176 ctype t;
4177 exprNode ret;
4178
4179 if (exprNode_isError (e))
4180 {
4181 qtype_free (q);
4182 lltok_release (tok);
4183 return exprNode_undefined;
4184 }
4185
4186 checkMacroParen (e);
4187
4188 c = qtype_getType (q);
4189 t = exprNode_getType (e);
4190
4191 ret = exprNode_createPartialCopy (e);
4192
4193 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4194 ret->typ = c;
4195 ret->kind = XPR_CAST;
4196 ret->edata = exprData_makeCast (tok, e, q);
4197
4198 if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
4199 {
4200 /*
4201 ** This is a bit of a hack to avoid a problem
4202 ** when the code does,
4203 ** (some other struct) x
4204 ** ...
4205 ** x->field
4206 */
4207
4208 ret->sref = sRef_copy (e->sref);
4209 usymtab_addForceMustAlias (ret->sref, e->sref);
4210 sRef_setTypeFull (ret->sref, c);
4211 DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
4212 sRef_unparseFull (ret->sref)));
4213 }
4214 else
4215 {
4216 ret->sref = e->sref;
4217 sRef_setTypeFull (ret->sref, c);
4218 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
4219 }
4220
4221 /*
4222 ** we allow
4223 ** abstract -> void
4224 ** 0 <-> abstract *
4225 ** void * <-> abstract * (if FLG_ABSTVOIDP)
4226 ** abstract * <-> void * (if FLG_ABSTVOIDP)
4227 */
4228
4229 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
4230 {
4231 ;
4232 }
4233 else if (ctype_isRealAP (c)) /* casting to array or pointer */
4234 {
4235 ctype bc = ctype_getBaseType (c);
4236 ctype bt = ctype_getBaseType (t);
4237 ctype rt = ctype_realType (t);
4238
4239 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
4240 && (ctype_isArrayPtr (rt)
4241 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4242 {
4243 voptgenerror
4244 (FLG_CASTFCNPTR,
4245 message ("Cast from function pointer type (%t) to "
4246 "non-function pointer (%t): %s",
4247 c, t, exprNode_unparse (ret)),
4248 e->loc);
4249 }
4250
4251 if (!ctype_isFunction (ctype_baseArrayPtr (c))
4252 && (ctype_isArrayPtr (rt)
4253 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4254 {
4255 voptgenerror
4256 (FLG_CASTFCNPTR,
4257 message ("Cast from non-function pointer type (%t) to "
4258 "function pointer (%t): %s",
4259 c, t, exprNode_unparse (ret)),
4260 e->loc);
4261 }
4262
4263 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
4264 !(ctype_isRealAbstract (bc)
4265 && context_hasAccess (ctype_typeId (bc))))
4266 {
4267 ; /* okay to cast zero */
4268 }
4269 else
4270 {
4271 if (ctype_isRealAbstract (bc)
4272 && !context_hasAccess (ctype_typeId (bc)))
4273 {
4274 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
4275 {
4276 vnoptgenerror
4277 (FLG_ABSTVOIDP,
4278 message ("Cast to underlying abstract type %t: %s",
4279 c, exprNode_unparse (ret)),
4280 e->loc);
4281 }
4282 else
4283 {
4284 voptgenerror
4285 (FLG_ABSTRACT,
4286 message ("Cast to underlying abstract type %t: %s",
4287 c, exprNode_unparse (ret)),
4288 e->loc);
4289 }
4290 }
4291
4292 if (ctype_isRealAbstract (bt)
4293 && !context_hasAccess (ctype_typeId (bt)))
4294 {
4295 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
4296 {
4297 vnoptgenerror
4298 (FLG_ABSTVOIDP,
4299 message ("Cast from underlying abstract type %t: %s",
4300 t, exprNode_unparse (ret)),
4301 e->loc);
4302 }
4303 else
4304 {
4305 voptgenerror
4306 (FLG_ABSTRACT,
4307 message ("Cast from underlying abstract type %t: %s",
4308 t, exprNode_unparse (ret)),
4309 e->loc);
4310 }
4311 }
4312 }
4313 }
4314 else
4315 {
4316 ctype bt = ctype_realType (ctype_getBaseType (t));
4317 ctype bc = ctype_realType (ctype_getBaseType (c));
4318
4319 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
4320 {
4321 if (ctype_match (c, t))
4322 {
4323 if (ctype_equal (c, t))
4324 {
4325 voptgenerror
4326 (FLG_TYPE,
4327 message ("Redundant cast involving abstract type %t: %s",
4328 bt, exprNode_unparse (ret)),
4329 e->loc);
4330 }
4331 }
4332 else
4333 {
4334 voptgenerror
4335 (FLG_ABSTRACT,
4336 message ("Cast from abstract type %t: %s",
4337 bt, exprNode_unparse (ret)),
4338 e->loc);
4339 }
4340 }
4341
4342 if (ctype_isAbstract (bc)
4343 && !context_hasAccess (ctype_typeId (bc)))
4344 {
4345 if (ctype_match (c, t))
4346 {
4347 ;
4348 }
4349 else
4350 {
4351 voptgenerror
4352 (FLG_ABSTRACT,
4353 message ("Cast to abstract type %t: %s", bc,
4354 exprNode_unparse (ret)),
4355 e->loc);
4356 }
4357 }
4358 }
4359
4360 if (ctype_isAbstract (c))
4361 {
4362 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
4363 {
4364 /* okay, cast exposed to abstract */
4365 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
4366 }
4367 else
4368 {
4369 if (ctype_isVisiblySharable (t)
4370 && sRef_isExternallyVisible (e->sref)
4371 && !(ctype_isAbstract (t)
4372 && context_hasAccess (ctype_typeId (t))))
4373 {
4374 voptgenerror
4375 (FLG_CASTEXPOSE,
4376 message ("Cast to abstract type from externally visible "
4377 "mutable storage exposes rep of %s: %s",
4378 ctype_unparse (c),
4379 exprNode_unparse (e)),
4380 e->loc);
4381 }
4382 }
4383 }
4384
4385 return (ret);
4386}
4387
4388static bool
4389evaluationOrderUndefined (lltok op)
4390{
4391 int opid = lltok_getTok (op);
4392
4393 return (opid != AND_OP && opid != OR_OP);
4394}
4395
4396static bool checkIntegral (/*@notnull@*/ exprNode e1,
4397 /*@notnull@*/ exprNode e2,
4398 /*@notnull@*/ exprNode ret,
4399 lltok op)
4400{
4401 bool error = FALSE;
4402
4403 ctype te1 = exprNode_getType (e1);
4404 ctype te2 = exprNode_getType (e2);
4405
4406 ctype tr1 = ctype_realishType (te1);
4407 ctype tr2 = ctype_realishType (te2);
4408
4409 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
4410 {
4411 ;
4412 }
4413 else
4414 {
4415 if (context_msgStrictOps ())
4416 {
4417 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
4418 {
4419 if (ctype_sameName (te1, te2))
4420 {
4421 error = optgenerror
4422 (FLG_STRICTOPS,
4423 message ("Operands of %s are non-integer (%t): %s",
4424 lltok_unparse (op), te1,
4425 exprNode_unparse (ret)),
4426 e1->loc);
4427 }
4428 else
4429 {
4430 error = optgenerror
4431 (FLG_STRICTOPS,
4432 message ("Operands of %s are non-integers (%t, %t): %s",
4433 lltok_unparse (op), te1, te2,
4434 exprNode_unparse (ret)),
4435 e1->loc);
4436 }
4437 }
4438 else if (!ctype_isInt (tr1))
4439 {
4440 error = optgenerror
4441 (FLG_STRICTOPS,
4442 message ("Left operand of %s is non-integer (%t): %s",
4443 lltok_unparse (op), te1, exprNode_unparse (ret)),
4444 e1->loc);
4445 }
4446 else
4447 /* !ctype_isInt (te2) */
4448 {
4449 error = optgenerror
4450 (FLG_STRICTOPS,
4451 message ("Right operand of %s is non-integer (%t): %s",
4452 lltok_unparse (op), te2, exprNode_unparse (ret)),
4453 e2->loc);
4454 }
4455 }
4456 }
4457
4458 return !error;
4459}
4460
4461/*
4462** returns exprNode representing e1 op e2
4463**
4464** uses msg if there are errors
4465** can be used for both assignment ops and regular ops
4466**
4467** modifies e1
4468*/
4469
4470static /*@only@*/ /*@notnull@*/ exprNode
4471exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
4472 /*@keep@*/ lltok op)
4473{
4474 ctype te1, te2, tr1, tr2, tret;
4475 int opid = lltok_getTok (op);
4476 bool hasError = FALSE;
4477 exprNode ret;
4478
4479 if (exprNode_isError (e1))
4480 {
4481 ret = exprNode_createPartialNVCopy (e2);
4482 }
4483 else
4484 {
4485 ret = exprNode_createPartialNVCopy (e1);
4486 }
4487
4488 ret->val = multiVal_undefined;
4489 ret->kind = XPR_OP;
4490 ret->edata = exprData_makeOp (e1, e2, op);
4491
4492 if (exprNode_isError (e1) || exprNode_isError (e2))
4493 {
4494 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
4495 || opid == EQ_OP || opid == NE_OP
4496 || opid == AND_OP || opid == OR_OP)
4497 {
4498 ret->typ = ctype_bool;
4499 }
4500
4501 if (exprNode_isDefined (e1))
4502 {
4503 exprNode_checkUse (ret, e1->sref, e1->loc);
4504 }
4505
4506 if (exprNode_isDefined (e2))
4507 {
4508 exprNode_mergeUSs (ret, e2);
4509 exprNode_checkUse (ret, e2->sref, e2->loc);
4510 }
4511
4512 return ret;
4513 }
4514
4515 tret = ctype_unknown;
4516 te1 = exprNode_getType (e1);
4517 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
4518
4519 te2 = exprNode_getType (e2);
4520
4521 tr1 = ctype_realishType (te1);
4522 tr2 = ctype_realishType (te2);
4523
4524 if (opid == OR_OP)
4525 {
4526 ret->guards = guardSet_or (ret->guards, e2->guards);
4527 }
4528 else if (opid == AND_OP)
4529 {
4530 ret->guards = guardSet_and (ret->guards, e2->guards);
4531 }
4532 else
4533 {
4534 /* no guards */
4535 }
4536
4537 if (opid == EQ_OP || opid == NE_OP)
4538 {
4539 exprNode temp1 = e1, temp2 = e2;
4540
4541 /* could do NULL == x */
4542
4543 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
4544 {
4545 temp1 = e2; temp2 = e1;
4546 }
4547
4548 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
4549 {
4550 reflectNullTest (temp1, (opid == NE_OP));
4551 guardSet_free (ret->guards);
4552 ret->guards = guardSet_copy (temp1->guards);
4553 }
4554 }
4555
4556 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
4557 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
4558 {
4559 tret = ctype_bool;
4560 }
4561
4562 if (anyAbstract (tr1, tr2) &&
4563 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
4564 (opid == AND_OP || opid == OR_OP
4565 || opid == EQ_OP || opid == NE_OP))))
4566 {
4567 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
4568 }
4569 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
4570 {
4571 /* unknown types, no comparisons possible */
4572 }
4573 else
4574 {
4575 switch (opid)
4576 {
4577 case TMULT: /* multiplication and division: */
4578 case TDIV: /* */
4579 case MUL_ASSIGN: /* numeric, numeric -> numeric */
4580 case DIV_ASSIGN: /* */
4581
4582 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
4583 break;
4584
4585 case TPLUS: /* addition and subtraction: */
4586 case TMINUS: /* pointer, int -> pointer */
4587 case SUB_ASSIGN: /* int, pointer -> pointer */
4588 case ADD_ASSIGN: /* numeric, numeric -> numeric */
4589
4590 tr1 = ctype_fixArrayPtr (tr1);
4591
4592 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
4593 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
4594 {
4595 /* pointer + int */
4596
4597 if (context_msgPointerArith ())
4598 {
4599 voptgenerror
4600 (FLG_POINTERARITH,
4601 message ("Pointer arithmetic (%t, %t): %s",
4602 te1, te2, exprNode_unparse (ret)),
4603 e1->loc);
4604 }
4605
4606 if (sRef_possiblyNull (e1->sref)
4607 && !usymtab_isGuarded (e1->sref))
4608 {
4609 voptgenerror
4610 (FLG_NULLPOINTERARITH,
4611 message ("Pointer arithmetic involving possibly "
4612 "null pointer %s: %s",
4613 exprNode_unparse (e1),
4614 exprNode_unparse (ret)),
4615 e1->loc);
4616 }
4617
4618 ret->sref = sRef_copy (e1->sref);
4619
4620 /* start modifications */
4621 /* added by Seejo on 4/16/2000 */
4622
4623 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4624 status */
4625 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
4626 //if (sRef_isKnown (e->sref)) {
4627 //ret->sref = sRef_makeAddress (e->sref);
4628 //}
4629
4630 int val;
4631 /*drl 1-4-2001
4632 added ugly fixed to stop
4633 program from crashing on point + int +int
4634 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
4635
4636 if (!multiVal_isInt (e2->val) )
4637 break;
4638 /*end drl*/
4639
4640 val = (int) multiVal_forceInt (e2->val);
4641
4642 /* Operator : + or += */
4643 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
4644 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
4645 val should not result in a
4646 size < 0 (size = 0 is ok !) */
4647
4648 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
4649
4650 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
4651 sRef_setNotNullTerminatedState(ret->sref);
4652 sRef_resetLen (ret->sref);
4653 } else {
4654 sRef_setNullTerminatedState(ret->sref);
4655 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
4656 }
4657 }
4658 }
4659
4660 /* Operator : - or -= */
4661 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
4662 if (sRef_getSize(e1->sref) >= 0) {
4663 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
4664 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
4665 }
4666 }
4667 }
4668
4669 /* end modifications */
4670
4671 sRef_setNullError (ret->sref);
4672
4673 /*
4674 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
4675 ** since is points to storage that should not be deallocated
4676 ** through this pointer.
4677 */
4678
4679 if (sRef_isOnly (ret->sref)
4680 || sRef_isFresh (ret->sref))
4681 {
4682 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
4683 }
4684
4685 tret = e1->typ;
4686 }
4687 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
4688 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
4689 {
4690 if (context_msgPointerArith ())
4691 {
4692 voptgenerror
4693 (FLG_POINTERARITH,
4694 message ("Pointer arithmetic (%t, %t): %s",
4695 te1, te2, exprNode_unparse (ret)),
4696 e1->loc);
4697 }
4698
4699 if (sRef_possiblyNull (e1->sref)
4700 && !usymtab_isGuarded (e1->sref))
4701 {
4702 voptgenerror
4703 (FLG_NULLPOINTERARITH,
4704 message ("Pointer arithmetic involving possibly "
4705 "null pointer %s: %s",
4706 exprNode_unparse (e2),
4707 exprNode_unparse (ret)),
4708 e2->loc);
4709 }
4710
4711 ret->sref = sRef_copy (e2->sref);
4712
4713 /* start modifications */
4714 /* added by Seejo on 4/16/2000 */
4715
4716 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4717 status */
4718
4719 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
4720 //if (sRef_isKnown (e->sref)) {
4721 //ret->sref = sRef_makeAddress (e->sref);
4722 //}
4723
4724 int val = (int) multiVal_forceInt (e1->val);
4725
4726 /* Operator : + or += */
4727 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
4728 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
4729 val should not result in a
4730 size < 0 (size = 0 is ok !) */
4731
4732 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
4733
4734 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
4735 sRef_setNotNullTerminatedState(ret->sref);
4736 sRef_resetLen (ret->sref);
4737 } else {
4738 sRef_setNullTerminatedState(ret->sref);
4739 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
4740 }
4741 }
4742 }
4743
4744 /* Operator : - or -= */
4745 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
4746 if (sRef_getSize(e2->sref) >= 0) {
4747 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
4748 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
4749 }
4750 }
4751 }
4752
4753 /* end modifications */
4754
4755 sRef_setNullError (ret->sref);
4756
4757 /*
4758 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
4759 ** since is points to storage that should not be deallocated
4760 ** through this pointer.
4761 */
4762
4763 if (sRef_isOnly (ret->sref)
4764 || sRef_isFresh (ret->sref)) {
4765 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
4766 }
4767
4768 tret = e2->typ;
4769 ret->sref = e2->sref;
4770 }
4771 else
4772 {
4773 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
4774 }
4775
4776 break;
4777
4778 case LEFT_ASSIGN: /* Shifts: should be unsigned values */
4779 case RIGHT_ASSIGN:
4780 case LEFT_OP:
4781 case RIGHT_OP:
4782 case TAMPERSAND: /* bitwise & */
4783 case AND_ASSIGN:
4784 case TCIRC: /* ^ (XOR) */
4785 case TBAR:
4786 case XOR_ASSIGN:
4787 case OR_ASSIGN:
4788 {
4789 bool reported = FALSE;
4790 flagcode code = FLG_BITWISEOPS;
4791
4792 if (opid == LEFT_OP || opid == LEFT_ASSIGN
4793 || opid == RIGHT_OP || opid == RIGHT_ASSIGN) {
4794 code = FLG_SHIFTSIGNED;
4795 }
4796
4797 if (!ctype_isUnsigned (tr1))
4798 {
4799 if (exprNode_isNonNegative (e1)) {
4800 ;
4801 } else {
4802 reported = optgenerror
4803 (code,
4804 message ("Left operand of %s is not unsigned value (%t): %s",
4805 lltok_unparse (op), te1,
4806 exprNode_unparse (ret)),
4807 e1->loc);
4808
4809 if (reported) {
4810 te1 = ctype_uint;
4811 }
4812 }
4813 }
4814 else
4815 {
4816 /* right need not be signed for shifts */
4817 if (code != FLG_SHIFTSIGNED
4818 && !ctype_isUnsigned (tr2))
4819 {
4820 if (!exprNode_isNonNegative (e2)) {
4821 reported = optgenerror
4822 (code,
4823 message ("Right operand of %s is not unsigned value (%t): %s",
4824 lltok_unparse (op), te2,
4825 exprNode_unparse (ret)),
4826 e2->loc);
4827 }
4828 }
4829 }
4830
4831 if (!reported)
4832 {
4833 if (!checkIntegral (e1, e2, ret, op)) {
4834 te1 = ctype_unknown;
4835 }
4836 }
4837
4838 DPRINTF (("Set: %s", ctype_unparse (te1)));
4839
4840 /*
4841 ** tret is the widest type of te1 and te2
4842 */
4843
4844 tret = ctype_widest (te1, te2);
4845 break;
4846 }
4847 case MOD_ASSIGN:
4848 case TPERCENT:
4849 if (checkIntegral (e1, e2, ret, op)) {
4850 tret = te1;
4851 } else {
4852 tret = ctype_unknown;
4853 }
4854 break;
4855 case EQ_OP:
4856 case NE_OP:
4857 case TLT: /* comparisons */
4858 case TGT: /* numeric, numeric -> bool */
4859 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
4860 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
4861 {
4862 ctype rtype = tr1;
4863 bool fepsilon = FALSE;
4864
4865 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
4866 {
4867 rtype = tr2;
4868 }
4869
4870 if (opid == TLT || opid == TGT)
4871 {
4872 uentry ue1 = exprNode_getUentry (e1);
4873 uentry ue2 = exprNode_getUentry (e2);
4874
4875 /*
4876 ** FLT_EPSILON, etc. really is a variable, not
4877 ** a constant.
4878 */
4879
4880 if (uentry_isVariable (ue1))
4881 {
4882 cstring uname = uentry_rawName (ue1);
4883
4884 if (cstring_equalLit (uname, "FLT_EPSILON")
4885 || cstring_equalLit (uname, "DBL_EPSILON")
4886 || cstring_equalLit (uname, "LDBL_EPSILON"))
4887 {
4888 fepsilon = TRUE;
4889 }
4890 }
4891
4892 if (uentry_isVariable (ue2))
4893 {
4894 cstring uname = uentry_rawName (ue2);
4895
4896 if (cstring_equalLit (uname, "FLT_EPSILON")
4897 || cstring_equalLit (uname, "DBL_EPSILON")
4898 || cstring_equalLit (uname, "LDBL_EPSILON"))
4899 {
4900 fepsilon = TRUE;
4901 }
4902 }
4903 }
4904
4905 if (fepsilon)
4906 {
4907 ; /* Don't complain. */
4908 }
4909 else
4910 {
4911 voptgenerror
4912 (FLG_REALCOMPARE,
4913 message ("Dangerous comparison involving %s types: %s",
4914 ctype_unparse (rtype),
4915 exprNode_unparse (ret)),
4916 ret->loc);
4917 }
4918 }
4919 /*@fallthrough@*/
4920 case LE_OP:
4921 case GE_OP:
4922
4923 /*
4924 ** Types should match.
4925 */
4926
4927 if (!exprNode_matchTypes (e1, e2))
4928 {
4929 hasError = gentypeerror
4930 (te1, e1, te2, e2,
4931 message ("Operands of %s have incompatible types (%t, %t): %s",
4932 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
4933 e1->loc);
4934
4935 }
4936
4937 if (hasError
4938 || (ctype_isForceRealNumeric (&tr1)
4939 && ctype_isForceRealNumeric (&tr2)) ||
4940 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
4941 {
4942 ; /* okay */
4943 }
4944 else
4945 {
4946 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
4947 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
4948 {
4949 voptgenerror
4950 (FLG_PTRNUMCOMPARE,
4951 message ("Comparison of pointer and numeric (%t, %t): %s",
4952 te1, te2, exprNode_unparse (ret)),
4953 e1->loc);
4954 }
4955 else
4956 {
4957 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
4958 }
4959 tret = ctype_bool;
4960 }
4961
4962 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
4963
4964 if ((opid == EQ_OP || opid == NE_OP) &&
4965 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
4966 {
4967 /*
4968 ** is one a variable?
4969 */
4970
4971 if (uentry_isVariable (exprNode_getUentry (e1))
4972 || uentry_isVariable (exprNode_getUentry (e2)))
4973 {
4974 /*
4975 ** comparisons with FALSE are okay
4976 */
4977
4978 if (exprNode_isFalseConstant (e1)
4979 || exprNode_isFalseConstant (e2))
4980 {
4981 ;
4982 }
4983 else
4984 {
4985 voptgenerror
4986 (FLG_BOOLCOMPARE,
4987 message
4988 ("Use of %q with %s variables (risks inconsistency because "
4989 "of multiple true values): %s",
4990 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
4991 context_printBoolName (), exprNode_unparse (ret)),
4992 e1->loc);
4993 }
4994 }
4995 }
4996 break;
4997
4998 case AND_OP: /* bool, bool -> bool */
4999 case OR_OP:
5000
5001 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5002 {
5003 ;
5004 }
5005 else
5006 {
5007 if (context_maybeSet (FLG_BOOLOPS))
5008 {
5009 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5010 {
5011 if (ctype_sameName (te1, te2))
5012 {
5013 voptgenerror
5014 (FLG_BOOLOPS,
5015 message ("Operands of %s are non-boolean (%t): %s",
5016 lltok_unparse (op), te1,
5017 exprNode_unparse (ret)),
5018 e1->loc);
5019 }
5020 else
5021 {
5022 voptgenerror
5023 (FLG_BOOLOPS,
5024 message
5025 ("Operands of %s are non-booleans (%t, %t): %s",
5026 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5027 e1->loc);
5028 }
5029 }
5030 else if (!ctype_isRealBool (te1))
5031 {
5032 voptgenerror
5033 (FLG_BOOLOPS,
5034 message ("Left operand of %s is non-boolean (%t): %s",
5035 lltok_unparse (op), te1, exprNode_unparse (ret)),
5036 e1->loc);
5037 }
5038 else if (!ctype_isRealBool (te2))
5039 {
5040 voptgenerror
5041 (FLG_BOOLOPS,
5042 message ("Right operand of %s is non-boolean (%t): %s",
5043 lltok_unparse (op), te2, exprNode_unparse (ret)),
5044 e2->loc);
5045 }
5046 else
5047 {
5048 ;
5049 }
5050 }
5051 tret = ctype_bool;
5052 }
5053 break;
5054 default: {
5055 llfatalbug
5056 (cstring_makeLiteral
5057 ("There has been a problem in the parser. This is due to a bug "
5058 "in either lclint, bison or gcc version 2.95 optimizations, "
5059 "but it has not been confirmed. Please try rebuidling LCLint "
5060 "without the -O<n> option."));
5061 }
5062 }
5063 }
5064
5065 DPRINTF (("Return type: %s", ctype_unparse (tret)));
5066 ret->typ = tret;
5067
5068 exprNode_checkUse (ret, e1->sref, e1->loc);
5069 exprNode_mergeUSs (ret, e2);
5070 exprNode_checkUse (ret, e2->sref, e2->loc);
5071
5072 return ret;
5073}
5074
5075/*@only@*/ exprNode
5076exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5077 /*@only@*/ lltok op)
5078{
5079 exprNode ret;
5080
5081 checkMacroParen (e1);
5082 checkMacroParen (e2);
5083
5084 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5085 {
5086 checkExpressionDefined (e1, e2, op);
5087 }
5088
5089 ret = exprNode_makeOp (e1, e2, op);
5090 return (ret);
5091}
5092
5093static
5094void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5095{
5096 /*
5097 ** This is somewhat bogus!
5098 **
5099 ** Assigning to a nested observer in a non-observer datatype
5100 ** should not produce an error.
5101 */
5102
5103 sRef ref = exprNode_getSref (e1);
5104
5105 DPRINTF (("Check assign mod: %s",
5106 sRef_unparseFull (ref)));
5107
5108 if (sRef_isObserver (ref)
5109 || ((sRef_isFileStatic (ref) || sRef_isGlobal (ref))
5110 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5111 {
5112 sRef base = sRef_getBase (ref);
5113
5114 if (sRef_isValid (base) && sRef_isObserver (base))
5115 {
5116 exprNode_checkModify (e1, ret);
5117 }
5118 else
5119 {
5120 exprNode_checkModifyVal (e1, ret);
5121 }
5122 }
5123 else
5124 {
5125 exprNode_checkModify (e1, ret);
5126 }
5127}
5128
5129exprNode
5130exprNode_assign (/*@only@*/ exprNode e1,
5131 /*@only@*/ exprNode e2, /*@only@*/ lltok op)
5132{
5133 bool isalloc = FALSE;
5134 bool isjustalloc = FALSE;
5135 exprNode ret;
5136
5137 DPRINTF (("%s [%s] <- %s [%s]",
5138 exprNode_unparse (e1),
5139 ctype_unparse (e1->typ),
5140 exprNode_unparse (e2),
5141 ctype_unparse (e2->typ)));
5142
5143 if (lltok_getTok (op) != TASSIGN)
5144 {
5145 ret = exprNode_makeOp (e1, e2, op);
5146 }
5147 else
5148 {
5149 ret = exprNode_createPartialCopy (e1);
5150 ret->kind = XPR_ASSIGN;
5151 ret->edata = exprData_makeOp (e1, e2, op);
5152
5153 if (!exprNode_isError (e2))
5154 {
5155 ret->sets = sRefSet_union (ret->sets, e2->sets);
5156 ret->msets = sRefSet_union (ret->msets, e2->msets);
5157 ret->uses = sRefSet_union (ret->uses, e2->uses);
5158 }
5159 }
5160
5161 checkExpressionDefined (e1, e2, op);
5162
5163 if (exprNode_isError (e1))
5164 {
5165 if (!exprNode_isError (e2))
5166 {
5167 ret->loc = fileloc_update (ret->loc, e2->loc);
5168 }
5169 else
5170 {
5171 ret->loc = fileloc_update (ret->loc, g_currentloc);
5172 }
5173 }
5174
5175 if (!exprNode_isError (e2))
5176 {
5177 checkMacroParen (e2);
5178 }
5179
5180 if (exprNode_isDefined (e1))
5181 {
5182 if (sRef_isMacroParamRef (e1->sref))
5183 {
5184 if (context_inIterDef ())
5185 {
5186 uentry ue = sRef_getUentry (e1->sref);
5187
5188 if (uentry_isYield (ue))
5189 {
5190 ;
5191 }
5192 else
5193 {
5194 if (fileloc_isDefined (e1->loc))
5195 {
5196 voptgenerror
5197 (FLG_MACROPARAMS,
5198 message ("Assignment to non-yield iter parameter: %q",
5199 sRef_unparse (e1->sref)),
5200 e1->loc);
5201 }
5202 else
5203 {
5204 voptgenerror
5205 (FLG_MACROPARAMS,
5206 message ("Assignment to non-yield iter parameter: %q",
5207 sRef_unparse (e1->sref)),
5208 g_currentloc);
5209 }
5210 }
5211 }
5212 else
5213 {
5214 if (fileloc_isDefined (e1->loc))
5215 {
5216 voptgenerror
5217 (FLG_MACROASSIGN,
5218 message ("Assignment to macro parameter: %q",
5219 sRef_unparse (e1->sref)),
5220 e1->loc);
5221 }
5222 else
5223 {
5224 voptgenerror
5225 (FLG_MACROASSIGN,
5226 message ("Assignment to macro parameter: %q",
5227 sRef_unparse (e1->sref)),
5228 g_currentloc);
5229 }
5230 }
5231 }
5232 else
5233 {
5234 exprNode_checkAssignMod (e1, ret);
5235 }
5236
5237 if (exprNode_isDefined (e2))
5238 {
5239 if (lltok_getTok (op) == TASSIGN)
5240 {
5241 ctype te1 = exprNode_getType (e1);
5242 ctype te2 = exprNode_getType (e2);
5243
5244 if (!ctype_forceMatch (te1, te2))
5245 {
5246 if (exprNode_matchLiteral (te1, e2))
5247 {
5248 ;
5249 }
5250 else
5251 {
5252 (void) gentypeerror
5253 (te2, e2, te1, e1,
5254 message ("Assignment of %t to %t: %s %s %s",
5255 te2, te1, exprNode_unparse (e1),
5256 lltok_unparse (op),
5257 exprNode_unparse (e2)),
5258 e1->loc);
5259 }
5260 }
5261 }
5262
5263 exprNode_mergeUSs (ret, e2);
5264 exprNode_checkUse (ret, e2->sref, e2->loc);
5265
5266 doAssign (e1, e2, FALSE);
5267 ret->sref = e1->sref;
5268 }
5269 else
5270 {
5271 if (exprNode_isDefined (e2))
5272 {
5273 exprNode_mergeUSs (ret, e2);
5274 exprNode_checkUse (ret, e2->sref, e2->loc);
5275 }
5276 }
5277
5278 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
5279 {
5280 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
5281 }
5282
5283 isjustalloc = sRef_isJustAllocated (e1->sref);
5284 isalloc = sRef_isAllocated (e1->sref);
5285
5286 if (sRef_isField (e1->sref))
5287 {
5288 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
5289
5290 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
5291 {
5292 exprNode_checkUse (ret, root, e1->loc);
5293 }
5294
5295 }
5296
5297 /*
5298 ** be careful! this defines e1->sref.
5299 */
5300
5301 if (!sRef_isMacroParamRef (e1->sref))
5302 {
5303 exprNode_checkSet (ret, e1->sref);
5304 }
5305
5306 if (isjustalloc)
5307 {
5308 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
5309 ? e2->loc : e1->loc);
5310 }
5311 else
5312 {
5313 if (isalloc)
5314 {
5315 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
5316 }
5317 }
5318 }
5319
5320 return ret;
5321}
5322
5323exprNode
5324exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
5325 /*@keep@*/ exprNode elseclause)
5326{
5327 exprNode ret;
5328
5329 if (!exprNode_isError (pred))
5330 {
5331 ret = exprNode_createPartialCopy (pred);
5332 checkMacroParen (pred);
5333 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
5334
5335 if (!exprNode_isError (ifclause))
5336 {
5337 checkMacroParen (ifclause); /* update macro counts! */
5338
5339 if (!exprNode_isError (elseclause))
5340 {
5341 checkMacroParen (elseclause);
5342
5343 if (!exprNode_matchTypes (ifclause, elseclause))
5344 {
5345 if (gentypeerror
5346 (exprNode_getType (ifclause),
5347 ifclause,
5348 exprNode_getType (elseclause),
5349 elseclause,
5350 message ("Conditional clauses are not of same type: "
5351 "%s (%t), %s (%t)",
5352 exprNode_unparse (ifclause),
5353 exprNode_getType (ifclause),
5354 exprNode_unparse (elseclause),
5355 exprNode_getType (elseclause)),
5356 ifclause->loc))
5357 {
5358 ret->sref = sRef_undefined;
5359 ret->typ = ctype_unknown;
5360 }
5361 }
5362 else
5363 {
5364 /* for now...should merge the states */
5365 ret->sref = ifclause->sref;
5366 ret->typ = ifclause->typ;
5367
5368 if (exprNode_isNullValue (ifclause))
5369 {
5370 ret->typ = elseclause->typ;
5371 }
5372 }
5373
5374 exprNode_checkUse (ret, pred->sref, pred->loc);
5375 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
5376 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5377
5378 exprNode_mergeCondUSs (ret, ifclause, elseclause);
5379
5380 }
5381 else
5382 {
5383 ret->typ = ifclause->typ;
5384
5385 exprNode_checkUse (pred, pred->sref, pred->loc);
5386 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
5387
5388 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
5389 }
5390 }
5391 else
5392 {
5393 if (!exprNode_isError (elseclause))
5394 {
5395 ret->typ = elseclause->typ;
5396
5397 exprNode_checkUse (pred, pred->sref, pred->loc);
5398 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5399
5400 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
5401 }
5402 }
5403 }
5404 else /* pred is error */
5405 {
5406 if (!exprNode_isError (ifclause))
5407 {
5408 ret = exprNode_createSemiCopy (ifclause);
5409
5410 checkMacroParen (ifclause); /* update macro counts! */
5411
5412 if (!exprNode_isError (elseclause))
5413 {
5414 checkMacroParen (elseclause);
5415
5416 ret->typ = ifclause->typ;
5417
5418 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
5419 {
5420 if (gentypeerror
5421 (exprNode_getType (ifclause),
5422 ifclause,
5423 exprNode_getType (elseclause),
5424 elseclause,
5425 message ("Conditional clauses are not of same type: "
5426 "%s (%t), %s (%t)",
5427 exprNode_unparse (ifclause),
5428 exprNode_getType (ifclause),
5429 exprNode_unparse (elseclause),
5430 exprNode_getType (elseclause)),
5431 ifclause->loc))
5432 {
5433 ret->typ = ctype_unknown;
5434 }
5435 }
5436
5437 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
5438 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5439
5440 exprNode_mergeCondUSs (ret, ifclause, elseclause);
5441 }
5442 }
5443 else if (!exprNode_isError (elseclause)) /* pred, if errors */
5444 {
5445 ret = exprNode_createSemiCopy (ifclause);
5446
5447 ret->typ = elseclause->typ;
5448 checkMacroParen (elseclause);
5449
5450 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5451 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
5452 }
5453 else /* all errors! */
5454 {
5455 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
5456 }
5457 }
5458
5459 ret->kind = XPR_COND;
5460 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
5461
5462 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
5463 {
5464 exprNode_combineControl (ret, ifclause, elseclause);
5465 }
5466
5467 return (ret);
5468}
5469
5470exprNode
5471exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
5472{
5473 ctype totype = qtype_getType (qt);
5474 exprNode ret =
5475 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
5476 ctype targ;
5477
5478 /*
5479 ** check use of va_arg : <valist>, type -> type
5480 */
5481
5482 if (exprNode_isError (arg))
5483 {
5484 }
5485 else
5486 {
5487 targ = exprNode_getType (arg);
5488
5489 /*
5490 ** arg should have be a pointer
5491 */
5492
5493 if (!ctype_isUA (targ) ||
5494 (!usymId_equal (ctype_typeId (targ),
5495 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
5496 {
5497 voptgenerror
5498 (FLG_TYPE,
5499 message ("First argument to va_arg is not a va_list (type %t): %s",
5500 targ, exprNode_unparse (arg)),
5501 arg->loc);
5502 }
5503
5504 exprNode_checkSet (ret, arg->sref);
5505 }
5506
5507 /*
5508 ** return type is totype
5509 */
5510
5511 ret->typ = totype;
5512 ret->kind = XPR_VAARG;
5513 ret->edata = exprData_makeCast (tok, arg, qt);
5514
5515 return (ret);
5516}
5517
5518exprNode exprNode_labelMarker (/*@only@*/ cstring label)
5519{
5520 exprNode ret = exprNode_createPlain (ctype_undefined);
5521 ret->kind = XPR_LABEL;
5522 ret->edata = exprData_makeLiteral (label);
5523 ret->isJumpPoint = TRUE;
5524
5525 return (ret); /* for now, ignore label */
5526}
5527
5528exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
5529{
5530 if (exprNode_isDefined (stmt))
5531 {
5532 stmt->isJumpPoint = TRUE;
5533
5534 /* This prevent stray no return path errors, etc. */
5535 stmt->exitCode = XK_MUSTEXIT;
5536 }
5537
5538 return (stmt);
5539}
5540
5541bool exprNode_isDefaultMarker (exprNode e)
5542{
5543 if (exprNode_isDefined (e))
5544 {
5545 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
5546 }
5547
5548 return FALSE;
5549}
5550
5551bool exprNode_isCaseMarker (exprNode e)
5552{
5553 if (exprNode_isDefined (e))
5554 {
5555 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
5556 }
5557
5558 return FALSE;
5559}
5560
5561bool exprNode_isLabelMarker (exprNode e)
5562{
5563 if (exprNode_isDefined (e))
5564 {
5565 return (e->kind == XPR_LABEL);
5566 }
5567
5568 return FALSE;
5569}
5570
5571exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
5572{
5573 exprNode ret = exprNode_createPartialCopy (test);
5574
5575 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
5576
5577 if (exprNode_isError (test)) {
5578 return ret;
5579 }
5580
5581 exprNode_checkUse (ret, test->sref, test->loc);
5582
5583 usymtab_setExitCode (ret->exitCode);
5584
5585 if (ret->mustBreak)
5586 {
5587 usymtab_setMustBreak ();
5588 }
5589
5590 ret->edata = exprData_makeSingle (test);
5591 ret->isJumpPoint = TRUE;
5592
5593 return ret;
5594}
5595
5596# if 0
5597exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
5598{
5599 exprNode ret = exprNode_createPartialCopy (test);
5600
5601 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
5602 ret->edata = exprData_makePair (test, stmt);
5603 ret->isJumpPoint = TRUE;
5604
5605 if (exprNode_isError (test))
5606 {
5607 return ret;
5608 }
5609
5610 exprNode_checkUse (ret, test->sref, test->loc);
5611
5612 if (exprNode_isError (stmt))
5613 {
5614 return ret;
5615 }
5616
5617 exprNode_mergeUSs (ret, stmt);
5618
5619 ret->exitCode = stmt->exitCode;
5620 ret->mustBreak = stmt->mustBreak;
5621 ret->canBreak = stmt->canBreak;
5622
5623 usymtab_setExitCode (ret->exitCode);
5624
5625 if (ret->mustBreak)
5626 {
5627 usymtab_setMustBreak ();
5628 }
5629
5630 return ret;
5631}
5632# endif
5633
5634/*@notnull@*/ /*@only@*/ exprNode
5635exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
5636{
5637 exprNode ret = exprNode_createTok (def);
5638
5639 ret->isJumpPoint = TRUE;
5640 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
5641 return (ret);
5642}
5643
5644bool
5645exprNode_mayEscape (exprNode e)
5646{
5647 if (exprNode_isDefined (e))
5648 {
5649 return exitkind_couldEscape (e->exitCode);
5650 }
5651 return FALSE;
5652}
5653
5654static bool
5655exprNode_mustBreak (exprNode e)
5656{
5657 if (exprNode_isDefined (e))
5658 {
5659 return e->mustBreak;
5660 }
5661 return FALSE;
5662}
5663
5664bool
5665exprNode_mustEscape (exprNode e)
5666{
5667 if (exprNode_isDefined (e))
5668 {
5669 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
5670 }
5671
5672 return FALSE;
5673}
5674
5675bool
5676exprNode_errorEscape (exprNode e)
5677{
5678 if (exprNode_isDefined (e))
5679 {
5680 return exitkind_isError (e->exitCode);
5681 }
5682
5683 return FALSE;
5684}
5685
5686exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
5687{
5688 exprNode ret = exprNode_createPartialCopy (e1);
5689
5690 ret->edata = exprData_makePair (e1, e2);
5691 ret->kind = XPR_STMTLIST;
5692
5693 if (exprNode_isDefined (e1))
5694 {
5695 ret->isJumpPoint = e1->isJumpPoint;
5696 ret->canBreak = e1->canBreak;
5697 }
5698 else
5699 {
5700 if (exprNode_isDefined (e2))
5701 {
5702 ret->loc = fileloc_update (ret->loc, e2->loc);
5703 }
5704 }
5705
5706 if (exprNode_isDefined (e2))
5707 {
5708 ret->exitCode = e2->exitCode;
5709 ret->mustBreak = e2->mustBreak;
5710 if (e2->canBreak) ret->canBreak = TRUE;
5711 }
5712
5713 /*
5714 ** if e1 must return, then e2 is unreachable!
5715 */
5716
5717 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
5718 {
5719 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
5720 && !(e2->isJumpPoint))
5721 {
5722 if (context_getFlag (FLG_UNREACHABLE))
5723 {
5724 exprNode nr = e2;
5725
5726 if (e2->kind == XPR_STMT)
5727 {
5728 nr = exprData_getUopNode (e2->edata);
5729 }
5730
5731 if ((nr->kind == XPR_TOK
5732 && lltok_isSemi (exprData_getTok (nr->edata))))
5733 {
5734 /* okay to have unreachable ";" */
5735 ret->exitCode = XK_MUSTEXIT;
5736 ret->canBreak = TRUE;
5737 }
5738 else
5739 {
5740 if (optgenerror (FLG_UNREACHABLE,
5741 message ("Unreachable code: %s",
5742 exprNode_unparseFirst (nr)),
5743 exprNode_loc (nr)))
5744 {
5745 ret->isJumpPoint = TRUE;
5746 ret->mustBreak = FALSE;
5747 ret->exitCode = XK_ERROR;
5748 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
5749 }
5750 else
5751 {
5752 ret->exitCode = XK_MUSTEXIT;
5753 ret->canBreak = TRUE;
5754 }
5755
5756 }
5757 }
5758 }
5759 else
5760 {
5761 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
5762 {
5763 /*
5764 ** We want a warning anytime we have:
5765 ** case xxx: ...
5766 ** yyy; <<<- no break or return
5767 ** case zzz: ...
5768 */
5769
5770 exprNode lastStmt = exprNode_lastStatement (e1);
5771
5772 if (exprNode_isDefined (lastStmt)
5773 && !exprNode_mustEscape (lastStmt)
5774 && !exprNode_mustBreak (lastStmt)
5775 && !exprNode_isCaseMarker (lastStmt)
5776 && !exprNode_isDefaultMarker (lastStmt)
5777 && !exprNode_isLabelMarker (lastStmt))
5778 {
5779 voptgenerror (FLG_CASEBREAK,
5780 cstring_makeLiteral
5781 ("Fall through case (no preceeding break)"),
5782 e2->loc);
5783 }
5784 }
5785 }
5786 }
5787
5788 exprNode_mergeUSs (ret, e2);
dc92450f 5789 // ret = exprNode_mergeEnvironments (ret, e1, e2);
616915dd 5790 usymtab_setExitCode (ret->exitCode);
5791
5792 if (ret->mustBreak)
5793 {
5794 usymtab_setMustBreak ();
5795 }
5796
5797 return ret;
5798}
5799
5800exprNode exprNode_createTok (/*@only@*/ lltok t)
5801{
5802 exprNode ret = exprNode_create (ctype_unknown);
5803 ret->kind = XPR_TOK;
5804 ret->edata = exprData_makeTok (t);
5805 return ret;
5806}
5807
5808exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
5809{
5810 if (!exprNode_isError (e))
5811 {
5812 exprNode_checkStatement(e);
5813 }
5814
5815 return (exprNode_statementError (e, t));
5816}
5817
5818static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
5819{
5820 exprNode ret = exprNode_createPartialCopy (e);
5821
5822 if (!exprNode_isError (e))
5823 {
5824 if (e->kind != XPR_ASSIGN)
5825 {
5826 exprNode_checkUse (ret, e->sref, e->loc);
5827 }
5828
5829 ret->exitCode = e->exitCode;
5830 ret->canBreak = e->canBreak;
5831 ret->mustBreak = e->mustBreak;
5832 }
5833
5834 ret->edata = exprData_makeUop (e, t);
5835 ret->kind = XPR_STMT;
5836
5837 return ret;
5838}
5839
5840exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
5841{
5842 if (!exprNode_isError (e))
5843 {
5844 if (e->kind != XPR_ASSIGN)
5845 {
5846 exprNode_checkUse (e, e->sref, e->loc);
5847 }
5848 }
5849
5850 return e;
5851}
5852
5853void exprNode_produceGuards (exprNode pred)
5854{
5855 if (!exprNode_isError (pred))
5856 {
5857 if (ctype_isRealPointer (pred->typ))
5858 {
5859 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
5860 }
5861
5862 exprNode_checkUse (pred, pred->sref, pred->loc);
5863 exprNode_resetSref (pred);
5864 }
5865}
5866
5867exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
5868{
5869 exprNode ret = exprNode_createPartialCopy (e);
5870
5871 if (!exprNode_isError (e))
5872 {
5873 ret->exitCode = e->exitCode;
5874 ret->canBreak = e->canBreak;
5875 ret->mustBreak = e->mustBreak;
5876 }
5877
5878 ret->edata = exprData_makeSingle (e);
5879 ret->kind = XPR_BLOCK;
5880 return ret;
5881}
5882
5883bool exprNode_isBlock (exprNode e)
5884{
5885 return (exprNode_isDefined (e)
5886 && ((e)->kind == XPR_BLOCK));
5887}
5888
5889bool exprNode_isAssign (exprNode e)
5890{
5891 if (exprNode_isDefined (e))
5892 {
5893 return (e->kind == XPR_ASSIGN);
5894 }
5895
5896 return FALSE;
5897}
5898
5899bool exprNode_isEmptyStatement (exprNode e)
5900{
5901 return (exprNode_isDefined (e)
5902 && (e->kind == XPR_TOK)
5903 && (lltok_isSemi (exprData_getTok (e->edata))));
5904}
5905
5906exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
5907{
5908 exprNode ret;
5909 bool emptyErr = FALSE;
5910
5911 if (context_maybeSet (FLG_IFEMPTY))
5912 {
5913 if (exprNode_isEmptyStatement (tclause))
5914 {
5915 emptyErr = optgenerror (FLG_IFEMPTY,
5916 cstring_makeLiteral
5917 ("Body of if statement is empty"),
5918 exprNode_loc (tclause));
5919 }
5920 }
5921
5922 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
5923 {
5924 if (exprNode_isDefined (tclause)
5925 && !exprNode_isBlock (tclause))
5926 {
5927 voptgenerror (FLG_IFBLOCK,
5928 message
5929 ("Body of if statement is not a block: %s",
5930 exprNode_unparse (tclause)),
5931 exprNode_loc (tclause));
5932 }
5933 }
5934
5935 if (exprNode_isError (pred))
5936 {
5937 if (exprNode_isError (tclause))
5938 {
5939 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
5940 }
5941 else
5942 {
5943 ret = exprNode_createPartialCopy (tclause);
5944 }
5945 }
5946 else
5947 {
5948 if (exprNode_mustEscape (pred))
5949 {
5950 voptgenerror
5951 (FLG_UNREACHABLE,
5952 message ("Predicate always exits: %s", exprNode_unparse (pred)),
5953 exprNode_loc (pred));
5954 }
5955
5956 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
5957 exprNode_checkUse (pred, pred->sref, pred->loc);
5958
5959 if (!exprNode_isError (tclause))
5960 {
5961 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
5962 }
5963
5964 ret = exprNode_createPartialCopy (pred);
5965 }
5966
5967 ret->kind = XPR_IF;
5968 ret->edata = exprData_makePair (pred, tclause);
5969
5970 ret->exitCode = XK_UNKNOWN;
5971
5972 if (exprNode_isDefined (tclause))
5973 {
5974 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
5975 ret->canBreak = tclause->canBreak;
5976 ret->sets = sRefSet_union (ret->sets, tclause->sets);
5977 ret->msets = sRefSet_union (ret->msets, tclause->msets);
5978 ret->uses = sRefSet_union (ret->uses, tclause->uses);
5979 }
5980
5981 ret->mustBreak = FALSE;
5982
5983 return ret;
5984}
5985
5986exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
5987 /*@only@*/ exprNode tclause,
5988 /*@only@*/ exprNode eclause)
5989{
5990 exprNode ret;
5991 bool tEmptyErr = FALSE;
5992 bool eEmptyErr = FALSE;
5993
5994 if (context_maybeSet (FLG_IFEMPTY))
5995 {
5996 if (exprNode_isEmptyStatement (tclause))
5997 {
5998 tEmptyErr = optgenerror
5999 (FLG_IFEMPTY,
6000 cstring_makeLiteral
6001 ("Body of if clause of if statement is empty"),
6002 exprNode_loc (tclause));
6003 }
6004
6005 if (exprNode_isEmptyStatement (eclause))
6006 {
6007 eEmptyErr = optgenerror
6008 (FLG_IFEMPTY,
6009 cstring_makeLiteral
6010 ("Body of else clause of if statement is empty"),
6011 exprNode_loc (eclause));
6012 }
6013 }
6014
6015 if (context_maybeSet (FLG_IFBLOCK))
6016 {
6017 if (!tEmptyErr
6018 && exprNode_isDefined (tclause)
6019 && !exprNode_isBlock (tclause))
6020 {
6021 voptgenerror (FLG_IFBLOCK,
6022 message
6023 ("Body of if clause of if statement is not a block: %s",
6024 exprNode_unparse (tclause)),
6025 exprNode_loc (tclause));
6026 }
6027
6028 if (!eEmptyErr
6029 && exprNode_isDefined (eclause)
6030 && !exprNode_isBlock (eclause)
6031 && !(eclause->kind == XPR_IF)
6032 && !(eclause->kind == XPR_IFELSE))
6033 {
6034 voptgenerror
6035 (FLG_IFBLOCK,
6036 message
6037 ("Body of else clause of if statement is not a block: %s",
6038 exprNode_unparse (eclause)),
6039 exprNode_loc (eclause));
6040 }
6041 }
6042
6043 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
6044 {
6045 if (exprNode_isDefined (eclause)
6046 && (eclause->kind == XPR_IF))
6047 {
6048 voptgenerror (FLG_ELSEIFCOMPLETE,
6049 message ("Incomplete else if logic (no final else): %s",
6050 exprNode_unparse (eclause)),
6051 exprNode_loc (eclause));
6052 }
6053 }
6054
6055 if (exprNode_isError (pred))
6056 {
6057 if (exprNode_isError (tclause))
6058 {
6059 if (exprNode_isError (eclause))
6060 {
6061 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6062 }
6063 else
6064 {
6065 ret = exprNode_createPartialCopy (eclause);
6066 }
6067 }
6068 else
6069 {
6070 ret = exprNode_createPartialCopy (tclause);
6071 }
6072 }
6073 else /* pred is okay */
6074 {
6075 ret = exprNode_createPartialCopy (pred);
6076
6077 if (exprNode_mustEscape (pred))
6078 {
6079 voptgenerror
6080 (FLG_UNREACHABLE,
6081 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6082 exprNode_loc (pred));
6083 }
6084
6085 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6086 exprNode_checkUse (ret, pred->sref, pred->loc);
6087
6088 exprNode_mergeCondUSs (ret, tclause, eclause);
6089 }
6090
6091 ret->kind = XPR_IFELSE;
6092 ret->edata = exprData_makeCond (pred, tclause, eclause);
6093
6094 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
6095 {
6096 exprNode_combineControl (ret, tclause, eclause);
6097 ret->loc = fileloc_update (ret->loc, eclause->loc);
6098 }
6099
6100 return ret;
6101}
6102
6103/*
6104** *allpaths <- TRUE iff all executions paths must go through the switch
6105*/
6106
6107static bool
6108checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
6109{
6110 exprNodeSList el = exprNode_flatten (e);
6111 bool mustReturn = TRUE; /* find a branch that doesn't */
6112 bool thisReturn = FALSE;
6113 bool hasDefault = FALSE;
6114 bool hasAllMembers = FALSE;
6115 bool inSwitch = FALSE;
6116 bool isEnumSwitch = FALSE;
6117 bool canBreak = FALSE;
6118 bool fallThrough = FALSE;
6119 ctype ct = ctype_unknown;
6120 enumNameSList usedEnums;
6121 enumNameList enums;
6122
6123 if (exprNode_isDefined (test))
6124 {
6125 ctype ttype;
6126
6127 ct = test->typ;
6128 ttype = ctype_realType (ct);
6129
6130 if (ctype_isEnum (ttype))
6131 {
6132 isEnumSwitch = TRUE;
6133 enums = ctype_elist (ttype);
6134 usedEnums = enumNameSList_new ();
6135 }
6136 }
6137
6138 exprNodeSList_elements (el, current)
6139 {
6140 if (exprNode_isDefined (current))
6141 {
6142 switch (current->kind)
6143 {
6144 case XPR_FTDEFAULT:
6145 case XPR_DEFAULT:
6146 if (hasDefault)
6147 {
6148 voptgenerror
6149 (FLG_CONTROL,
6150 message ("Duplicate default cases in switch"),
6151 exprNode_loc (current));
6152 }
6153 /*@fallthrough@*/
6154 case XPR_FTCASE:
6155 case XPR_CASE:
6156 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
6157 {
6158 hasDefault = TRUE;
6159 }
6160 else
6161 {
6162 if (isEnumSwitch)
6163 {
6164 exprNode st = exprData_getSingle (current->edata);
6165 uentry ue = exprNode_getUentry (st);
6166
6167 if (uentry_isValid (ue))
6168 {
6169 cstring cname = uentry_rawName (ue);
6170
6171 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
6172 {
6173 if (enumNameSList_member
6174 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
6175 {
6176 voptgenerror
6177 (FLG_CONTROL,
6178 message ("Duplicate case in switch: %s",
6179 cname),
6180 current->loc);
6181 }
6182 else
6183 {
6184 enumNameSList_addh (usedEnums, cname);
6185 }
6186 }
6187 else
6188 {
6189 voptgenerror
6190 (FLG_TYPE,
6191 message ("Case in switch not %s member: %s",
6192 ctype_unparse (ct), cname),
6193 current->loc);
6194 }
6195 }
6196 }
6197 }
6198
6199 if (inSwitch && !fallThrough)
6200 {
6201 if (!thisReturn || canBreak)
6202 {
6203 mustReturn = FALSE;
6204 }
6205 }
6206
6207 fallThrough = TRUE;
6208 inSwitch = TRUE;
6209 thisReturn = FALSE;
6210 canBreak = FALSE;
6211 /*@switchbreak@*/ break;
6212 default:
6213 thisReturn = thisReturn || exprNode_mustEscape (current);
6214 canBreak = canBreak || current->canBreak;
6215 if (canBreak) fallThrough = FALSE;
6216 }
6217 }
6218 } end_exprNodeSList_elements;
6219
6220 if (inSwitch) /* check the last one! */
6221 {
6222 if (!thisReturn || canBreak)
6223 {
6224 mustReturn = FALSE;
6225 }
6226 }
6227
6228 if (isEnumSwitch)
6229 {
6230 if (!hasDefault
6231 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
6232 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
6233 {
6234 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
6235
6236 voptgenerror (FLG_MISSCASE,
6237 message ("Missing case%s in switch: %q",
6238 cstring_makeLiteralTemp
6239 ((enumNameSList_size (unused) > 1) ? "s" : ""),
6240 enumNameSList_unparse (unused)),
6241 g_currentloc);
6242
6243 enumNameSList_free (unused);
6244 }
6245 else
6246 {
6247 hasAllMembers = TRUE;
6248 *allpaths = TRUE;
6249 }
6250
6251 enumNameSList_free (usedEnums);
6252 }
6253 else
6254 {
6255 *allpaths = hasDefault;
6256 }
6257
6258 exprNodeSList_free (el);
6259 return ((hasDefault || hasAllMembers) && mustReturn);
6260}
6261
6262exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
6263{
6264 exprNode ret = exprNode_createPartialCopy (e);
6265 bool allpaths;
6266
6267 DPRINTF (("Switch: %s", exprNode_unparse (s)));
6268
6269 ret->kind = XPR_SWITCH;
6270 ret->edata = exprData_makePair (e, s);
6271
6272 if (!exprNode_isError (s))
6273 {
6274 exprNode fs = exprNode_firstStatement (s);
6275 ret->loc = fileloc_update (ret->loc, s->loc);
6276
6277 if (exprNode_isUndefined (fs)
6278 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
6279 || exprNode_isDefaultMarker (fs)) {
6280 ;
6281 } else {
6282 voptgenerror (FLG_FIRSTCASE,
6283 message
6284 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
6285 fs->loc);
6286 }
6287 }
6288
6289 if (!exprNode_isError (e))
6290 {
6291 if (checkSwitchExpr (e, s, &allpaths))
6292 {
6293 ret->exitCode = XK_MUSTRETURN;
6294 }
6295 else
6296 {
6297 ret->exitCode = e->exitCode;
6298 }
6299
6300 ret->canBreak = e->canBreak;
6301 ret->mustBreak = e->mustBreak;
6302 }
6303 /*
6304 ** forgot this!
6305 ** exprNode.c:3883,32: Variable allpaths used before definition
6306 */
6307 else
6308 {
6309 allpaths = FALSE;
6310 }
6311
6312 DPRINTF (("Context exit switch!"));
6313 context_exitSwitch (ret, allpaths);
6314 DPRINTF (("Context exit switch done!"));
6315
6316 return ret;
6317}
6318
6319static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
6320 /*@notnull@*/ exprNode body)
6321{
6322 sRefSet tuses = test->uses;
6323
6324 if (!sRefSet_isEmpty (test->uses))
6325 {
6326 sRefSet sets = sRefSet_newCopy (body->sets);
6327 bool hasError = TRUE;
6328 bool innerState = FALSE;
6329 sRefSet tuncon = sRefSet_undefined;
6330
6331 sets = sRefSet_union (sets, test->sets);
6332 sets = sRefSet_union (sets, body->msets);
6333 sets = sRefSet_union (sets, test->msets);
6334
6335 sRefSet_allElements (tuses, el)
6336 {
6337 if (sRef_isUnconstrained (el))
6338 {
6339 tuncon = sRefSet_insert (tuncon, el);
6340 }
6341 else
6342 {
6343 if (sRefSet_member (sets, el))
6344 {
6345 hasError = FALSE;
6346 break;
6347 }
6348 }
6349
6350 if (sRef_isInternalState (el)
6351 || sRef_isFileStatic (sRef_getRootBase (el)))
6352 {
6353 innerState = TRUE;
6354 }
6355 } end_sRefSet_allElements ;
6356
6357 if (hasError)
6358 {
6359 sRefSet suncon = sRefSet_undefined;
6360 bool sinner = FALSE;
6361
6362 sRefSet_allElements (sets, el)
6363 {
6364 if (sRef_isUnconstrained (el))
6365 {
6366 suncon = sRefSet_insert (suncon, el);
6367 }
6368 else if (sRef_isInternalState (el))
6369 {
6370 sinner = TRUE;
6371 }
6372 else
6373 {
6374 ;
6375 }
6376 } end_sRefSet_allElements ;
6377
6378 if (sinner && innerState)
6379 {
6380 ;
6381 }
6382 else if (sRefSet_isEmpty (tuncon)
6383 && sRefSet_isEmpty (suncon))
6384 {
6385 voptgenerror
6386 (FLG_INFLOOPS,
6387 message
6388 ("Suspected infinite loop. No value used in loop test (%q) "
6389 "is modified by test or loop body.",
6390 sRefSet_unparsePlain (tuses)),
6391 test->loc);
6392 }
6393 else
6394 {
6395 if (sRefSet_isEmpty (tuncon))
6396 {
6397 voptgenerror
6398 (FLG_INFLOOPSUNCON,
6399 message ("Suspected infinite loop. No condition values "
6400 "modified. Modification possible through "
6401 "unconstrained calls: %q",
6402 sRefSet_unparsePlain (suncon)),
6403 test->loc);
6404 }
6405 else
6406 {
6407 voptgenerror
6408 (FLG_INFLOOPSUNCON,
6409 message ("Suspected infinite loop. No condition values "
6410 "modified. Possible undetected dependency through "
6411 "unconstrained calls in loop test: %q",
6412 sRefSet_unparsePlain (tuncon)),
6413 test->loc);
6414 }
6415 }
6416 }
6417
6418 sRefSet_free (sets);
6419 }
6420}
6421
6422exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
6423{
6424 exprNode ret;
6425 bool emptyErr = FALSE;
616915dd 6426
6427 if (context_maybeSet (FLG_WHILEEMPTY))
6428 {
6429 if (exprNode_isEmptyStatement (b))
6430 {
6431 emptyErr = optgenerror
6432 (FLG_WHILEEMPTY,
6433 cstring_makeLiteral
6434 ("Body of while statement is empty"),
6435 exprNode_loc (b));
6436 }
6437 }
6438
6439 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
6440 {
6441 if (exprNode_isDefined (b)
6442 && !exprNode_isBlock (b))
6443 {
6444 if (context_inIterDef ()
6445 && (b->kind == XPR_STMTLIST
6446 || b->kind == XPR_TOK))
6447 {
6448 ; /* no error */
6449 }
6450 else
6451 {
6452 voptgenerror (FLG_WHILEBLOCK,
6453 message
6454 ("Body of while statement is not a block: %s",
6455 exprNode_unparse (b)),
6456 exprNode_loc (b));
6457 }
6458 }
6459 }
6460
6461 if (exprNode_isError (t))
6462 {
6463 if (exprNode_isError (b))
6464 {
6465 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6466 }
6467 else
6468 {
6469 ret = exprNode_createPartialCopy (b);
6470 }
6471 }
6472 else
6473 {
6474 exprNode test;
6475
6476 ret = exprNode_createPartialCopy (t);
6477
6478 llassert (t->kind == XPR_WHILEPRED);
6479
6480 test = exprData_getSingle (t->edata);
6481
6482 if (!exprNode_isError (b) && exprNode_isDefined (test))
6483 {
6484 if (context_maybeSet (FLG_INFLOOPS)
6485 || context_maybeSet (FLG_INFLOOPSUNCON))
6486 {
6487 /*
6488 ** check that some variable in the predicate is set by the body
6489 ** if the predicate uses any variables
6490 */
6491
6492 checkInfiniteLoop (test, b);
6493 }
6494
6495 exprNode_mergeUSs (ret, b);
6496
6497 if (exprNode_isDefined (b))
6498 {
6499 ret->exitCode = exitkind_makeConditional (b->exitCode);
6500 }
6501 }
6502 }
6503
6504 ret->edata = exprData_makePair (t, b);
6505 ret->kind = XPR_WHILE;
6506
6507 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
6508 {
6509 voptgenerror
6510 (FLG_CONTROL,
6511 message ("Predicate always exits: %s", exprNode_unparse (t)),
6512 exprNode_loc (t));
6513 }
6514
6515 ret->exitCode = XK_NEVERESCAPE;
6516
6517 /*
6518 ** If loop is infinite, and there is no break inside,
6519 ** exit code is never reach.
6520 */
6521
6522 if (exprNode_knownIntValue (t))
6523 {
6524 if (!exprNode_isZero (t))
6525 {
6526 if (exprNode_isDefined (b))
6527 {
6528 if (!b->canBreak)
6529 {
6530 /* Really, it means never reached. */
6531 ret->exitCode = XK_MUSTEXIT;
6532 }
6533 }
6534 }
6535 }
6536 else
6537 {
6538 ;
6539 }
6540
6541 ret->canBreak = FALSE;
6542 ret->mustBreak = FALSE;
6543
6544 return ret;
6545}
6546
6547/*
6548** do { b } while (t);
6549**
6550** note: body passed as first argument
6551*/
6552
6553exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
6554{
6555 exprNode ret;
6556
6557 if (exprNode_isError (t))
6558 {
6559 if (exprNode_isError (b))
6560 {
6561 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6562 }
6563 else
6564 {
6565 ret = exprNode_createPartialCopy (b);
6566
6567 ret->exitCode = exitkind_makeConditional (b->exitCode);
6568 exprNode_checkUse (ret, b->sref, b->loc);
6569 ret->exitCode = b->exitCode;
6570 ret->canBreak = b->canBreak;
6571 ret->mustBreak = b->mustBreak;
6572 }
6573 }
6574 else
6575 {
6576 ret = exprNode_createPartialCopy (t);
6577 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
6578
6579 if (!exprNode_isError (b))
6580 {
6581 /*
6582 ** forgot the copy's --- why wasn't this detected??
6583 */
6584
6585 ret->sets = sRefSet_copy (ret->sets, b->sets);
6586 ret->msets = sRefSet_copy (ret->msets, b->msets);
6587 ret->uses = sRefSet_copy (ret->uses, b->uses);
6588
6589 /* left this out --- causes and aliasing bug (infinite loop)
6590 should be detected?? */
6591
6592 exprNode_checkUse (ret, b->sref, b->loc);
6593 exprNode_mergeUSs (ret, t);
6594 exprNode_checkUse (ret, t->sref, t->loc);
6595
6596 ret->exitCode = b->exitCode;
6597 ret->canBreak = b->canBreak;
6598 ret->mustBreak = b->mustBreak;
6599 }
6600 }
6601
6602 context_exitDoWhileClause (t);
6603
6604 ret->kind = XPR_DOWHILE;
6605 ret->edata = exprData_makePair (t, b);
6606 return ret;
6607}
6608
6609exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
6610{
6611 exprNode ret;
6612 bool emptyErr = FALSE;
6613
6614 if (context_maybeSet (FLG_FOREMPTY))
6615 {
6616 if (exprNode_isEmptyStatement (body))
6617 {
6618 emptyErr = optgenerror
6619 (FLG_FOREMPTY,
6620 cstring_makeLiteral
6621 ("Body of for statement is empty"),
6622 exprNode_loc (body));
6623 }
6624 }
6625
6626 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
6627 {
6628 if (exprNode_isDefined (body)
6629 && !exprNode_isBlock (body))
6630 {
6631 if (context_inIterDef ()
6632 && (body->kind == XPR_STMTLIST
6633 || body->kind == XPR_TOK))
6634 {
6635 ; /* no error */
6636 }
6637 else
6638 {
6639 voptgenerror (FLG_FORBLOCK,
6640 message
6641 ("Body of for statement is not a block: %s",
6642 exprNode_unparse (body)),
6643 exprNode_loc (body));
6644 }
6645 }
6646 }
6647
6648 /*
6649 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
6650 */
6651
6652 if (exprNode_isError (body))
6653 {
6654 ret = exprNode_createPartialCopy (inc);
6655 }
6656 else
6657 {
6658 ret = exprNode_createPartialCopy (body);
6659
6660 ret->exitCode = exitkind_makeConditional (body->exitCode);
6661
6662 exprNode_mergeUSs (inc, body);
6663
6664 if (exprNode_isDefined (inc))
6665 {
6666 exprNode tmp;
6667
6668 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
6669
6670
6671 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
6672 exprNode_freeShallow (tmp);
6673
6674 context_clearMessageAnnote ();
6675 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
6676
6677 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
6678 exprNode_freeShallow (tmp);
6679
6680 context_clearMessageAnnote ();
6681
6682 ret->uses = sRefSet_copy (ret->uses, inc->uses);
6683 ret->sets = sRefSet_copy (ret->sets, inc->sets);
6684 ret->msets = sRefSet_copy (ret->msets, inc->msets);
6685 }
6686 }
6687
6688 ret->kind = XPR_FOR;
6689 ret->edata = exprData_makePair (inc, body);
6690
6691 if (exprNode_isDefined (inc)) {
6692 exprNode test = exprData_getTripleTest (inc->edata);
6693
6694 if (exprNode_isUndefined (test)) {
6695 if (exprNode_isDefined (body)) {
6696 if (!body->canBreak) {
6697 /* Really, it means never reached. */
6698 ret->exitCode = XK_MUSTEXIT;
6699 }
6700 }
6701 }
6702 }
6703
6704 return (ret);
6705}
6706
6707/*
6708** for (init; test; inc)
6709** ==>
6710** init;
6711** while (test) { body; inc; }
6712**
6713** Now: check use of init (may set vars for test)
6714** check use of test
6715** no checks on inc
6716_*/
6717
6718/*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
6719{
6720 exprNode test;
6721
6722 if (exprNode_isError (pred)) return guardSet_undefined;
6723
6724 llassert (pred->kind == XPR_FORPRED);
6725
6726 test = exprData_getTripleTest (pred->edata);
6727
6728 if (!exprNode_isError (test))
6729 {
6730 return (test->guards);
6731 }
6732
6733 return guardSet_undefined;
6734}
6735
6736exprNode exprNode_whilePred (/*@only@*/ exprNode test)
6737{
6738 exprNode ret = exprNode_createSemiCopy (test);
6739
6740 if (exprNode_isDefined (test))
6741 {
6742 exprNode_copySets (ret, test);
6743 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
6744 exprNode_checkUse (ret, test->sref, test->loc);
6745
6746 exprNode_produceGuards (test);
6747
6748 ret->guards = guardSet_copy (test->guards);
6749 }
6750
6751 ret->edata = exprData_makeSingle (test);
6752 ret->kind = XPR_WHILEPRED;
6753 return ret;
6754}
6755
6756exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
6757 /*@only@*/ exprNode inc)
6758{
6759 exprNode ret;
6760
6761 /*
6762 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
6763 */
6764
6765 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
6766
6767 if (!exprNode_isError (inc))
6768 {
6769 ret = exprNode_createPartialCopy (inc);
6770 }
6771 else
6772 {
6773 if (!exprNode_isError (init))
6774 {
6775 ret = exprNode_createPartialCopy (init);
6776 }
6777 else if (!exprNode_isError (test))
6778 {
6779 ret = exprNode_createPartialCopy (test);
6780 }
6781 else
6782 {
6783 ret = exprNode_createUnknown ();
6784 }
6785 }
6786
6787 exprNode_mergeUSs (ret, init);
6788
6789 if (exprNode_isDefined (init))
6790 {
6791 exprNode_checkUse (ret, init->sref, init->loc);
6792 }
6793
6794 exprNode_mergeUSs (ret, test);
6795
6796 if (exprNode_isDefined (test))
6797 {
6798 exprNode_checkUse (ret, test->sref, test->loc);
6799 }
6800
6801 ret->kind = XPR_FORPRED;
6802 ret->edata = exprData_makeFor (init, test, inc);
6803 return (ret);
6804}
6805
6806/*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
6807{
6808 exprNode ret = exprNode_createUnknown ();
6809
6810 if (context_inMacro ())
6811 {
6812 voptgenerror (FLG_MACROSTMT,
6813 message ("Macro %s uses goto (not functional)",
6814 context_inFunctionName ()),
6815 g_currentloc);
6816 }
6817
6818 ret->kind = XPR_GOTO;
6819 ret->edata = exprData_makeLiteral (label);
6820 ret->mustBreak = TRUE;
6821 ret->exitCode = XK_GOTO;
6822 ret->canBreak = TRUE;
6823 return ret;
6824}
6825
6826exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
6827{
6828 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
6829
6830 ret->kind = XPR_CONTINUE;
6831 ret->edata = exprData_makeTok (l);
6832 ret->canBreak = TRUE;
6833 ret->mustBreak = TRUE;
6834
6835 if (qcontinue == QSAFEBREAK)
6836 {
6837 ; /* no checking */
6838 }
6839 else if (qcontinue == QINNERCONTINUE)
6840 {
6841 if (!context_inDeepLoop ())
6842 {
6843 voptgenerror
6844 (FLG_LOOPLOOPCONTINUE,
6845 cstring_makeLiteral ("Continue statement marked with innercontinue "
6846 "is not inside a nested loop"),
6847 exprNode_loc (ret));
6848 }
6849 }
6850 else if (qcontinue == BADTOK)
6851 {
6852 if (context_inDeepLoop ())
6853 {
6854 voptgenerror
6855 (FLG_LOOPLOOPCONTINUE,
6856 cstring_makeLiteral ("Continue statement in nested loop"),
6857 exprNode_loc (ret));
6858 }
6859 }
6860 else
6861 {
6862 llbuglit ("exprNode_continue: bad qcontinue");
6863 }
6864
6865 return ret;
6866}
6867
6868exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
6869{
6870 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
6871 clause breakClause = context_breakClause ();
6872
6873 ret->kind = XPR_BREAK;
6874 ret->edata = exprData_makeTok (l);
6875 ret->canBreak = TRUE;
6876 ret->mustBreak = TRUE;
6877
6878 if (breakClause == NOCLAUSE)
6879 {
6880 voptgenerror
6881 (FLG_SYNTAX,
6882 cstring_makeLiteral ("Break not inside while, for or switch statement"),
6883 exprNode_loc (ret));
6884 }
6885 else
6886 {
6887 if (bqual != BADTOK)
6888 {
6889 switch (bqual)
6890 {
6891 case QSAFEBREAK:
6892 break;
6893 case QINNERBREAK:
6894 if (breakClause == SWITCHCLAUSE)
6895 {
6896 if (!context_inDeepSwitch ())
6897 {
6898 voptgenerror (FLG_SYNTAX,
6899 cstring_makeLiteral
6900 ("Break preceded by innerbreak is not in a deep switch"),
6901 exprNode_loc (ret));
6902 }
6903 }
6904 else
6905 {
6906 if (!context_inDeepLoop ())
6907 {
6908 voptgenerror (FLG_SYNTAX,
6909 cstring_makeLiteral
6910 ("Break preceded by innerbreak is not in a deep loop"),
6911 exprNode_loc (ret));
6912 }
6913 }
6914 break;
6915 case QLOOPBREAK:
6916 if (breakClause == SWITCHCLAUSE)
6917 {
6918 voptgenerror (FLG_SYNTAX,
6919 cstring_makeLiteral
6920 ("Break preceded by loopbreak is breaking a switch"),
6921 exprNode_loc (ret));
6922 }
6923 break;
6924 case QSWITCHBREAK:
6925 if (breakClause != SWITCHCLAUSE)
6926 {
6927 voptgenerror
6928 (FLG_SYNTAX,
6929 message ("Break preceded by switchbreak is breaking %s",
6930 cstring_makeLiteralTemp
6931 ((breakClause == WHILECLAUSE
6932 || breakClause == DOWHILECLAUSE) ? "a while loop"
6933 : (breakClause == FORCLAUSE) ? "a for loop"
6934 : (breakClause == ITERCLAUSE) ? "an iterator"
6935 : "<error loop>")),
6936 exprNode_loc (ret));
6937 }
6938 break;
6939 BADDEFAULT;
6940 }
6941 }
6942 else
6943 {
6944 if (breakClause == SWITCHCLAUSE)
6945 {
6946 clause nextBreakClause = context_nextBreakClause ();
6947
6948 switch (nextBreakClause)
6949 {
6950 case NOCLAUSE: break;
6951 case WHILECLAUSE:
6952 case DOWHILECLAUSE:
6953 case FORCLAUSE:
6954 case ITERCLAUSE:
6955 voptgenerror
6956 (FLG_LOOPSWITCHBREAK,
6957 cstring_makeLiteral ("Break statement in switch inside loop"),
6958 exprNode_loc (ret));
6959 break;
6960 case SWITCHCLAUSE:
6961 voptgenerror
6962 (FLG_SWITCHSWITCHBREAK,
6963 cstring_makeLiteral ("Break statement in switch inside switch"),
6964 exprNode_loc (ret));
6965 break;
6966 BADDEFAULT;
6967 }
6968 }
6969 else
6970 {
6971 if (context_inDeepLoop ())
6972 {
6973 voptgenerror
6974 (FLG_LOOPLOOPBREAK,
6975 cstring_makeLiteral ("Break statement in nested loop"),
6976 exprNode_loc (ret));
6977 }
6978 else
6979 {
6980 if (context_inDeepLoopSwitch ())
6981 {
6982 voptgenerror
6983 (FLG_SWITCHLOOPBREAK,
6984 cstring_makeLiteral ("Break statement in loop inside switch"),
6985 exprNode_loc (ret));
6986 }
6987 }
6988 }
6989 }
6990 }
6991
6992 return ret;
6993}
6994
6995exprNode exprNode_nullReturn (/*@only@*/ lltok t)
6996{
6997 fileloc loc = lltok_getLoc (t);
6998 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
6999
7000 context_returnFunction ();
7001 exprChecks_checkNullReturn (loc);
7002
7003 ret->kind = XPR_NULLRETURN;
7004 ret->edata = exprData_makeTok (t);
7005 ret->exitCode = XK_MUSTRETURN;
7006 return ret;
7007}
7008
7009exprNode exprNode_return (/*@only@*/ exprNode e)
7010{
7011 exprNode ret;
7012
7013 if (exprNode_isError (e))
7014 {
7015 ret = exprNode_createUnknown ();
7016 }
7017 else
7018 {
7019 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
7020
7021 exprNode_checkUse (ret, e->sref, e->loc);
7022 exprNode_checkReturn (e);
7023 }
7024
7025 context_returnFunction ();
7026 ret->kind = XPR_RETURN;
7027 ret->edata = exprData_makeSingle (e);
7028 ret->exitCode = XK_MUSTRETURN;
7029
7030 return (ret);
7031}
7032
7033exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
7034{
7035 exprNode ret;
7036
7037 if (exprNode_isError (e1))
7038 {
7039 if (exprNode_isError (e2))
7040 {
7041 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
7042 }
7043 else
7044 {
7045 ret = exprNode_createPartialCopy (e2);
7046 exprNode_checkUse (ret, e2->sref, e2->loc);
7047 ret->sref = e2->sref;
7048 }
7049 }
7050 else
7051 {
7052 ret = exprNode_createPartialCopy (e1);
7053
7054 exprNode_checkUse (ret, e1->sref, e1->loc);
7055
7056 if (!exprNode_isError (e2))
7057 {
7058 exprNode_mergeUSs (ret, e2);
7059 exprNode_checkUse (ret, e2->sref, e2->loc);
7060 ret->sref = e2->sref;
7061 }
7062 }
7063
7064 ret->kind = XPR_COMMA;
7065 ret->edata = exprData_makePair (e1, e2);
7066
7067 if (exprNode_isDefined (e1))
7068 {
7069 if (exprNode_isDefined (e2))
7070 {
7071 ret->typ = e2->typ;
7072
7073 if (exprNode_mustEscape (e1) || e1->mustBreak)
7074 {
7075 voptgenerror
7076 (FLG_UNREACHABLE,
7077 message ("Second clause of comma expression is unreachable: %s",
7078 exprNode_unparse (e2)),
7079 exprNode_loc (e2));
7080 }
7081
7082 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
7083 ret->mustBreak = e1->mustBreak || e2->mustBreak;
7084 ret->canBreak = e1->canBreak || e2->canBreak;
7085 }
7086 else
7087 {
7088 if (exprNode_mustEscape (e1) || e1->mustBreak)
7089 {
7090 voptgenerror
7091 (FLG_UNREACHABLE,
7092 message ("Second clause of comma expression is unreachable: %s",
7093 exprNode_unparse (e2)),
7094 exprNode_loc (e2));
7095 }
7096
7097 ret->exitCode = e1->exitCode;
7098 ret->canBreak = e1->canBreak;
7099 }
7100 }
7101 else
7102 {
7103 if (exprNode_isDefined (e2))
7104 {
7105 ret->exitCode = e2->exitCode;
7106 ret->mustBreak = e2->mustBreak;
7107 ret->canBreak = e2->canBreak;
7108 }
7109 }
7110
7111 return (ret);
7112}
7113
7114static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
7115{
7116 ctype t1 = exprNode_getType (el);
7117 ctype t2 = exprNode_getType (val);
7118 bool hasError = FALSE;
7119
7120 if (ctype_isUnknown (t1))
7121 {
7122 voptgenerror (FLG_IMPTYPE,
7123 message ("Variable has unknown (implicitly int) type: %s",
7124 exprNode_unparse (el)),
7125 el->loc);
7126
7127 t1 = ctype_int;
7128 el->typ = ctype_int;
7129 }
7130
7131 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
7132 {
7133 exprNodeList vals = exprData_getArgs (val->edata);
7134
7135 if (ctype_isRealAP (t1))
7136 {
7137 int i = 0;
7138 int nerrors = 0;
7139
7140 exprNodeList_elements (vals, oneval)
7141 {
7142 cstring istring = message ("%d", i);
7143 exprNode newel =
7144 exprNode_arrayFetch
7145 (exprNode_fakeCopy (el),
7146 exprNode_numLiteral (ctype_int, istring,
7147 fileloc_copy (el->loc), i));
7148
7149 if (exprNode_isDefined (newel))
7150 {
7151 if (exprNodeList_size (vals) == 1
7152 && ctype_isString (exprNode_getType (oneval))
7153 && ctype_isChar (exprNode_getType (newel)))
7154 {
7155 exprNode_freeIniter (newel);
7156 }
7157 else
7158 {
7159 if (exprNode_checkOneInit (newel, oneval))
7160 {
7161 hasError = TRUE;
7162 nerrors++;
7163
7164 if (nerrors > 3 && exprNodeList_size (vals) > 6)
7165 {
7166 llgenmsg
7167 (message ("Additional initialization errors "
7168 "for %s not reported",
7169 exprNode_unparse (el)),
7170 exprNode_loc (el));
7171 exprNode_freeIniter (newel);
7172 break;
7173 }
7174 else
7175 {
7176 exprNode_freeIniter (newel);
7177 }
7178 }
7179 else
7180 {
7181 exprNode_freeIniter (newel);
7182 }
7183 }
7184 }
7185
7186 cstring_free (istring);
7187 i++;
7188 /*@-branchstate@*/
7189 } end_exprNodeList_elements;
7190 /*@=branchstate@*/
7191 }
7192 else if (ctype_isStruct (ctype_realType (t1)))
7193 {
7194 uentryList fields = ctype_getFields (t1);
7195 int i = 0;
7196
7197 if (uentryList_size (fields) != exprNodeList_size (vals))
7198 {
7199 if (uentryList_size (fields) > exprNodeList_size (vals))
7200 {
7201 hasError = optgenerror
7202 (FLG_FULLINITBLOCK,
7203 message ("Initializer block for "
7204 "%s has %d field%p, but %s has %d field%p: %q",
7205 exprNode_unparse (el),
7206 exprNodeList_size (vals),
7207 ctype_unparse (t1),
7208 uentryList_size (fields),
7209 exprNodeList_unparse (vals)),
7210 val->loc);
7211 }
7212 else
7213 {
7214 hasError = optgenerror
7215 (FLG_TYPE,
7216 message ("Initializer block for "
7217 "%s has %d field%p, but %s has %d field%p: %q",
7218 exprNode_unparse (el),
7219 exprNodeList_size (vals),
7220 ctype_unparse (t1),
7221 uentryList_size (fields),
7222 exprNodeList_unparse (vals)),
7223 val->loc);
7224 }
7225 }
7226 else
7227 {
7228 exprNodeList_elements (vals, oneval)
7229 {
7230 uentry thisfield = uentryList_getN (fields, i);
7231 exprNode newel =
7232 exprNode_fieldAccess (exprNode_fakeCopy (el),
7233 uentry_getName (thisfield));
7234
7235 if (exprNode_isDefined (newel))
7236 {
7237 if (exprNode_checkOneInit (newel, oneval))
7238 {
7239 hasError = TRUE;
7240 }
7241
7242 exprNode_freeIniter (newel);
7243 }
7244
7245 i++;
7246 } end_exprNodeList_elements;
7247 }
7248 }
7249 else
7250 {
7251 hasError = optgenerror
7252 (FLG_TYPE,
7253 message ("Initializer block used for "
7254 "%s where %t is expected: %s",
7255 exprNode_unparse (el), t1, exprNode_unparse (val)),
7256 val->loc);
7257 }
7258 }
7259 else
7260 {
7261 if (exprNode_isDefined (val))
7262 {
7263 doAssign (el, val, TRUE);
7264
7265 if (!exprNode_matchType (t1, val))
7266 {
7267 hasError = gentypeerror
7268 (t1, val, t2, el,
7269 message ("Initial value of %s is type %t, "
7270 "expects %t: %s",
7271 exprNode_unparse (el),
7272 t2, t1, exprNode_unparse (val)),
7273 val->loc);
7274 }
7275 }
7276 }
7277
7278 return hasError;
7279}
7280
7281exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
7282 /*@only@*/ exprNode e)
7283{
7284 uentry ue = usymtab_lookup (idDecl_observeId (t));
7285 bool isUsed = uentry_isUsed (ue);
7286 exprNode ret = exprNode_fromIdentifierAux (ue);
7287 ctype ct = ctype_realishType (ret->typ);
7288 fileloc loc;
7289
7290 if (ctype_isUnknown (ct))
7291 {
7292 voptgenerror (FLG_IMPTYPE,
7293 message ("Variable has unknown (implicitly int) type: %s",
7294 idDecl_getName (t)),
7295 exprNode_isDefined (e) ? exprNode_loc (e) : g_currentloc);
7296
7297 ct = ctype_int;
7298 }
7299
7300 if (exprNode_isError (e))
7301 {
7302 e = exprNode_createUnknown ();
7303 loc = g_currentloc;
7304
7305 /* error: assume initializer is defined */
7306 sRef_setDefined (ret->sref, loc);
7307 }
7308 else
7309 {
7310 loc = exprNode_loc (e);
7311
7312 /*
7313 ** evs - 9 Apr 1995
7314 **
7315 ** was addSafeUse --- what's the problem?
7316 **
7317 ** int x = 3, y = x ?
7318 */
7319
7320 exprNode_checkUse (ret, e->sref, e->loc);
7321
7322 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
7323 {
7324 exprNode lhs = exprNode_createId (ue);
7325
7326 /*
7327 ** static storage should be undefined before initializing
7328 */
7329
7330 if (uentry_isStatic (ue))
7331 {
7332 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
7333 }
7334
7335 (void) exprNode_checkOneInit (lhs, e);
7336
7337 if (uentry_isStatic (ue))
7338 {
7339 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
7340 }
7341
7342 exprNode_free (lhs);
7343 }
7344 else
7345 {
7346 if (!exprNode_matchType (ct, e))
7347 {
7348 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
7349 {
7350 ;
7351 }
7352 else
7353 {
7354 (void) gentypeerror
7355 (exprNode_getType (e), e, exprNode_getType (ret), ret,
7356 message
7357 ("Variable %s initialized to type %t, expects %t: %s",
7358 exprNode_unparse (ret), exprNode_getType (e),
7359 exprNode_getType (ret),
7360 exprNode_unparse (e)),
7361 e->loc);
7362 }
7363 }
7364 }
7365
7366 if (uentry_isStatic (ue))
7367 {
7368 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
7369 }
7370
7371 doAssign (ret, e, TRUE);
7372
7373 if (uentry_isStatic (ue))
7374 {
7375 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
7376 }
7377 }
7378
7379 if (context_inIterDef ())
7380 {
7381 /* should check if it is yield */
7382 uentry_setUsed (ue, loc);
7383 }
7384 else
7385 {
7386 if (!isUsed) /* could be @unused@-qualified variable */
7387 {
7388 uentry_setNotUsed (ue);
7389 }
7390 }
7391
7392 ret->exitCode = XK_NEVERESCAPE;
7393 ret->mustBreak = FALSE;
7394
7395 /*
7396 ** Must be before new kind is assigned!
7397 */
7398
7399 exprData_free (ret->edata, ret->kind);
7400
7401 ret->kind = XPR_INIT;
7402 ret->edata = exprData_makeInit (t, e);
7403 exprNode_mergeUSs (ret, e);
7404 return ret;
7405}
7406
7407exprNode exprNode_iter (/*@observer@*/ uentry name,
7408 /*@only@*/ exprNodeList alist,
7409 /*@only@*/ exprNode body,
7410 /*@observer@*/ uentry end)
7411{
7412 exprNode ret;
7413 cstring iname;
7414
7415 llassert (uentry_isValid (name));
7416
7417 uentry_setUsed (name, exprNode_loc (body));
7418
7419 ret = exprNode_createPartialCopy (body);
7420 iname = uentry_getName (name);
7421
7422 if (uentry_isInvalid (end))
7423 {
7424 llerror (FLG_ITER,
7425 message ("Iter %s not balanced with end_%s", iname, iname));
7426 }
7427 else
7428 {
7429 cstring ename = uentry_getName (end);
7430
7431 if (!cstring_equalPrefix (ename, "end_"))
7432 {
7433 llerror (FLG_ITER, message ("Iter %s not balanced with end_%s: %s",
7434 iname, iname, ename));
7435 }
7436 else
7437 {
7438 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
7439 {
7440 llerror (FLG_ITER,
7441 message ("Iter %s not balanced with end_%s: %s",
7442 iname, iname, ename));
7443 }
7444 }
7445
7446 cstring_free (ename);
7447 }
7448
7449 context_exitIterClause (body);
7450
7451 ret->kind = XPR_ITER;
7452 ret->edata = exprData_makeIter (name, alist, body, end);
7453
7454 if (uentry_isIter (name))
7455 {
7456 (void) checkArgsReal (name, body,
7457 uentry_getParams (name), alist, TRUE, ret);
7458 }
7459
7460 cstring_free (iname);
7461
7462 return ret;
7463}
7464
7465exprNode
7466exprNode_iterNewId (/*@only@*/ cstring s)
7467{
7468 exprNode e = exprNode_new ();
7469 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
7470
7471 llassert (processingIterVars ());
7472
7473 e->loc = context_getSaveLocation ();
7474
7475 if (fileloc_isUndefined (e->loc))
7476 {
7477 fileloc_free (e->loc);
7478 e->loc = fileloc_copy (g_currentloc);
7479 }
7480
7481 e->uses = sRefSet_new ();
7482 e->sets = sRefSet_new ();
7483 e->msets = sRefSet_new ();
7484 e->kind = XPR_VAR;
7485 e->val = multiVal_unknown ();
7486 e->guards = guardSet_new ();
7487 e->sref = defref;
7488 e->isJumpPoint = FALSE;
7489 e->exitCode = XK_NEVERESCAPE;
7490
7491 /*> missing fields, detected by lclint <*/
7492 e->canBreak = FALSE;
7493 e->mustBreak = FALSE;
7494 e->etext = cstring_undefined;
7495
7496 if (uentry_isYield (ue))
7497 {
7498 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
7499 fileloc_copy (e->loc),
7500 FALSE);
7501 sRef sr;
7502
7503 uue = usymtab_supEntrySrefReturn (uue);
7504
7505 sr = uentry_getSref (uue);
7506 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
7507 sr = uentry_getSref (uue);
7508 sRef_setDefined (sr, e->loc);
7509
7510 e->typ = uentry_getType (uue);
7511 e->sref = sr;
7512 e->edata = exprData_makeId (uue);
7513 uentry_setUsed (uue, g_currentloc);
7514 }
7515 else
7516 {
7517 uentry uue;
7518
7519 sRef_setGlobalScope ();
7520 uue = uentry_makeVariableLoc (s, ctype_unknown);
7521
7522 e->typ = ctype_unknown;
7523 e->edata = exprData_makeId (uue);
7524
7525 uentry_setUsed (uue, e->loc);
7526 uentry_setHasNameError (uue);
7527
7528 if (context_getFlag (FLG_REPEATUNRECOG))
7529 {
7530 uentry_markOwned (uue);
7531 }
7532 else
7533 {
7534 usymtab_supGlobalEntry (uue);
7535 }
7536
7537 sRef_clearGlobalScope ();
7538
7539 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
7540 e->loc);
7541 }
7542
7543
7544 cstring_free (s);
84c9ffbf 7545
7546 exprNode_defineConstraints(e);
616915dd 7547 return (e);
7548}
7549
7550exprNode
7551exprNode_iterExpr (/*@returned@*/ exprNode e)
7552{
7553 if (!processingIterVars ())
7554 {
7555 llcontbuglit ("checkIterParam: not in iter");
7556 return e;
7557 }
7558
7559 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
7560 iterParamNo ())))
7561 {
7562 if (exprNode_isDefined (e))
7563 {
7564 if (fileloc_isDefined (e->loc))
7565 {
7566 voptgenerror
7567 (FLG_ITER,
7568 message ("Yield parameter is not simple identifier: %s",
7569 exprNode_unparse (e)),
7570 e->loc);
7571 }
7572 else
7573 {
7574 voptgenerror
7575 (FLG_ITER,
7576 message ("Yield parameter is not simple identifier: %s",
7577 exprNode_unparse (e)),
7578 g_currentloc);
7579
7580 }
7581 }
7582 }
7583 return e;
7584}
7585
7586exprNode
7587exprNode_iterId (/*@observer@*/ uentry c)
7588{
7589 uentry ue;
7590
7591 llassert (processingIterVars ());
7592
7593 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
7594 iterParamNo ());
7595
7596 if (uentry_isYield (ue))
7597 {
7598 ctype ct = uentry_getType (ue);
7599 exprNode e = exprNode_createPlain (ct);
7600 cstring name = uentry_getName (c);
7601 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
7602
7603 uentry_setUsed (ue, g_currentloc);
7604 uentry_setHasNameError (ue);
7605
7606 cstring_free (name);
7607
7608 e->kind = XPR_VAR;
7609 e->edata = exprData_makeId (le);
7610 e->loc = context_getSaveLocation ();
7611 e->sref = uentry_getSref (le);
7612
7613 usymtab_supEntrySref (le);
7614
7615 if (!context_inHeader ())
7616 {
7617 if (optgenerror
7618 (FLG_ITER,
7619 message ("Yield parameter shadows local declaration: %q",
7620 uentry_getName (c)),
7621 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
7622 {
7623 uentry_showWhereDeclared (c);
7624 }
7625 }
7626
7627 return e;
7628 }
7629
7630 return (exprNode_fromIdentifierAux (c));
7631}
7632
7633exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
7634{
7635 exprNode ret = exprNode_create (ctype_unknown);
7636
7637 ret->kind = XPR_ITERCALL;
7638 ret->edata = exprData_makeIterCall (name, alist);
7639
7640 if (uentry_isIter (name))
7641 {
7642 uentryList params = uentry_getParams (name);
7643
7644 if (context_inIterDef ()
7645 && uentryList_size (params) == exprNodeList_size (alist))
7646 {
7647 int i = 0;
7648
7649 exprNodeList_elements (alist, arg)
7650 {
7651 uentry parg = uentryList_getN (params, i);
7652
7653 if (uentry_isYield (parg))
7654 {
7655 uentry ue = exprNode_getUentry (arg);
7656
7657 if (uentry_isValid (ue))
7658 {
7659 ;
7660 }
7661 }
7662
7663 i++;
7664 } end_exprNodeList_elements;
7665 }
7666
7667 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
7668 checkUnspecCall (ret, params, alist);
7669 }
7670
7671 return ret;
7672}
7673
7674/*@exposed@*/ sRef exprNode_getSref (exprNode e)
7675{
7676 if (exprNode_isDefined (e))
7677 {
7678 /*@access sRef@*/
7679 if (e->sref == defref) /*@noaccess sRef@*/
7680 {
7681 /*@-mods@*/
7682 e->sref = sRef_makeUnknown ();
7683 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
7684 /*@=mods@*/
7685 return e->sref;
7686 }
7687 else
7688 {
7689 return e->sref;
7690 }
7691 }
7692 else
7693 {
7694 return sRef_undefined;
7695 }
7696}
7697
7698/*@observer@*/ cstring
7699exprNode_unparseFirst (exprNode e)
7700{
7701 if (exprNode_isDefined (e))
7702 {
7703 cstring ret;
7704
7705 if (e->kind == XPR_STMTLIST
7706 || e->kind == XPR_COMMA || e->kind == XPR_COND)
7707 {
7708 exprNode first = exprData_getPairA (e->edata);
7709
7710 if (exprNode_isDefined (first))
7711 {
7712 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
7713 }
7714 else
7715 {
7716 return (cstring_makeLiteralTemp ("..."));
7717 }
7718 }
7719
7720 ret = cstring_elide (exprNode_unparse (e), 20);
7721 cstring_markOwned (ret);
7722
7723 return (ret);
7724 }
7725 else
7726 {
7727 return cstring_makeLiteralTemp ("<error>");
7728 }
7729}
7730
7731/*@observer@*/ cstring
7732exprNode_unparse (exprNode e)
7733{
7734 if (exprNode_isError (e))
7735 {
7736 return cstring_makeLiteralTemp ("<error>");
7737 }
7738
7739 if (cstring_isDefined (e->etext))
7740 {
7741 return e->etext;
7742 }
7743 else
7744 {
7745 cstring ret = exprNode_doUnparse (e);
7746
7747 /*@-modifies@*/ /* benevolent */
7748 e->etext = ret;
7749 /*@=modifies@*/
7750 return ret;
7751 }
7752}
7753
7754/*@observer@*/ fileloc
7755exprNode_loc (exprNode e)
7756{
7757 if (exprNode_isError (e))
7758 {
7759 return (g_currentloc);
7760 }
7761 else
7762 {
7763 return (e->loc);
7764 }
7765}
7766
7767/*
7768** executes exprNode e
7769** recursively rexecutes as though in original parse using
7770** information in e->edata
7771*/
7772
7773static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
7774{
7775 exprNodeList ret = exprNodeList_new ();
7776
7777 exprNodeList_elements (e, current)
7778 {
7779 exprNodeList_addh (ret, exprNode_effect (current));
7780 } end_exprNodeList_elements;
7781
7782 return ret;
7783}
7784
7785static /*@only@*/ exprNode exprNode_effect (exprNode e)
7786 /*@globals internalState@*/
7787{
7788 bool innerEffect = inEffect;
7789 exprNode ret;
7790 exprData data;
7791
7792 inEffect = TRUE;
7793
7794 context_clearJustPopped ();
7795
7796 if (exprNode_isError (e))
7797 {
7798 ret = exprNode_undefined;
7799 }
7800 else
7801 {
7802 /*
7803 ** Turn off expose and dependent transfer checking.
7804 ** Need to pass exposed internal nodes,
7805 ** [ copying would be a waste! ]
7806 ** [ Actually, I think I wasted a lot more time than its worth ]
7807 ** [ trying to do this. ]
7808 */
7809
7810 /*@-exposetrans@*/
7811 /*@-observertrans@*/
7812 /*@-dependenttrans@*/
7813
7814 data = e->edata;
7815
7816 switch (e->kind)
7817 {
7818 case XPR_PARENS:
7819 ret = exprNode_addParens (exprData_getUopTok (data),
7820 exprNode_effect (exprData_getUopNode (data)));
7821 break;
7822 case XPR_ASSIGN:
7823 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
7824 exprNode_effect (exprData_getOpB (data)),
7825 exprData_getOpTok (data));
7826 break;
7827 case XPR_INITBLOCK:
7828 ret = exprNode_undefined;
7829 break;
7830 case XPR_CALL:
7831 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
7832 exprNodeList_effect (exprData_getArgs (data)));
7833 break;
7834 case XPR_EMPTY:
7835 ret = e;
7836 break;
7837
7838 case XPR_LABEL:
7839 ret = e;
7840 break;
7841
7842 case XPR_CONST:
7843 case XPR_VAR:
7844 {
7845 cstring id = exprData_getId (data);
7846 uentry ue = usymtab_lookupSafe (id);
7847
7848 ret = exprNode_fromIdentifierAux (ue);
7849 ret->loc = fileloc_update (ret->loc, e->loc);
7850 break;
7851 }
7852 case XPR_BODY:
7853 ret = e;
7854 break;
7855 case XPR_FETCH:
7856 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
7857 exprNode_effect (exprData_getPairB (data)));
7858 break;
7859 case XPR_OP:
7860 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
7861 exprNode_effect (exprData_getOpB (data)),
7862 exprData_getOpTok (data));
7863 break;
7864
7865 case XPR_POSTOP:
7866 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
7867 exprData_getUopTok (data));
7868 break;
7869 case XPR_PREOP:
7870 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
7871 exprData_getUopTok (data));
7872 break;
7873
7874 case XPR_OFFSETOF:
7875 case XPR_SIZEOFT:
7876 case XPR_SIZEOF:
7877 case XPR_ALIGNOFT:
7878 case XPR_ALIGNOF:
7879 ret = e;
7880 break;
7881
7882 case XPR_VAARG:
7883 ret = exprNode_vaArg (exprData_getCastTok (data),
7884 exprNode_effect (exprData_getCastNode (data)),
7885 exprData_getCastType (data));
7886 break;
7887
7888 case XPR_CAST:
7889 ret = exprNode_cast (exprData_getCastTok (data),
7890 exprNode_effect (exprData_getCastNode (data)),
7891 exprData_getCastType (data));
7892 break;
7893 case XPR_ITERCALL:
7894 ret = exprNode_iterStart (exprData_getIterCallIter (data),
7895 exprNodeList_effect
7896 (exprData_getIterCallArgs (data)));
7897 break;
7898
7899 case XPR_ITER:
7900 ret = exprNode_iter (exprData_getIterSname (data),
7901 exprNodeList_effect (exprData_getIterAlist (data)),
7902 exprNode_effect (exprData_getIterBody (data)),
7903 exprData_getIterEname (data));
7904 break;
7905
7906 case XPR_FOR:
7907 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
7908 exprNode_effect (exprData_getPairB (data)));
7909 break;
7910
7911 case XPR_FORPRED:
7912 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
7913 exprNode_effect (exprData_getTripleTest (data)),
7914 exprNode_effect (exprData_getTripleInc (data)));
7915 break;
7916
7917 case XPR_TOK:
7918 ret = exprNode_createTok (exprData_getTok (data));
7919 break;
7920
7921 case XPR_GOTO:
7922 ret = exprNode_goto (exprData_getLiteral (data));
7923 ret->loc = fileloc_update (ret->loc, e->loc);
7924 break;
7925
7926 case XPR_CONTINUE:
7927 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
7928 break;
7929
7930 case XPR_BREAK:
7931 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
7932 break;
7933
7934 case XPR_RETURN:
7935 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
7936 break;
7937
7938 case XPR_NULLRETURN:
7939 ret = exprNode_nullReturn (exprData_getTok (data));
7940 break;
7941
7942 case XPR_COMMA:
7943 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
7944 exprNode_effect (exprData_getPairB (data)));
7945 break;
7946
7947 case XPR_COND:
7948 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
7949 exprNode_effect (exprData_getTripleTrue (data)),
7950 exprNode_effect (exprData_getTripleFalse (data)));
7951 break;
7952 case XPR_IF:
7953 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
7954 exprNode_effect (exprData_getPairB (data)));
7955 break;
7956
7957 case XPR_IFELSE:
7958 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
7959 exprNode_effect (exprData_getTripleTrue (data)),
7960 exprNode_effect (exprData_getTripleFalse (data)));
7961 break;
7962 case XPR_WHILEPRED:
7963 ret = exprNode_whilePred (exprData_getSingle (data));
7964 break;
7965
7966 case XPR_WHILE:
7967 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
7968 exprNode_effect (exprData_getPairB (data)));
7969 break;
7970
7971 case XPR_DOWHILE:
7972 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
7973 exprNode_effect (exprData_getPairB (data)));
7974 break;
7975
7976 case XPR_BLOCK:
7977 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
7978 break;
7979
7980 case XPR_STMT:
7981 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
7982 exprData_getUopTok (data));
7983 break;
7984
7985 case XPR_STMTLIST:
7986 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
7987 exprNode_effect (exprData_getPairB (data)));
7988 break;
7989
7990 case XPR_FTCASE:
7991 case XPR_CASE:
7992 ret = exprNode_caseMarker
7993 (exprNode_effect (exprData_getSingle (data)),
7994 TRUE);
7995 break;
7996
7997 case XPR_FTDEFAULT:
7998 case XPR_DEFAULT:
7999 ret = exprNode_createTok (exprData_getTok (data));
8000 break;
8001
8002 case XPR_SWITCH:
8003 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
8004 exprNode_effect (exprData_getPairB (data)));
8005 break;
8006
8007 case XPR_INIT:
8008 ret = exprNode_makeInitialization
8009 (exprData_getInitId (data),
8010 exprNode_effect (exprData_getInitNode (data)));
8011 break;
8012
8013 case XPR_FACCESS:
8014 ret = exprNode_fieldAccess (exprNode_effect (exprData_getFieldNode (data)),
8015 cstring_copy (exprData_getFieldName (data)));
8016 break;
8017
8018 case XPR_ARROW:
8019 ret = exprNode_arrowAccess (exprNode_effect (exprData_getFieldNode (data)),
8020 cstring_copy (exprData_getFieldName (data)));
8021 break;
8022
8023 case XPR_STRINGLITERAL:
8024 ret = e;
8025 break;
8026
8027 case XPR_NUMLIT:
8028 ret = e;
8029 break;
8030
8031 case XPR_NODE:
8032 ret = e;
8033 break;
8034 /*@-branchstate@*/
8035 }
8036 /*@=branchstate@*/
8037 /*@=observertrans@*/
8038 /*@=exposetrans@*/
8039 /*@=dependenttrans@*/
8040 }
8041
8042 if (!innerEffect)
8043 {
8044 inEffect = FALSE;
8045 }
8046
8047 return ret;
8048}
8049
8050static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
8051{
8052 cstring ret;
8053 exprData data;
8054
8055 if (exprNode_isError (e))
8056 {
8057 return cstring_undefined;
8058 }
8059
8060 data = e->edata;
8061
8062 switch (e->kind)
8063 {
8064 case XPR_PARENS:
8065 ret = exprNode_rootVarName (exprData_getUopNode (data));
8066 break;
8067 case XPR_ASSIGN:
8068 ret = exprNode_rootVarName (exprData_getOpA (data));
8069 break;
8070 case XPR_CONST:
8071 case XPR_VAR:
8072 ret = exprData_getId (data);
8073 break;
8074 case XPR_LABEL:
8075 case XPR_TOK:
8076 case XPR_ITERCALL:
8077 case XPR_EMPTY:
8078 case XPR_CALL:
8079 case XPR_INITBLOCK:
8080 case XPR_BODY:
8081 case XPR_FETCH:
8082 case XPR_OP:
8083 case XPR_POSTOP:
8084 case XPR_PREOP:
8085 case XPR_OFFSETOF:
8086 case XPR_ALIGNOFT:
8087 case XPR_ALIGNOF:
8088 case XPR_SIZEOFT:
8089 case XPR_SIZEOF:
8090 case XPR_VAARG:
8091 case XPR_CAST:
8092 case XPR_ITER:
8093 case XPR_FOR:
8094 case XPR_FORPRED:
8095 case XPR_BREAK:
8096 case XPR_RETURN:
8097 case XPR_NULLRETURN:
8098 case XPR_COMMA:
8099 case XPR_COND:
8100 case XPR_IF:
8101 case XPR_IFELSE:
8102 case XPR_WHILE:
8103 case XPR_WHILEPRED:
8104 case XPR_DOWHILE:
8105 case XPR_GOTO:
8106 case XPR_CONTINUE:
8107 case XPR_FTDEFAULT:
8108 case XPR_DEFAULT:
8109 case XPR_SWITCH:
8110 case XPR_FTCASE:
8111 case XPR_CASE:
8112 case XPR_BLOCK:
8113 case XPR_STMT:
8114 case XPR_STMTLIST:
8115 case XPR_INIT:
8116 case XPR_FACCESS:
8117 case XPR_ARROW:
8118 case XPR_NODE:
8119 case XPR_NUMLIT:
8120 case XPR_STRINGLITERAL:
8121 ret = cstring_undefined;
8122 break;
8123 }
8124
8125 return ret;
8126}
8127
8128
8129static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
8130{
8131 cstring ret;
8132 exprData data;
8133
8134 if (exprNode_isError (e))
8135 {
8136 static /*@only@*/ cstring error = cstring_undefined;
8137
8138 if (!cstring_isDefined (error))
8139 {
8140 error = cstring_makeLiteral ("<error>");
8141 }
8142
8143 return error;
8144 }
8145
8146 data = e->edata;
8147
8148 switch (e->kind)
8149 {
8150 case XPR_PARENS:
8151 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
8152 break;
8153 case XPR_ASSIGN:
8154 ret = message ("%s %s %s",
8155 exprNode_unparse (exprData_getOpA (data)),
8156 lltok_unparse (exprData_getOpTok (data)),
8157 exprNode_unparse (exprData_getOpB (data)));
8158 break;
8159 case XPR_CALL:
8160 ret = message ("%s(%q)",
8161 exprNode_unparse (exprData_getFcn (data)),
8162 exprNodeList_unparse (exprData_getArgs (data)));
8163 break;
8164 case XPR_INITBLOCK:
8165 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
8166 break;
8167 case XPR_EMPTY:
8168 ret = cstring_undefined;
8169 break;
8170 case XPR_LABEL:
8171 ret = message ("%s:", exprData_getId (data));
8172 break;
8173 case XPR_CONST:
8174 case XPR_VAR:
8175 ret = cstring_copy (exprData_getId (data));
8176 break;
8177 case XPR_FETCH:
8178 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
8179 exprNode_unparse (exprData_getPairB (data)));
8180 break;
8181 case XPR_BODY:
8182 ret = message ("<body>");
8183 break;
8184 case XPR_OP:
8185 ret = message ("%s %s %s",
8186 exprNode_unparse (exprData_getOpA (data)),
8187 lltok_unparse (exprData_getOpTok (data)),
8188 exprNode_unparse (exprData_getOpB (data)));
8189 break;
8190
8191 case XPR_PREOP:
8192 ret = message ("%s%s",
8193 lltok_unparse (exprData_getUopTok (data)),
8194 exprNode_unparse (exprData_getUopNode (data)));
8195 break;
8196
8197 case XPR_POSTOP:
8198 ret = message ("%s%s",
8199 exprNode_unparse (exprData_getUopNode (data)),
8200 lltok_unparse (exprData_getUopTok (data)));
8201 break;
8202
8203 case XPR_OFFSETOF:
8204 ret = message ("offsetof(%s,%q)",
8205 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
8206 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
8207 break;
8208
8209 case XPR_SIZEOFT:
8210 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8211 break;
8212
8213 case XPR_SIZEOF:
8214 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
8215 break;
8216
8217 case XPR_ALIGNOFT:
8218 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8219 break;
8220
8221 case XPR_ALIGNOF:
8222 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
8223 break;
8224
8225 case XPR_VAARG:
8226 ret = message ("va_arg(%s, %q)",
8227 exprNode_unparse (exprData_getCastNode (data)),
8228 qtype_unparse (exprData_getCastType (data)));
8229 break;
8230
8231 case XPR_ITERCALL:
8232 ret = message ("%q(%q)",
8233 uentry_getName (exprData_getIterCallIter (data)),
8234 exprNodeList_unparse (exprData_getIterCallArgs (data)));
8235 break;
8236 case XPR_ITER:
8237 ret = message ("%q(%q) %s %q",
8238 uentry_getName (exprData_getIterSname (data)),
8239 exprNodeList_unparse (exprData_getIterAlist (data)),
8240 exprNode_unparse (exprData_getIterBody (data)),
8241 uentry_getName (exprData_getIterEname (data)));
8242 break;
8243 case XPR_CAST:
8244 ret = message ("(%q)%s",
8245 qtype_unparse (exprData_getCastType (data)),
8246 exprNode_unparse (exprData_getCastNode (data)));
8247 break;
8248
8249 case XPR_FOR:
8250 ret = message ("%s %s",
8251 exprNode_unparse (exprData_getPairA (data)),
8252 exprNode_unparse (exprData_getPairB (data)));
8253 break;
8254
8255 case XPR_FORPRED:
8256 ret = message ("for (%s; %s; %s)",
8257 exprNode_unparse (exprData_getTripleInit (data)),
8258 exprNode_unparse (exprData_getTripleTest (data)),
8259 exprNode_unparse (exprData_getTripleInc (data)));
8260 break;
8261
8262 case XPR_GOTO:
8263 ret = message ("goto %s", exprData_getLiteral (data));
8264 break;
8265
8266 case XPR_CONTINUE:
8267 ret = cstring_makeLiteral ("continue");
8268 break;
8269
8270 case XPR_BREAK:
8271 ret = cstring_makeLiteral ("break");
8272 break;
8273
8274 case XPR_RETURN:
8275 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
8276 break;
8277
8278 case XPR_NULLRETURN:
8279 ret = cstring_makeLiteral ("return");
8280 break;
8281
8282 case XPR_COMMA:
8283 ret = message ("%s, %s",
8284 exprNode_unparse (exprData_getPairA (data)),
8285 exprNode_unparse (exprData_getPairB (data)));
8286 break;
8287
8288 case XPR_COND:
8289 ret = message ("%s ? %s : %s",
8290 exprNode_unparse (exprData_getTriplePred (data)),
8291 exprNode_unparse (exprData_getTripleTrue (data)),
8292 exprNode_unparse (exprData_getTripleFalse (data)));
8293 break;
8294 case XPR_IF:
8295 ret = message ("if (%s) %s",
8296 exprNode_unparse (exprData_getPairA (data)),
8297 exprNode_unparse (exprData_getPairB (data)));
8298 break;
8299
8300 case XPR_IFELSE:
8301 ret = message ("if (%s) %s else %s",
8302 exprNode_unparse (exprData_getTriplePred (data)),
8303 exprNode_unparse (exprData_getTripleTrue (data)),
8304 exprNode_unparse (exprData_getTripleFalse (data)));
8305 break;
8306 case XPR_WHILE:
8307 ret = message ("while (%s) %s",
8308 exprNode_unparse (exprData_getPairA (data)),
8309 exprNode_unparse (exprData_getPairB (data)));
8310 break;
8311
8312 case XPR_WHILEPRED:
8313 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
8314 break;
8315
8316 case XPR_TOK:
8317 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
8318 break;
8319
8320 case XPR_DOWHILE:
8321 ret = message ("do { %s } while (%s)",
8322 exprNode_unparse (exprData_getPairB (data)),
8323 exprNode_unparse (exprData_getPairA (data)));
8324 break;
8325
8326 case XPR_BLOCK:
8327 ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
8328 break;
8329
8330 case XPR_STMT:
8331 ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
8332 break;
8333
8334 case XPR_STMTLIST:
8335 ret = message ("%s; %s",
8336 exprNode_unparse (exprData_getPairA (data)),
8337 exprNode_unparse (exprData_getPairB (data)));
8338 break;
8339
8340 case XPR_FTDEFAULT:
8341 case XPR_DEFAULT:
8342 ret = cstring_makeLiteral ("default:");
8343 break;
8344
8345 case XPR_SWITCH:
8346 ret = message ("switch (%s) %s",
8347 exprNode_unparse (exprData_getPairA (data)),
8348 exprNode_unparse (exprData_getPairB (data)));
8349 break;
8350
8351 case XPR_FTCASE:
8352 case XPR_CASE:
8353 ret = message ("case %s:",
8354 exprNode_unparse (exprData_getSingle (data)));
8355 break;
8356
8357 case XPR_INIT:
8358 ret = message ("%s = %s",
8359 idDecl_getName (exprData_getInitId (data)),
8360 exprNode_unparse (exprData_getInitNode (data)));
8361 break;
8362
8363 case XPR_FACCESS:
8364 ret = message ("%s.%s",
8365 exprNode_unparse (exprData_getFieldNode (data)),
8366 exprData_getFieldName (data));
8367 break;
8368
8369 case XPR_ARROW:
8370 ret = message ("%s->%s",
8371 exprNode_unparse (exprData_getFieldNode (data)),
8372 exprData_getFieldName (data));
8373 break;
8374
8375 case XPR_STRINGLITERAL:
8376 ret = cstring_copy (exprData_getLiteral (data));
8377 break;
8378
8379 case XPR_NUMLIT:
8380 ret = cstring_copy (exprData_getLiteral (data));
8381 break;
8382
8383 case XPR_NODE:
8384 ret = cstring_makeLiteral ("<node>");
8385 break;
8386 }
8387
8388 return ret;
8389}
8390
8391bool
8392exprNode_isCharLit (exprNode e)
8393{
8394 if (exprNode_isDefined (e))
8395 {
8396 return (multiVal_isChar (exprNode_getValue (e)));
8397 }
8398 else
8399 {
8400 return FALSE;
8401 }
8402}
8403
8404bool
8405exprNode_isNumLit (exprNode e)
8406{
8407 if (exprNode_isDefined (e))
8408 {
8409 return (multiVal_isInt (exprNode_getValue (e)));
8410 }
8411 else
8412 {
8413 return FALSE;
8414 }
8415}
8416
8417static bool
8418exprNode_isFalseConstant (exprNode e)
8419{
8420 if (exprNode_isDefined (e))
8421 {
8422 cstring s = exprNode_rootVarName (e);
8423
8424 if (cstring_equal (s, context_getFalseName ()))
8425 {
8426 return TRUE;
8427 }
8428 }
8429
8430 return FALSE;
8431}
8432
8433bool
8434exprNode_matchLiteral (ctype expected, exprNode e)
8435{
8436 if (exprNode_isDefined (e))
8437 {
8438 multiVal m = exprNode_getValue (e);
8439
8440 if (multiVal_isDefined (m))
8441 {
8442 if (multiVal_isInt (m))
8443 {
8444 long int val = multiVal_forceInt (m);
8445
8446 if (ctype_isDirectBool (ctype_realishType (expected)))
8447 {
8448 if (val == 0)
8449 {
8450 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
8451 }
8452 else
8453 {
8454 return FALSE;
8455 }
8456 }
8457
8458 if (ctype_isRealInt (expected))
8459 {
8460 /*
8461 ** unsigned <- [ constant >= 0 is okay ]
8462 */
8463
8464 if (ctype_isUnsigned (expected))
8465 {
8466 if (val < 0)
8467 {
8468 return FALSE;
8469 }
8470 }
8471
8472 /*
8473 ** No checks on sizes of integers...maybe add
8474 ** these later.
8475 */
8476
8477 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
8478 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
8479 bool_unparse (ctype_isInt (exprNode_getType (e)))));
8480
8481 if (context_getFlag (FLG_NUMLITERAL)
8482 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
8483 return TRUE;
8484 } else {
8485 if (val == 0) {
8486 return TRUE;
8487 } else {
8488 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
8489 }
8490 }
8491 }
8492 else if (ctype_isChar (expected))
8493 {
8494 return FALSE;
8495 }
8496 else if (ctype_isArrayPtr (expected))
8497 {
8498 return (val == 0);
8499 }
8500 else if (ctype_isAnyFloat (expected))
8501 {
8502 return (context_getFlag (FLG_NUMLITERAL));
8503 }
8504 else
8505 {
8506 return FALSE;
8507 }
8508 }
8509 else if (multiVal_isDouble (m))
8510 {
8511 if (ctype_isAnyFloat (expected))
8512 {
8513 return TRUE;
8514 }
8515 }
8516 else if (multiVal_isChar (m))
8517 {
8518 char val = multiVal_forceChar (m);
8519
8520 if (ctype_isChar (expected))
8521 {
8522 if (ctype_isUnsigned (expected) && ((int)val) < 0)
8523 {
8524 return FALSE;
8525 }
8526 else
8527 {
8528 return TRUE;
8529 }
8530 }
8531 }
8532 else
8533 {
8534 return FALSE;
8535 }
8536 }
8537 }
8538
8539 return FALSE;
8540}
8541
8542bool
8543exprNode_matchType (ctype expected, exprNode e)
8544{
8545 ctype actual;
8546
8547 if (!exprNode_isDefined (e)) return TRUE;
8548
8549 actual = ctype_realishType (exprNode_getType (e));
8550
8551 if (ctype_match (ctype_realishType (expected), actual))
8552 {
8553 return TRUE;
8554 }
8555
8556 llassert (!exprNode_isError (e));
8557 return (exprNode_matchLiteral (expected, e));
8558}
8559
8560static bool
8561exprNode_matchTypes (exprNode e1, exprNode e2)
8562{
8563 ctype t1;
8564 ctype t2;
8565
8566 if (!exprNode_isDefined (e1)) return TRUE;
8567 if (!exprNode_isDefined (e2)) return TRUE;
8568
8569 /*
8570 ** realish type --- keep bools, bools
8571 */
8572
8573 t1 = ctype_realishType (exprNode_getType (e1));
8574 t2 = ctype_realishType (exprNode_getType (e2));
8575
8576 if (ctype_match (t1, t2))
8577 {
8578 return TRUE;
8579 }
8580
8581 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
8582}
8583
8584/*
8585** pass e as ct
8586*/
8587
8588static bool
8589 exprNode_matchArgType (ctype ct, exprNode e)
8590{
8591 ctype et;
8592
8593 if (!exprNode_isDefined (e))
8594 {
8595 return TRUE;
8596 }
8597
8598 et = ctype_realType (exprNode_getType (e));
8599
8600 if (ctype_matchArg (ct, et)) return TRUE;
8601
8602 llassert (!exprNode_isError (e));
8603 return (exprNode_matchLiteral (ct, e));
8604}
8605
8606static /*@only@*/ exprNodeSList
8607 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
8608{
8609 if (exprNode_isDefined (e))
8610 {
8611 if (e->kind == XPR_STMTLIST)
8612 {
8613 return (exprNodeSList_append
8614 (exprNode_flatten (exprData_getPairA (e->edata)),
8615 exprNode_flatten (exprData_getPairB (e->edata))));
8616 }
8617 else if (e->kind == XPR_BLOCK)
8618 {
8619 return (exprNode_flatten (exprData_getSingle (e->edata)));
8620 }
8621 else
8622 {
8623 return (exprNodeSList_singleton (e));
8624 }
8625 }
8626
8627 return exprNodeSList_new ();
8628}
8629
8630static /*@exposed@*/ exprNode
8631exprNode_lastStatement (/*@returned@*/ exprNode e)
8632{
8633 if (exprNode_isDefined (e))
8634 {
8635 if (e->kind == XPR_STMTLIST)
8636 {
8637 exprNode b = exprData_getPairB (e->edata);
8638
8639 if (exprNode_isDefined (b))
8640 {
8641 return exprNode_lastStatement (b);
8642 }
8643 else
8644 {
8645 return exprNode_lastStatement (exprData_getPairA (e->edata));
8646 }
8647 }
8648 else if (e->kind == XPR_BLOCK)
8649 {
8650 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
8651 }
8652 else
8653 {
8654 return (e);
8655 }
8656 }
8657
8658 return exprNode_undefined;
8659}
8660
8661static /*@exposed@*/ exprNode
8662exprNode_firstStatement (/*@returned@*/ exprNode e)
8663{
8664 if (exprNode_isDefined (e))
8665 {
8666 if (e->kind == XPR_STMTLIST)
8667 {
8668 exprNode b = exprData_getPairA (e->edata);
8669
8670 if (exprNode_isDefined (b))
8671 {
8672 return exprNode_firstStatement (b);
8673 }
8674 else
8675 {
8676 return exprNode_firstStatement (exprData_getPairB (e->edata));
8677 }
8678 }
8679 else if (e->kind == XPR_BLOCK)
8680 {
8681 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
8682 }
8683 else
8684 {
8685 return (e);
8686 }
8687 }
8688
8689 return exprNode_undefined;
8690}
8691
8692static void
8693exprNode_mergeUSs (exprNode res, exprNode other)
8694{
8695 if (exprNode_isDefined (res) && exprNode_isDefined (other))
8696 {
8697 res->msets = sRefSet_union (res->msets, other->msets);
8698 res->sets = sRefSet_union (res->sets, other->sets);
8699 res->uses = sRefSet_union (res->uses, other->uses);
8700 }
8701}
8702
8703static void
8704exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
8705{
8706 if (exprNode_isDefined (res))
8707 {
8708 if (exprNode_isDefined (other1))
8709 {
8710 res->sets = sRefSet_union (res->sets, other1->sets);
8711 res->msets = sRefSet_union (res->msets, other1->msets);
8712 res->uses = sRefSet_union (res->uses, other1->uses);
8713 }
8714 if (exprNode_isDefined (other2))
8715 {
8716 res->sets = sRefSet_union (res->sets, other2->sets);
8717 res->msets = sRefSet_union (res->msets, other2->msets);
8718 res->uses = sRefSet_union (res->uses, other2->uses);
8719 }
8720 }
8721}
8722
8723/*
8724** modifies e->uses
8725**
8726** Reports errors is s is not defined.
8727*/
8728
8729static void
8730exprNode_addUse (exprNode e, sRef s)
8731{
8732 if (exprNode_isDefined (e))
8733 {
8734 e->uses = sRefSet_insert (e->uses, s);
8735 }
8736}
8737
8738void
8739exprNode_checkUse (exprNode e, sRef s, fileloc loc)
8740{
8741 if (sRef_isKnown (s) && !sRef_isConst (s))
8742 {
8743 /*
8744 ** need to check all outer types are useable
8745 */
8746
8747 DPRINTF (("Check use: %s / %s",
8748 exprNode_unparse (e), sRef_unparse (s)));
8749
8750 exprNode_addUse (e, s);
8751
8752 if (!context_inProtectVars ())
8753 {
8754 /*
8755 ** only report the deepest error
8756 */
8757
8758 sRef errorRef = sRef_undefined;
8759 sRef lastRef = sRef_undefined;
8760 bool deadRef = FALSE;
8761 bool unuseable = FALSE;
8762 bool errorMaybe = FALSE;
8763
8764 while (sRef_isValid (s) && sRef_isKnown (s))
8765 {
8766 ynm readable = sRef_isReadable (s);
8767
8768 if (!(ynm_toBoolStrict (readable)))
8769 {
8770 if (ynm_isMaybe (readable))
8771 {
8772 lastRef = errorRef;
8773 errorRef = s;
8774 deadRef = sRef_isPossiblyDead (errorRef);
8775 unuseable = sRef_isUnuseable (errorRef);
8776 errorMaybe = TRUE;
8777 }
8778 else
8779 {
8780 lastRef = errorRef;
8781 errorRef = s;
8782 deadRef = sRef_isDead (errorRef);
8783 unuseable = sRef_isUnuseable (errorRef);
8784 errorMaybe = FALSE;
8785 }
8786
8787 if (!sRef_isPartial (s))
8788 {
8789 sRef_setDefined (s, fileloc_undefined);
8790 }
8791 }
8792
8793 s = sRef_getBaseSafe (s);
8794 } /* end while */
8795
8796 if (sRef_isValid (errorRef))
8797 {
8798 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
8799 && sRef_isPointer (errorRef))
8800 {
8801 errorRef = lastRef;
8802 }
8803
8804 if (deadRef)
8805 {
8806 if (sRef_isThroughArrayFetch (errorRef))
8807 {
8808 if (optgenerror
8809 (FLG_STRICTUSERELEASED,
8810 message ("%q %q may be used after being released",
8811 sRef_unparseKindNamePlain (errorRef),
8812 sRef_unparse (errorRef)),
8813 loc))
8814 {
8815 sRef_showRefKilled (errorRef);
8816
8817 if (sRef_isKept (errorRef))
8818 {
8819 sRef_clearAliasState (errorRef, loc);
8820 }
8821 }
8822 }
8823 else
8824 {
8825 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
8826
8827 if (optgenerror
8828 (FLG_USERELEASED,
8829 message ("%q %q %qused after being released",
8830 sRef_unparseKindNamePlain (errorRef),
8831 sRef_unparse (errorRef),
8832 cstring_makeLiteral (errorMaybe
8833 ? "may be " : "")),
8834 loc))
8835 {
8836 sRef_showRefKilled (errorRef);
8837
8838 if (sRef_isKept (errorRef))
8839 {
8840 sRef_clearAliasState (errorRef, loc);
8841 }
8842 }
8843 }
8844 }
8845 else if (unuseable)
8846 {
8847 if (optgenerror
8848 (FLG_USEDEF,
8849 message ("%q %q%qused in inconsistent state",
8850 sRef_unparseKindName (errorRef),
8851 sRef_unparseOpt (errorRef),
8852 cstring_makeLiteral (errorMaybe ? "may be " : "")),
8853 loc))
8854 {
8855 sRef_showStateInconsistent (errorRef);
8856 }
8857 }
8858 else
8859 {
8860 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
8861
8862 voptgenerror
8863 (FLG_USEDEF,
8864 message ("%q %q%qused before definition",
8865 sRef_unparseKindName (errorRef),
8866 sRef_unparseOpt (errorRef),
8867 cstring_makeLiteral (errorMaybe ? "may be " : "")),
8868 loc);
8869 }
8870
8871 sRef_setDefined (errorRef, loc);
8872
8873 if (sRef_isAddress (errorRef))
8874 {
8875 sRef_setDefined (sRef_getRootBase (errorRef), loc);
8876 }
8877 } /* end is error */
8878 }
8879 }
8880
8881 setCodePoint ();
8882}
8883
8884static void
8885checkSafeUse (exprNode e, sRef s)
8886{
8887 if (exprNode_isDefined (e) && sRef_isKnown (s))
8888 {
8889 e->uses = sRefSet_insert (e->uses, s);
8890 }
8891}
8892
8893static void
8894exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
8895{
8896 if (exprNode_isDefined (e))
8897 {
8898 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
8899 }
8900}
8901
8902void
8903exprNode_checkSet (exprNode e, sRef s)
8904{
8905 sRef defines = sRef_undefined;
8906
8907 if (sRef_isValid (s) && !sRef_isNothing (s))
8908 {
8909 uentry ue = sRef_getBaseUentry (s);
8910
8911 if (uentry_isValid (ue))
8912 {
8913 uentry_setLset (ue);
8914 }
8915
8916 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
8917 {
8918 voptgenerror (FLG_USEDEF,
8919 message ("Attempt to set unuseable storage: %q",
8920 sRef_unparse (s)),
8921 exprNode_loc (e));
8922 }
8923
8924 if (sRef_isMeaningful (s))
8925 {
8926
8927 if (sRef_isDead (s))
8928 {
8929 sRef base = sRef_getBaseSafe (s);
8930
8931 if (sRef_isValid (base)
8932 && sRef_isDead (base))
8933 {
8934 sRef_setPartial (s, exprNode_loc (e));
8935 }
8936
8937 defines = s; /* okay - modifies for only param */
8938 }
8939 else if (sRef_isPartial (s))
8940 {
8941 sRef eref = exprNode_getSref (e);
8942
8943 if (!sRef_isPartial (eref))
8944 {
8945 /*
8946 ** should do something different here???
8947 */
8948
8949 sRef_setDefinedComplete (eref, exprNode_loc (e));
8950 }
8951 else
8952 {
8953 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
8954 }
8955
8956 if (sRef_isMeaningful (eref))
8957 {
8958 defines = eref;
8959 }
8960 else
8961 {
8962 defines = s;
8963 }
8964 }
8965 else if (sRef_isAllocated (s))
8966 {
8967 sRef eref = exprNode_getSref (e);
8968
8969
8970 if (!sRef_isAllocated (eref))
8971 {
8972 sRef_setDefinedComplete (eref, exprNode_loc (e));
8973 }
8974 else
8975 {
8976 sRef base = sRef_getBaseSafe (eref);
8977
8978 if (sRef_isValid (base))
8979 {
8980 sRef_setPdefined (base, exprNode_loc (e));
8981 }
8982 }
8983
8984 defines = s;
8985 }
8986 else
8987 {
8988 sRef_setDefinedNCComplete (s, exprNode_loc (e));
8989 defines = s;
8990 }
8991
8992 }
8993 else /* not meaningful...but still need to insert it */
8994 {
8995 defines = s;
8996 }
8997 }
8998
8999 if (exprNode_isDefined (e) && sRef_isValid (defines))
9000 {
9001 e->sets = sRefSet_insert (e->sets, defines);
9002 }
9003}
9004
9005void
9006exprNode_checkMSet (exprNode e, sRef s)
9007{
9008 if (sRef_isValid (s) && !sRef_isNothing (s))
9009 {
9010 uentry ue = sRef_getBaseUentry (s);
9011
9012 if (uentry_isValid (ue))
9013 {
9014 uentry_setLset (ue);
9015 }
9016
9017 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9018 {
9019 voptgenerror (FLG_USEDEF,
9020 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
9021 exprNode_loc (e));
9022 }
9023
9024 if (sRef_isMeaningful (s))
9025 {
9026 sRef_setDefinedComplete (s, exprNode_loc (e));
9027 }
9028
9029 if (exprNode_isDefined (e))
9030 {
9031 e->msets = sRefSet_insert (e->msets, s);
9032 }
9033 }
9034}
9035
9036static void
9037checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
9038{
9039 checkAnyCall (fcn, cstring_undefined, params, args,
9040 FALSE, sRefSet_undefined, FALSE, 0);
9041}
9042
9043static void
9044checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
9045 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
9046{
9047 setCodePoint ();
9048
9049 if (uentry_isYield (ucurrent))
9050 {
9051 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
9052 exprNode_checkSet (current, current->sref);
9053 }
9054 else
9055 {
9056 if (uentry_isSefParam (ucurrent))
9057 {
9058 sRefSet sets = current->sets;
9059 sRef ref = exprNode_getSref (current);
9060
9061 if (sRef_isMacroParamRef (ref))
9062 {
9063 uentry ue = sRef_getUentry (ref);
9064
9065 if (!uentry_isSefParam (ue))
9066 {
9067 voptgenerror
9068 (FLG_SEFPARAMS,
9069 message
9070 ("Parameter %d to %s is declared sef, but "
9071 "the argument is a macro parameter declared "
9072 "without sef: %s",
9073 argno, exprNode_unparse (fcn),
9074 exprNode_unparse (current)),
9075 exprNode_loc (current));
9076 }
9077 }
9078
9079 if (!sRefSet_isEmpty (sets))
9080 {
9081 sRefSet reported = sRefSet_undefined;
9082
9083 sRefSet_realElements (current->sets, el)
9084 {
9085 if (sRefSet_isSameNameMember (reported, el))
9086 {
9087 ; /* don't report again */
9088 }
9089 else
9090 {
9091 if (sRef_isUnconstrained (el))
9092 {
9093 voptgenerror
9094 (FLG_SEFUNSPEC,
9095 message
9096 ("Parameter %d to %s is declared sef, but "
9097 "the argument calls unconstrained function %s "
9098 "(no guarantee it will not modify something): %s",
9099 argno, exprNode_unparse (fcn),
9100 sRef_unconstrainedName (el),
9101 exprNode_unparse (current)),
9102 exprNode_loc (current));
9103 }
9104 else
9105 {
9106 voptgenerror
9107 (FLG_SEFPARAMS,
9108 message
9109 ("Parameter %d to %s is declared sef, but "
9110 "the argument may modify %q: %s",
9111 argno, exprNode_unparse (fcn),
9112 sRef_unparse (el),
9113 exprNode_unparse (current)),
9114 exprNode_loc (current));
9115 }
9116 }
9117 } end_sRefSet_realElements;
9118 }
9119 }
9120
9121 checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs);
9122 exprNode_mergeUSs (fcn, current);
9123 }
9124}
9125
9126static void
9127 checkAnyCall (/*@dependent@*/ exprNode fcn,
9128 /*@dependent@*/ cstring fname,
9129 uentryList pn,
9130 exprNodeList args,
9131 bool hasMods, sRefSet mods,
9132 bool isSpec,
9133 int specialArgs)
9134{
9135 int paramno = 0;
9136 int nargs = exprNodeList_size (args);
9137
9138 setCodePoint ();
9139
9140 /*
9141 ** concat all args ud's to f, add each arg sref as a use unless
9142 ** it was specified as "out", in which case it is a def.
9143 */
9144
9145 uentryList_reset (pn);
9146
9147 /*
9148 ** aliasing checks:
9149 **
9150 ** if paramn is only or unique, no other arg may alias argn
9151 */
9152
9153 exprNodeList_elements (args, current)
9154 {
9155 paramno++;
9156
9157 if (exprNode_isDefined (current))
9158 {
9159 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
9160 {
9161 uentry ucurrent = uentryList_current (pn);
9162
9163 if (specialArgs == 0
9164 || (paramno < specialArgs))
9165 {
9166 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
9167
9168 if (context_maybeSet (FLG_ALIASUNIQUE))
9169 {
9170 if (uentry_isOnly (ucurrent)
9171 || uentry_isUnique (ucurrent))
9172 {
9173 checkUniqueParams (fcn, current, args,
9174 paramno, ucurrent);
9175 }
9176 }
9177 }
9178 }
9179 else /* uentry is undefined */
9180 {
9181 if (specialArgs == 0)
9182 {
9183 exprNode_checkUseParam (current);
9184 }
9185
9186 exprNode_mergeUSs (fcn, current);
9187 }
9188 }
9189 uentryList_advanceSafe (pn);
9190 } end_exprNodeList_elements;
9191
9192 if (hasMods)
9193 {
9194 setCodePoint ();
9195
9196 sRefSet_allElements (mods, s)
9197 {
9198 sRef fb;
9199 sRef rb = sRef_getRootBase (s);
9200
9201 if (sRef_isGlobal (rb))
9202 {
9203 context_usedGlobal (rb);
9204 }
9205
9206 fb = sRef_fixBaseParam (s, args);
9207
9208 if (!sRef_isMacroParamRef (fb))
9209 {
9210 if (sRef_isNothing (fb))
9211 {
9212 ;
9213 }
9214 else
9215 {
9216 if (sRef_isValid (fb))
9217 {
9218 uentry ue = sRef_getBaseUentry (s);
9219
9220 if (uentry_isValid (ue))
9221 {
9222 uentry_setLset (ue);
9223 }
9224 }
9225
9226 fcn->sets = sRefSet_insert (fcn->sets, fb);
9227 }
9228 }
9229 sRef_clearDerivedComplete (s);
9230 } end_sRefSet_allElements;
9231
9232 setCodePoint ();
9233 }
9234 else
9235 {
9236 if (context_hasMods ())
9237 {
9238 if (context_maybeSet (FLG_MODUNCON))
9239 {
9240 voptgenerror
9241 (FLG_MODUNCON,
9242 message ("Undetected modification possible "
9243 "from call to unconstrained function %s: %s",
9244 fname,
9245 exprNode_unparse (fcn)),
9246 exprNode_loc (fcn));
9247 }
9248 }
9249 else
9250 {
9251 if (context_maybeSet (FLG_MODUNCONNOMODS)
9252 && !(context_inIterDef () || context_inIterEnd ()))
9253 {
9254 voptgenerror
9255 (FLG_MODUNCONNOMODS,
9256 message ("Undetected modification possible "
9257 "from call to unconstrained function %s: %s",
9258 fname,
9259 exprNode_unparse (fcn)),
9260 exprNode_loc (fcn));
9261 }
9262 }
9263
9264 exprNode_checkSetAny (fcn, fname);
9265 }
9266}
9267
9268void exprNode_checkUseParam (exprNode current)
9269{
9270 if (exprNode_isDefined (current))
9271 {
9272 exprNode_checkUse (current, current->sref, current->loc);
9273 }
9274}
9275
9276static ctype
9277 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
9278 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
9279 lltok op)
9280{
9281 ctype ret = tr1;
9282
9283 if (!ctype_match (tr1, tr2))
9284 {
9285 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
9286 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
9287 {
9288 ;
9289 }
9290 else
9291 {
9292 (void) gentypeerror
9293 (tr1, e1, tr2, e2,
9294 message ("Incompatible types for %s (%s, %s): %s %s %s",
9295 lltok_unparse (op),
9296 ctype_unparse (te1),
9297 ctype_unparse (te2),
9298 exprNode_unparse (e1), lltok_unparse (op),
9299 exprNode_unparse (e2)),
9300 e1->loc);
9301 }
9302 ret = ctype_unknown;
9303 }
9304 else
9305 {
9306 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
9307 {
9308 ret = ctype_resolveNumerics (tr1, tr2);
9309 }
9310 else if (!context_msgStrictOps ())
9311 {
9312 if (ctype_isPointer (tr1))
9313 {
9314 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
9315 {
9316 ret = ctype_int;
9317 }
9318 else if (ctype_isInt (tr2))
9319 {
9320 ret = te1;
9321 }
9322 else
9323 {
9324 ret = ctype_unknown;
9325 }
9326 }
9327 else if (ctype_isPointer (tr2))
9328 {
9329 if (ctype_isPointer (tr1))
9330 {
9331 ret = ctype_int;
9332 }
9333 else if (ctype_isInt (tr1))
9334 {
9335 ret = te2;
9336 }
9337 else
9338 {
9339 ret = ctype_unknown;
9340 }
9341 }
9342 else
9343 {
9344 ret = ctype_resolveNumerics (tr1, tr2);
9345 }
9346 }
9347 else
9348 {
9349 int opid = lltok_getTok (op);
9350 bool comparop = (opid == EQ_OP || opid == NE_OP
9351 || opid == TLT || opid == TGT
9352 || opid == LE_OP || opid == GE_OP);
9353
9354 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
9355 {
9356 if (comparop
9357 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
9358 || (ctype_isBool (tr1) && ctype_isBool (tr2))
9359 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
9360 {
9361 ; /* no error */
9362 }
9363 else
9364 {
9365 if (ctype_sameName (te1, te2))
9366 {
9367 voptgenerror
9368 (FLG_STRICTOPS,
9369 message ("Operands of %s are non-numeric (%t): %s %s %s",
9370 lltok_unparse (op), te1,
9371 exprNode_unparse (e1), lltok_unparse (op),
9372 exprNode_unparse (e2)),
9373 e1->loc);
9374 }
9375 else
9376 {
9377 voptgenerror
9378 (FLG_STRICTOPS,
9379 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
9380 lltok_unparse (op), te1, te2,
9381 exprNode_unparse (e1), lltok_unparse (op),
9382 exprNode_unparse (e2)),
9383 e1->loc);
9384 }
9385 }
9386 }
9387 else if (!ctype_isNumeric (tr1))
9388 {
9389 voptgenerror
9390 (FLG_STRICTOPS,
9391 message ("Right operand of %s is non-numeric (%t): %s %s %s",
9392 lltok_unparse (op), te1,
9393 exprNode_unparse (e1), lltok_unparse (op),
9394 exprNode_unparse (e2)),
9395 e1->loc);
9396 }
9397 else
9398 {
9399 if (!ctype_isNumeric (tr2))
9400 {
9401 voptgenerror
9402 (FLG_STRICTOPS,
9403 message ("Left operand of %s is non-numeric (%t): %s %s %s",
9404 lltok_unparse (op), te2,
9405 exprNode_unparse (e1), lltok_unparse (op),
9406 exprNode_unparse (e2)),
9407 e2->loc);
9408 }
9409 }
9410
9411 ret = ctype_unknown;
9412 }
9413 }
9414
9415 return ret;
9416}
9417
9418static void
9419abstractOpError (ctype tr1, ctype tr2, lltok op,
9420 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
9421 fileloc loc1, fileloc loc2)
9422{
9423 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
9424 {
9425 if (ctype_match (tr1, tr2))
9426 {
9427 voptgenerror
9428 (FLG_ABSTRACT,
9429 message ("Operands of %s are abstract type (%t): %s %s %s",
9430 lltok_unparse (op), tr1,
9431 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9432 loc1);
9433 }
9434 else
9435 {
9436 voptgenerror
9437 (FLG_ABSTRACT,
9438 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
9439 lltok_unparse (op), tr1, tr2,
9440 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9441 loc1);
9442 }
9443 }
9444 else if (ctype_isRealAbstract (tr1))
9445 {
9446 voptgenerror
9447 (FLG_ABSTRACT,
9448 message ("Left operand of %s is abstract type (%t): %s %s %s",
9449 lltok_unparse (op), tr1,
9450 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9451 loc1);
9452 }
9453 else
9454 {
9455 if (ctype_isRealAbstract (tr2))
9456 {
9457 voptgenerror
9458 (FLG_ABSTRACT,
9459 message ("Right operand of %s is abstract type (%t): %s %s %s",
9460 lltok_unparse (op), tr2,
9461 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9462 loc2);
9463 }
9464 }
9465}
9466
9467/*
9468** e1 <= e2
9469**
9470** requies e1 and e2 and not error exprNode's.
9471**
9472** Checks:
9473**
9474** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
9475** the rep of the abstract type is exposed.
9476**
9477** The order is very important:
9478**
9479** check rep expose (move into check transfer)
9480** check transfer
9481** setup aliases
9482*/
9483
9484/*
9485** This isn't really a sensible procedure, but the indententation
9486** was getting too deep.
9487*/
9488
9489static void
9490checkOneRepExpose (sRef ysr, sRef base,
9491 /*@notnull@*/ exprNode e1,
9492 /*@notnull@*/ exprNode e2, ctype ct,
9493 sRef s2b)
9494{
9495 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
9496 || sRef_isOwned (ysr) || sRef_isExposed (ysr)))
9497 {
9498 if (sRef_isAnyParam (base) && !sRef_isExposed (base))
9499 {
9500 if (sRef_isIReference (ysr))
9501 {
9502 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
9503 {
9504 voptgenerror
9505 (FLG_ASSIGNEXPOSE,
9506 message
9507 ("Assignment of mutable component of parameter %q "
9508 "to component of abstract "
9509 "type %s exposes rep: %s = %s",
9510 sRef_unparse (base),
9511 ctype_unparse (ct),
9512 exprNode_unparse (e1), exprNode_unparse (e2)),
9513 e1->loc);
9514 }
9515 else
9516 {
9517 voptgenerror
9518 (FLG_ASSIGNEXPOSE,
9519 message
9520 ("Assignment of mutable component of parameter %q "
9521 "(through alias %q) to component of abstract "
9522 "type %s exposes rep: %s = %s",
9523 sRef_unparse (base),
9524 sRef_unparse (e2->sref),
9525 ctype_unparse (ct),
9526 exprNode_unparse (e1), exprNode_unparse (e2)),
9527 e1->loc);
9528 }
9529 }
9530 else
9531 {
9532 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
9533 {
9534 voptgenerror
9535 (FLG_ASSIGNEXPOSE,
9536 message ("Assignment of mutable parameter %q "
9537 "to component of abstract type %s "
9538 "exposes rep: %s = %s",
9539 sRef_unparse (base),
9540 ctype_unparse (ct),
9541 exprNode_unparse (e1),
9542 exprNode_unparse (e2)),
9543 e1->loc);
9544 }
9545 else
9546 {
9547 voptgenerror
9548 (FLG_ASSIGNEXPOSE,
9549 message ("Assignment of mutable parameter %q "
9550 "(through alias %q) to "
9551 "component of abstract type %s exposes "
9552 "rep: %s = %s",
9553 sRef_unparse (base),
9554 sRef_unparse (e2->sref),
9555 ctype_unparse (ct),
9556 exprNode_unparse (e1),
9557 exprNode_unparse (e2)),
9558 e1->loc);
9559 }
9560 }
9561 }
9562
9563 if (sRef_isGlobal (s2b))
9564 {
9565 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
9566 {
9567 voptgenerror
9568 (FLG_REPEXPOSE,
9569 message ("Assignment of global %q "
9570 "to component of "
9571 "abstract type %s exposes rep: %s = %s",
9572 sRef_unparse (base),
9573 ctype_unparse (ct),
9574 exprNode_unparse (e1), exprNode_unparse (e2)),
9575 e1->loc);
9576 }
9577 else
9578 {
9579 voptgenerror
9580 (FLG_REPEXPOSE,
9581 message ("Assignment of global %q (through alias %q) "
9582 "to component of "
9583 "abstract type %s exposes rep: %s = %s",
9584 sRef_unparse (base),
9585 sRef_unparse (e2->sref),
9586 ctype_unparse (ct),
9587 exprNode_unparse (e1), exprNode_unparse (e2)),
9588 e1->loc);
9589 }
9590 }
9591 }
9592}
9593
9594static void
9595doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
9596{
9597 if (ctype_isRealFunction (exprNode_getType (e1))
9598 && !ctype_isRealPointer (exprNode_getType (e1)))
9599 {
9600 voptgenerror
9601 (FLG_TYPE,
9602 message ("Invalid left-hand side of assignment (function type %s): %s",
9603 ctype_unparse (exprNode_getType (e1)),
9604 exprNode_unparse (e1)),
9605 e1->loc);
9606 }
9607
9608 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
9609 {
9610 ctype t2 = exprNode_getType (e2);
9611 sRef sr = sRef_getRootBase (e1->sref);
9612 ctype ct = sRef_getType (sr);
9613
9614 if (ctype_isAbstract (t2)
9615 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
9616 {
9617 /* it is immutable, okay to reference */
9618 goto donerepexpose;
9619 }
9620
9621 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
9622 {
9623 sRef s2b = sRef_getRootBase (e2->sref);
9624 sRef s1 = e1->sref;
9625 sRef s1b = sRef_getRootBase (s1);
9626 sRefSet aliases;
9627
9628 aliases = usymtab_canAlias (e2->sref);
9629
9630 if (!sRef_similar (s2b, s1b)
9631 && !sRef_isExposed (s1)
9632 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
9633 {
9634 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
9635 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
9636 && !sRef_isExposed (s2b))
9637 {
9638 if (sRef_isIReference (e2->sref))
9639 {
9640 voptgenerror
9641 (FLG_ASSIGNEXPOSE,
9642 message
9643 ("Assignment of mutable component of parameter %q "
9644 "to component of abstract type %s exposes rep: %s = %s",
9645 sRef_unparse (s2b),
9646 ctype_unparse (ct),
9647 exprNode_unparse (e1), exprNode_unparse (e2)),
9648 e1->loc);
9649 }
9650 else
9651 {
9652 voptgenerror
9653 (FLG_ASSIGNEXPOSE,
9654 message ("Assignment of mutable parameter %q to "
9655 "component of abstract type %s exposes rep: %s = %s",
9656 sRef_unparse (s2b),
9657 ctype_unparse (ct),
9658 exprNode_unparse (e1), exprNode_unparse (e2)),
9659 e1->loc);
9660 }
9661 }
9662
9663 if (sRef_isGlobal (s2b))
9664 {
9665 voptgenerror
9666 (FLG_ASSIGNEXPOSE,
9667 message ("Assignment of global %q to component of "
9668 "abstract type %s exposes rep: %s = %s",
9669 sRef_unparse (s2b),
9670 ctype_unparse (ct),
9671 exprNode_unparse (e1), exprNode_unparse (e2)),
9672 e1->loc);
9673 }
9674
9675 sRefSet_realElements (aliases, ysr)
9676 {
9677 sRef base = sRef_getRootBase (ysr);
9678
9679 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
9680 || sRef_sameName (base, s1b))
9681 {
9682 ; /* error already reported or same sref */
9683 }
9684 else
9685 {
9686 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
9687 }
9688 } end_sRefSet_realElements;
9689 }
9690 sRefSet_free (aliases);
9691 }
9692 }
9693
9694 donerepexpose:
9695
9696 /*
9697 ** function variables don't really work...
9698 */
9699
9700 if (!ctype_isFunction (ctype_realType (e2->typ)))
9701 {
9702 if (isInit)
9703 {
9704 checkInitTransfer (e1, e2);
9705 }
9706 else
9707 {
9708 checkAssignTransfer (e1, e2);
9709 }
9710 }
9711 else
9712 {
9713 sRef fref = e2->sref;
9714
9715 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
9716 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
9717
9718 /* Need to typecheck the annotation on the parameters */
9719
9720 if (ctype_isRealFunction (e1->typ)) {
9721 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
9722 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
9723
9724 if (!uentryList_isMissingParams (e1p)
9725 && !uentryList_isMissingParams (e2p)
9726 && uentryList_size (e1p) > 0) {
9727 if (uentryList_size (e1p) == uentryList_size (e2p)) {
9728 int n = 0;
9729
9730 uentryList_elements (e1p, el1) {
9731 uentry el2;
9732
9733 el2 = uentryList_getN (e2p, n);
9734 n++;
9735 uentry_checkMatchParam (el1, el2, n, e2);
9736 } end_uentryList_elements;
9737 }
9738 }
9739 }
9740 }
9741
9742 if (isInit && sRef_isGlobal (e1->sref))
9743 {
9744 ;
9745 }
9746 else
9747 {
9748 updateAliases (e1, e2);
9749 }
dc92450f 9750 // updateEnvironment (e1, e2);
616915dd 9751}
9752
9753static void
9754checkMacroParen (exprNode e)
9755{
9756 if (exprNode_isError (e) || e->kind == XPR_CAST)
9757 {
9758 ;
9759 }
9760 else
9761 {
9762 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
9763 {
9764 voptgenerror
9765 (FLG_MACROPARENS,
9766 message ("Macro parameter used without parentheses: %s",
9767 exprNode_unparse (e)),
9768 e->loc);
9769 }
9770 }
9771}
9772
9773static void
9774reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
9775{
9776 if (isnull)
9777 {
9778 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
9779 }
9780 else
9781 {
9782 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
9783 }
9784}
9785
9786/*
9787** e1 <= e2
9788**
9789** if e2 is a parameter or global derived location which
9790** can be modified (that is, e2 is a mutable abstract type,
9791** or a derived pointer), then e1 can alias e2.
9792**
9793** e1 can alias everything which e2 can alias.
9794**
9795** Also, if e1 is guarded, remove from guard sets!
9796*/
9797
9798static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
9799{
9800 if (!context_inProtectVars ())
9801 {
9802 /*
9803 ** depends on types of e1 and e2
9804 */
9805
9806 sRef s1 = e1->sref;
9807 sRef s2 = e2->sref;
9808 ctype t1 = exprNode_getType (e1);
9809
9810 /* handle pointer sRefs, record fields, arrays, etc... */
9811
9812 if (!ctype_isRealSU (t1))
9813 {
9814 sRef_copyRealDerivedComplete (s1, s2);
9815 }
9816
9817 if (ctype_isMutable (t1) && sRef_isKnown (s1))
9818 {
9819 usymtab_clearAlias (s1);
9820 usymtab_addMustAlias (s1, s2);
9821 }
9822
9823 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
9824 {
9825 usymtab_unguard (s1);
9826 }
9827 }
9828}
9829
9830exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
9831{
9832 if (exprNode_isDefined (e))
9833 {
9834 e->loc = fileloc_update (e->loc, loc);
9835 }
9836 else
9837 {
9838 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
9839 }
9840
9841 return (e);
9842}
9843
9844static void checkUniqueParams (exprNode fcn,
9845 /*@notnull@*/ exprNode current,
9846 exprNodeList args,
9847 int paramno, uentry ucurrent)
9848{
9849 int iparamno = 0;
9850 sRef thisref = exprNode_getSref (current);
9851
9852 /*
9853 ** Check if any argument could match this argument.
9854 */
9855
9856 exprNodeList_elements (args, icurrent)
9857 {
9858 iparamno++;
9859
9860 if (iparamno != paramno)
9861 {
9862 sRef sr = exprNode_getSref (icurrent);
9863
9864 if (sRef_similarRelaxed (thisref, sr))
9865 {
9866 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
9867 {
9868 voptgenerror
9869 (FLG_ALIASUNIQUE,
9870 message
9871 ("Parameter %d (%s) to function %s is declared %s but "
9872 "is aliased by parameter %d (%s)",
9873 paramno,
9874 exprNode_unparse (current),
9875 exprNode_unparse (fcn),
9876 alkind_unparse (uentry_getAliasKind (ucurrent)),
9877 iparamno, exprNode_unparse (icurrent)),
9878 current->loc);
9879 }
9880 }
9881 else
9882 {
9883 sRefSet aliases = usymtab_canAlias (sr);
9884
9885 sRefSet_allElements (aliases, asr)
9886 {
9887 if (ctype_isUnknown (sRef_getType (thisref)))
9888 {
9889 sRef_setType (thisref, uentry_getType (ucurrent));
9890 }
9891
9892 if (sRef_similarRelaxed (thisref, asr))
9893 {
9894 if (sRef_isExternal (asr))
9895 {
9896 if (sRef_isLocalState (thisref))
9897 {
9898 ; /* okay */
9899 }
9900 else
9901 {
9902 sRef base = sRef_getRootBase (asr);
9903
9904 if (!sRef_similar (sRef_getBase (asr), thisref))
9905 {
9906 if (sRef_isUnique (base) || sRef_isOnly (base)
9907 || sRef_isKept (base)
9908 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
9909 || (sRef_isAddress (thisref)
9910 && sRef_isLocalVar (sRef_getRootBase (thisref))))
9911 {
9912 ; /* okay, no error */
9913 }
9914 else
9915 {
9916 voptgenerror
9917 (FLG_MAYALIASUNIQUE,
9918 message
9919 ("Parameter %d (%s) to function %s is declared %s but "
9920 "may be aliased externally by parameter %d (%s)",
9921 paramno,
9922 exprNode_unparse (current),
9923 exprNode_unparse (fcn),
9924 alkind_unparse (uentry_getAliasKind (ucurrent)),
9925 iparamno, exprNode_unparse (icurrent)),
9926 current->loc);
9927 }
9928 }
9929 }
9930 }
9931 else
9932 {
9933 voptgenerror
9934 (FLG_ALIASUNIQUE,
9935 message
9936 ("Parameter %d (%s) to function %s is declared %s but "
9937 "is aliased externally by parameter %d (%s) through "
9938 "alias %q",
9939 paramno,
9940 exprNode_unparse (current),
9941 exprNode_unparse (fcn),
9942 alkind_unparse (uentry_getAliasKind (ucurrent)),
9943 iparamno, exprNode_unparse (icurrent),
9944 sRef_unparse (asr)),
9945 current->loc);
9946 }
9947 }
9948 } end_sRefSet_allElements;
9949 sRefSet_free (aliases);
9950 }
9951 }
9952 } end_exprNodeList_elements;
9953}
9954
9955long exprNode_getLongValue (exprNode e) {
9956 long value;
9957
9958 if (exprNode_hasValue (e)
9959 && multiVal_isInt (exprNode_getValue (e)))
9960 {
9961 value = multiVal_forceInt (exprNode_getValue (e));
9962 }
9963 else
9964 {
9965 value = 0;
9966 }
9967
9968 return value;
9969}
9970
d46ce6a4 9971/*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
616915dd 9972{
84c9ffbf 9973 if (exprNode_isDefined (p_e) )
d46ce6a4 9974 return ( p_e->loc );
616915dd 9975 else
9976 return fileloc_undefined;
9977}
9978
9979fileloc exprNode_getNextSequencePoint (exprNode e)
9980{
9981 /*
9982 ** Returns the location of the sequence point following e.
9983 **
9984 ** Only works for statements (for now).
9985 */
9986
9987 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
9988 lltok t = exprData_getUopTok (e->edata);
9989 return lltok_getLoc (t);
9990 } else {
9991 #warning fix
9992 // llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
9993 return fileloc_undefined;
9994 }
9995 }
9996
9997
9280addf 9998/*drl added
9999 */
d46ce6a4 10000exprNode exprNode_fakeCopy (/*@returned@*/ exprNode e)
9280addf 10001{
10002 /*@-temptrans@*/ /*@-retalias@*/
10003 return e;
10004 /*@=temptrans@*/ /*@=retalias@*/
10005}
10006
10007exprNode exprNode_createNew(ctype c)
10008{
10009 exprNode ret;
10010
10011 ret = exprNode_createPlain (c);
10012
10013 return ret;
10014}
This page took 1.508325 seconds and 5 git commands to generate.