]> andersk Git - splint.git/blame - src/exprNode.c
Added checking for union initializers.
[splint.git] / src / exprNode.c
CommitLineData
616915dd 1/*
11db3170 2** Splint - 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
11db3170 22** For more information: http://www.splint.org
616915dd 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*/
11db3170 4319 /*DRL 6/8/01 I decided to disable all Splint warnings here since the code
84c9ffbf 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 "
11db3170 5794 "from a problem with bison v. 1.25. Please try rebuidling Splint "
28bf4b0b 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
146e25eb 7897 DPRINTF (("Check one init: %s / %s",
7898 exprNode_unparse (el),
7899 exprNode_unparse (val)));
7900
616915dd 7901 if (ctype_isUnknown (t1))
7902 {
7903 voptgenerror (FLG_IMPTYPE,
7904 message ("Variable has unknown (implicitly int) type: %s",
7905 exprNode_unparse (el)),
7906 el->loc);
7907
7908 t1 = ctype_int;
7909 el->typ = ctype_int;
7910 }
7911
7912 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
7913 {
7914 exprNodeList vals = exprData_getArgs (val->edata);
7915
7534721d 7916 DPRINTF (("Check one init: %s", exprNodeList_unparse (vals)));
7917 DPRINTF (("Type: %s", ctype_unparse (t1)));
7918
616915dd 7919 if (ctype_isRealAP (t1))
7920 {
7921 int i = 0;
7922 int nerrors = 0;
7923
7534721d 7924 if (ctype_isFixedArray (t1))
7925 {
7926 int nelements = long_toInt (ctype_getArraySize (t1));
7927
7928 if (exprNode_isStringLiteral (val))
7929 {
7930 exprNode_checkStringLiteralLength (t1, val);
7931 }
7932 else
7933 {
7934 if (exprNodeList_size (vals) != nelements)
7935 {
7936 hasError = optgenerror
7937 (exprNodeList_size (vals) > nelements ? FLG_INITSIZE : FLG_INITALLELEMENTS,
7938 message ("Initializer block for "
7939 "%s has %d element%&, but declared as %s: %q",
7940 exprNode_unparse (el),
7941 exprNodeList_size (vals),
7942 ctype_unparse (t1),
7943 exprNodeList_unparse (vals)),
7944 val->loc);
7945 }
7946 }
7947 }
7948
616915dd 7949 exprNodeList_elements (vals, oneval)
7950 {
7951 cstring istring = message ("%d", i);
7952 exprNode newel =
7953 exprNode_arrayFetch
7954 (exprNode_fakeCopy (el),
7955 exprNode_numLiteral (ctype_int, istring,
7956 fileloc_copy (el->loc), i));
7957
7958 if (exprNode_isDefined (newel))
7959 {
7960 if (exprNodeList_size (vals) == 1
7961 && ctype_isString (exprNode_getType (oneval))
7962 && ctype_isChar (exprNode_getType (newel)))
7963 {
7964 exprNode_freeIniter (newel);
7965 }
7966 else
7967 {
7968 if (exprNode_checkOneInit (newel, oneval))
7969 {
7970 hasError = TRUE;
7971 nerrors++;
7972
7973 if (nerrors > 3 && exprNodeList_size (vals) > 6)
7974 {
7975 llgenmsg
7976 (message ("Additional initialization errors "
7977 "for %s not reported",
7978 exprNode_unparse (el)),
7979 exprNode_loc (el));
7980 exprNode_freeIniter (newel);
7981 break;
7982 }
7983 else
7984 {
7985 exprNode_freeIniter (newel);
7986 }
7987 }
7988 else
7989 {
7990 exprNode_freeIniter (newel);
7991 }
7992 }
7993 }
7994
7995 cstring_free (istring);
7996 i++;
7997 /*@-branchstate@*/
7998 } end_exprNodeList_elements;
7999 /*@=branchstate@*/
8000 }
8001 else if (ctype_isStruct (ctype_realType (t1)))
8002 {
8003 uentryList fields = ctype_getFields (t1);
8004 int i = 0;
8005
8006 if (uentryList_size (fields) != exprNodeList_size (vals))
8007 {
8008 if (uentryList_size (fields) > exprNodeList_size (vals))
8009 {
8010 hasError = optgenerror
8011 (FLG_FULLINITBLOCK,
8012 message ("Initializer block for "
28bf4b0b 8013 "%s has %d field%&, but %s has %d field%&: %q",
616915dd 8014 exprNode_unparse (el),
8015 exprNodeList_size (vals),
8016 ctype_unparse (t1),
8017 uentryList_size (fields),
8018 exprNodeList_unparse (vals)),
8019 val->loc);
8020 }
8021 else
8022 {
8023 hasError = optgenerror
8024 (FLG_TYPE,
8025 message ("Initializer block for "
28bf4b0b 8026 "%s has %d field%&, but %s has %d field%&: %q",
616915dd 8027 exprNode_unparse (el),
8028 exprNodeList_size (vals),
8029 ctype_unparse (t1),
8030 uentryList_size (fields),
8031 exprNodeList_unparse (vals)),
8032 val->loc);
8033 }
8034 }
8035 else
8036 {
8037 exprNodeList_elements (vals, oneval)
8038 {
8039 uentry thisfield = uentryList_getN (fields, i);
8040 exprNode newel =
28bf4b0b 8041 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8042 exprNode_loc (el),
8043 uentry_getName (thisfield));
616915dd 8044
8045 if (exprNode_isDefined (newel))
8046 {
8047 if (exprNode_checkOneInit (newel, oneval))
8048 {
8049 hasError = TRUE;
8050 }
8051
8052 exprNode_freeIniter (newel);
8053 }
8054
8055 i++;
8056 } end_exprNodeList_elements;
8057 }
8058 }
146e25eb 8059 /* evans 2001-12-30: added to fix bug reported by Jim Zelenka */
8060 else if (ctype_isUnion (ctype_realType (t1)))
8061 {
8062 uentryList fields = ctype_getFields (t1);
8063 int i = 0;
8064
8065 /*
8066 ** Union initializers set the first member always.
8067 */
8068
8069 DPRINTF (("Union initializer: %s / %s",
8070 exprNode_unparse (el), ctype_unparse (ctype_realType (t1))));
8071
8072 if (exprNodeList_size (vals) != 1)
8073 {
8074 hasError = optgenerror
8075 (FLG_TYPE,
8076 message ("Initializer block for union "
8077 "%s has %d elements, union initializers should have one element: %q",
8078 exprNode_unparse (el),
8079 exprNodeList_size (vals),
8080 exprNodeList_unparse (vals)),
8081 val->loc);
8082 }
8083 else
8084 {
8085 exprNode oneval = exprNodeList_head (vals);
8086 uentry thisfield = uentryList_getN (fields, i);
8087 exprNode newel =
8088 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8089 exprNode_loc (el),
8090 uentry_getName (thisfield));
8091
8092 if (exprNode_isDefined (newel))
8093 {
8094 if (exprNode_checkOneInit (newel, oneval))
8095 {
8096 hasError = TRUE;
8097 }
8098
8099 exprNode_freeIniter (newel);
8100 }
8101 }
8102 }
616915dd 8103 else
8104 {
8105 hasError = optgenerror
8106 (FLG_TYPE,
8107 message ("Initializer block used for "
8108 "%s where %t is expected: %s",
8109 exprNode_unparse (el), t1, exprNode_unparse (val)),
8110 val->loc);
8111 }
8112 }
8113 else
8114 {
8115 if (exprNode_isDefined (val))
8116 {
8117 doAssign (el, val, TRUE);
8118
8119 if (!exprNode_matchType (t1, val))
8120 {
8121 hasError = gentypeerror
8122 (t1, val, t2, el,
8123 message ("Initial value of %s is type %t, "
8124 "expects %t: %s",
8125 exprNode_unparse (el),
8126 t2, t1, exprNode_unparse (val)),
8127 val->loc);
8128 }
8129 }
8130 }
8131
8132 return hasError;
8133}
8134
28bf4b0b 8135static exprNode
8136exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
8137{
8138 exprNode ret;
8139
146e25eb 8140 DPRINTF (("Initialization: %s", idDecl_unparse (t)));
8141
28bf4b0b 8142 if (usymtab_exists (idDecl_observeId (t)))
8143 {
8144 uentry ue = usymtab_lookup (idDecl_observeId (t));
8145 ret = exprNode_createId (ue);
8146
8147 /*@i723 don't do this...but why? */
8148# if 0
8149 ct = ctype_realishType (ret->typ);
8150
8151 DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
8152
8153 if (ctype_isUnknown (ct))
8154 {
8155 if (uentry_isAnyTag (ue))
8156 {
8157 voptgenerror
8158 (FLG_IMPTYPE,
8159 message ("%s used but not previously declared: %s",
8160 uentry_ekindName (ue),
8161 idDecl_getName (t)),
8162 g_currentloc);
8163
8164 }
8165 else
8166 {
8167 voptgenerror
8168 (FLG_IMPTYPE,
8169 message ("Variable has unknown (implicitly int) type: %s",
8170 idDecl_getName (t)),
8171 g_currentloc);
8172 }
8173
8174 ct = ctype_int;
8175 }
8176# endif
8177 }
8178 else
8179 {
7ebcc5bb 8180 uentry ue;
8181
8182 DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
8183
8184 ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
8185 /*!! fileloc_copy (g_currentloc)); */
8186 /*@i32!!! should get error without this */
146e25eb 8187
28bf4b0b 8188 ret = exprNode_fromIdentifierAux (ue);
8189
8190 /*
8191 ** No error - this happens in old style declarations:
8192
8193 voptgenerror
8194 (FLG_UNRECOG,
8195 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8196 g_currentloc);
8197
8198 **
8199 */
8200 }
8201
8202 exprData_free (ret->edata, ret->kind);
8203 ret->edata = exprData_undefined;
e83c79ec 8204
28bf4b0b 8205 ret->exitCode = XK_NEVERESCAPE;
8206 ret->mustBreak = FALSE;
8207 ret->kind = XPR_INIT;
8208 return ret;
8209}
8210
8211exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8212{
8213 exprNode ret = exprNode_makeInitializationAux (t);
8214 llassert (ret->edata == exprData_undefined);
8215 ret->edata = exprData_makeInit (t, exprNode_undefined);
8216 return ret;
8217}
8218
616915dd 8219exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8220 /*@only@*/ exprNode e)
8221{
8222 uentry ue = usymtab_lookup (idDecl_observeId (t));
28bf4b0b 8223 exprNode ret = exprNode_makeInitializationAux (t);
8224 fileloc loc = exprNode_loc (e);
b072092f 8225
616915dd 8226 if (exprNode_isError (e))
8227 {
8228 e = exprNode_createUnknown ();
28bf4b0b 8229 idDecl_free (t);
616915dd 8230
8231 /* error: assume initializer is defined */
28bf4b0b 8232 sRef_setDefined (ret->sref, g_currentloc);
616915dd 8233 }
8234 else
8235 {
28bf4b0b 8236 ctype ct = ctype_realishType (ret->typ);
8237
616915dd 8238 /*
8239 ** evs - 9 Apr 1995
8240 **
8241 ** was addSafeUse --- what's the problem?
8242 **
8243 ** int x = 3, y = x ?
8244 */
8245
28bf4b0b 8246 exprData_free (ret->edata, ret->kind);
8247 ret->edata = exprData_makeInit (t, e);
8248
616915dd 8249 exprNode_checkUse (ret, e->sref, e->loc);
8250
8251 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8252 {
8253 exprNode lhs = exprNode_createId (ue);
8254
8255 /*
8256 ** static storage should be undefined before initializing
8257 */
8258
8259 if (uentry_isStatic (ue))
8260 {
8261 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8262 }
146e25eb 8263
616915dd 8264 (void) exprNode_checkOneInit (lhs, e);
8265
8266 if (uentry_isStatic (ue))
8267 {
8268 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8269 }
8270
8271 exprNode_free (lhs);
8272 }
8273 else
8274 {
8275 if (!exprNode_matchType (ct, e))
8276 {
8277 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
8278 {
8279 ;
8280 }
8281 else
8282 {
8283 (void) gentypeerror
8284 (exprNode_getType (e), e, exprNode_getType (ret), ret,
8285 message
28bf4b0b 8286 ("Variable %q initialized to type %t, expects %t: %s",
8287 uentry_getName (ue), exprNode_getType (e),
616915dd 8288 exprNode_getType (ret),
8289 exprNode_unparse (e)),
8290 e->loc);
8291 }
8292 }
8293 }
8294
8295 if (uentry_isStatic (ue))
8296 {
8297 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8298 }
8299
8300 doAssign (ret, e, TRUE);
8301
8302 if (uentry_isStatic (ue))
8303 {
8304 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8305 }
8306 }
8307
8308 if (context_inIterDef ())
8309 {
8310 /* should check if it is yield */
8311 uentry_setUsed (ue, loc);
8312 }
8313 else
8314 {
28bf4b0b 8315 ;
616915dd 8316 }
8317
616915dd 8318 exprNode_mergeUSs (ret, e);
8319 return ret;
8320}
8321
8322exprNode exprNode_iter (/*@observer@*/ uentry name,
8323 /*@only@*/ exprNodeList alist,
8324 /*@only@*/ exprNode body,
8325 /*@observer@*/ uentry end)
8326{
8327 exprNode ret;
8328 cstring iname;
8329
8330 llassert (uentry_isValid (name));
8331
8332 uentry_setUsed (name, exprNode_loc (body));
8333
8334 ret = exprNode_createPartialCopy (body);
8335 iname = uentry_getName (name);
8336
8337 if (uentry_isInvalid (end))
8338 {
8339 llerror (FLG_ITER,
8340 message ("Iter %s not balanced with end_%s", iname, iname));
8341 }
8342 else
8343 {
8344 cstring ename = uentry_getName (end);
8345
68de3f33 8346 if (!cstring_equalPrefixLit (ename, "end_"))
616915dd 8347 {
8348 llerror (FLG_ITER, message ("Iter %s not balanced with end_%s: %s",
8349 iname, iname, ename));
8350 }
8351 else
8352 {
8353 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8354 {
8355 llerror (FLG_ITER,
8356 message ("Iter %s not balanced with end_%s: %s",
8357 iname, iname, ename));
8358 }
8359 }
8360
8361 cstring_free (ename);
8362 }
8363
8364 context_exitIterClause (body);
8365
8366 ret->kind = XPR_ITER;
8367 ret->edata = exprData_makeIter (name, alist, body, end);
8368
8369 if (uentry_isIter (name))
8370 {
8371 (void) checkArgsReal (name, body,
8372 uentry_getParams (name), alist, TRUE, ret);
8373 }
8374
8375 cstring_free (iname);
8376
8377 return ret;
8378}
8379
8380exprNode
8381exprNode_iterNewId (/*@only@*/ cstring s)
8382{
8383 exprNode e = exprNode_new ();
8384 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8385
8386 llassert (processingIterVars ());
8387
8388 e->loc = context_getSaveLocation ();
8389
8390 if (fileloc_isUndefined (e->loc))
8391 {
8392 fileloc_free (e->loc);
8393 e->loc = fileloc_copy (g_currentloc);
8394 }
8395
8396 e->uses = sRefSet_new ();
8397 e->sets = sRefSet_new ();
8398 e->msets = sRefSet_new ();
8399 e->kind = XPR_VAR;
8400 e->val = multiVal_unknown ();
8401 e->guards = guardSet_new ();
8402 e->sref = defref;
8403 e->isJumpPoint = FALSE;
8404 e->exitCode = XK_NEVERESCAPE;
8405
8406 /*> missing fields, detected by lclint <*/
8407 e->canBreak = FALSE;
8408 e->mustBreak = FALSE;
8409 e->etext = cstring_undefined;
8410
8411 if (uentry_isYield (ue))
8412 {
8413 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8414 fileloc_copy (e->loc),
8415 FALSE);
8416 sRef sr;
8417
8418 uue = usymtab_supEntrySrefReturn (uue);
8419
8420 sr = uentry_getSref (uue);
8421 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8422 sr = uentry_getSref (uue);
8423 sRef_setDefined (sr, e->loc);
8424
8425 e->typ = uentry_getType (uue);
8426 e->sref = sr;
8427 e->edata = exprData_makeId (uue);
8428 uentry_setUsed (uue, g_currentloc);
8429 }
8430 else
8431 {
8432 uentry uue;
8433
8434 sRef_setGlobalScope ();
8435 uue = uentry_makeVariableLoc (s, ctype_unknown);
8436
8437 e->typ = ctype_unknown;
8438 e->edata = exprData_makeId (uue);
8439
8440 uentry_setUsed (uue, e->loc);
8441 uentry_setHasNameError (uue);
8442
8443 if (context_getFlag (FLG_REPEATUNRECOG))
8444 {
8445 uentry_markOwned (uue);
8446 }
8447 else
8448 {
8449 usymtab_supGlobalEntry (uue);
8450 }
8451
8452 sRef_clearGlobalScope ();
8453
8454 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8455 e->loc);
8456 }
8457
8458
8459 cstring_free (s);
84c9ffbf 8460
8461 exprNode_defineConstraints(e);
616915dd 8462 return (e);
8463}
8464
8465exprNode
8466exprNode_iterExpr (/*@returned@*/ exprNode e)
8467{
8468 if (!processingIterVars ())
8469 {
8470 llcontbuglit ("checkIterParam: not in iter");
8471 return e;
8472 }
8473
8474 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8475 iterParamNo ())))
8476 {
8477 if (exprNode_isDefined (e))
8478 {
8479 if (fileloc_isDefined (e->loc))
8480 {
8481 voptgenerror
8482 (FLG_ITER,
8483 message ("Yield parameter is not simple identifier: %s",
8484 exprNode_unparse (e)),
8485 e->loc);
8486 }
8487 else
8488 {
8489 voptgenerror
8490 (FLG_ITER,
8491 message ("Yield parameter is not simple identifier: %s",
8492 exprNode_unparse (e)),
8493 g_currentloc);
8494
8495 }
8496 }
8497 }
8498 return e;
8499}
8500
8501exprNode
8502exprNode_iterId (/*@observer@*/ uentry c)
8503{
8504 uentry ue;
8505
8506 llassert (processingIterVars ());
8507
8508 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8509 iterParamNo ());
8510
8511 if (uentry_isYield (ue))
8512 {
8513 ctype ct = uentry_getType (ue);
8514 exprNode e = exprNode_createPlain (ct);
8515 cstring name = uentry_getName (c);
8516 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8517
8518 uentry_setUsed (ue, g_currentloc);
8519 uentry_setHasNameError (ue);
8520
8521 cstring_free (name);
8522
8523 e->kind = XPR_VAR;
8524 e->edata = exprData_makeId (le);
8525 e->loc = context_getSaveLocation ();
8526 e->sref = uentry_getSref (le);
8527
8528 usymtab_supEntrySref (le);
8529
8530 if (!context_inHeader ())
8531 {
8532 if (optgenerror
8533 (FLG_ITER,
8534 message ("Yield parameter shadows local declaration: %q",
8535 uentry_getName (c)),
8536 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8537 {
8538 uentry_showWhereDeclared (c);
8539 }
8540 }
8541
8542 return e;
8543 }
8544
8545 return (exprNode_fromIdentifierAux (c));
8546}
8547
8548exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8549{
8550 exprNode ret = exprNode_create (ctype_unknown);
8551
8552 ret->kind = XPR_ITERCALL;
8553 ret->edata = exprData_makeIterCall (name, alist);
8554
8555 if (uentry_isIter (name))
8556 {
8557 uentryList params = uentry_getParams (name);
8558
8559 if (context_inIterDef ()
8560 && uentryList_size (params) == exprNodeList_size (alist))
8561 {
8562 int i = 0;
8563
8564 exprNodeList_elements (alist, arg)
8565 {
8566 uentry parg = uentryList_getN (params, i);
8567
8568 if (uentry_isYield (parg))
8569 {
8570 uentry ue = exprNode_getUentry (arg);
8571
8572 if (uentry_isValid (ue))
8573 {
8574 ;
8575 }
8576 }
8577
8578 i++;
8579 } end_exprNodeList_elements;
8580 }
8581
8582 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8583 checkUnspecCall (ret, params, alist);
8584 }
8585
8586 return ret;
8587}
8588
8589/*@exposed@*/ sRef exprNode_getSref (exprNode e)
8590{
8591 if (exprNode_isDefined (e))
8592 {
8593 /*@access sRef@*/
8594 if (e->sref == defref) /*@noaccess sRef@*/
8595 {
8596 /*@-mods@*/
8597 e->sref = sRef_makeUnknown ();
8598 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8599 /*@=mods@*/
8600 return e->sref;
8601 }
8602 else
8603 {
8604 return e->sref;
8605 }
8606 }
8607 else
8608 {
8609 return sRef_undefined;
8610 }
8611}
8612
8613/*@observer@*/ cstring
8614exprNode_unparseFirst (exprNode e)
8615{
8616 if (exprNode_isDefined (e))
8617 {
8618 cstring ret;
8619
8620 if (e->kind == XPR_STMTLIST
8621 || e->kind == XPR_COMMA || e->kind == XPR_COND)
8622 {
8623 exprNode first = exprData_getPairA (e->edata);
8624
8625 if (exprNode_isDefined (first))
8626 {
8627 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8628 }
8629 else
8630 {
8631 return (cstring_makeLiteralTemp ("..."));
8632 }
8633 }
8634
8635 ret = cstring_elide (exprNode_unparse (e), 20);
8636 cstring_markOwned (ret);
8637
8638 return (ret);
8639 }
8640 else
8641 {
8642 return cstring_makeLiteralTemp ("<error>");
8643 }
8644}
8645
8646/*@observer@*/ cstring
28bf4b0b 8647exprNode_unparse (/*@temp@*/ exprNode e)
616915dd 8648{
8649 if (exprNode_isError (e))
8650 {
8651 return cstring_makeLiteralTemp ("<error>");
8652 }
8653
8654 if (cstring_isDefined (e->etext))
8655 {
8656 return e->etext;
8657 }
8658 else
8659 {
8660 cstring ret = exprNode_doUnparse (e);
8661
8662 /*@-modifies@*/ /* benevolent */
8663 e->etext = ret;
8664 /*@=modifies@*/
8665 return ret;
8666 }
8667}
8668
8669/*@observer@*/ fileloc
8670exprNode_loc (exprNode e)
8671{
8672 if (exprNode_isError (e))
8673 {
8674 return (g_currentloc);
8675 }
8676 else
8677 {
8678 return (e->loc);
8679 }
8680}
8681
8682/*
8683** executes exprNode e
8684** recursively rexecutes as though in original parse using
8685** information in e->edata
8686*/
8687
8688static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
8689{
8690 exprNodeList ret = exprNodeList_new ();
8691
8692 exprNodeList_elements (e, current)
8693 {
8694 exprNodeList_addh (ret, exprNode_effect (current));
8695 } end_exprNodeList_elements;
8696
8697 return ret;
8698}
8699
8700static /*@only@*/ exprNode exprNode_effect (exprNode e)
8701 /*@globals internalState@*/
8702{
8703 bool innerEffect = inEffect;
8704 exprNode ret;
8705 exprData data;
8706
8707 inEffect = TRUE;
8708
8709 context_clearJustPopped ();
8710
8711 if (exprNode_isError (e))
8712 {
8713 ret = exprNode_undefined;
8714 }
8715 else
8716 {
8717 /*
8718 ** Turn off expose and dependent transfer checking.
8719 ** Need to pass exposed internal nodes,
8720 ** [ copying would be a waste! ]
8721 ** [ Actually, I think I wasted a lot more time than its worth ]
8722 ** [ trying to do this. ]
8723 */
8724
8725 /*@-exposetrans@*/
8726 /*@-observertrans@*/
8727 /*@-dependenttrans@*/
8728
8729 data = e->edata;
8730
8731 switch (e->kind)
8732 {
8733 case XPR_PARENS:
8734 ret = exprNode_addParens (exprData_getUopTok (data),
8735 exprNode_effect (exprData_getUopNode (data)));
8736 break;
8737 case XPR_ASSIGN:
8738 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
8739 exprNode_effect (exprData_getOpB (data)),
8740 exprData_getOpTok (data));
8741 break;
8742 case XPR_INITBLOCK:
8743 ret = exprNode_undefined;
8744 break;
8745 case XPR_CALL:
8746 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
8747 exprNodeList_effect (exprData_getArgs (data)));
8748 break;
8749 case XPR_EMPTY:
8750 ret = e;
8751 break;
8752
8753 case XPR_LABEL:
8754 ret = e;
8755 break;
8756
8757 case XPR_CONST:
8758 case XPR_VAR:
8759 {
8760 cstring id = exprData_getId (data);
8761 uentry ue = usymtab_lookupSafe (id);
8762
8763 ret = exprNode_fromIdentifierAux (ue);
8764 ret->loc = fileloc_update (ret->loc, e->loc);
8765 break;
8766 }
8767 case XPR_BODY:
8768 ret = e;
8769 break;
8770 case XPR_FETCH:
8771 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
8772 exprNode_effect (exprData_getPairB (data)));
8773 break;
8774 case XPR_OP:
8775 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
8776 exprNode_effect (exprData_getOpB (data)),
8777 exprData_getOpTok (data));
8778 break;
8779
8780 case XPR_POSTOP:
8781 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
8782 exprData_getUopTok (data));
8783 break;
8784 case XPR_PREOP:
8785 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
8786 exprData_getUopTok (data));
8787 break;
8788
8789 case XPR_OFFSETOF:
8790 case XPR_SIZEOFT:
8791 case XPR_SIZEOF:
8792 case XPR_ALIGNOFT:
8793 case XPR_ALIGNOF:
8794 ret = e;
8795 break;
8796
8797 case XPR_VAARG:
8798 ret = exprNode_vaArg (exprData_getCastTok (data),
8799 exprNode_effect (exprData_getCastNode (data)),
8800 exprData_getCastType (data));
8801 break;
8802
8803 case XPR_CAST:
8804 ret = exprNode_cast (exprData_getCastTok (data),
8805 exprNode_effect (exprData_getCastNode (data)),
8806 exprData_getCastType (data));
8807 break;
8808 case XPR_ITERCALL:
8809 ret = exprNode_iterStart (exprData_getIterCallIter (data),
8810 exprNodeList_effect
8811 (exprData_getIterCallArgs (data)));
8812 break;
8813
8814 case XPR_ITER:
8815 ret = exprNode_iter (exprData_getIterSname (data),
8816 exprNodeList_effect (exprData_getIterAlist (data)),
8817 exprNode_effect (exprData_getIterBody (data)),
8818 exprData_getIterEname (data));
8819 break;
8820
8821 case XPR_FOR:
8822 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
8823 exprNode_effect (exprData_getPairB (data)));
8824 break;
8825
8826 case XPR_FORPRED:
8827 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
8828 exprNode_effect (exprData_getTripleTest (data)),
8829 exprNode_effect (exprData_getTripleInc (data)));
8830 break;
8831
8832 case XPR_TOK:
8833 ret = exprNode_createTok (exprData_getTok (data));
8834 break;
8835
8836 case XPR_GOTO:
8837 ret = exprNode_goto (exprData_getLiteral (data));
8838 ret->loc = fileloc_update (ret->loc, e->loc);
8839 break;
8840
8841 case XPR_CONTINUE:
8842 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
8843 break;
8844
8845 case XPR_BREAK:
8846 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
8847 break;
8848
8849 case XPR_RETURN:
8850 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
8851 break;
8852
8853 case XPR_NULLRETURN:
8854 ret = exprNode_nullReturn (exprData_getTok (data));
8855 break;
8856
8857 case XPR_COMMA:
8858 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
8859 exprNode_effect (exprData_getPairB (data)));
8860 break;
8861
8862 case XPR_COND:
8863 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
8864 exprNode_effect (exprData_getTripleTrue (data)),
8865 exprNode_effect (exprData_getTripleFalse (data)));
8866 break;
8867 case XPR_IF:
8868 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
8869 exprNode_effect (exprData_getPairB (data)));
8870 break;
8871
8872 case XPR_IFELSE:
8873 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
8874 exprNode_effect (exprData_getTripleTrue (data)),
8875 exprNode_effect (exprData_getTripleFalse (data)));
8876 break;
8877 case XPR_WHILEPRED:
8878 ret = exprNode_whilePred (exprData_getSingle (data));
8879 break;
8880
8881 case XPR_WHILE:
8882 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
8883 exprNode_effect (exprData_getPairB (data)));
8884 break;
8885
8886 case XPR_DOWHILE:
8887 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
8888 exprNode_effect (exprData_getPairB (data)));
8889 break;
8890
8891 case XPR_BLOCK:
8892 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
8893 break;
8894
8895 case XPR_STMT:
8896 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
8897 exprData_getUopTok (data));
8898 break;
8899
8900 case XPR_STMTLIST:
8901 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
8902 exprNode_effect (exprData_getPairB (data)));
8903 break;
8904
8905 case XPR_FTCASE:
8906 case XPR_CASE:
8907 ret = exprNode_caseMarker
8908 (exprNode_effect (exprData_getSingle (data)),
8909 TRUE);
8910 break;
8911
8912 case XPR_FTDEFAULT:
8913 case XPR_DEFAULT:
8914 ret = exprNode_createTok (exprData_getTok (data));
8915 break;
8916
8917 case XPR_SWITCH:
8918 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
8919 exprNode_effect (exprData_getPairB (data)));
8920 break;
8921
8922 case XPR_INIT:
8923 ret = exprNode_makeInitialization
8924 (exprData_getInitId (data),
8925 exprNode_effect (exprData_getInitNode (data)));
8926 break;
8927
8928 case XPR_FACCESS:
28bf4b0b 8929 ret = exprNode_fieldAccessAux
8930 (exprNode_effect (exprData_getFieldNode (data)),
8931 exprNode_loc (exprData_getFieldNode (data)),
8932 cstring_copy (exprData_getFieldName (data)));
616915dd 8933 break;
8934
8935 case XPR_ARROW:
28bf4b0b 8936 ret = exprNode_arrowAccessAux
8937 (exprNode_effect (exprData_getFieldNode (data)),
8938 exprNode_loc (exprData_getFieldNode (data)),
8939 cstring_copy (exprData_getFieldName (data)));
616915dd 8940 break;
8941
8942 case XPR_STRINGLITERAL:
8943 ret = e;
8944 break;
8945
8946 case XPR_NUMLIT:
8947 ret = e;
8948 break;
8949
8950 case XPR_NODE:
8951 ret = e;
8952 break;
8953 /*@-branchstate@*/
8954 }
8955 /*@=branchstate@*/
8956 /*@=observertrans@*/
8957 /*@=exposetrans@*/
8958 /*@=dependenttrans@*/
8959 }
8960
8961 if (!innerEffect)
8962 {
8963 inEffect = FALSE;
8964 }
8965
8966 return ret;
8967}
8968
8969static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
8970{
8971 cstring ret;
8972 exprData data;
8973
8974 if (exprNode_isError (e))
8975 {
8976 return cstring_undefined;
8977 }
8978
8979 data = e->edata;
8980
8981 switch (e->kind)
8982 {
8983 case XPR_PARENS:
8984 ret = exprNode_rootVarName (exprData_getUopNode (data));
8985 break;
8986 case XPR_ASSIGN:
8987 ret = exprNode_rootVarName (exprData_getOpA (data));
8988 break;
8989 case XPR_CONST:
8990 case XPR_VAR:
8991 ret = exprData_getId (data);
8992 break;
e83c79ec 8993 case XPR_INIT:
8994 ret = idDecl_getName (exprData_getInitId (data));
8995 break;
616915dd 8996 case XPR_LABEL:
8997 case XPR_TOK:
8998 case XPR_ITERCALL:
8999 case XPR_EMPTY:
9000 case XPR_CALL:
9001 case XPR_INITBLOCK:
9002 case XPR_BODY:
9003 case XPR_FETCH:
9004 case XPR_OP:
9005 case XPR_POSTOP:
9006 case XPR_PREOP:
9007 case XPR_OFFSETOF:
9008 case XPR_ALIGNOFT:
9009 case XPR_ALIGNOF:
9010 case XPR_SIZEOFT:
9011 case XPR_SIZEOF:
9012 case XPR_VAARG:
9013 case XPR_CAST:
9014 case XPR_ITER:
9015 case XPR_FOR:
9016 case XPR_FORPRED:
9017 case XPR_BREAK:
9018 case XPR_RETURN:
9019 case XPR_NULLRETURN:
9020 case XPR_COMMA:
9021 case XPR_COND:
9022 case XPR_IF:
9023 case XPR_IFELSE:
9024 case XPR_WHILE:
9025 case XPR_WHILEPRED:
9026 case XPR_DOWHILE:
9027 case XPR_GOTO:
9028 case XPR_CONTINUE:
9029 case XPR_FTDEFAULT:
9030 case XPR_DEFAULT:
9031 case XPR_SWITCH:
9032 case XPR_FTCASE:
9033 case XPR_CASE:
9034 case XPR_BLOCK:
9035 case XPR_STMT:
9036 case XPR_STMTLIST:
616915dd 9037 case XPR_FACCESS:
9038 case XPR_ARROW:
9039 case XPR_NODE:
9040 case XPR_NUMLIT:
9041 case XPR_STRINGLITERAL:
9042 ret = cstring_undefined;
9043 break;
9044 }
9045
9046 return ret;
9047}
9048
616915dd 9049static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
9050{
9051 cstring ret;
9052 exprData data;
9053
9054 if (exprNode_isError (e))
9055 {
9056 static /*@only@*/ cstring error = cstring_undefined;
9057
9058 if (!cstring_isDefined (error))
9059 {
9060 error = cstring_makeLiteral ("<error>");
9061 }
9062
9063 return error;
9064 }
9065
9066 data = e->edata;
9067
9068 switch (e->kind)
9069 {
9070 case XPR_PARENS:
9071 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
9072 break;
9073 case XPR_ASSIGN:
9074 ret = message ("%s %s %s",
9075 exprNode_unparse (exprData_getOpA (data)),
9076 lltok_unparse (exprData_getOpTok (data)),
9077 exprNode_unparse (exprData_getOpB (data)));
9078 break;
9079 case XPR_CALL:
9080 ret = message ("%s(%q)",
9081 exprNode_unparse (exprData_getFcn (data)),
9082 exprNodeList_unparse (exprData_getArgs (data)));
9083 break;
9084 case XPR_INITBLOCK:
9085 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
9086 break;
9087 case XPR_EMPTY:
9088 ret = cstring_undefined;
9089 break;
9090 case XPR_LABEL:
9091 ret = message ("%s:", exprData_getId (data));
9092 break;
9093 case XPR_CONST:
9094 case XPR_VAR:
9095 ret = cstring_copy (exprData_getId (data));
9096 break;
9097 case XPR_FETCH:
9098 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
9099 exprNode_unparse (exprData_getPairB (data)));
9100 break;
9101 case XPR_BODY:
9102 ret = message ("<body>");
9103 break;
9104 case XPR_OP:
9105 ret = message ("%s %s %s",
9106 exprNode_unparse (exprData_getOpA (data)),
9107 lltok_unparse (exprData_getOpTok (data)),
9108 exprNode_unparse (exprData_getOpB (data)));
9109 break;
9110
9111 case XPR_PREOP:
9112 ret = message ("%s%s",
9113 lltok_unparse (exprData_getUopTok (data)),
9114 exprNode_unparse (exprData_getUopNode (data)));
9115 break;
9116
9117 case XPR_POSTOP:
9118 ret = message ("%s%s",
9119 exprNode_unparse (exprData_getUopNode (data)),
9120 lltok_unparse (exprData_getUopTok (data)));
9121 break;
9122
9123 case XPR_OFFSETOF:
9124 ret = message ("offsetof(%s,%q)",
9125 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
9126 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
9127 break;
9128
9129 case XPR_SIZEOFT:
9130 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9131 break;
9132
9133 case XPR_SIZEOF:
9134 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
9135 break;
9136
9137 case XPR_ALIGNOFT:
9138 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9139 break;
9140
9141 case XPR_ALIGNOF:
9142 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
9143 break;
9144
9145 case XPR_VAARG:
9146 ret = message ("va_arg(%s, %q)",
9147 exprNode_unparse (exprData_getCastNode (data)),
9148 qtype_unparse (exprData_getCastType (data)));
9149 break;
9150
9151 case XPR_ITERCALL:
9152 ret = message ("%q(%q)",
9153 uentry_getName (exprData_getIterCallIter (data)),
9154 exprNodeList_unparse (exprData_getIterCallArgs (data)));
9155 break;
9156 case XPR_ITER:
9157 ret = message ("%q(%q) %s %q",
9158 uentry_getName (exprData_getIterSname (data)),
9159 exprNodeList_unparse (exprData_getIterAlist (data)),
9160 exprNode_unparse (exprData_getIterBody (data)),
9161 uentry_getName (exprData_getIterEname (data)));
9162 break;
9163 case XPR_CAST:
9164 ret = message ("(%q)%s",
9165 qtype_unparse (exprData_getCastType (data)),
9166 exprNode_unparse (exprData_getCastNode (data)));
9167 break;
9168
9169 case XPR_FOR:
9170 ret = message ("%s %s",
9171 exprNode_unparse (exprData_getPairA (data)),
9172 exprNode_unparse (exprData_getPairB (data)));
9173 break;
9174
9175 case XPR_FORPRED:
9176 ret = message ("for (%s; %s; %s)",
9177 exprNode_unparse (exprData_getTripleInit (data)),
9178 exprNode_unparse (exprData_getTripleTest (data)),
9179 exprNode_unparse (exprData_getTripleInc (data)));
9180 break;
9181
9182 case XPR_GOTO:
9183 ret = message ("goto %s", exprData_getLiteral (data));
9184 break;
9185
9186 case XPR_CONTINUE:
9187 ret = cstring_makeLiteral ("continue");
9188 break;
9189
9190 case XPR_BREAK:
9191 ret = cstring_makeLiteral ("break");
9192 break;
9193
9194 case XPR_RETURN:
9195 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
9196 break;
9197
9198 case XPR_NULLRETURN:
9199 ret = cstring_makeLiteral ("return");
9200 break;
9201
9202 case XPR_COMMA:
9203 ret = message ("%s, %s",
9204 exprNode_unparse (exprData_getPairA (data)),
9205 exprNode_unparse (exprData_getPairB (data)));
9206 break;
9207
9208 case XPR_COND:
9209 ret = message ("%s ? %s : %s",
9210 exprNode_unparse (exprData_getTriplePred (data)),
9211 exprNode_unparse (exprData_getTripleTrue (data)),
9212 exprNode_unparse (exprData_getTripleFalse (data)));
9213 break;
9214 case XPR_IF:
9215 ret = message ("if (%s) %s",
9216 exprNode_unparse (exprData_getPairA (data)),
9217 exprNode_unparse (exprData_getPairB (data)));
9218 break;
9219
9220 case XPR_IFELSE:
9221 ret = message ("if (%s) %s else %s",
9222 exprNode_unparse (exprData_getTriplePred (data)),
9223 exprNode_unparse (exprData_getTripleTrue (data)),
9224 exprNode_unparse (exprData_getTripleFalse (data)));
9225 break;
9226 case XPR_WHILE:
9227 ret = message ("while (%s) %s",
9228 exprNode_unparse (exprData_getPairA (data)),
9229 exprNode_unparse (exprData_getPairB (data)));
9230 break;
9231
9232 case XPR_WHILEPRED:
9233 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9234 break;
9235
9236 case XPR_TOK:
9237 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9238 break;
9239
9240 case XPR_DOWHILE:
9241 ret = message ("do { %s } while (%s)",
9242 exprNode_unparse (exprData_getPairB (data)),
9243 exprNode_unparse (exprData_getPairA (data)));
9244 break;
9245
9246 case XPR_BLOCK:
9247 ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
9248 break;
9249
9250 case XPR_STMT:
9251 ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
9252 break;
9253
9254 case XPR_STMTLIST:
9255 ret = message ("%s; %s",
9256 exprNode_unparse (exprData_getPairA (data)),
9257 exprNode_unparse (exprData_getPairB (data)));
9258 break;
9259
9260 case XPR_FTDEFAULT:
9261 case XPR_DEFAULT:
9262 ret = cstring_makeLiteral ("default:");
9263 break;
9264
9265 case XPR_SWITCH:
9266 ret = message ("switch (%s) %s",
9267 exprNode_unparse (exprData_getPairA (data)),
9268 exprNode_unparse (exprData_getPairB (data)));
9269 break;
9270
9271 case XPR_FTCASE:
9272 case XPR_CASE:
9273 ret = message ("case %s:",
9274 exprNode_unparse (exprData_getSingle (data)));
9275 break;
9276
9277 case XPR_INIT:
28bf4b0b 9278 if (exprNode_isError (exprData_getInitNode (data)))
9279 {
9280 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9281 }
9282 else
9283 {
9284 ret = message ("%q = %s",
9285 idDecl_unparseC (exprData_getInitId (data)),
9286 exprNode_unparse (exprData_getInitNode (data)));
9287 }
616915dd 9288 break;
9289
9290 case XPR_FACCESS:
9291 ret = message ("%s.%s",
9292 exprNode_unparse (exprData_getFieldNode (data)),
9293 exprData_getFieldName (data));
9294 break;
9295
9296 case XPR_ARROW:
9297 ret = message ("%s->%s",
9298 exprNode_unparse (exprData_getFieldNode (data)),
9299 exprData_getFieldName (data));
9300 break;
9301
9302 case XPR_STRINGLITERAL:
28bf4b0b 9303 ret = message ("\"%s\"", exprData_getLiteral (data));
616915dd 9304 break;
9305
9306 case XPR_NUMLIT:
9307 ret = cstring_copy (exprData_getLiteral (data));
9308 break;
9309
9310 case XPR_NODE:
9311 ret = cstring_makeLiteral ("<node>");
9312 break;
9313 }
9314
9315 return ret;
9316}
9317
28bf4b0b 9318bool
9319exprNode_isInitializer (exprNode e)
9320{
9321 return (exprNode_isDefined (e)
9322 && e->kind == XPR_INIT);
9323}
9324
616915dd 9325bool
9326exprNode_isCharLit (exprNode e)
9327{
9328 if (exprNode_isDefined (e))
9329 {
9330 return (multiVal_isChar (exprNode_getValue (e)));
9331 }
9332 else
9333 {
9334 return FALSE;
9335 }
9336}
9337
9338bool
9339exprNode_isNumLit (exprNode e)
9340{
9341 if (exprNode_isDefined (e))
9342 {
9343 return (multiVal_isInt (exprNode_getValue (e)));
9344 }
9345 else
9346 {
9347 return FALSE;
9348 }
9349}
9350
9351static bool
9352exprNode_isFalseConstant (exprNode e)
9353{
9354 if (exprNode_isDefined (e))
9355 {
9356 cstring s = exprNode_rootVarName (e);
9357
9358 if (cstring_equal (s, context_getFalseName ()))
9359 {
9360 return TRUE;
9361 }
9362 }
9363
9364 return FALSE;
9365}
9366
9367bool
9368exprNode_matchLiteral (ctype expected, exprNode e)
9369{
9370 if (exprNode_isDefined (e))
9371 {
9372 multiVal m = exprNode_getValue (e);
9373
9374 if (multiVal_isDefined (m))
9375 {
9376 if (multiVal_isInt (m))
9377 {
9378 long int val = multiVal_forceInt (m);
9379
9380 if (ctype_isDirectBool (ctype_realishType (expected)))
9381 {
9382 if (val == 0)
9383 {
9384 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9385 }
9386 else
9387 {
9388 return FALSE;
9389 }
9390 }
9391
9392 if (ctype_isRealInt (expected))
9393 {
9394 /*
9395 ** unsigned <- [ constant >= 0 is okay ]
9396 */
9397
9398 if (ctype_isUnsigned (expected))
9399 {
9400 if (val < 0)
9401 {
9402 return FALSE;
9403 }
9404 }
9405
9406 /*
9407 ** No checks on sizes of integers...maybe add
9408 ** these later.
9409 */
9410
9411 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9412 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9413 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9414
9415 if (context_getFlag (FLG_NUMLITERAL)
9416 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9417 return TRUE;
9418 } else {
9419 if (val == 0) {
9420 return TRUE;
9421 } else {
9422 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9423 }
9424 }
9425 }
9426 else if (ctype_isChar (expected))
9427 {
9428 return FALSE;
9429 }
9430 else if (ctype_isArrayPtr (expected))
9431 {
8fe44445 9432 /*
9433 ** evans 2001-10-14: We allow 0 to match any pointer, but only if the type matches or is void *.
9434 */
9435
9436 if (val == 0)
9437 {
9438 if (ctype_match (exprNode_getType (e), expected)
9439 || ctype_isVoidPointer (exprNode_getType (e)))
9440 {
9441 return TRUE;
9442 }
9443 }
9444 else
9445 {
9446 return FALSE;
9447 }
616915dd 9448 }
9449 else if (ctype_isAnyFloat (expected))
9450 {
9451 return (context_getFlag (FLG_NUMLITERAL));
9452 }
9453 else
9454 {
9455 return FALSE;
9456 }
9457 }
9458 else if (multiVal_isDouble (m))
9459 {
9460 if (ctype_isAnyFloat (expected))
9461 {
9462 return TRUE;
9463 }
9464 }
9465 else if (multiVal_isChar (m))
9466 {
9467 char val = multiVal_forceChar (m);
9468
9469 if (ctype_isChar (expected))
9470 {
9471 if (ctype_isUnsigned (expected) && ((int)val) < 0)
9472 {
9473 return FALSE;
9474 }
9475 else
9476 {
9477 return TRUE;
9478 }
9479 }
9480 }
9481 else
9482 {
9483 return FALSE;
9484 }
9485 }
9486 }
9487
9488 return FALSE;
9489}
9490
9491bool
9492exprNode_matchType (ctype expected, exprNode e)
9493{
9494 ctype actual;
9495
9496 if (!exprNode_isDefined (e)) return TRUE;
9497
9498 actual = ctype_realishType (exprNode_getType (e));
9499
9500 if (ctype_match (ctype_realishType (expected), actual))
9501 {
9502 return TRUE;
9503 }
9504
9505 llassert (!exprNode_isError (e));
9506 return (exprNode_matchLiteral (expected, e));
9507}
9508
9509static bool
9510exprNode_matchTypes (exprNode e1, exprNode e2)
9511{
9512 ctype t1;
9513 ctype t2;
9514
9515 if (!exprNode_isDefined (e1)) return TRUE;
9516 if (!exprNode_isDefined (e2)) return TRUE;
9517
9518 /*
9519 ** realish type --- keep bools, bools
9520 */
9521
9522 t1 = ctype_realishType (exprNode_getType (e1));
9523 t2 = ctype_realishType (exprNode_getType (e2));
9524
9525 if (ctype_match (t1, t2))
9526 {
9527 return TRUE;
9528 }
9529
8fe44445 9530 DPRINTF (("Matching literal! %s %s %s %s",
9531 ctype_unparse (t1), exprNode_unparse (e2),
9532 ctype_unparse (t2), exprNode_unparse (e1)));
9533
616915dd 9534 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9535}
9536
9537/*
9538** pass e as ct
9539*/
9540
9541static bool
9542 exprNode_matchArgType (ctype ct, exprNode e)
9543{
9544 ctype et;
9545
9546 if (!exprNode_isDefined (e))
9547 {
9548 return TRUE;
9549 }
9550
9551 et = ctype_realType (exprNode_getType (e));
9552
9553 if (ctype_matchArg (ct, et)) return TRUE;
9554
9555 llassert (!exprNode_isError (e));
9556 return (exprNode_matchLiteral (ct, e));
9557}
9558
9559static /*@only@*/ exprNodeSList
9560 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9561{
9562 if (exprNode_isDefined (e))
9563 {
9564 if (e->kind == XPR_STMTLIST)
9565 {
9566 return (exprNodeSList_append
9567 (exprNode_flatten (exprData_getPairA (e->edata)),
9568 exprNode_flatten (exprData_getPairB (e->edata))));
9569 }
9570 else if (e->kind == XPR_BLOCK)
9571 {
9572 return (exprNode_flatten (exprData_getSingle (e->edata)));
9573 }
9574 else
9575 {
9576 return (exprNodeSList_singleton (e));
9577 }
9578 }
9579
9580 return exprNodeSList_new ();
9581}
9582
9583static /*@exposed@*/ exprNode
9584exprNode_lastStatement (/*@returned@*/ exprNode e)
9585{
9586 if (exprNode_isDefined (e))
9587 {
9588 if (e->kind == XPR_STMTLIST)
9589 {
9590 exprNode b = exprData_getPairB (e->edata);
9591
9592 if (exprNode_isDefined (b))
9593 {
9594 return exprNode_lastStatement (b);
9595 }
9596 else
9597 {
9598 return exprNode_lastStatement (exprData_getPairA (e->edata));
9599 }
9600 }
9601 else if (e->kind == XPR_BLOCK)
9602 {
9603 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
9604 }
9605 else
9606 {
9607 return (e);
9608 }
9609 }
9610
9611 return exprNode_undefined;
9612}
9613
9614static /*@exposed@*/ exprNode
9615exprNode_firstStatement (/*@returned@*/ exprNode e)
9616{
9617 if (exprNode_isDefined (e))
9618 {
9619 if (e->kind == XPR_STMTLIST)
9620 {
9621 exprNode b = exprData_getPairA (e->edata);
9622
9623 if (exprNode_isDefined (b))
9624 {
9625 return exprNode_firstStatement (b);
9626 }
9627 else
9628 {
9629 return exprNode_firstStatement (exprData_getPairB (e->edata));
9630 }
9631 }
9632 else if (e->kind == XPR_BLOCK)
9633 {
9634 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
9635 }
9636 else
9637 {
9638 return (e);
9639 }
9640 }
9641
9642 return exprNode_undefined;
9643}
9644
9645static void
9646exprNode_mergeUSs (exprNode res, exprNode other)
9647{
9648 if (exprNode_isDefined (res) && exprNode_isDefined (other))
9649 {
9650 res->msets = sRefSet_union (res->msets, other->msets);
9651 res->sets = sRefSet_union (res->sets, other->sets);
9652 res->uses = sRefSet_union (res->uses, other->uses);
9653 }
9654}
9655
9656static void
9657exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
9658{
9659 if (exprNode_isDefined (res))
9660 {
9661 if (exprNode_isDefined (other1))
9662 {
9663 res->sets = sRefSet_union (res->sets, other1->sets);
9664 res->msets = sRefSet_union (res->msets, other1->msets);
9665 res->uses = sRefSet_union (res->uses, other1->uses);
9666 }
9667 if (exprNode_isDefined (other2))
9668 {
9669 res->sets = sRefSet_union (res->sets, other2->sets);
9670 res->msets = sRefSet_union (res->msets, other2->msets);
9671 res->uses = sRefSet_union (res->uses, other2->uses);
9672 }
9673 }
9674}
9675
9676/*
9677** modifies e->uses
9678**
9679** Reports errors is s is not defined.
9680*/
9681
9682static void
28bf4b0b 9683exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
616915dd 9684{
9685 if (exprNode_isDefined (e))
9686 {
9687 e->uses = sRefSet_insert (e->uses, s);
9688 }
9689}
9690
9691void
28bf4b0b 9692exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
616915dd 9693{
9694 if (sRef_isKnown (s) && !sRef_isConst (s))
9695 {
9696 /*
9697 ** need to check all outer types are useable
9698 */
9699
9700 DPRINTF (("Check use: %s / %s",
9701 exprNode_unparse (e), sRef_unparse (s)));
28bf4b0b 9702
616915dd 9703 exprNode_addUse (e, s);
9704
9705 if (!context_inProtectVars ())
9706 {
9707 /*
9708 ** only report the deepest error
9709 */
9710
9711 sRef errorRef = sRef_undefined;
9712 sRef lastRef = sRef_undefined;
9713 bool deadRef = FALSE;
9714 bool unuseable = FALSE;
9715 bool errorMaybe = FALSE;
9716
9717 while (sRef_isValid (s) && sRef_isKnown (s))
9718 {
9719 ynm readable = sRef_isReadable (s);
9720
28bf4b0b 9721 DPRINTF (("Readable: %s / %s",
9722 sRef_unparseFull (s), ynm_unparse (readable)));
9723
616915dd 9724 if (!(ynm_toBoolStrict (readable)))
9725 {
9726 if (ynm_isMaybe (readable))
9727 {
9728 lastRef = errorRef;
9729 errorRef = s;
cd7d9b17 9730 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
616915dd 9731 deadRef = sRef_isPossiblyDead (errorRef);
9732 unuseable = sRef_isUnuseable (errorRef);
9733 errorMaybe = TRUE;
9734 }
9735 else
9736 {
9737 lastRef = errorRef;
9738 errorRef = s;
9739 deadRef = sRef_isDead (errorRef);
9740 unuseable = sRef_isUnuseable (errorRef);
9741 errorMaybe = FALSE;
9742 }
9743
9744 if (!sRef_isPartial (s))
9745 {
cd7d9b17 9746 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
616915dd 9747 sRef_setDefined (s, fileloc_undefined);
9748 }
9749 }
9750
9751 s = sRef_getBaseSafe (s);
9752 } /* end while */
9753
9754 if (sRef_isValid (errorRef))
9755 {
9756 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
9757 && sRef_isPointer (errorRef))
9758 {
9759 errorRef = lastRef;
9760 }
9761
9762 if (deadRef)
9763 {
9764 if (sRef_isThroughArrayFetch (errorRef))
9765 {
9766 if (optgenerror
9767 (FLG_STRICTUSERELEASED,
9768 message ("%q %q may be used after being released",
9769 sRef_unparseKindNamePlain (errorRef),
9770 sRef_unparse (errorRef)),
9771 loc))
9772 {
9773 sRef_showRefKilled (errorRef);
9774
9775 if (sRef_isKept (errorRef))
9776 {
9777 sRef_clearAliasState (errorRef, loc);
9778 }
9779 }
9780 }
9781 else
9782 {
9783 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
9784
9785 if (optgenerror
9786 (FLG_USERELEASED,
9787 message ("%q %q %qused after being released",
9788 sRef_unparseKindNamePlain (errorRef),
9789 sRef_unparse (errorRef),
9790 cstring_makeLiteral (errorMaybe
9791 ? "may be " : "")),
9792 loc))
9793 {
9794 sRef_showRefKilled (errorRef);
9795
9796 if (sRef_isKept (errorRef))
9797 {
9798 sRef_clearAliasState (errorRef, loc);
9799 }
9800 }
9801 }
9802 }
9803 else if (unuseable)
9804 {
9805 if (optgenerror
9806 (FLG_USEDEF,
9807 message ("%q %q%qused in inconsistent state",
9808 sRef_unparseKindName (errorRef),
9809 sRef_unparseOpt (errorRef),
9810 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9811 loc))
9812 {
9813 sRef_showStateInconsistent (errorRef);
9814 }
9815 }
9816 else
9817 {
28bf4b0b 9818 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
616915dd 9819
9820 voptgenerror
9821 (FLG_USEDEF,
9822 message ("%q %q%qused before definition",
9823 sRef_unparseKindName (errorRef),
9824 sRef_unparseOpt (errorRef),
9825 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9826 loc);
cd7d9b17 9827
9828 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
616915dd 9829 }
9830
9831 sRef_setDefined (errorRef, loc);
9832
9833 if (sRef_isAddress (errorRef))
9834 {
9835 sRef_setDefined (sRef_getRootBase (errorRef), loc);
9836 }
9837 } /* end is error */
9838 }
9839 }
9840
9841 setCodePoint ();
9842}
9843
9844static void
28bf4b0b 9845checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
616915dd 9846{
9847 if (exprNode_isDefined (e) && sRef_isKnown (s))
9848 {
9849 e->uses = sRefSet_insert (e->uses, s);
9850 }
9851}
9852
9853static void
9854exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
9855{
9856 if (exprNode_isDefined (e))
9857 {
9858 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
9859 }
9860}
9861
9862void
28bf4b0b 9863exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
616915dd 9864{
9865 sRef defines = sRef_undefined;
9866
9867 if (sRef_isValid (s) && !sRef_isNothing (s))
9868 {
9869 uentry ue = sRef_getBaseUentry (s);
9870
9871 if (uentry_isValid (ue))
9872 {
9873 uentry_setLset (ue);
9874 }
9875
9876 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9877 {
9878 voptgenerror (FLG_USEDEF,
9879 message ("Attempt to set unuseable storage: %q",
9880 sRef_unparse (s)),
9881 exprNode_loc (e));
9882 }
9883
9884 if (sRef_isMeaningful (s))
1d239d69 9885 {
616915dd 9886 if (sRef_isDead (s))
9887 {
9888 sRef base = sRef_getBaseSafe (s);
9889
9890 if (sRef_isValid (base)
9891 && sRef_isDead (base))
9892 {
9893 sRef_setPartial (s, exprNode_loc (e));
9894 }
9895
9896 defines = s; /* okay - modifies for only param */
9897 }
9898 else if (sRef_isPartial (s))
9899 {
9900 sRef eref = exprNode_getSref (e);
9901
9902 if (!sRef_isPartial (eref))
9903 {
9904 /*
9905 ** should do something different here???
9906 */
9907
9908 sRef_setDefinedComplete (eref, exprNode_loc (e));
9909 }
9910 else
9911 {
9912 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
9913 }
9914
9915 if (sRef_isMeaningful (eref))
9916 {
9917 defines = eref;
9918 }
9919 else
9920 {
9921 defines = s;
9922 }
9923 }
9924 else if (sRef_isAllocated (s))
9925 {
9926 sRef eref = exprNode_getSref (e);
9927
9928
9929 if (!sRef_isAllocated (eref))
9930 {
9931 sRef_setDefinedComplete (eref, exprNode_loc (e));
9932 }
9933 else
9934 {
9935 sRef base = sRef_getBaseSafe (eref);
9936
9937 if (sRef_isValid (base))
9938 {
9939 sRef_setPdefined (base, exprNode_loc (e));
9940 }
9941 }
9942
9943 defines = s;
9944 }
9945 else
9946 {
9947 sRef_setDefinedNCComplete (s, exprNode_loc (e));
9948 defines = s;
9949 }
9950
9951 }
9952 else /* not meaningful...but still need to insert it */
9953 {
9954 defines = s;
9955 }
9956 }
9957
9958 if (exprNode_isDefined (e) && sRef_isValid (defines))
9959 {
9960 e->sets = sRefSet_insert (e->sets, defines);
9961 }
9962}
9963
9964void
28bf4b0b 9965exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
616915dd 9966{
9967 if (sRef_isValid (s) && !sRef_isNothing (s))
9968 {
9969 uentry ue = sRef_getBaseUentry (s);
9970
9971 if (uentry_isValid (ue))
9972 {
9973 uentry_setLset (ue);
9974 }
9975
9976 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9977 {
9978 voptgenerror (FLG_USEDEF,
9979 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
9980 exprNode_loc (e));
9981 }
9982
9983 if (sRef_isMeaningful (s))
9984 {
9985 sRef_setDefinedComplete (s, exprNode_loc (e));
9986 }
9987
9988 if (exprNode_isDefined (e))
9989 {
9990 e->msets = sRefSet_insert (e->msets, s);
9991 }
9992 }
9993}
9994
9995static void
9996checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
9997{
9998 checkAnyCall (fcn, cstring_undefined, params, args,
9999 FALSE, sRefSet_undefined, FALSE, 0);
10000}
10001
10002static void
10003checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
10004 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
10005{
10006 setCodePoint ();
10007
10008 if (uentry_isYield (ucurrent))
10009 {
10010 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
10011 exprNode_checkSet (current, current->sref);
10012 }
10013 else
10014 {
10015 if (uentry_isSefParam (ucurrent))
10016 {
10017 sRefSet sets = current->sets;
10018 sRef ref = exprNode_getSref (current);
10019
10020 if (sRef_isMacroParamRef (ref))
10021 {
10022 uentry ue = sRef_getUentry (ref);
10023
10024 if (!uentry_isSefParam (ue))
10025 {
10026 voptgenerror
10027 (FLG_SEFPARAMS,
10028 message
10029 ("Parameter %d to %s is declared sef, but "
10030 "the argument is a macro parameter declared "
10031 "without sef: %s",
10032 argno, exprNode_unparse (fcn),
10033 exprNode_unparse (current)),
10034 exprNode_loc (current));
10035 }
10036 }
10037
10038 if (!sRefSet_isEmpty (sets))
10039 {
10040 sRefSet reported = sRefSet_undefined;
10041
10042 sRefSet_realElements (current->sets, el)
10043 {
10044 if (sRefSet_isSameNameMember (reported, el))
10045 {
10046 ; /* don't report again */
10047 }
10048 else
10049 {
10050 if (sRef_isUnconstrained (el))
10051 {
10052 voptgenerror
10053 (FLG_SEFUNSPEC,
10054 message
10055 ("Parameter %d to %s is declared sef, but "
10056 "the argument calls unconstrained function %s "
10057 "(no guarantee it will not modify something): %s",
10058 argno, exprNode_unparse (fcn),
10059 sRef_unconstrainedName (el),
10060 exprNode_unparse (current)),
10061 exprNode_loc (current));
10062 }
10063 else
10064 {
10065 voptgenerror
10066 (FLG_SEFPARAMS,
10067 message
10068 ("Parameter %d to %s is declared sef, but "
10069 "the argument may modify %q: %s",
10070 argno, exprNode_unparse (fcn),
10071 sRef_unparse (el),
10072 exprNode_unparse (current)),
10073 exprNode_loc (current));
10074 }
10075 }
10076 } end_sRefSet_realElements;
10077 }
10078 }
10079
10080 checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs);
10081 exprNode_mergeUSs (fcn, current);
10082 }
10083}
10084
10085static void
10086 checkAnyCall (/*@dependent@*/ exprNode fcn,
10087 /*@dependent@*/ cstring fname,
10088 uentryList pn,
10089 exprNodeList args,
10090 bool hasMods, sRefSet mods,
10091 bool isSpec,
10092 int specialArgs)
10093{
10094 int paramno = 0;
10095 int nargs = exprNodeList_size (args);
10096
10097 setCodePoint ();
10098
10099 /*
10100 ** concat all args ud's to f, add each arg sref as a use unless
10101 ** it was specified as "out", in which case it is a def.
10102 */
10103
10104 uentryList_reset (pn);
10105
10106 /*
10107 ** aliasing checks:
10108 **
10109 ** if paramn is only or unique, no other arg may alias argn
10110 */
10111
10112 exprNodeList_elements (args, current)
10113 {
10114 paramno++;
10115
10116 if (exprNode_isDefined (current))
10117 {
10118 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
10119 {
10120 uentry ucurrent = uentryList_current (pn);
10121
10122 if (specialArgs == 0
10123 || (paramno < specialArgs))
10124 {
28bf4b0b 10125 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
616915dd 10126
10127 if (context_maybeSet (FLG_ALIASUNIQUE))
10128 {
10129 if (uentry_isOnly (ucurrent)
10130 || uentry_isUnique (ucurrent))
10131 {
10132 checkUniqueParams (fcn, current, args,
10133 paramno, ucurrent);
10134 }
10135 }
10136 }
10137 }
10138 else /* uentry is undefined */
10139 {
10140 if (specialArgs == 0)
10141 {
10142 exprNode_checkUseParam (current);
10143 }
10144
10145 exprNode_mergeUSs (fcn, current);
10146 }
10147 }
10148 uentryList_advanceSafe (pn);
10149 } end_exprNodeList_elements;
10150
10151 if (hasMods)
10152 {
10153 setCodePoint ();
10154
10155 sRefSet_allElements (mods, s)
10156 {
10157 sRef fb;
10158 sRef rb = sRef_getRootBase (s);
10159
28bf4b0b 10160 if (sRef_isFileOrGlobalScope (rb))
616915dd 10161 {
10162 context_usedGlobal (rb);
10163 }
10164
10165 fb = sRef_fixBaseParam (s, args);
10166
10167 if (!sRef_isMacroParamRef (fb))
10168 {
10169 if (sRef_isNothing (fb))
10170 {
10171 ;
10172 }
10173 else
10174 {
10175 if (sRef_isValid (fb))
10176 {
10177 uentry ue = sRef_getBaseUentry (s);
10178
10179 if (uentry_isValid (ue))
10180 {
10181 uentry_setLset (ue);
10182 }
10183 }
10184
10185 fcn->sets = sRefSet_insert (fcn->sets, fb);
10186 }
10187 }
10188 sRef_clearDerivedComplete (s);
10189 } end_sRefSet_allElements;
10190
10191 setCodePoint ();
10192 }
10193 else
10194 {
10195 if (context_hasMods ())
10196 {
10197 if (context_maybeSet (FLG_MODUNCON))
10198 {
10199 voptgenerror
10200 (FLG_MODUNCON,
10201 message ("Undetected modification possible "
10202 "from call to unconstrained function %s: %s",
10203 fname,
10204 exprNode_unparse (fcn)),
10205 exprNode_loc (fcn));
10206 }
10207 }
10208 else
10209 {
10210 if (context_maybeSet (FLG_MODUNCONNOMODS)
10211 && !(context_inIterDef () || context_inIterEnd ()))
10212 {
10213 voptgenerror
10214 (FLG_MODUNCONNOMODS,
10215 message ("Undetected modification possible "
10216 "from call to unconstrained function %s: %s",
10217 fname,
10218 exprNode_unparse (fcn)),
10219 exprNode_loc (fcn));
10220 }
10221 }
10222
10223 exprNode_checkSetAny (fcn, fname);
10224 }
10225}
10226
10227void exprNode_checkUseParam (exprNode current)
10228{
10229 if (exprNode_isDefined (current))
10230 {
10231 exprNode_checkUse (current, current->sref, current->loc);
10232 }
10233}
10234
10235static ctype
10236 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10237 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10238 lltok op)
10239{
10240 ctype ret = tr1;
10241
10242 if (!ctype_match (tr1, tr2))
10243 {
10244 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10245 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10246 {
8fe44445 10247 DPRINTF (("No error: [%s] %s / [%s] %s",
10248 exprNode_unparse (e1), ctype_unparse (tr1),
10249 exprNode_unparse (e2), ctype_unparse (tr2)));
616915dd 10250 }
10251 else
10252 {
10253 (void) gentypeerror
10254 (tr1, e1, tr2, e2,
10255 message ("Incompatible types for %s (%s, %s): %s %s %s",
10256 lltok_unparse (op),
10257 ctype_unparse (te1),
10258 ctype_unparse (te2),
10259 exprNode_unparse (e1), lltok_unparse (op),
10260 exprNode_unparse (e2)),
10261 e1->loc);
10262 }
10263 ret = ctype_unknown;
10264 }
10265 else
10266 {
10267 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
10268 {
10269 ret = ctype_resolveNumerics (tr1, tr2);
10270 }
10271 else if (!context_msgStrictOps ())
10272 {
10273 if (ctype_isPointer (tr1))
10274 {
10275 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10276 {
10277 ret = ctype_int;
10278 }
10279 else if (ctype_isInt (tr2))
10280 {
10281 ret = te1;
10282 }
10283 else
10284 {
10285 ret = ctype_unknown;
10286 }
10287 }
10288 else if (ctype_isPointer (tr2))
10289 {
10290 if (ctype_isPointer (tr1))
10291 {
10292 ret = ctype_int;
10293 }
10294 else if (ctype_isInt (tr1))
10295 {
10296 ret = te2;
10297 }
10298 else
10299 {
10300 ret = ctype_unknown;
10301 }
10302 }
10303 else
10304 {
10305 ret = ctype_resolveNumerics (tr1, tr2);
10306 }
10307 }
10308 else
10309 {
10310 int opid = lltok_getTok (op);
10311 bool comparop = (opid == EQ_OP || opid == NE_OP
10312 || opid == TLT || opid == TGT
10313 || opid == LE_OP || opid == GE_OP);
10314
10315 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10316 {
10317 if (comparop
10318 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10319 || (ctype_isBool (tr1) && ctype_isBool (tr2))
10320 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10321 {
10322 ; /* no error */
10323 }
10324 else
10325 {
10326 if (ctype_sameName (te1, te2))
10327 {
10328 voptgenerror
10329 (FLG_STRICTOPS,
10330 message ("Operands of %s are non-numeric (%t): %s %s %s",
10331 lltok_unparse (op), te1,
10332 exprNode_unparse (e1), lltok_unparse (op),
10333 exprNode_unparse (e2)),
10334 e1->loc);
10335 }
10336 else
10337 {
10338 voptgenerror
10339 (FLG_STRICTOPS,
10340 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10341 lltok_unparse (op), te1, te2,
10342 exprNode_unparse (e1), lltok_unparse (op),
10343 exprNode_unparse (e2)),
10344 e1->loc);
10345 }
10346 }
10347 }
10348 else if (!ctype_isNumeric (tr1))
10349 {
10350 voptgenerror
10351 (FLG_STRICTOPS,
10352 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10353 lltok_unparse (op), te1,
10354 exprNode_unparse (e1), lltok_unparse (op),
10355 exprNode_unparse (e2)),
10356 e1->loc);
10357 }
10358 else
10359 {
10360 if (!ctype_isNumeric (tr2))
10361 {
10362 voptgenerror
10363 (FLG_STRICTOPS,
10364 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10365 lltok_unparse (op), te2,
10366 exprNode_unparse (e1), lltok_unparse (op),
10367 exprNode_unparse (e2)),
10368 e2->loc);
10369 }
10370 }
10371
10372 ret = ctype_unknown;
10373 }
10374 }
10375
10376 return ret;
10377}
10378
10379static void
10380abstractOpError (ctype tr1, ctype tr2, lltok op,
10381 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10382 fileloc loc1, fileloc loc2)
10383{
10384 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10385 {
10386 if (ctype_match (tr1, tr2))
10387 {
10388 voptgenerror
10389 (FLG_ABSTRACT,
10390 message ("Operands of %s are abstract type (%t): %s %s %s",
10391 lltok_unparse (op), tr1,
10392 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10393 loc1);
10394 }
10395 else
10396 {
10397 voptgenerror
10398 (FLG_ABSTRACT,
10399 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10400 lltok_unparse (op), tr1, tr2,
10401 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10402 loc1);
10403 }
10404 }
10405 else if (ctype_isRealAbstract (tr1))
10406 {
10407 voptgenerror
10408 (FLG_ABSTRACT,
10409 message ("Left operand of %s is abstract type (%t): %s %s %s",
10410 lltok_unparse (op), tr1,
10411 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10412 loc1);
10413 }
10414 else
10415 {
10416 if (ctype_isRealAbstract (tr2))
10417 {
10418 voptgenerror
10419 (FLG_ABSTRACT,
10420 message ("Right operand of %s is abstract type (%t): %s %s %s",
10421 lltok_unparse (op), tr2,
10422 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10423 loc2);
10424 }
10425 }
10426}
10427
10428/*
10429** e1 <= e2
10430**
10431** requies e1 and e2 and not error exprNode's.
10432**
10433** Checks:
10434**
10435** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10436** the rep of the abstract type is exposed.
10437**
10438** The order is very important:
10439**
10440** check rep expose (move into check transfer)
10441** check transfer
10442** setup aliases
10443*/
10444
10445/*
10446** This isn't really a sensible procedure, but the indententation
10447** was getting too deep.
10448*/
10449
10450static void
10451checkOneRepExpose (sRef ysr, sRef base,
10452 /*@notnull@*/ exprNode e1,
10453 /*@notnull@*/ exprNode e2, ctype ct,
10454 sRef s2b)
10455{
10456 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
08eb3d0e 10457 || sRef_isOwned (ysr)
10458 || sRef_isExposed (ysr)))
616915dd 10459 {
08eb3d0e 10460 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10461 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10462
616915dd 10463 {
10464 if (sRef_isIReference (ysr))
10465 {
10466 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10467 {
10468 voptgenerror
10469 (FLG_ASSIGNEXPOSE,
10470 message
10471 ("Assignment of mutable component of parameter %q "
10472 "to component of abstract "
10473 "type %s exposes rep: %s = %s",
10474 sRef_unparse (base),
10475 ctype_unparse (ct),
10476 exprNode_unparse (e1), exprNode_unparse (e2)),
10477 e1->loc);
10478 }
10479 else
10480 {
10481 voptgenerror
10482 (FLG_ASSIGNEXPOSE,
10483 message
10484 ("Assignment of mutable component of parameter %q "
10485 "(through alias %q) to component of abstract "
10486 "type %s exposes rep: %s = %s",
10487 sRef_unparse (base),
10488 sRef_unparse (e2->sref),
10489 ctype_unparse (ct),
10490 exprNode_unparse (e1), exprNode_unparse (e2)),
10491 e1->loc);
10492 }
10493 }
10494 else
10495 {
10496 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10497 {
10498 voptgenerror
10499 (FLG_ASSIGNEXPOSE,
10500 message ("Assignment of mutable parameter %q "
10501 "to component of abstract type %s "
10502 "exposes rep: %s = %s",
10503 sRef_unparse (base),
10504 ctype_unparse (ct),
10505 exprNode_unparse (e1),
10506 exprNode_unparse (e2)),
10507 e1->loc);
10508 }
10509 else
10510 {
10511 voptgenerror
10512 (FLG_ASSIGNEXPOSE,
10513 message ("Assignment of mutable parameter %q "
10514 "(through alias %q) to "
10515 "component of abstract type %s exposes "
10516 "rep: %s = %s",
10517 sRef_unparse (base),
10518 sRef_unparse (e2->sref),
10519 ctype_unparse (ct),
10520 exprNode_unparse (e1),
10521 exprNode_unparse (e2)),
10522 e1->loc);
10523 }
10524 }
10525 }
10526
28bf4b0b 10527 if (sRef_isFileOrGlobalScope (s2b))
616915dd 10528 {
10529 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10530 {
10531 voptgenerror
10532 (FLG_REPEXPOSE,
10533 message ("Assignment of global %q "
10534 "to component of "
10535 "abstract type %s exposes rep: %s = %s",
10536 sRef_unparse (base),
10537 ctype_unparse (ct),
10538 exprNode_unparse (e1), exprNode_unparse (e2)),
10539 e1->loc);
10540 }
10541 else
10542 {
10543 voptgenerror
10544 (FLG_REPEXPOSE,
10545 message ("Assignment of global %q (through alias %q) "
10546 "to component of "
10547 "abstract type %s exposes rep: %s = %s",
10548 sRef_unparse (base),
10549 sRef_unparse (e2->sref),
10550 ctype_unparse (ct),
10551 exprNode_unparse (e1), exprNode_unparse (e2)),
10552 e1->loc);
10553 }
10554 }
10555 }
10556}
10557
10558static void
10559doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
10560{
7534721d 10561 DPRINTF (("Do assign: %s <- %s",
10562 exprNode_unparse (e1), exprNode_unparse (e2)));
10563 DPRINTF (("Ctype: %s", ctype_unparse (exprNode_getType (e1))));
10564
616915dd 10565 if (ctype_isRealFunction (exprNode_getType (e1))
10566 && !ctype_isRealPointer (exprNode_getType (e1)))
10567 {
10568 voptgenerror
10569 (FLG_TYPE,
10570 message ("Invalid left-hand side of assignment (function type %s): %s",
10571 ctype_unparse (exprNode_getType (e1)),
10572 exprNode_unparse (e1)),
10573 e1->loc);
10574 }
10575
10576 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
10577 {
10578 ctype t2 = exprNode_getType (e2);
10579 sRef sr = sRef_getRootBase (e1->sref);
10580 ctype ct = sRef_getType (sr);
10581
10582 if (ctype_isAbstract (t2)
10583 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
10584 {
10585 /* it is immutable, okay to reference */
10586 goto donerepexpose;
10587 }
10588
10589 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
10590 {
10591 sRef s2b = sRef_getRootBase (e2->sref);
10592 sRef s1 = e1->sref;
10593 sRef s1b = sRef_getRootBase (s1);
10594 sRefSet aliases;
10595
10596 aliases = usymtab_canAlias (e2->sref);
10597
10598 if (!sRef_similar (s2b, s1b)
10599 && !sRef_isExposed (s1)
10600 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
10601 {
10602 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
10603 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
10604 && !sRef_isExposed (s2b))
10605 {
10606 if (sRef_isIReference (e2->sref))
10607 {
10608 voptgenerror
10609 (FLG_ASSIGNEXPOSE,
10610 message
10611 ("Assignment of mutable component of parameter %q "
10612 "to component of abstract type %s exposes rep: %s = %s",
10613 sRef_unparse (s2b),
10614 ctype_unparse (ct),
10615 exprNode_unparse (e1), exprNode_unparse (e2)),
10616 e1->loc);
10617 }
10618 else
10619 {
10620 voptgenerror
10621 (FLG_ASSIGNEXPOSE,
10622 message ("Assignment of mutable parameter %q to "
10623 "component of abstract type %s exposes rep: %s = %s",
10624 sRef_unparse (s2b),
10625 ctype_unparse (ct),
10626 exprNode_unparse (e1), exprNode_unparse (e2)),
10627 e1->loc);
10628 }
10629 }
10630
28bf4b0b 10631 if (sRef_isFileOrGlobalScope (s2b))
616915dd 10632 {
10633 voptgenerror
10634 (FLG_ASSIGNEXPOSE,
10635 message ("Assignment of global %q to component of "
10636 "abstract type %s exposes rep: %s = %s",
10637 sRef_unparse (s2b),
10638 ctype_unparse (ct),
10639 exprNode_unparse (e1), exprNode_unparse (e2)),
10640 e1->loc);
10641 }
10642
10643 sRefSet_realElements (aliases, ysr)
10644 {
10645 sRef base = sRef_getRootBase (ysr);
10646
10647 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
10648 || sRef_sameName (base, s1b))
10649 {
10650 ; /* error already reported or same sref */
10651 }
10652 else
10653 {
10654 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
10655 }
10656 } end_sRefSet_realElements;
10657 }
10658 sRefSet_free (aliases);
10659 }
10660 }
10661
10662 donerepexpose:
10663
10664 /*
10665 ** function variables don't really work...
10666 */
10667
10668 if (!ctype_isFunction (ctype_realType (e2->typ)))
10669 {
10670 if (isInit)
10671 {
28bf4b0b 10672 DPRINTF (("Check init: %s / %s",
10673 exprNode_unparse (e1), exprNode_unparse (e2)));
616915dd 10674 checkInitTransfer (e1, e2);
10675 }
10676 else
10677 {
10678 checkAssignTransfer (e1, e2);
10679 }
10680 }
10681 else
10682 {
10683 sRef fref = e2->sref;
10684
10685 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
10686 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
10687
10688 /* Need to typecheck the annotation on the parameters */
10689
10690 if (ctype_isRealFunction (e1->typ)) {
10691 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
10692 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
10693
10694 if (!uentryList_isMissingParams (e1p)
10695 && !uentryList_isMissingParams (e2p)
10696 && uentryList_size (e1p) > 0) {
10697 if (uentryList_size (e1p) == uentryList_size (e2p)) {
10698 int n = 0;
10699
10700 uentryList_elements (e1p, el1) {
10701 uentry el2;
10702
10703 el2 = uentryList_getN (e2p, n);
10704 n++;
10705 uentry_checkMatchParam (el1, el2, n, e2);
10706 } end_uentryList_elements;
10707 }
10708 }
10709 }
10710 }
10711
7534721d 10712 if (exprNode_isStringLiteral (e2))
10713 {
10714 exprNode_checkStringLiteralLength (exprNode_getType (e1), e2);
10715 }
10716
28bf4b0b 10717 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
616915dd 10718 {
10719 ;
10720 }
10721 else
10722 {
28bf4b0b 10723 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
616915dd 10724 updateAliases (e1, e2);
10725 }
616915dd 10726}
10727
10728static void
10729checkMacroParen (exprNode e)
10730{
10731 if (exprNode_isError (e) || e->kind == XPR_CAST)
10732 {
10733 ;
10734 }
10735 else
10736 {
10737 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
10738 {
10739 voptgenerror
10740 (FLG_MACROPARENS,
10741 message ("Macro parameter used without parentheses: %s",
10742 exprNode_unparse (e)),
10743 e->loc);
10744 }
10745 }
10746}
10747
10748static void
10749reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
10750{
10751 if (isnull)
10752 {
10753 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
10754 }
10755 else
10756 {
10757 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
10758 }
10759}
10760
10761/*
10762** e1 <= e2
10763**
10764** if e2 is a parameter or global derived location which
10765** can be modified (that is, e2 is a mutable abstract type,
10766** or a derived pointer), then e1 can alias e2.
10767**
10768** e1 can alias everything which e2 can alias.
10769**
10770** Also, if e1 is guarded, remove from guard sets!
10771*/
10772
10773static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
10774{
10775 if (!context_inProtectVars ())
10776 {
10777 /*
10778 ** depends on types of e1 and e2
10779 */
10780
10781 sRef s1 = e1->sref;
10782 sRef s2 = e2->sref;
10783 ctype t1 = exprNode_getType (e1);
10784
10785 /* handle pointer sRefs, record fields, arrays, etc... */
10786
10787 if (!ctype_isRealSU (t1))
10788 {
28bf4b0b 10789 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
616915dd 10790 sRef_copyRealDerivedComplete (s1, s2);
10791 }
28bf4b0b 10792 else
10793 {
10794 /*
10795 ** Fields should alias
10796 */
10797
10798 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
10799 }
616915dd 10800
10801 if (ctype_isMutable (t1) && sRef_isKnown (s1))
10802 {
10803 usymtab_clearAlias (s1);
10804 usymtab_addMustAlias (s1, s2);
28bf4b0b 10805 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
10806 }
10807 else
10808 {
10809 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
616915dd 10810 }
10811
10812 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
10813 {
10814 usymtab_unguard (s1);
10815 }
10816 }
10817}
10818
10819exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
10820{
10821 if (exprNode_isDefined (e))
10822 {
10823 e->loc = fileloc_update (e->loc, loc);
10824 }
10825 else
10826 {
10827 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
10828 }
10829
10830 return (e);
10831}
10832
10833static void checkUniqueParams (exprNode fcn,
10834 /*@notnull@*/ exprNode current,
10835 exprNodeList args,
10836 int paramno, uentry ucurrent)
10837{
10838 int iparamno = 0;
10839 sRef thisref = exprNode_getSref (current);
10840
10841 /*
10842 ** Check if any argument could match this argument.
10843 */
10844
10845 exprNodeList_elements (args, icurrent)
10846 {
10847 iparamno++;
10848
10849 if (iparamno != paramno)
10850 {
10851 sRef sr = exprNode_getSref (icurrent);
10852
10853 if (sRef_similarRelaxed (thisref, sr))
10854 {
10855 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
10856 {
10857 voptgenerror
10858 (FLG_ALIASUNIQUE,
10859 message
10860 ("Parameter %d (%s) to function %s is declared %s but "
10861 "is aliased by parameter %d (%s)",
10862 paramno,
10863 exprNode_unparse (current),
10864 exprNode_unparse (fcn),
10865 alkind_unparse (uentry_getAliasKind (ucurrent)),
10866 iparamno, exprNode_unparse (icurrent)),
10867 current->loc);
10868 }
10869 }
10870 else
10871 {
10872 sRefSet aliases = usymtab_canAlias (sr);
10873
10874 sRefSet_allElements (aliases, asr)
10875 {
10876 if (ctype_isUnknown (sRef_getType (thisref)))
10877 {
10878 sRef_setType (thisref, uentry_getType (ucurrent));
10879 }
10880
10881 if (sRef_similarRelaxed (thisref, asr))
10882 {
10883 if (sRef_isExternal (asr))
10884 {
10885 if (sRef_isLocalState (thisref))
10886 {
10887 ; /* okay */
10888 }
10889 else
10890 {
10891 sRef base = sRef_getRootBase (asr);
10892
10893 if (!sRef_similar (sRef_getBase (asr), thisref))
10894 {
10895 if (sRef_isUnique (base) || sRef_isOnly (base)
10896 || sRef_isKept (base)
10897 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
10898 || (sRef_isAddress (thisref)
10899 && sRef_isLocalVar (sRef_getRootBase (thisref))))
10900 {
10901 ; /* okay, no error */
10902 }
10903 else
10904 {
10905 voptgenerror
10906 (FLG_MAYALIASUNIQUE,
10907 message
10908 ("Parameter %d (%s) to function %s is declared %s but "
10909 "may be aliased externally by parameter %d (%s)",
10910 paramno,
10911 exprNode_unparse (current),
10912 exprNode_unparse (fcn),
10913 alkind_unparse (uentry_getAliasKind (ucurrent)),
10914 iparamno, exprNode_unparse (icurrent)),
10915 current->loc);
10916 }
10917 }
10918 }
10919 }
10920 else
10921 {
10922 voptgenerror
10923 (FLG_ALIASUNIQUE,
10924 message
10925 ("Parameter %d (%s) to function %s is declared %s but "
10926 "is aliased externally by parameter %d (%s) through "
10927 "alias %q",
10928 paramno,
10929 exprNode_unparse (current),
10930 exprNode_unparse (fcn),
10931 alkind_unparse (uentry_getAliasKind (ucurrent)),
10932 iparamno, exprNode_unparse (icurrent),
10933 sRef_unparse (asr)),
10934 current->loc);
10935 }
10936 }
10937 } end_sRefSet_allElements;
10938 sRefSet_free (aliases);
10939 }
10940 }
10941 } end_exprNodeList_elements;
10942}
10943
10944long exprNode_getLongValue (exprNode e) {
10945 long value;
10946
10947 if (exprNode_hasValue (e)
10948 && multiVal_isInt (exprNode_getValue (e)))
10949 {
10950 value = multiVal_forceInt (exprNode_getValue (e));
10951 }
10952 else
10953 {
7534721d 10954 /*@!! BADBRANCH;*/
616915dd 10955 value = 0;
10956 }
10957
10958 return value;
10959}
10960
d46ce6a4 10961/*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
616915dd 10962{
84c9ffbf 10963 if (exprNode_isDefined (p_e) )
d46ce6a4 10964 return ( p_e->loc );
616915dd 10965 else
10966 return fileloc_undefined;
10967}
10968
bb25bea6 10969/*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
616915dd 10970{
10971 /*
10972 ** Returns the location of the sequence point following e.
10973 **
10974 ** Only works for statements (for now).
10975 */
10976
10977 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
10978 lltok t = exprData_getUopTok (e->edata);
bb25bea6 10979 return fileloc_copy(lltok_getLoc (t));
616915dd 10980 } else {
b7b694d6 10981 /* drl possible problem : warning fix
10982 llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
10983 */
616915dd 10984 return fileloc_undefined;
10985 }
10986 }
10987
9280addf 10988exprNode exprNode_createNew(ctype c)
10989{
10990 exprNode ret;
10991
10992 ret = exprNode_createPlain (c);
10993
10994 return ret;
10995}
d30bc0c7 10996
10997bool exprNode_isInitBlock (exprNode e)
10998{
10999 return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);
11000}
This page took 1.615372 seconds and 5 git commands to generate.