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