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