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