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