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