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