]> 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 {
6970c11b 3211 fileloc loc = exprNode_loc (f);
3212
ccf0a4a8 3213 metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3120b462 3214
ccf0a4a8 3215 metaStateConstraintList_elements (mscl, msc)
3120b462 3216 {
ccf0a4a8 3217 metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3218 metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3219 metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
6970c11b 3220 cstring key = metaStateInfo_getName (msinfo);
ccf0a4a8 3221 sRef mlsr = metaStateSpecifier_getSref (msspec);
3222 sRef s;
3223 sRef lastref = sRef_undefined;
3224 stateValue sval = stateValue_undefined;
3225
3226 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3227 metaStateConstraint_unparse (msc)));
3228 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3229
3230 if (sRef_isResult (sRef_getRootBase (mlsr)))
12f2ffe9 3231 {
ccf0a4a8 3232 s = exprNode_getSref (ret);
12f2ffe9 3233 }
3234 else
3235 {
ccf0a4a8 3236 s = sRef_fixBaseParam (mlsr, args);
12f2ffe9 3237 }
ccf0a4a8 3238
3239 DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3240
3241 while (metaStateExpression_isDefined (msexpr))
12f2ffe9 3242 {
ccf0a4a8 3243 metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
ccf0a4a8 3244 metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
6970c11b 3245 sRef msr, fs;
3246
ccf0a4a8 3247 DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3248
3249 if (metaStateExpression_isMerge (msexpr))
3250 {
3251 msexpr = metaStateExpression_getRest (msexpr);
3252 }
3253 else
3254 {
3255 msexpr = metaStateExpression_undefined;
3256 }
3257
3258 if (metaStateInfo_isDefined (msi))
3259 {
3260 /* Must match lhs state */
3261 llassert (metaStateInfo_equal (msinfo, msi));
3262 }
3263
6970c11b 3264 if (metaStateSpecifier_isElipsis (ms))
12f2ffe9 3265 {
6970c11b 3266 /*
3267 ** For elipsis, we need to merge all the relevant elipsis parameters
3268 **
3269 */
12f2ffe9 3270
6970c11b 3271 uentryList params = uentry_getParams (le);
3272 int paramno = uentryList_size (params) - 1;
3273
3274 if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
12f2ffe9 3275 {
6970c11b 3276 voptgenerror
3277 (FLG_TYPE,
3278 message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3279 uentry_getName (le)),
3280 uentry_whereLast (le));
3281 /*@innerbreak@*/ break;
3282 }
3283
3284 while (paramno < exprNodeList_size (args))
3285 {
3286 exprNode arg = exprNodeList_getN (args, paramno);
3287 fs = exprNode_getSref (arg);
3288 DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3289
3290 /* cut and pasted... gack*/
3291 if (stateValue_isDefined (sval))
ccf0a4a8 3292 {
6970c11b 3293 /* Use combination table to merge old state value with new one: */
3294 stateValue tval = sRef_getMetaStateValue (fs, key);
ccf0a4a8 3295
6970c11b 3296 if (stateValue_isDefined (tval))
3297 {
3298 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3299 cstring msg = cstring_undefined;
3300 int nval = stateCombinationTable_lookup (sctable,
3301 stateValue_getValue (sval),
3302 stateValue_getValue (tval),
3303 &msg);
3304 DPRINTF (("Combining: %s + %s -> %d",
3305 stateValue_unparseValue (sval, msinfo),
3306 stateValue_unparseValue (tval, msinfo),
3307 nval));
3308
3309 if (nval == stateValue_error)
3310 {
3311 llassert (cstring_isDefined (msg));
3312
3313 if (optgenerror
3314 (FLG_STATEMERGE,
3315 message
3316 ("Attributes merged in ensures clause in states that "
3317 "cannot be combined (%q is %q, %q is %q): %s",
3318 sRef_unparse (lastref),
3319 stateValue_unparseValue (sval, msinfo),
3320 sRef_unparse (fs),
3321 stateValue_unparseValue (tval, msinfo),
3322 msg),
3323 exprNode_loc (f)))
3324 {
3325 sRef_showMetaStateInfo (fs, key);
3326 }
3327 }
3328
3329 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3330 loc = exprNode_loc (arg);
3331 }
3332 else
ccf0a4a8 3333 {
6970c11b 3334 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3335 }
3336 }
3337 else
3338 {
3339 sval = sRef_getMetaStateValue (fs, key);
ccf0a4a8 3340 }
3341
6970c11b 3342 lastref = fs;
3343
3344 if (stateValue_isError (sval))
3345 {
3346 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3347 }
3348
3349
3350 paramno++;
ccf0a4a8 3351 }
3352 }
3353 else
3354 {
6970c11b 3355 msr = metaStateSpecifier_getSref (ms);
ccf0a4a8 3356
6970c11b 3357
3358 llassert (sRef_isParam (sRef_getRootBase (msr)));
3359 fs = sRef_fixBaseParam (msr, args);
3360
3361 if (stateValue_isDefined (sval))
3362 {
3363 /* Use combination table to merge old state value with new one: */
3364 stateValue tval = sRef_getMetaStateValue (fs, key);
3365
3366 if (stateValue_isDefined (tval))
3367 {
3368 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3369 cstring msg = cstring_undefined;
3370 int nval = stateCombinationTable_lookup (sctable,
3371 stateValue_getValue (sval),
3372 stateValue_getValue (tval),
3373 &msg);
3374 DPRINTF (("Combining: %s + %s -> %d",
3375 stateValue_unparseValue (sval, msinfo),
3376 stateValue_unparseValue (tval, msinfo),
3377 nval));
3378
3379 if (nval == stateValue_error)
3380 {
3381 llassert (cstring_isDefined (msg));
3382
3383 if (optgenerror
3384 (FLG_STATEMERGE,
3385 message
3386 ("Attributes merged in ensures clause in states that "
3387 "cannot be combined (%q is %q, %q is %q): %s",
3388 sRef_unparse (lastref),
3389 stateValue_unparseValue (sval, msinfo),
3390 sRef_unparse (fs),
3391 stateValue_unparseValue (tval, msinfo),
3392 msg),
3393 exprNode_loc (f)))
3394 {
3395 sRef_showMetaStateInfo (fs, key);
3396 }
3397 }
3398
3399 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3400 }
3401 else
3402 {
3403 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3404 }
3405 }
3406 else
3407 {
3408 sval = sRef_getMetaStateValue (fs, key);
3409 }
3410
3411 lastref = fs;
3412
3413 if (stateValue_isError (sval))
3414 {
3415 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3416 }
12f2ffe9 3417 }
12f2ffe9 3418 }
6970c11b 3419
ccf0a4a8 3420 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3421
3422 if (stateValue_isDefined (sval))
12f2ffe9 3423 {
6970c11b 3424 sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
12f2ffe9 3425 }
ccf0a4a8 3426 else
12f2ffe9 3427 {
ccf0a4a8 3428 DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
12f2ffe9 3429 }
ccf0a4a8 3430 } end_metaStateConstraintList_elements ;
ba45e1e4 3431
ccf0a4a8 3432 metaStateConstraintList_free (mscl);
28bf4b0b 3433 }
3434 }
3435}
3436
3437static void
3438checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3439{
3440 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3441 exprNode_unparse (f), exprNodeList_unparse (args),
3442 uentry_unparseFull (le),
3443 stateClauseList_unparse (uentry_getStateClauseList (le))));
3444
3445 if (uentry_isValid (le) && uentry_isFunction (le))
3446 {
3447 stateClauseList sclauses = uentry_getStateClauseList (le);
3448
3449 if (stateClauseList_isDefined (sclauses))
3450 {
3451 DPRINTF (("Check requires: %s / %s / %s",
3452 uentry_unparse (le),
3453 exprNode_unparse (f), exprNodeList_unparse (args)));
3454
3455 stateClauseList_elements (sclauses, cl)
3456 {
3457 DPRINTF (("Check clause: %s / %s",
3458 stateClause_unparse (cl),
3459 bool_unparse (stateClause_hasRequires (cl))));
3460
3461 if (stateClause_hasRequires (cl))
3462 {
3463 sRefSet osrs = sRefSet_undefined;
3464 sRefSet srs;
3465
3466 if (stateClause_isGlobal (cl))
3467 {
3468 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3469 osrs = srs;
3470 }
3471 else
3472 {
3473 srs = stateClause_getRefs (cl);
3474 }
3475
3476 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3477
3478 if (stateClause_setsMetaState (cl))
3479 {
3480 qual q = stateClause_getMetaQual (cl);
3481 annotationInfo ainfo = qual_getAnnotationInfo (q);
3482 metaStateInfo minfo = annotationInfo_getState (ainfo);
3483 cstring key = metaStateInfo_getName (minfo);
3484 int mvalue = annotationInfo_getValue (ainfo);
3485
3486 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3487
3488 sRefSet_elements (srs, sel)
3489 {
3490 sRef s = sRef_fixBaseParam (sel, args);
3491
3492 if (sRef_isResult (sRef_getRootBase (sel)))
3493 {
ccf0a4a8 3494 BADBRANCH;
28bf4b0b 3495 }
3496 else
3497 {
3498 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3499 sRef_unparseFull (sel), sRef_unparseFull (s),
3500 key, mvalue));
3501
3502 if (!sRef_checkMetaStateValue (s, key, mvalue))
3503 {
3504 DPRINTF (("HERE: %s", sRef_unparse (s)));
3505 if (optgenerror
3506 (FLG_STATETRANSFER,
3507 message
990ec868 3508 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
28bf4b0b 3509 uentry_getName (le),
3510 sRef_isGlobalMarker (s)
3511 ? message ("")
3512 : message (" by %q", sRef_unparse (s)),
3513 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3514 minfo),
3515 stateClause_unparse (cl)),
3516 exprNode_loc (f)))
3517 {
3518 sRef_showAliasInfo (s);
3519 }
3520 else
3521 {
3522 DPRINTF (("Error supressed!"));
3523 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3524 DPRINTF (("Context supress: %s",
3525 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3526 }
3527 }
3528 }
3529 } end_sRefSet_elements;
3530 }
3531 else
3532 {
3533 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3534 int eparam = stateClause_getStateParameter (cl);
3535
3536 DPRINTF (("Reflect after clause: %s / %s",
3537 stateClause_unparse (cl),
3538 sRefSet_unparse (srs)));
3539
3540 sRefSet_elements (srs, sel)
3541 {
3542 sRef s;
3543
3544 DPRINTF (("elements: %s", sRef_unparse (sel)));
3545 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3546
3547 s = sRef_fixBaseParam (sel, args);
3548
3549 DPRINTF (("elements: %s", sRef_unparse (s)));
3550 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3551
3552 if (sRef_isResult (sRef_getRootBase (sel)))
3553 {
3554 ; /*@i423 what do we do about results */
3555 }
3556 else
3557 {
3558 DPRINTF (("Reflecting state clause on: %s / %s",
3559 sRef_unparse (sel), sRef_unparse (s)));
3560
3561 modf (s, eparam, exprNode_loc (f));
3562 }
3563 } end_sRefSet_elements;
3564 }
3565
3566 sRefSet_free (osrs);
3567 }
3568 } end_stateClauseList_elements ;
3569 }
3570 }
3571}
3572
616915dd 3573static /*@only@*/ exprNode
3574functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3575 ctype t, /*@keep@*/ exprNodeList args)
3576{
3577 /* requires f is a non-error exprNode, with type function */
3578 cstring fname = exprNode_unparse (f);
3579 uentry le = exprNode_getUentry (f);
3580 exprNode ret = exprNode_createPartialCopy (f);
3581 int special;
3582
3583 setCodePoint ();
28bf4b0b 3584
3585 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3586
3587 ret->typ = ctype_getReturnType (t);
616915dd 3588 ret->kind = XPR_CALL;
3589
3590 ret->edata = exprData_makeCall (f, args);
3591
3592 /*
3593 ** Order of these steps is very important!
3594 **
3595 ** Must check for argument dependencies before messing up uses and sets.
3596 */
3597
3598 if (context_getFlag (FLG_EVALORDER))
3599 {
3600 exprNodeList_elements (args, current)
3601 {
3602 if (exprNode_isDefined (current))
3603 {
3604 exprNode_addUse (current, current->sref);
3605 }
3606 } end_exprNodeList_elements;
3607
3608 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3609 {
3610 checkSequencing (f, args);
3611 }
3612
3613 exprNodeList_elements (args, current)
3614 {
3615 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3616 {
3617 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3618 }
3619 } end_exprNodeList_elements ;
3620 }
3621
3622 special = checkArgs (le, f, t, args, ret);
3623 checkGlobMods (f, le, args, ret, special);
28bf4b0b 3624 checkRequiresClause (le, f, args);
3625 setCodePoint ();
616915dd 3626
616915dd 3627 if (uentry_isValid (le)
3628 && (uentry_isFunction (le)
3629 || (uentry_isVariable (le)
3630 && ctype_isFunction (uentry_getType (le)))))
3631 {
3632 exitkind exk = uentry_getExitCode (le);
3633
3634 /* f->typ is already set to the return type */
3635
ccf0a4a8 3636 DPRINTF (("Function: %s", uentry_unparseFull (le)));
616915dd 3637 ret->sref = uentry_returnedRef (le, args);
28bf4b0b 3638 DPRINTF (("Returned: %s / %s",
3639 uentry_unparseFull (le),
3640 sRef_unparseFull (ret->sref)));
ccf0a4a8 3641
616915dd 3642 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3643 {
3644 qual nullPred = uentry_nullPred (le);
3645
3646 if (qual_isTrueNull (nullPred))
3647 {
3648 exprNode arg = exprNodeList_head (args);
3649
3650 if (exprNode_isDefined (arg))
3651 {
3652 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3653 }
3654 }
3655 else if (qual_isFalseNull (nullPred))
3656 {
3657 exprNode arg = exprNodeList_head (args);
3658
3659 if (exprNode_isDefined (arg))
3660 {
3661 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3662 }
3663 }
3664 else
3665 {
3666 llassert (qual_isUnknown (nullPred));
3667 }
3668 }
3669
3670 if (exitkind_isConditionalExit (exk))
3671 {
3672 /*
3673 ** True exit is:
3674 ** if (arg0) then { exit! } else { ; }
3675 ** False exit is:
3676 ** if (arg0) then { ; } else { exit! }
3677 */
3678
3679 exprNode firstArg;
3680
3681 llassert (!exprNodeList_isEmpty (args));
3682 firstArg = exprNodeList_head (args);
3683
3684 if (exprNode_isDefined (firstArg)
3685 && !guardSet_isEmpty (firstArg->guards))
3686 {
3687 usymtab_trueBranch (guardSet_undefined);
3688 usymtab_altBranch (guardSet_undefined);
3689
3690 if (exitkind_isTrueExit (exk))
3691 {
3692 usymtab_popBranches (firstArg,
3693 exprNode_makeMustExit (),
3694 exprNode_undefined,
3695 TRUE, TRUEEXITCLAUSE);
3696 }
3697 else
3698 {
3699 usymtab_popBranches (firstArg,
3700 exprNode_undefined,
3701 exprNode_makeMustExit (),
3702 TRUE, FALSEEXITCLAUSE);
3703 }
3704 }
3705
3706 ret->exitCode = XK_MAYEXIT;
3707 }
3708 else if (exitkind_mustExit (exk))
3709 {
3710 ret->exitCode = XK_MUSTEXIT;
3711 }
3712 else if (exitkind_couldExit (exk))
3713 {
3714 ret->exitCode = XK_MAYEXIT;
3715 }
3716 else
3717 {
3718 ;
3719 }
3720
3721 if (cstring_equalLit (fname, "exit"))
3722 {
3723 if (exprNodeList_size (args) == 1)
3724 {
3725 exprNode arg = exprNodeList_head (args);
3726
3727 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3728 {
3729 long int val = multiVal_forceInt (exprNode_getValue (arg));
3730
3731 if (val != 0)
3732 {
3733 voptgenerror
3734 (FLG_EXITARG,
3735 message
3736 ("Argument to exit has implementation defined behavior: %s",
3737 exprNode_unparse (arg)),
3738 exprNode_loc (arg));
3739 }
3740 }
3741 }
3742 }
3743 }
3744 else
3745 {
3746 ret->sref = defref;
3747 exprNode_checkSetAny (ret, uentry_rawName (le));
3748 }
3749
ccf0a4a8 3750 DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3751 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3752 reflectEnsuresClause (ret, le, f, args);
3753 setCodePoint ();
3754
616915dd 3755 return (ret);
3756}
3757
3758/*
3759** this is yucky! should keep the uentry as part of exprNode!
3760*/
3761
3762/*@observer@*/ uentry
3763exprNode_getUentry (exprNode e)
3764{
3765 if (exprNode_isError (e))
3766 {
3767 return uentry_undefined;
3768 }
3769 else
3770 {
3771 cstring s = exprNode_rootVarName (e);
3772 uentry ue = usymtab_lookupSafe (s);
3773
3774 return ue;
3775 }
3776}
3777
3778exprNode
3779exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3780{
3781 exprNode ret = exprNode_createPlain (ctype_unknown);
3782
3783 ret->kind = XPR_INITBLOCK;
3784 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3785 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3786
3787 return (ret);
3788}
3789
3790exprNode
3791exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3792{
3793 ctype t;
3794
3795 setCodePoint ();
3796
3797 if (exprNode_isUndefined (f))
3798 {
3799 exprNode_free (f);
3800 exprNodeList_free (args);
3801 return exprNode_undefined;
3802 }
3803
3804 t = exprNode_getType (f);
3805
3806 if (sRef_isLocalVar (f->sref))
3807 {
3808 exprNode_checkUse (f, f->sref, f->loc);
3809
3810 if (sRef_possiblyNull (f->sref))
3811 {
3812 if (!usymtab_isGuarded (f->sref))
3813 {
3814 if (optgenerror (FLG_NULLDEREF,
3815 message ("Function call using %s pointer %q",
3816 sRef_nullMessage (f->sref),
3817 sRef_unparse (f->sref)),
3818 f->loc))
3819 {
3820 sRef_showNullInfo (f->sref);
3821 sRef_setNullError (f->sref);
3822 }
3823 }
3824 }
3825 }
3826
3827 setCodePoint ();
3828
3829 if (ctype_isRealFunction (t))
3830 {
3831 exprNode ret = functionCallSafe (f, t, args);
3832 setCodePoint ();
3833 return ret;
3834 }
3835 else if (ctype_isUnknown (t))
3836 {
3837 exprNode ret = exprNode_createPartialCopy (f);
3838 cstring tstring;
3839
3840 setCodePoint ();
3841
3842 ret->typ = t;
3843 exprNodeList_elements (args, current)
3844 {
3845 if (exprNode_isDefined (current))
3846 {
3847 exprNode_checkUse (ret, current->sref, ret->loc);
3848
3849 /*
3850 ** also, anything derivable from current->sref may be used
3851 */
3852
3853 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3854 exprNode_mergeUSs (ret, current);
3855 }
3856 } end_exprNodeList_elements;
3857
3858 ret->edata = exprData_makeCall (f, args);
3859 ret->kind = XPR_CALL;
3860
3861 tstring = cstring_copy (exprNode_unparse (f));
3862
3863 cstring_markOwned (tstring);
3864 exprNode_checkSetAny (ret, tstring);
3865
3866 return (ret);
3867 }
3868 else
3869 {
3870 voptgenerror (FLG_TYPE,
3871 message ("Call to non-function (type %t): %s", t,
3872 exprNode_unparse (f)),
3873 f->loc);
3874 exprNode_free (f);
3875 exprNodeList_free (args);
3876
3877 return (exprNode_makeError ());
3878 }
3879}
3880
28bf4b0b 3881static exprNode
3882exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
3883 /*@only@*/ cstring f)
616915dd 3884{
3885 exprNode ret = exprNode_createPartialCopy (s);
3886
3887 ret->kind = XPR_FACCESS;
3888
3889 if (exprNode_isError (s))
3890 {
3891 ret->edata = exprData_makeField (s, f);
3892 return ret;
3893 }
3894 else
3895 {
3896 ctype t = exprNode_getType (s);
3897 ctype tr = ctype_realType (t);
28bf4b0b 3898
616915dd 3899 checkMacroParen (s);
3900
3901 ret->edata = exprData_makeField (s, f);
28bf4b0b 3902
616915dd 3903 if (ctype_isStructorUnion (tr))
3904 {
3905 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
3906
3907 if (uentry_isUndefined (tf))
3908 {
3909 voptgenerror (FLG_TYPE,
3910 message ("Access non-existent field %s of %t: %s", f, t,
3911 exprNode_unparse (ret)),
28bf4b0b 3912 loc);
3913 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
616915dd 3914 return (ret);
3915 }
3916 else
3917 {
3918 uentry_setUsed (tf, exprNode_loc (ret));
3919
3920 ret->typ = uentry_getType (tf);
3921 checkSafeUse (ret, s->sref);
3922
3923 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
28bf4b0b 3924 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
616915dd 3925 return (ret);
3926 }
3927 }
3928 else /* isStructorUnion */
3929 {
3930 if (ctype_isRealAbstract (tr))
3931 {
3932 voptgenerror
3933 (FLG_ABSTRACT,
3934 message ("Access field of abstract type (%t): %s.%s",
3935 t, exprNode_unparse (s), f),
28bf4b0b 3936 loc);
616915dd 3937 ret->typ = ctype_unknown;
3938 }
3939 else
3940 {
3941 if (ctype_isKnown (tr))
3942 {
3943 voptgenerror
3944 (FLG_TYPE,
3945 message
3946 ("Access field of non-struct or union (%t): %s.%s",
3947 t, exprNode_unparse (s), f),
28bf4b0b 3948 loc);
616915dd 3949
3950 ret->typ = ctype_unknown;
3951 }
3952 else
3953 {
3954 cstring sn = cstring_copy (f);
28bf4b0b 3955
616915dd 3956 checkSafeUse (ret, s->sref);
3957 cstring_markOwned (sn);
3958 ret->sref = sRef_makeField (s->sref, sn);
616915dd 3959 return (ret);
3960 }
3961 }
28bf4b0b 3962
616915dd 3963 return (ret);
3964 }
3965 }
3966 BADEXIT;
3967}
3968
28bf4b0b 3969exprNode
3970exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
3971 /*@only@*/ cstring f)
3972{
3973 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
3974 lltok_release (dot);
3975 return res;
3976}
3977
616915dd 3978exprNode
3979exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
3980{
3981 exprNode ret = exprNode_createPartialCopy (e);
3982
3983 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
3984 ret->kind = XPR_PARENS;
3985 ret->edata = exprData_makeUop (e, lpar);
3986
3987 if (!exprNode_isError (e))
3988 {
3989 ret->exitCode = e->exitCode;
3990 ret->canBreak = e->canBreak;
3991 ret->mustBreak = e->mustBreak;
3992 ret->isJumpPoint = e->isJumpPoint;
3993 ret->sref = e->sref;
3994 }
3995
3996 return ret;
3997}
3998
28bf4b0b 3999static exprNode
4000exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4001 /*@only@*/ cstring f)
616915dd 4002{
4003 exprNode ret = exprNode_createPartialCopy (s);
4004
4005 ret->edata = exprData_makeField (s, f);
4006 ret->kind = XPR_ARROW;
28bf4b0b 4007
616915dd 4008 if (exprNode_isError (s))
4009 {
4010 return (ret);
4011 }
4012 else
4013 {
28bf4b0b 4014 ctype t = exprNode_getType (s);
4015 ctype tr = ctype_realType (t);
4016
4017 checkMacroParen (s);
4018
4019 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4020
4021 if (ctype_isRealPointer (tr))
4022 {
4023 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4024
4025 if (ctype_isStructorUnion (b))
4026 {
4027 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4028
4029 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4030 {
4031 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4032 {
4033 if (optgenerror
4034 (FLG_NULLDEREF,
4035 message ("Arrow access from %s pointer%q: %s",
4036 sRef_nullMessage (s->sref),
4037 sRef_unparsePreOpt (s->sref),
4038 exprNode_unparse (ret)),
4039 loc))
4040 {
4041 sRef_showNullInfo (s->sref);
4042 sRef_setNullError (s->sref);
4043 }
4044 }
4045 }
4046
4047 if (uentry_isUndefined (fentry))
4048 {
4049 voptgenerror
4050 (FLG_TYPE,
4051 message ("Access non-existent field %s of %t: %s",
4052 f, t, exprNode_unparse (ret)),
4053 loc);
4054 ret->typ = ctype_unknown;
4055 return (ret);
4056 }
4057 else
4058 {
4059 /*
4060 ** was safeUse: shouldn't be safe!
4061 **
4062 ** to do rec->field
4063 ** rec must be defined,
4064 ** *rec must be allocated
4065 ** rec->field need only be defined it if is an rvalue
4066 */
4067
4068 uentry_setUsed (fentry, exprNode_loc (ret));
4069 ret->typ = uentry_getType (fentry);
4070
4071 exprNode_checkUse (ret, s->sref, s->loc);
4072
4073 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4074 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4075 return (ret);
4076 }
4077 }
4078 else /* Pointer to something that is not a struct or union*/
4079 {
4080 if (ctype_isRealAbstract (tr))
4081 {
4082 ctype xrt = ctype_forceRealType (tr);
4083
4084 voptgenerror
4085 (FLG_ABSTRACT,
4086 message ("Arrow access field of abstract type (%t): %s->%s",
4087 t, exprNode_unparse (s), f),
4088 loc);
4089
4090 /*
4091 ** Set the state correctly, as if the abstraction is broken.
4092 */
4093
4094 if (ctype_isRealPointer (xrt) &&
4095 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4096 ctype_isStructorUnion (b)))
4097 {
4098 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4099 ret->typ = uentry_getType (fentry);
4100 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4101 }
4102 else
4103 {
4104 ret->typ = ctype_unknown;
4105 ret->sref = sRef_undefined;
4106 }
4107 }
4108 else /* not a struct, union or abstract */
4109 {
4110 if (ctype_isUnknown (tr)) {
4111 cstring sn = cstring_copy (f);
4112
4113 DPRINTF (("Here: %s", exprNode_unparse (s)));
4114
4115 exprNode_checkUse (ret, s->sref, s->loc);
4116 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4117
4118 cstring_markOwned (sn);
4119 ret->sref = sRef_makeArrow (s->sref, sn);
4120
4121 ret->kind = XPR_ARROW;
4122 return (ret);
4123 } else {
4124 voptgenerror
4125 (FLG_TYPE,
4126 message ("Arrow access field of non-struct or union "
4127 "pointer (%t): %s->%s",
4128 t, exprNode_unparse (s), f),
4129 loc);
4130
4131 ret->typ = ctype_unknown;
4132 ret->sref = sRef_undefined;
4133 }
4134 }
4135 }
4136 }
4137 else /* its not a pointer */
4138 {
4139 if (!ctype_isUnknown (tr))
4140 {
4141 voptgenerror
4142 (FLG_TYPE,
4143 message ("Arrow access of non-pointer (%t): %s->%s",
4144 t, exprNode_unparse (s), f),
4145 loc);
4146
4147 ret->typ = ctype_unknown;
4148 ret->sref = sRef_undefined;
4149 }
4150 else
4151 {
4152 cstring sn = cstring_copy (f);
4153
4154 DPRINTF (("Here: %s", exprNode_unparse (s)));
4155
4156 exprNode_checkUse (ret, s->sref, s->loc);
4157 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4158
4159 cstring_markOwned (sn);
4160 ret->sref = sRef_makeArrow (s->sref, sn);
4161
4162 ret->kind = XPR_ARROW;
4163 return (ret);
4164 }
4165 }
4166
616915dd 4167 return (ret);
4168 }
4169 BADEXIT;
4170}
4171
28bf4b0b 4172exprNode
4173exprNode_arrowAccess (/*@only@*/ exprNode s,
4174 /*@only@*/ lltok arrow,
4175 /*@only@*/ cstring f)
4176{
4177 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4178 lltok_release (arrow);
4179 return res;
4180}
4181
616915dd 4182/*
4183** only postOp's in C: i++ and i--
4184*/
4185
4186exprNode
4187exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4188{
4189 /* check modification also */
4190 /* cstring opname = lltok_unparse (op);*/
4191 ctype t;
4192 exprNode ret = exprNode_createPartialCopy (e);
4193
4194 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4195 ret->kind = XPR_POSTOP;
4196 ret->edata = exprData_makeUop (e, op);
4197
4198 if (!exprNode_isDefined (e))
4199 {
4200 return ret;
4201 }
4202
4203 checkMacroParen (e);
4204
4205 exprNode_checkUse (ret, e->sref, e->loc);
4206 exprNode_checkSet (ret, e->sref);
4207
4208 t = exprNode_getType (e);
4209
4210 if (sRef_isUnsafe (e->sref))
4211 {
4212 voptgenerror (FLG_MACROPARAMS,
4213 message ("Operand of %s is macro parameter (non-functional): %s%s",
4214 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4215 e->loc);
4216 sRef_makeSafe (e->sref);
4217 sRef_makeSafe (ret->sref);
4218 }
4219
4220 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4221 {
4222 ret->typ = e->typ;
4223 }
4224 else
4225 {
4226 if (ctype_isRealAbstract (t))
4227 {
4228 voptgenerror
4229 (FLG_ABSTRACT,
4230 message ("Operand of %s is abstract type (%t): %s",
4231 lltok_unparse (op), t, exprNode_unparse (e)),
4232 e->loc);
4233 }
4234 else
4235 {
4236 voptgenerror
4237 (FLG_TYPE,
4238 message ("Operand of %s is non-numeric (%t): %s",
4239 lltok_unparse (op), t, exprNode_unparse (e)),
4240 e->loc);
4241 }
4242 ret->typ = ctype_unknown;
4243 }
4244
4245 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4246
4247 exprNode_checkModify (e, ret);
4248
4249 /* added 7/11/2000 D.L */
84c9ffbf 4250 /*@i223*/
4251 /*DRL 6/8/01 I decided to disable all LCLint Warning here since the code
4252 probably needs a rewrite any way */
4253
4254 /*@ignore@*/
4255
dc92450f 4256 // updateEnvironmentForPostOp (e);
616915dd 4257
4258 /* start modifications */
4259 /* added by Seejo on 4/16/2000 */
4260
4261 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4262 status */
4263 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4264
4265 ret->sref = sRef_copy (e->sref);
4266
4267 /* Operator : ++ */
4268 if (lltok_getTok (op) == INC_OP) {
4269 if (sRef_getSize(e->sref) > 0) {
4270
4271 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4272
4273 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4274 /* Assumption: there is only 1 \0 in the buffer */
4275 /* This will not be correct if there are 2 \0's in the buffer */
4276 sRef_setNotNullTerminatedState(ret->sref);
4277 sRef_resetLen(ret->sref);
4278 } else {
4279 sRef_setNullTerminatedState(ret->sref);
4280 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4281 }
4282 if (sRef_isNullTerminated (ret->sref))
4283 printf ("ret->sref is Null Terminated\n");
4284 else if (sRef_isPossiblyNullTerminated (ret->sref))
4285 printf ("ret->sref is Possibly Null Terminated\n");
4286 else if (sRef_isNotNullTerminated (ret->sref))
4287 printf ("ret->sref is Not Null Terminated\n");
4288 }
4289 }
4290
4291 /* Operator : -- */
4292 if (lltok_getTok (op) == DEC_OP) {
4293 if (sRef_getSize(e->sref) >= 0) {
4294 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4295 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4296 }
4297 }
4298 }
84c9ffbf 4299 /*@end@*/
616915dd 4300 /* end modifications */
4301
4302 return ret;
4303}
4304
4305exprNode
4306exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4307{
4308 bool checkMod = FALSE;
4309 ctype te, tr;
4310 int opid = lltok_getTok (op);
4311 exprNode ret = exprNode_createSemiCopy (e);
4312
4313 exprNode_copySets (ret, e);
4314
4315 multiVal_free (ret->val);
4316 ret->val = multiVal_undefined;
4317 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4318 ret->kind = XPR_PREOP;
4319 ret->edata = exprData_makeUop (e, op);
4320
4321 if (exprNode_isError (e))
4322 {
4323 return ret;
4324 }
4325
4326 checkMacroParen (e);
4327
4328 te = exprNode_getType (e);
4329 tr = ctype_realType (te);
4330
4331 if (opid != TAMPERSAND)
4332 {
4333 exprNode_checkUse (ret, e->sref, e->loc);
4334
4335 if (ctype_isRealAbstract (tr)
4336 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4337 {
4338 if (optgenerror (FLG_ABSTRACT,
4339 message ("Operand of %s is abstract type (%t): %s",
4340 lltok_unparse (op), tr,
4341 exprNode_unparse (ret)),
4342 e->loc))
4343 {
4344 tr = te = ctype_unknown;
4345 ret->typ = ctype_unknown;
4346 sRef_setNullError (e->sref);
4347 }
4348 }
4349 }
4350
4351 switch (opid)
4352 {
4353 case INC_OP:
4354 case DEC_OP: /* should also check modification! */
616915dd 4355 if (sRef_isMacroParamRef (e->sref))
4356 {
4357 voptgenerror
4358 (FLG_MACROPARAMS,
4359 message ("Operand of %s is macro parameter (non-functional): %s",
4360 lltok_unparse (op), exprNode_unparse (ret)),
4361 e->loc);
4362 }
4363 else
4364 {
4365 exprNode_checkSet (ret, e->sref);
4366 }
4367
4368 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4369 {
4370 }
4371 else
4372 {
4373 if (context_msgStrictOps ())
4374 {
4375 voptgenerror
4376 (FLG_STRICTOPS,
4377 message ("Operand of %s is non-numeric (%t): %s",
4378 lltok_unparse (op), te, exprNode_unparse (ret)),
4379 e->loc);
4380 }
4381 ret->typ = ctype_int;
4382 }
4383
4384 /* start modifications */
4385 /* added by Seejo on 4/16/2000 */
4386
4387 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4388 status */
4389 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4390
4391 ret->sref = sRef_copy (e->sref);
4392
4393 /* Operator : ++ */
4394 if (lltok_getTok (op) == INC_OP) {
4395 if (sRef_getSize(e->sref) > 0) {
4396
4397 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4398
4399 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4400 /* Assumption: there is only 1 \0 in the buffer */
4401 /* This will not be correct if there are 2 \0's in the buffer */
4402 sRef_setNotNullTerminatedState(ret->sref);
4403 sRef_resetLen (ret->sref);
4404 } else {
4405 sRef_setNullTerminatedState(ret->sref);
4406 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4407 }
4408 }
4409 }
4410
4411 /* Operator : -- */
4412 if (lltok_getTok (op) == DEC_OP) {
4413 if (sRef_getSize(e->sref) >= 0) {
4414 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4415 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4416 }
4417 }
4418 }
4419
4420 /* end modifications */
4421
4422 checkMod = TRUE;
4423 break;
4424
4425 case TMINUS:
4426 case TPLUS:
4427 if (ctype_isForceRealNumeric (&tr))
4428 {
4429 if (opid == TMINUS)
4430 {
4431 ret->val = multiVal_invert (exprNode_getValue (e));
4432 }
4433 else
4434 {
4435 ret->val = multiVal_copy (exprNode_getValue (e));
4436 }
4437 }
4438 else
4439 {
4440 if (context_msgStrictOps ())
4441 {
4442 voptgenerror
4443 (FLG_STRICTOPS,
4444 message ("Operand of %s is non-numeric (%t): %s",
4445 lltok_unparse (op), te, exprNode_unparse (ret)),
4446 e->loc);
4447 }
4448
4449 ret->typ = ctype_int;
4450 }
4451 break;
4452
4453 case TEXCL: /* maybe this should be restricted */
4454 guardSet_flip (ret->guards);
4455
28bf4b0b 4456 if (ctype_isRealBool (te) || ctype_isUnknown (te))
616915dd 4457 {
4458 ;
4459 }
4460 else
4461 {
4462 if (ctype_isRealPointer (tr))
4463 {
4464 if (sRef_isKnown (e->sref))
4465 {
4466 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4467 }
28bf4b0b 4468
616915dd 4469 voptgenerror2n
4470 (FLG_BOOLOPS, FLG_PTRNEGATE,
4471 message ("Operand of %s is non-boolean (%t): %s",
4472 lltok_unparse (op), te, exprNode_unparse (ret)),
4473 e->loc);
4474 }
4475 else
4476 {
4477 voptgenerror
4478 (FLG_BOOLOPS,
4479 message ("Operand of %s is non-boolean (%t): %s",
4480 lltok_unparse (op), te, exprNode_unparse (ret)),
4481 e->loc);
4482 }
4483
4484 ret->typ = ctype_bool;
4485 }
4486 break;
4487
4488 case TTILDE:
4489 if (ctype_isForceRealInt (&tr))
4490 {
4491 }
4492 else
4493 {
4494 if (context_msgStrictOps ())
4495 {
4496 voptgenerror
4497 (FLG_STRICTOPS,
4498 message ("Operand of %s is non-integer (%t): %s",
4499 lltok_unparse (op), te, exprNode_unparse (ret)),
4500 e->loc);
4501 }
4502
4503 if (ctype_isInt (e->typ))
4504 {
4505 ret->typ = e->typ;
4506 }
4507 else
4508 {
4509 ret->typ = ctype_int;
4510 }
4511 }
4512 break;
4513
4514 case TAMPERSAND:
4515 ret->typ = ctype_makePointer (e->typ);
4516
4517 if (sRef_isKnown (e->sref))
4518 {
4519 ret->sref = sRef_makeAddress (e->sref);
4520 }
4521
4522 break;
4523
4524 case TMULT:
4525
4526 if (ctype_isAP (tr))
4527 {
4528 ret->typ = ctype_baseArrayPtr (e->typ);
4529 }
4530 else
4531 {
4532 if (ctype_isKnown (te))
4533 {
4534 if (ctype_isFunction (te))
4535 {
4536 ret->typ = e->typ;
4537
4538 voptgenerror
4539 (FLG_FCNDEREF,
4540 message ("Dereference of function type (%t): %s",
4541 te, exprNode_unparse (ret)),
4542 e->loc);
4543 }
4544 else
4545 {
4546 voptgenerror (FLG_TYPE,
4547 message ("Dereference of non-pointer (%t): %s",
4548 te, exprNode_unparse (ret)),
4549 e->loc);
4550 ret->typ = ctype_unknown;
4551 }
4552 }
4553 else
4554 {
4555 ret->typ = ctype_unknown;
4556 }
4557
4558 }
4559
4560 if (sRef_isKnown (e->sref))
4561 {
4562 if (sRef_possiblyNull (e->sref))
4563 {
4564 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4565 {
4566 if (optgenerror
4567 (FLG_NULLDEREF,
4568 message ("Dereference of %s pointer %q: %s",
4569 sRef_nullMessage (e->sref),
4570 sRef_unparse (e->sref),
4571 exprNode_unparse (ret)),
4572 e->loc))
4573 {
4574 sRef_showNullInfo (e->sref);
4575 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4576 }
4577 }
4578 }
4579
4580 ret->sref = sRef_makePointer (e->sref);
4581 }
4582 break;
4583
4584 default:
4585 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4586 }
4587
4588 if (checkMod)
4589 {
4590 exprNode_checkModify (e, ret);
4591 }
4592
4593 return ret;
4594}
4595
4596/*
4597** any reason to disallow sizeof (abstract type) ?
4598*/
4599
4600/*
4601** used by both sizeof
4602*/
4603
4604static
4605ctype sizeof_resultType (void)
4606{
4607 static ctype sizet = ctype_unknown;
4608
4609 if (ctype_isUnknown (sizet))
4610 {
4611 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4612 {
4613 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4614 }
4615 else
4616 {
4617 sizet = ctype_ulint;
4618 }
4619 }
4620 return sizet;
4621}
4622
4623exprNode
4624exprNode_sizeofType (/*@only@*/ qtype qt)
4625{
4626 exprNode ret = exprNode_create (sizeof_resultType ());
4627 ctype ct = qtype_getType (qt);
4628
4629 ret->kind = XPR_SIZEOFT;
4630 ret->edata = exprData_makeSizeofType (qt);
4631
4632 voptgenerror (FLG_SIZEOFTYPE,
4633 message ("Parameter to sizeof is type %s: %s",
4634 ctype_unparse (ct),
4635 exprNode_unparse (ret)),
4636 ret->loc);
4637
4638 return (ret);
4639}
4640
4641exprNode
4642exprNode_alignofType (/*@only@*/ qtype qt)
4643{
4644 exprNode ret = exprNode_create (sizeof_resultType ());
4645 ctype ct = qtype_getType (qt);
4646
4647 ret->kind = XPR_ALIGNOFT;
4648 ret->edata = exprData_makeSizeofType (qt);
4649
4650 voptgenerror (FLG_SIZEOFTYPE,
4651 message ("Parameter to alignof is type %s: %s",
4652 ctype_unparse (ct),
4653 exprNode_unparse (ret)),
4654 ret->loc);
4655
4656 return (ret);
4657}
4658
4659exprNode exprNode_offsetof (qtype qt, cstringList s)
4660{
4661 exprNode ret = exprNode_create (sizeof_resultType ());
4662 ctype ct = qtype_getType (qt);
4663
4664 ret->kind = XPR_OFFSETOF;
4665 ret->edata = exprData_makeOffsetof (qt, s);
4666
4667 if (!ctype_isRealSU (ct))
4668 {
4669 voptgenerror (FLG_TYPE,
4670 message ("First parameter to offsetof is not a "
4671 "struct or union type (type %s): %s",
4672 ctype_unparse (ct),
4673 exprNode_unparse (ret)),
4674 ret->loc);
4675 }
4676 else
4677 {
4678 ctype lt = ct;
4679
4680 cstringList_elements (s, el) {
4681 uentryList fields;
4682 uentry fld;
4683
4684 if (ctype_isUndefined (lt))
4685 {
4686 break;
4687 }
4688 else if (!ctype_isRealSU (lt))
4689 {
4690 voptgenerror (FLG_TYPE,
4691 message ("Inner offsetof type is not a "
4692 "struct or union type (type %s before field %s): %s",
4693 ctype_unparse (lt), el,
4694 exprNode_unparse (ret)),
4695 ret->loc);
4696 break;
4697 }
4698 else
4699 {
4700 fields = ctype_getFields (ctype_realType (lt));
4701 fld = uentryList_lookupField (fields, el);
4702 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4703
4704 if (uentry_isUndefined (fld))
4705 {
4706 if (ctype_equal (lt, ct)) {
4707 voptgenerror (FLG_TYPE,
4708 message ("Field %s in offsetof is not the "
4709 "name of a field of %s: %s",
4710 el,
4711 ctype_unparse (ct),
4712 exprNode_unparse (ret)),
4713 ret->loc);
4714 } else {
4715 voptgenerror (FLG_TYPE,
4716 message ("Deep field %s in offsetof is not the "
4717 "name of a field of %s: %s",
4718 el,
4719 ctype_unparse (lt),
4720 exprNode_unparse (ret)),
4721 ret->loc);
4722 }
4723 }
4724 else
4725 {
4726 lt = uentry_getType (fld);
4727 }
4728 }
4729 } end_cstringList_elements;
4730
4731 /* Should report error if its a bit field - behavior is undefined! */
4732 }
4733
4734 return (ret);
4735}
4736
4737/*@only@*/ exprNode
4738exprNode_sizeofExpr (/*@only@*/ exprNode e)
4739{
4740 exprNode ret;
4741
4742 if (exprNode_isUndefined (e))
4743 {
4744 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4745 ret->edata = exprData_makeSingle (e);
4746 ret->typ = sizeof_resultType ();
4747 ret->kind = XPR_SIZEOF;
4748 }
4749 else
4750 {
4751 uentry u = exprNode_getUentry (e);
4752
4753 ret = exprNode_createPartialCopy (e);
4754 ret->edata = exprData_makeSingle (e);
4755
4756 ret->typ = sizeof_resultType ();
4757 ret->kind = XPR_SIZEOF;
4758
4759 if (uentry_isValid (u)
4760 && uentry_isRefParam (u)
4761 && ctype_isRealArray (uentry_getType (u)))
4762 {
4763 voptgenerror
4764 (FLG_SIZEOFFORMALARRAY,
4765 message ("Parameter to sizeof is an array-type function parameter: %s",
4766 exprNode_unparse (ret)),
4767 ret->loc);
4768 }
4769 }
4770
4771 /*
4772 ** sizeof (x) doesn't "really" use x
4773 */
4774
4775 return (ret);
4776}
4777
4778/*@only@*/ exprNode
4779exprNode_alignofExpr (/*@only@*/ exprNode e)
4780{
4781 exprNode ret;
4782
4783 if (exprNode_isUndefined (e))
4784 {
4785 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4786 }
4787 else
4788 {
4789 ret = exprNode_createPartialCopy (e);
4790 }
4791
4792 ret->edata = exprData_makeSingle (e);
4793 ret->typ = sizeof_resultType ();
4794 ret->kind = XPR_ALIGNOF;
4795
4796 /*
4797 ** sizeof (x) doesn't "really" use x
4798 */
4799
4800 return (ret);
4801}
4802
4803/*@only@*/ exprNode
4804exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4805{
4806 ctype c;
4807 ctype t;
4808 exprNode ret;
4809
4810 if (exprNode_isError (e))
4811 {
4812 qtype_free (q);
4813 lltok_release (tok);
4814 return exprNode_undefined;
4815 }
4816
4817 checkMacroParen (e);
4818
4819 c = qtype_getType (q);
4820 t = exprNode_getType (e);
4821
4822 ret = exprNode_createPartialCopy (e);
4823
4824 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4825 ret->typ = c;
4826 ret->kind = XPR_CAST;
4827 ret->edata = exprData_makeCast (tok, e, q);
4828
4829 if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
4830 {
4831 /*
4832 ** This is a bit of a hack to avoid a problem
4833 ** when the code does,
4834 ** (some other struct) x
4835 ** ...
4836 ** x->field
4837 */
4838
4839 ret->sref = sRef_copy (e->sref);
4840 usymtab_addForceMustAlias (ret->sref, e->sref);
4841 sRef_setTypeFull (ret->sref, c);
4842 DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
4843 sRef_unparseFull (ret->sref)));
4844 }
4845 else
4846 {
4847 ret->sref = e->sref;
4848 sRef_setTypeFull (ret->sref, c);
4849 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
4850 }
4851
4852 /*
4853 ** we allow
4854 ** abstract -> void
4855 ** 0 <-> abstract *
4856 ** void * <-> abstract * (if FLG_ABSTVOIDP)
4857 ** abstract * <-> void * (if FLG_ABSTVOIDP)
4858 */
4859
4860 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
4861 {
4862 ;
4863 }
4864 else if (ctype_isRealAP (c)) /* casting to array or pointer */
4865 {
4866 ctype bc = ctype_getBaseType (c);
4867 ctype bt = ctype_getBaseType (t);
4868 ctype rt = ctype_realType (t);
4869
4870 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
4871 && (ctype_isArrayPtr (rt)
4872 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4873 {
4874 voptgenerror
4875 (FLG_CASTFCNPTR,
4876 message ("Cast from function pointer type (%t) to "
4877 "non-function pointer (%t): %s",
4878 c, t, exprNode_unparse (ret)),
4879 e->loc);
4880 }
4881
4882 if (!ctype_isFunction (ctype_baseArrayPtr (c))
4883 && (ctype_isArrayPtr (rt)
4884 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4885 {
4886 voptgenerror
4887 (FLG_CASTFCNPTR,
4888 message ("Cast from non-function pointer type (%t) to "
4889 "function pointer (%t): %s",
4890 c, t, exprNode_unparse (ret)),
4891 e->loc);
4892 }
4893
4894 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
4895 !(ctype_isRealAbstract (bc)
4896 && context_hasAccess (ctype_typeId (bc))))
4897 {
4898 ; /* okay to cast zero */
4899 }
4900 else
4901 {
4902 if (ctype_isRealAbstract (bc)
4903 && !context_hasAccess (ctype_typeId (bc)))
4904 {
4905 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
4906 {
4907 vnoptgenerror
4908 (FLG_ABSTVOIDP,
4909 message ("Cast to underlying abstract type %t: %s",
4910 c, exprNode_unparse (ret)),
4911 e->loc);
4912 }
4913 else
4914 {
4915 voptgenerror
4916 (FLG_ABSTRACT,
4917 message ("Cast to underlying abstract type %t: %s",
4918 c, exprNode_unparse (ret)),
4919 e->loc);
4920 }
4921 }
4922
4923 if (ctype_isRealAbstract (bt)
4924 && !context_hasAccess (ctype_typeId (bt)))
4925 {
4926 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
4927 {
4928 vnoptgenerror
4929 (FLG_ABSTVOIDP,
4930 message ("Cast from underlying abstract type %t: %s",
4931 t, exprNode_unparse (ret)),
4932 e->loc);
4933 }
4934 else
4935 {
4936 voptgenerror
4937 (FLG_ABSTRACT,
4938 message ("Cast from underlying abstract type %t: %s",
4939 t, exprNode_unparse (ret)),
4940 e->loc);
4941 }
4942 }
4943 }
4944 }
4945 else
4946 {
4947 ctype bt = ctype_realType (ctype_getBaseType (t));
4948 ctype bc = ctype_realType (ctype_getBaseType (c));
4949
4950 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
4951 {
4952 if (ctype_match (c, t))
4953 {
4954 if (ctype_equal (c, t))
4955 {
4956 voptgenerror
4957 (FLG_TYPE,
4958 message ("Redundant cast involving abstract type %t: %s",
4959 bt, exprNode_unparse (ret)),
4960 e->loc);
4961 }
4962 }
4963 else
4964 {
4965 voptgenerror
4966 (FLG_ABSTRACT,
4967 message ("Cast from abstract type %t: %s",
4968 bt, exprNode_unparse (ret)),
4969 e->loc);
4970 }
4971 }
4972
4973 if (ctype_isAbstract (bc)
4974 && !context_hasAccess (ctype_typeId (bc)))
4975 {
4976 if (ctype_match (c, t))
4977 {
4978 ;
4979 }
4980 else
4981 {
28bf4b0b 4982 DPRINTF (("No access to: %s / %d",
4983 ctype_unparse (bc), ctype_typeId (bc)));
4984 DPRINTF (("Context %s %s",
4985 bool_unparse (context_inFunctionLike ()),
4986 context_unparse ()));
616915dd 4987 voptgenerror
4988 (FLG_ABSTRACT,
4989 message ("Cast to abstract type %t: %s", bc,
4990 exprNode_unparse (ret)),
4991 e->loc);
4992 }
4993 }
4994 }
4995
4996 if (ctype_isAbstract (c))
4997 {
4998 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
4999 {
5000 /* okay, cast exposed to abstract */
5001 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
5002 }
5003 else
5004 {
5005 if (ctype_isVisiblySharable (t)
5006 && sRef_isExternallyVisible (e->sref)
5007 && !(ctype_isAbstract (t)
5008 && context_hasAccess (ctype_typeId (t))))
5009 {
5010 voptgenerror
5011 (FLG_CASTEXPOSE,
5012 message ("Cast to abstract type from externally visible "
5013 "mutable storage exposes rep of %s: %s",
5014 ctype_unparse (c),
5015 exprNode_unparse (e)),
5016 e->loc);
5017 }
5018 }
5019 }
5020
5021 return (ret);
5022}
5023
5024static bool
5025evaluationOrderUndefined (lltok op)
5026{
5027 int opid = lltok_getTok (op);
5028
5029 return (opid != AND_OP && opid != OR_OP);
5030}
5031
5032static bool checkIntegral (/*@notnull@*/ exprNode e1,
5033 /*@notnull@*/ exprNode e2,
5034 /*@notnull@*/ exprNode ret,
5035 lltok op)
5036{
5037 bool error = FALSE;
5038
5039 ctype te1 = exprNode_getType (e1);
5040 ctype te2 = exprNode_getType (e2);
5041
5042 ctype tr1 = ctype_realishType (te1);
5043 ctype tr2 = ctype_realishType (te2);
5044
5045 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5046 {
5047 ;
5048 }
5049 else
5050 {
5051 if (context_msgStrictOps ())
5052 {
5053 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5054 {
5055 if (ctype_sameName (te1, te2))
5056 {
5057 error = optgenerror
5058 (FLG_STRICTOPS,
5059 message ("Operands of %s are non-integer (%t): %s",
5060 lltok_unparse (op), te1,
5061 exprNode_unparse (ret)),
5062 e1->loc);
5063 }
5064 else
5065 {
5066 error = optgenerror
5067 (FLG_STRICTOPS,
5068 message ("Operands of %s are non-integers (%t, %t): %s",
5069 lltok_unparse (op), te1, te2,
5070 exprNode_unparse (ret)),
5071 e1->loc);
5072 }
5073 }
5074 else if (!ctype_isInt (tr1))
5075 {
5076 error = optgenerror
5077 (FLG_STRICTOPS,
5078 message ("Left operand of %s is non-integer (%t): %s",
5079 lltok_unparse (op), te1, exprNode_unparse (ret)),
5080 e1->loc);
5081 }
5082 else
5083 /* !ctype_isInt (te2) */
5084 {
5085 error = optgenerror
5086 (FLG_STRICTOPS,
5087 message ("Right operand of %s is non-integer (%t): %s",
5088 lltok_unparse (op), te2, exprNode_unparse (ret)),
5089 e2->loc);
5090 }
5091 }
5092 }
5093
5094 return !error;
5095}
5096
5097/*
5098** returns exprNode representing e1 op e2
5099**
5100** uses msg if there are errors
5101** can be used for both assignment ops and regular ops
5102**
5103** modifies e1
5104*/
5105
5106static /*@only@*/ /*@notnull@*/ exprNode
5107exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
5108 /*@keep@*/ lltok op)
5109{
5110 ctype te1, te2, tr1, tr2, tret;
5111 int opid = lltok_getTok (op);
5112 bool hasError = FALSE;
5113 exprNode ret;
5114
5115 if (exprNode_isError (e1))
5116 {
5117 ret = exprNode_createPartialNVCopy (e2);
5118 }
5119 else
5120 {
5121 ret = exprNode_createPartialNVCopy (e1);
5122 }
5123
5124 ret->val = multiVal_undefined;
5125 ret->kind = XPR_OP;
5126 ret->edata = exprData_makeOp (e1, e2, op);
5127
5128 if (exprNode_isError (e1) || exprNode_isError (e2))
5129 {
5130 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5131 || opid == EQ_OP || opid == NE_OP
5132 || opid == AND_OP || opid == OR_OP)
5133 {
5134 ret->typ = ctype_bool;
5135 }
5136
5137 if (exprNode_isDefined (e1))
5138 {
5139 exprNode_checkUse (ret, e1->sref, e1->loc);
5140 }
5141
5142 if (exprNode_isDefined (e2))
5143 {
5144 exprNode_mergeUSs (ret, e2);
5145 exprNode_checkUse (ret, e2->sref, e2->loc);
5146 }
5147
5148 return ret;
5149 }
5150
5151 tret = ctype_unknown;
5152 te1 = exprNode_getType (e1);
5153 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5154
5155 te2 = exprNode_getType (e2);
5156
5157 tr1 = ctype_realishType (te1);
5158 tr2 = ctype_realishType (te2);
5159
5160 if (opid == OR_OP)
5161 {
5162 ret->guards = guardSet_or (ret->guards, e2->guards);
5163 }
5164 else if (opid == AND_OP)
5165 {
5166 ret->guards = guardSet_and (ret->guards, e2->guards);
5167 }
5168 else
5169 {
5170 /* no guards */
5171 }
5172
5173 if (opid == EQ_OP || opid == NE_OP)
5174 {
5175 exprNode temp1 = e1, temp2 = e2;
5176
5177 /* could do NULL == x */
5178
5179 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5180 {
5181 temp1 = e2; temp2 = e1;
5182 }
5183
5184 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5185 {
5186 reflectNullTest (temp1, (opid == NE_OP));
5187 guardSet_free (ret->guards);
5188 ret->guards = guardSet_copy (temp1->guards);
5189 }
5190 }
5191
5192 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5193 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5194 {
5195 tret = ctype_bool;
5196 }
5197
5198 if (anyAbstract (tr1, tr2) &&
5199 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
5200 (opid == AND_OP || opid == OR_OP
5201 || opid == EQ_OP || opid == NE_OP))))
5202 {
5203 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
5204 }
5205 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5206 {
5207 /* unknown types, no comparisons possible */
5208 }
5209 else
5210 {
5211 switch (opid)
5212 {
5213 case TMULT: /* multiplication and division: */
5214 case TDIV: /* */
5215 case MUL_ASSIGN: /* numeric, numeric -> numeric */
5216 case DIV_ASSIGN: /* */
5217
5218 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5219 break;
5220
5221 case TPLUS: /* addition and subtraction: */
5222 case TMINUS: /* pointer, int -> pointer */
5223 case SUB_ASSIGN: /* int, pointer -> pointer */
5224 case ADD_ASSIGN: /* numeric, numeric -> numeric */
5225
5226 tr1 = ctype_fixArrayPtr (tr1);
5227
5228 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5229 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5230 {
5231 /* pointer + int */
5232
5233 if (context_msgPointerArith ())
5234 {
5235 voptgenerror
5236 (FLG_POINTERARITH,
5237 message ("Pointer arithmetic (%t, %t): %s",
5238 te1, te2, exprNode_unparse (ret)),
5239 e1->loc);
5240 }
5241
ccf0a4a8 5242 /*
5243 ** Swap terms so e1 is always the pointer
5244 */
5245
5246 if (ctype_isRealPointer (tr1))
5247 {
5248 ;
5249 }
5250 else
5251 {
5252 exprNode_swap (e1, e2);
5253 }
5254
5255
616915dd 5256 if (sRef_possiblyNull (e1->sref)
5257 && !usymtab_isGuarded (e1->sref))
5258 {
5259 voptgenerror
5260 (FLG_NULLPOINTERARITH,
5261 message ("Pointer arithmetic involving possibly "
5262 "null pointer %s: %s",
5263 exprNode_unparse (e1),
5264 exprNode_unparse (ret)),
5265 e1->loc);
5266 }
5267
5268 ret->sref = sRef_copy (e1->sref);
5269
ccf0a4a8 5270 /* start modifications */
5271 /* added by Seejo on 4/16/2000 */
616915dd 5272
ccf0a4a8 5273 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5274 status */
5275 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
616915dd 5276 //if (sRef_isKnown (e->sref)) {
5277 //ret->sref = sRef_makeAddress (e->sref);
5278 //}
ccf0a4a8 5279
5280 int val;
5281 /*drl 1-4-2001
5282 added ugly fixed to stop
5283 program from crashing on point + int +int
5284 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5285
5286 if (!multiVal_isInt (e2->val) )
5287 break;
5288 /*end drl*/
5289
5290 val = (int) multiVal_forceInt (e2->val);
5291
5292 /* Operator : + or += */
5293 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5294 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5295 val should not result in a
5296 size < 0 (size = 0 is ok !) */
5297
5298 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5299
5300 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5301 sRef_setNotNullTerminatedState(ret->sref);
5302 sRef_resetLen (ret->sref);
5303 } else {
5304 sRef_setNullTerminatedState(ret->sref);
5305 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5306 }
5307 }
5308 }
5309
5310 /* Operator : - or -= */
5311 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5312 if (sRef_getSize(e1->sref) >= 0) {
5313 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5314 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5315 }
5316 }
5317 }
616915dd 5318
ccf0a4a8 5319 /* end modifications */
616915dd 5320
5321 sRef_setNullError (ret->sref);
5322
5323 /*
5324 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5325 ** since is points to storage that should not be deallocated
5326 ** through this pointer.
5327 */
5328
5329 if (sRef_isOnly (ret->sref)
5330 || sRef_isFresh (ret->sref))
5331 {
5332 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5333 }
5334
5335 tret = e1->typ;
5336 }
5337 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5338 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5339 {
5340 if (context_msgPointerArith ())
5341 {
5342 voptgenerror
5343 (FLG_POINTERARITH,
5344 message ("Pointer arithmetic (%t, %t): %s",
5345 te1, te2, exprNode_unparse (ret)),
5346 e1->loc);
5347 }
5348
5349 if (sRef_possiblyNull (e1->sref)
5350 && !usymtab_isGuarded (e1->sref))
5351 {
5352 voptgenerror
5353 (FLG_NULLPOINTERARITH,
5354 message ("Pointer arithmetic involving possibly "
5355 "null pointer %s: %s",
5356 exprNode_unparse (e2),
5357 exprNode_unparse (ret)),
5358 e2->loc);
5359 }
5360
5361 ret->sref = sRef_copy (e2->sref);
5362
5363 /* start modifications */
5364 /* added by Seejo on 4/16/2000 */
5365
5366 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5367 status */
5368
5369 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5370 //if (sRef_isKnown (e->sref)) {
5371 //ret->sref = sRef_makeAddress (e->sref);
5372 //}
5373
5374 int val = (int) multiVal_forceInt (e1->val);
5375
5376 /* Operator : + or += */
5377 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5378 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5379 val should not result in a
5380 size < 0 (size = 0 is ok !) */
5381
5382 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5383
5384 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5385 sRef_setNotNullTerminatedState(ret->sref);
5386 sRef_resetLen (ret->sref);
5387 } else {
5388 sRef_setNullTerminatedState(ret->sref);
5389 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5390 }
5391 }
5392 }
5393
5394 /* Operator : - or -= */
5395 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5396 if (sRef_getSize(e2->sref) >= 0) {
5397 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5398 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5399 }
5400 }
5401 }
5402
5403 /* end modifications */
5404
5405 sRef_setNullError (ret->sref);
5406
5407 /*
5408 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5409 ** since is points to storage that should not be deallocated
5410 ** through this pointer.
5411 */
5412
5413 if (sRef_isOnly (ret->sref)
5414 || sRef_isFresh (ret->sref)) {
5415 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5416 }
5417
5418 tret = e2->typ;
5419 ret->sref = e2->sref;
5420 }
5421 else
5422 {
5423 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5424 }
5425
5426 break;
5427
5428 case LEFT_ASSIGN: /* Shifts: should be unsigned values */
5429 case RIGHT_ASSIGN:
5430 case LEFT_OP:
5431 case RIGHT_OP:
5432 case TAMPERSAND: /* bitwise & */
5433 case AND_ASSIGN:
5434 case TCIRC: /* ^ (XOR) */
5435 case TBAR:
5436 case XOR_ASSIGN:
5437 case OR_ASSIGN:
5438 {
5439 bool reported = FALSE;
5440 flagcode code = FLG_BITWISEOPS;
5441
5442 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5443 || opid == RIGHT_OP || opid == RIGHT_ASSIGN) {
5444 code = FLG_SHIFTSIGNED;
5445 }
5446
5447 if (!ctype_isUnsigned (tr1))
5448 {
5449 if (exprNode_isNonNegative (e1)) {
5450 ;
5451 } else {
5452 reported = optgenerror
5453 (code,
5454 message ("Left operand of %s is not unsigned value (%t): %s",
5455 lltok_unparse (op), te1,
5456 exprNode_unparse (ret)),
5457 e1->loc);
5458
5459 if (reported) {
5460 te1 = ctype_uint;
5461 }
5462 }
5463 }
5464 else
5465 {
5466 /* right need not be signed for shifts */
5467 if (code != FLG_SHIFTSIGNED
5468 && !ctype_isUnsigned (tr2))
5469 {
5470 if (!exprNode_isNonNegative (e2)) {
5471 reported = optgenerror
5472 (code,
5473 message ("Right operand of %s is not unsigned value (%t): %s",
5474 lltok_unparse (op), te2,
5475 exprNode_unparse (ret)),
5476 e2->loc);
5477 }
5478 }
5479 }
5480
5481 if (!reported)
5482 {
5483 if (!checkIntegral (e1, e2, ret, op)) {
5484 te1 = ctype_unknown;
5485 }
5486 }
5487
5488 DPRINTF (("Set: %s", ctype_unparse (te1)));
5489
5490 /*
5491 ** tret is the widest type of te1 and te2
5492 */
5493
5494 tret = ctype_widest (te1, te2);
5495 break;
5496 }
5497 case MOD_ASSIGN:
5498 case TPERCENT:
5499 if (checkIntegral (e1, e2, ret, op)) {
5500 tret = te1;
5501 } else {
5502 tret = ctype_unknown;
5503 }
5504 break;
5505 case EQ_OP:
5506 case NE_OP:
5507 case TLT: /* comparisons */
5508 case TGT: /* numeric, numeric -> bool */
5509 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5510 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5511 {
5512 ctype rtype = tr1;
5513 bool fepsilon = FALSE;
5514
5515 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5516 {
5517 rtype = tr2;
5518 }
5519
5520 if (opid == TLT || opid == TGT)
5521 {
5522 uentry ue1 = exprNode_getUentry (e1);
5523 uentry ue2 = exprNode_getUentry (e2);
5524
5525 /*
5526 ** FLT_EPSILON, etc. really is a variable, not
5527 ** a constant.
5528 */
5529
5530 if (uentry_isVariable (ue1))
5531 {
5532 cstring uname = uentry_rawName (ue1);
5533
5534 if (cstring_equalLit (uname, "FLT_EPSILON")
5535 || cstring_equalLit (uname, "DBL_EPSILON")
5536 || cstring_equalLit (uname, "LDBL_EPSILON"))
5537 {
5538 fepsilon = TRUE;
5539 }
5540 }
5541
5542 if (uentry_isVariable (ue2))
5543 {
5544 cstring uname = uentry_rawName (ue2);
5545
5546 if (cstring_equalLit (uname, "FLT_EPSILON")
5547 || cstring_equalLit (uname, "DBL_EPSILON")
5548 || cstring_equalLit (uname, "LDBL_EPSILON"))
5549 {
5550 fepsilon = TRUE;
5551 }
5552 }
5553 }
5554
5555 if (fepsilon)
5556 {
5557 ; /* Don't complain. */
5558 }
5559 else
5560 {
5561 voptgenerror
5562 (FLG_REALCOMPARE,
5563 message ("Dangerous comparison involving %s types: %s",
5564 ctype_unparse (rtype),
5565 exprNode_unparse (ret)),
5566 ret->loc);
5567 }
5568 }
5569 /*@fallthrough@*/
5570 case LE_OP:
5571 case GE_OP:
5572
5573 /*
5574 ** Types should match.
5575 */
5576
5577 if (!exprNode_matchTypes (e1, e2))
5578 {
5579 hasError = gentypeerror
5580 (te1, e1, te2, e2,
5581 message ("Operands of %s have incompatible types (%t, %t): %s",
5582 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5583 e1->loc);
5584
5585 }
5586
5587 if (hasError
5588 || (ctype_isForceRealNumeric (&tr1)
5589 && ctype_isForceRealNumeric (&tr2)) ||
5590 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5591 {
5592 ; /* okay */
5593 }
5594 else
5595 {
5596 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5597 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5598 {
5599 voptgenerror
5600 (FLG_PTRNUMCOMPARE,
5601 message ("Comparison of pointer and numeric (%t, %t): %s",
5602 te1, te2, exprNode_unparse (ret)),
5603 e1->loc);
5604 }
5605 else
5606 {
5607 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5608 }
5609 tret = ctype_bool;
5610 }
5611
5612 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5613
5614 if ((opid == EQ_OP || opid == NE_OP) &&
5615 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5616 {
5617 /*
5618 ** is one a variable?
5619 */
5620
5621 if (uentry_isVariable (exprNode_getUentry (e1))
5622 || uentry_isVariable (exprNode_getUentry (e2)))
5623 {
5624 /*
5625 ** comparisons with FALSE are okay
5626 */
5627
5628 if (exprNode_isFalseConstant (e1)
5629 || exprNode_isFalseConstant (e2))
5630 {
5631 ;
5632 }
5633 else
5634 {
5635 voptgenerror
5636 (FLG_BOOLCOMPARE,
5637 message
5638 ("Use of %q with %s variables (risks inconsistency because "
5639 "of multiple true values): %s",
5640 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5641 context_printBoolName (), exprNode_unparse (ret)),
5642 e1->loc);
5643 }
5644 }
5645 }
5646 break;
5647
5648 case AND_OP: /* bool, bool -> bool */
5649 case OR_OP:
5650
5651 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5652 {
5653 ;
5654 }
5655 else
5656 {
5657 if (context_maybeSet (FLG_BOOLOPS))
5658 {
5659 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5660 {
5661 if (ctype_sameName (te1, te2))
5662 {
5663 voptgenerror
5664 (FLG_BOOLOPS,
5665 message ("Operands of %s are non-boolean (%t): %s",
5666 lltok_unparse (op), te1,
5667 exprNode_unparse (ret)),
5668 e1->loc);
5669 }
5670 else
5671 {
5672 voptgenerror
5673 (FLG_BOOLOPS,
5674 message
5675 ("Operands of %s are non-booleans (%t, %t): %s",
5676 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5677 e1->loc);
5678 }
5679 }
5680 else if (!ctype_isRealBool (te1))
5681 {
5682 voptgenerror
5683 (FLG_BOOLOPS,
5684 message ("Left operand of %s is non-boolean (%t): %s",
5685 lltok_unparse (op), te1, exprNode_unparse (ret)),
5686 e1->loc);
5687 }
5688 else if (!ctype_isRealBool (te2))
5689 {
5690 voptgenerror
5691 (FLG_BOOLOPS,
5692 message ("Right operand of %s is non-boolean (%t): %s",
5693 lltok_unparse (op), te2, exprNode_unparse (ret)),
5694 e2->loc);
5695 }
5696 else
5697 {
5698 ;
5699 }
5700 }
5701 tret = ctype_bool;
5702 }
5703 break;
5704 default: {
5705 llfatalbug
5706 (cstring_makeLiteral
28bf4b0b 5707 ("There has been a problem in the parser. This is believed to result "
5708 "from a problem with bison v. 1.25. Please try rebuidling LCLint "
5709 "using the pre-compiled grammar files by commenting out the "
5710 "BISON= line in the top-level Makefile."));
616915dd 5711 }
5712 }
5713 }
5714
5715 DPRINTF (("Return type: %s", ctype_unparse (tret)));
5716 ret->typ = tret;
5717
5718 exprNode_checkUse (ret, e1->sref, e1->loc);
5719 exprNode_mergeUSs (ret, e2);
5720 exprNode_checkUse (ret, e2->sref, e2->loc);
5721
5722 return ret;
5723}
5724
5725/*@only@*/ exprNode
5726exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5727 /*@only@*/ lltok op)
5728{
5729 exprNode ret;
5730
5731 checkMacroParen (e1);
5732 checkMacroParen (e2);
5733
5734 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5735 {
5736 checkExpressionDefined (e1, e2, op);
5737 }
5738
5739 ret = exprNode_makeOp (e1, e2, op);
5740 return (ret);
5741}
5742
5743static
5744void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5745{
5746 /*
5747 ** This is somewhat bogus!
5748 **
5749 ** Assigning to a nested observer in a non-observer datatype
5750 ** should not produce an error.
5751 */
5752
5753 sRef ref = exprNode_getSref (e1);
5754
5755 DPRINTF (("Check assign mod: %s",
5756 sRef_unparseFull (ref)));
5757
5758 if (sRef_isObserver (ref)
28bf4b0b 5759 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
616915dd 5760 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5761 {
5762 sRef base = sRef_getBase (ref);
5763
5764 if (sRef_isValid (base) && sRef_isObserver (base))
5765 {
5766 exprNode_checkModify (e1, ret);
5767 }
5768 else
5769 {
5770 exprNode_checkModifyVal (e1, ret);
5771 }
5772 }
5773 else
5774 {
5775 exprNode_checkModify (e1, ret);
5776 }
5777}
5778
5779exprNode
5780exprNode_assign (/*@only@*/ exprNode e1,
5781 /*@only@*/ exprNode e2, /*@only@*/ lltok op)
5782{
5783 bool isalloc = FALSE;
5784 bool isjustalloc = FALSE;
5785 exprNode ret;
5786
5787 DPRINTF (("%s [%s] <- %s [%s]",
5788 exprNode_unparse (e1),
5789 ctype_unparse (e1->typ),
5790 exprNode_unparse (e2),
5791 ctype_unparse (e2->typ)));
5792
5793 if (lltok_getTok (op) != TASSIGN)
5794 {
5795 ret = exprNode_makeOp (e1, e2, op);
5796 }
5797 else
5798 {
5799 ret = exprNode_createPartialCopy (e1);
5800 ret->kind = XPR_ASSIGN;
5801 ret->edata = exprData_makeOp (e1, e2, op);
5802
5803 if (!exprNode_isError (e2))
5804 {
5805 ret->sets = sRefSet_union (ret->sets, e2->sets);
5806 ret->msets = sRefSet_union (ret->msets, e2->msets);
5807 ret->uses = sRefSet_union (ret->uses, e2->uses);
5808 }
5809 }
5810
5811 checkExpressionDefined (e1, e2, op);
5812
5813 if (exprNode_isError (e1))
5814 {
5815 if (!exprNode_isError (e2))
5816 {
5817 ret->loc = fileloc_update (ret->loc, e2->loc);
5818 }
5819 else
5820 {
5821 ret->loc = fileloc_update (ret->loc, g_currentloc);
5822 }
5823 }
5824
5825 if (!exprNode_isError (e2))
5826 {
5827 checkMacroParen (e2);
5828 }
5829
5830 if (exprNode_isDefined (e1))
5831 {
5832 if (sRef_isMacroParamRef (e1->sref))
5833 {
5834 if (context_inIterDef ())
5835 {
5836 uentry ue = sRef_getUentry (e1->sref);
5837
5838 if (uentry_isYield (ue))
5839 {
5840 ;
5841 }
5842 else
5843 {
5844 if (fileloc_isDefined (e1->loc))
5845 {
5846 voptgenerror
5847 (FLG_MACROPARAMS,
5848 message ("Assignment to non-yield iter parameter: %q",
5849 sRef_unparse (e1->sref)),
5850 e1->loc);
5851 }
5852 else
5853 {
5854 voptgenerror
5855 (FLG_MACROPARAMS,
5856 message ("Assignment to non-yield iter parameter: %q",
5857 sRef_unparse (e1->sref)),
5858 g_currentloc);
5859 }
5860 }
5861 }
5862 else
5863 {
5864 if (fileloc_isDefined (e1->loc))
5865 {
5866 voptgenerror
5867 (FLG_MACROASSIGN,
5868 message ("Assignment to macro parameter: %q",
5869 sRef_unparse (e1->sref)),
5870 e1->loc);
5871 }
5872 else
5873 {
5874 voptgenerror
5875 (FLG_MACROASSIGN,
5876 message ("Assignment to macro parameter: %q",
5877 sRef_unparse (e1->sref)),
5878 g_currentloc);
5879 }
ccf0a4a8 5880
5881 exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
616915dd 5882 }
5883 }
5884 else
5885 {
5886 exprNode_checkAssignMod (e1, ret);
5887 }
5888
5889 if (exprNode_isDefined (e2))
5890 {
5891 if (lltok_getTok (op) == TASSIGN)
5892 {
5893 ctype te1 = exprNode_getType (e1);
5894 ctype te2 = exprNode_getType (e2);
5895
5896 if (!ctype_forceMatch (te1, te2))
5897 {
5898 if (exprNode_matchLiteral (te1, e2))
5899 {
5900 ;
5901 }
5902 else
5903 {
5904 (void) gentypeerror
5905 (te2, e2, te1, e1,
5906 message ("Assignment of %t to %t: %s %s %s",
5907 te2, te1, exprNode_unparse (e1),
5908 lltok_unparse (op),
5909 exprNode_unparse (e2)),
5910 e1->loc);
5911 }
5912 }
5913 }
5914
5915 exprNode_mergeUSs (ret, e2);
5916 exprNode_checkUse (ret, e2->sref, e2->loc);
5917
5918 doAssign (e1, e2, FALSE);
5919 ret->sref = e1->sref;
5920 }
5921 else
5922 {
5923 if (exprNode_isDefined (e2))
5924 {
5925 exprNode_mergeUSs (ret, e2);
5926 exprNode_checkUse (ret, e2->sref, e2->loc);
5927 }
5928 }
5929
5930 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
5931 {
5932 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
5933 }
5934
5935 isjustalloc = sRef_isJustAllocated (e1->sref);
5936 isalloc = sRef_isAllocated (e1->sref);
5937
5938 if (sRef_isField (e1->sref))
5939 {
5940 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
5941
5942 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
5943 {
5944 exprNode_checkUse (ret, root, e1->loc);
5945 }
5946
5947 }
5948
5949 /*
5950 ** be careful! this defines e1->sref.
5951 */
ccf0a4a8 5952
5953 /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
5954
5955 exprNode_checkSet (ret, e1->sref);
616915dd 5956
5957 if (isjustalloc)
5958 {
5959 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
5960 ? e2->loc : e1->loc);
5961 }
5962 else
5963 {
5964 if (isalloc)
5965 {
5966 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
5967 }
5968 }
5969 }
5970
5971 return ret;
5972}
5973
5974exprNode
5975exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
5976 /*@keep@*/ exprNode elseclause)
5977{
5978 exprNode ret;
5979
5980 if (!exprNode_isError (pred))
5981 {
5982 ret = exprNode_createPartialCopy (pred);
5983 checkMacroParen (pred);
5984 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
5985
5986 if (!exprNode_isError (ifclause))
5987 {
5988 checkMacroParen (ifclause); /* update macro counts! */
5989
5990 if (!exprNode_isError (elseclause))
5991 {
5992 checkMacroParen (elseclause);
5993
5994 if (!exprNode_matchTypes (ifclause, elseclause))
5995 {
5996 if (gentypeerror
5997 (exprNode_getType (ifclause),
5998 ifclause,
5999 exprNode_getType (elseclause),
6000 elseclause,
6001 message ("Conditional clauses are not of same type: "
6002 "%s (%t), %s (%t)",
6003 exprNode_unparse (ifclause),
6004 exprNode_getType (ifclause),
6005 exprNode_unparse (elseclause),
6006 exprNode_getType (elseclause)),
6007 ifclause->loc))
6008 {
6009 ret->sref = sRef_undefined;
6010 ret->typ = ctype_unknown;
6011 }
6012 }
6013 else
6014 {
6015 /* for now...should merge the states */
6016 ret->sref = ifclause->sref;
6017 ret->typ = ifclause->typ;
6018
6019 if (exprNode_isNullValue (ifclause))
6020 {
6021 ret->typ = elseclause->typ;
6022 }
6023 }
6024
6025 exprNode_checkUse (ret, pred->sref, pred->loc);
6026 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6027 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6028
6029 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6030
6031 }
6032 else
6033 {
6034 ret->typ = ifclause->typ;
6035
6036 exprNode_checkUse (pred, pred->sref, pred->loc);
6037 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6038
6039 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6040 }
6041 }
6042 else
6043 {
6044 if (!exprNode_isError (elseclause))
6045 {
6046 ret->typ = elseclause->typ;
6047
6048 exprNode_checkUse (pred, pred->sref, pred->loc);
6049 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6050
6051 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6052 }
6053 }
6054 }
6055 else /* pred is error */
6056 {
6057 if (!exprNode_isError (ifclause))
6058 {
6059 ret = exprNode_createSemiCopy (ifclause);
6060
6061 checkMacroParen (ifclause); /* update macro counts! */
6062
6063 if (!exprNode_isError (elseclause))
6064 {
6065 checkMacroParen (elseclause);
6066
6067 ret->typ = ifclause->typ;
6068
6069 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6070 {
6071 if (gentypeerror
6072 (exprNode_getType (ifclause),
6073 ifclause,
6074 exprNode_getType (elseclause),
6075 elseclause,
6076 message ("Conditional clauses are not of same type: "
6077 "%s (%t), %s (%t)",
6078 exprNode_unparse (ifclause),
6079 exprNode_getType (ifclause),
6080 exprNode_unparse (elseclause),
6081 exprNode_getType (elseclause)),
6082 ifclause->loc))
6083 {
6084 ret->typ = ctype_unknown;
6085 }
6086 }
6087
6088 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6089 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6090
6091 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6092 }
6093 }
6094 else if (!exprNode_isError (elseclause)) /* pred, if errors */
6095 {
6096 ret = exprNode_createSemiCopy (ifclause);
6097
6098 ret->typ = elseclause->typ;
6099 checkMacroParen (elseclause);
6100
6101 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6102 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6103 }
6104 else /* all errors! */
6105 {
7ebcc5bb 6106 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
616915dd 6107 }
6108 }
6109
6110 ret->kind = XPR_COND;
6111 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
6112
6113 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6114 {
6115 exprNode_combineControl (ret, ifclause, elseclause);
6116 }
6117
6118 return (ret);
6119}
6120
6121exprNode
6122exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6123{
6124 ctype totype = qtype_getType (qt);
6125 exprNode ret =
6126 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6127 ctype targ;
6128
6129 /*
6130 ** check use of va_arg : <valist>, type -> type
6131 */
6132
6133 if (exprNode_isError (arg))
6134 {
6135 }
6136 else
6137 {
6138 targ = exprNode_getType (arg);
6139
6140 /*
6141 ** arg should have be a pointer
6142 */
6143
6144 if (!ctype_isUA (targ) ||
6145 (!usymId_equal (ctype_typeId (targ),
6146 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6147 {
6148 voptgenerror
6149 (FLG_TYPE,
6150 message ("First argument to va_arg is not a va_list (type %t): %s",
6151 targ, exprNode_unparse (arg)),
6152 arg->loc);
6153 }
6154
6155 exprNode_checkSet (ret, arg->sref);
6156 }
6157
6158 /*
6159 ** return type is totype
6160 */
6161
6162 ret->typ = totype;
6163 ret->kind = XPR_VAARG;
6164 ret->edata = exprData_makeCast (tok, arg, qt);
6165
6166 return (ret);
6167}
6168
6169exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6170{
6171 exprNode ret = exprNode_createPlain (ctype_undefined);
6172 ret->kind = XPR_LABEL;
6173 ret->edata = exprData_makeLiteral (label);
6174 ret->isJumpPoint = TRUE;
6175
6176 return (ret); /* for now, ignore label */
6177}
6178
6179exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6180{
6181 if (exprNode_isDefined (stmt))
6182 {
6183 stmt->isJumpPoint = TRUE;
6184
6185 /* This prevent stray no return path errors, etc. */
6186 stmt->exitCode = XK_MUSTEXIT;
6187 }
6188
6189 return (stmt);
6190}
6191
6192bool exprNode_isDefaultMarker (exprNode e)
6193{
6194 if (exprNode_isDefined (e))
6195 {
6196 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6197 }
6198
6199 return FALSE;
6200}
6201
6202bool exprNode_isCaseMarker (exprNode e)
6203{
6204 if (exprNode_isDefined (e))
6205 {
6206 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6207 }
6208
6209 return FALSE;
6210}
6211
6212bool exprNode_isLabelMarker (exprNode e)
6213{
6214 if (exprNode_isDefined (e))
6215 {
6216 return (e->kind == XPR_LABEL);
6217 }
6218
6219 return FALSE;
6220}
6221
6222exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6223{
6224 exprNode ret = exprNode_createPartialCopy (test);
6225
6226 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6227
6228 if (exprNode_isError (test)) {
6229 return ret;
6230 }
6231
6232 exprNode_checkUse (ret, test->sref, test->loc);
6233
6234 usymtab_setExitCode (ret->exitCode);
6235
6236 if (ret->mustBreak)
6237 {
6238 usymtab_setMustBreak ();
6239 }
6240
6241 ret->edata = exprData_makeSingle (test);
6242 ret->isJumpPoint = TRUE;
6243
6244 return ret;
6245}
6246
6247# if 0
6248exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6249{
6250 exprNode ret = exprNode_createPartialCopy (test);
6251
6252 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6253 ret->edata = exprData_makePair (test, stmt);
6254 ret->isJumpPoint = TRUE;
6255
6256 if (exprNode_isError (test))
6257 {
6258 return ret;
6259 }
6260
6261 exprNode_checkUse (ret, test->sref, test->loc);
6262
6263 if (exprNode_isError (stmt))
6264 {
6265 return ret;
6266 }
6267
6268 exprNode_mergeUSs (ret, stmt);
6269
6270 ret->exitCode = stmt->exitCode;
6271 ret->mustBreak = stmt->mustBreak;
6272 ret->canBreak = stmt->canBreak;
6273
6274 usymtab_setExitCode (ret->exitCode);
6275
6276 if (ret->mustBreak)
6277 {
6278 usymtab_setMustBreak ();
6279 }
6280
6281 return ret;
6282}
6283# endif
6284
6285/*@notnull@*/ /*@only@*/ exprNode
6286exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6287{
6288 exprNode ret = exprNode_createTok (def);
6289
6290 ret->isJumpPoint = TRUE;
6291 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6292 return (ret);
6293}
6294
6295bool
6296exprNode_mayEscape (exprNode e)
6297{
6298 if (exprNode_isDefined (e))
6299 {
6300 return exitkind_couldEscape (e->exitCode);
6301 }
6302 return FALSE;
6303}
6304
6305static bool
6306exprNode_mustBreak (exprNode e)
6307{
6308 if (exprNode_isDefined (e))
6309 {
6310 return e->mustBreak;
6311 }
6312 return FALSE;
6313}
6314
6315bool
6316exprNode_mustEscape (exprNode e)
6317{
6318 if (exprNode_isDefined (e))
6319 {
6320 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6321 }
6322
6323 return FALSE;
6324}
6325
6326bool
6327exprNode_errorEscape (exprNode e)
6328{
6329 if (exprNode_isDefined (e))
6330 {
6331 return exitkind_isError (e->exitCode);
6332 }
6333
6334 return FALSE;
6335}
6336
6337exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6338{
6339 exprNode ret = exprNode_createPartialCopy (e1);
6340
28bf4b0b 6341 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6342
616915dd 6343 ret->edata = exprData_makePair (e1, e2);
6344 ret->kind = XPR_STMTLIST;
6345
6346 if (exprNode_isDefined (e1))
6347 {
6348 ret->isJumpPoint = e1->isJumpPoint;
6349 ret->canBreak = e1->canBreak;
6350 }
6351 else
6352 {
6353 if (exprNode_isDefined (e2))
6354 {
6355 ret->loc = fileloc_update (ret->loc, e2->loc);
6356 }
6357 }
6358
6359 if (exprNode_isDefined (e2))
6360 {
6361 ret->exitCode = e2->exitCode;
6362 ret->mustBreak = e2->mustBreak;
6363 if (e2->canBreak) ret->canBreak = TRUE;
6364 }
6365
6366 /*
6367 ** if e1 must return, then e2 is unreachable!
6368 */
6369
6370 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6371 {
6372 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6373 && !(e2->isJumpPoint))
6374 {
6375 if (context_getFlag (FLG_UNREACHABLE))
6376 {
6377 exprNode nr = e2;
6378
6379 if (e2->kind == XPR_STMT)
6380 {
6381 nr = exprData_getUopNode (e2->edata);
6382 }
6383
6384 if ((nr->kind == XPR_TOK
6385 && lltok_isSemi (exprData_getTok (nr->edata))))
6386 {
6387 /* okay to have unreachable ";" */
6388 ret->exitCode = XK_MUSTEXIT;
6389 ret->canBreak = TRUE;
6390 }
6391 else
6392 {
6393 if (optgenerror (FLG_UNREACHABLE,
6394 message ("Unreachable code: %s",
6395 exprNode_unparseFirst (nr)),
6396 exprNode_loc (nr)))
6397 {
6398 ret->isJumpPoint = TRUE;
6399 ret->mustBreak = FALSE;
6400 ret->exitCode = XK_ERROR;
6401 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6402 }
6403 else
6404 {
6405 ret->exitCode = XK_MUSTEXIT;
6406 ret->canBreak = TRUE;
6407 }
6408
6409 }
6410 }
6411 }
6412 else
6413 {
6414 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6415 {
6416 /*
6417 ** We want a warning anytime we have:
6418 ** case xxx: ...
6419 ** yyy; <<<- no break or return
6420 ** case zzz: ...
6421 */
6422
6423 exprNode lastStmt = exprNode_lastStatement (e1);
6424
6425 if (exprNode_isDefined (lastStmt)
6426 && !exprNode_mustEscape (lastStmt)
6427 && !exprNode_mustBreak (lastStmt)
6428 && !exprNode_isCaseMarker (lastStmt)
6429 && !exprNode_isDefaultMarker (lastStmt)
6430 && !exprNode_isLabelMarker (lastStmt))
6431 {
6432 voptgenerror (FLG_CASEBREAK,
6433 cstring_makeLiteral
6434 ("Fall through case (no preceeding break)"),
6435 e2->loc);
6436 }
6437 }
6438 }
6439 }
6440
6441 exprNode_mergeUSs (ret, e2);
28bf4b0b 6442
616915dd 6443 usymtab_setExitCode (ret->exitCode);
6444
6445 if (ret->mustBreak)
6446 {
6447 usymtab_setMustBreak ();
6448 }
6449
6450 return ret;
6451}
6452
6453exprNode exprNode_createTok (/*@only@*/ lltok t)
6454{
28bf4b0b 6455 exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6456 ret = exprNode_create (ctype_unknown);
616915dd 6457 ret->kind = XPR_TOK;
6458 ret->edata = exprData_makeTok (t);
6459 return ret;
6460}
6461
6462exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6463{
6464 if (!exprNode_isError (e))
6465 {
6466 exprNode_checkStatement(e);
6467 }
6468
6469 return (exprNode_statementError (e, t));
6470}
6471
6472static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6473{
6474 exprNode ret = exprNode_createPartialCopy (e);
6475
6476 if (!exprNode_isError (e))
6477 {
6478 if (e->kind != XPR_ASSIGN)
6479 {
6480 exprNode_checkUse (ret, e->sref, e->loc);
6481 }
6482
6483 ret->exitCode = e->exitCode;
6484 ret->canBreak = e->canBreak;
6485 ret->mustBreak = e->mustBreak;
6486 }
6487
6488 ret->edata = exprData_makeUop (e, t);
6489 ret->kind = XPR_STMT;
6490
6491 return ret;
6492}
6493
6494exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6495{
6496 if (!exprNode_isError (e))
6497 {
6498 if (e->kind != XPR_ASSIGN)
6499 {
6500 exprNode_checkUse (e, e->sref, e->loc);
6501 }
6502 }
6503
6504 return e;
6505}
6506
6507void exprNode_produceGuards (exprNode pred)
6508{
6509 if (!exprNode_isError (pred))
6510 {
6511 if (ctype_isRealPointer (pred->typ))
6512 {
6513 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6514 }
6515
6516 exprNode_checkUse (pred, pred->sref, pred->loc);
6517 exprNode_resetSref (pred);
6518 }
6519}
6520
6521exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6522{
6523 exprNode ret = exprNode_createPartialCopy (e);
6524
6525 if (!exprNode_isError (e))
6526 {
6527 ret->exitCode = e->exitCode;
6528 ret->canBreak = e->canBreak;
6529 ret->mustBreak = e->mustBreak;
6530 }
6531
6532 ret->edata = exprData_makeSingle (e);
6533 ret->kind = XPR_BLOCK;
6534 return ret;
6535}
6536
6537bool exprNode_isBlock (exprNode e)
6538{
6539 return (exprNode_isDefined (e)
6540 && ((e)->kind == XPR_BLOCK));
6541}
6542
6543bool exprNode_isAssign (exprNode e)
6544{
6545 if (exprNode_isDefined (e))
6546 {
6547 return (e->kind == XPR_ASSIGN);
6548 }
6549
6550 return FALSE;
6551}
6552
6553bool exprNode_isEmptyStatement (exprNode e)
6554{
6555 return (exprNode_isDefined (e)
6556 && (e->kind == XPR_TOK)
6557 && (lltok_isSemi (exprData_getTok (e->edata))));
6558}
6559
6560exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6561{
6562 exprNode ret;
6563 bool emptyErr = FALSE;
6564
6565 if (context_maybeSet (FLG_IFEMPTY))
6566 {
6567 if (exprNode_isEmptyStatement (tclause))
6568 {
6569 emptyErr = optgenerror (FLG_IFEMPTY,
6570 cstring_makeLiteral
6571 ("Body of if statement is empty"),
6572 exprNode_loc (tclause));
6573 }
6574 }
6575
6576 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6577 {
6578 if (exprNode_isDefined (tclause)
6579 && !exprNode_isBlock (tclause))
6580 {
6581 voptgenerror (FLG_IFBLOCK,
6582 message
6583 ("Body of if statement is not a block: %s",
6584 exprNode_unparse (tclause)),
6585 exprNode_loc (tclause));
6586 }
6587 }
6588
6589 if (exprNode_isError (pred))
6590 {
6591 if (exprNode_isError (tclause))
6592 {
7ebcc5bb 6593 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
616915dd 6594 }
6595 else
6596 {
6597 ret = exprNode_createPartialCopy (tclause);
6598 }
6599 }
6600 else
6601 {
6602 if (exprNode_mustEscape (pred))
6603 {
6604 voptgenerror
6605 (FLG_UNREACHABLE,
6606 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6607 exprNode_loc (pred));
6608 }
6609
6610 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6611 exprNode_checkUse (pred, pred->sref, pred->loc);
6612
6613 if (!exprNode_isError (tclause))
6614 {
6615 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
6616 }
6617
6618 ret = exprNode_createPartialCopy (pred);
6619 }
6620
6621 ret->kind = XPR_IF;
6622 ret->edata = exprData_makePair (pred, tclause);
6623
6624 ret->exitCode = XK_UNKNOWN;
6625
6626 if (exprNode_isDefined (tclause))
6627 {
6628 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
6629 ret->canBreak = tclause->canBreak;
6630 ret->sets = sRefSet_union (ret->sets, tclause->sets);
6631 ret->msets = sRefSet_union (ret->msets, tclause->msets);
6632 ret->uses = sRefSet_union (ret->uses, tclause->uses);
6633 }
6634
6635 ret->mustBreak = FALSE;
6636
6637 return ret;
6638}
6639
6640exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
6641 /*@only@*/ exprNode tclause,
6642 /*@only@*/ exprNode eclause)
6643{
6644 exprNode ret;
6645 bool tEmptyErr = FALSE;
6646 bool eEmptyErr = FALSE;
6647
6648 if (context_maybeSet (FLG_IFEMPTY))
6649 {
6650 if (exprNode_isEmptyStatement (tclause))
6651 {
6652 tEmptyErr = optgenerror
6653 (FLG_IFEMPTY,
6654 cstring_makeLiteral
6655 ("Body of if clause of if statement is empty"),
6656 exprNode_loc (tclause));
6657 }
6658
6659 if (exprNode_isEmptyStatement (eclause))
6660 {
6661 eEmptyErr = optgenerror
6662 (FLG_IFEMPTY,
6663 cstring_makeLiteral
6664 ("Body of else clause of if statement is empty"),
6665 exprNode_loc (eclause));
6666 }
6667 }
6668
6669 if (context_maybeSet (FLG_IFBLOCK))
6670 {
6671 if (!tEmptyErr
6672 && exprNode_isDefined (tclause)
6673 && !exprNode_isBlock (tclause))
6674 {
6675 voptgenerror (FLG_IFBLOCK,
6676 message
6677 ("Body of if clause of if statement is not a block: %s",
6678 exprNode_unparse (tclause)),
6679 exprNode_loc (tclause));
6680 }
6681
6682 if (!eEmptyErr
6683 && exprNode_isDefined (eclause)
6684 && !exprNode_isBlock (eclause)
6685 && !(eclause->kind == XPR_IF)
6686 && !(eclause->kind == XPR_IFELSE))
6687 {
6688 voptgenerror
6689 (FLG_IFBLOCK,
6690 message
6691 ("Body of else clause of if statement is not a block: %s",
6692 exprNode_unparse (eclause)),
6693 exprNode_loc (eclause));
6694 }
6695 }
6696
6697 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
6698 {
6699 if (exprNode_isDefined (eclause)
6700 && (eclause->kind == XPR_IF))
6701 {
6702 voptgenerror (FLG_ELSEIFCOMPLETE,
6703 message ("Incomplete else if logic (no final else): %s",
6704 exprNode_unparse (eclause)),
6705 exprNode_loc (eclause));
6706 }
6707 }
6708
6709 if (exprNode_isError (pred))
6710 {
6711 if (exprNode_isError (tclause))
6712 {
6713 if (exprNode_isError (eclause))
6714 {
7ebcc5bb 6715 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
616915dd 6716 }
6717 else
6718 {
6719 ret = exprNode_createPartialCopy (eclause);
6720 }
6721 }
6722 else
6723 {
6724 ret = exprNode_createPartialCopy (tclause);
6725 }
6726 }
6727 else /* pred is okay */
6728 {
6729 ret = exprNode_createPartialCopy (pred);
6730
6731 if (exprNode_mustEscape (pred))
6732 {
6733 voptgenerror
6734 (FLG_UNREACHABLE,
6735 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6736 exprNode_loc (pred));
6737 }
6738
6739 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6740 exprNode_checkUse (ret, pred->sref, pred->loc);
6741
6742 exprNode_mergeCondUSs (ret, tclause, eclause);
6743 }
6744
6745 ret->kind = XPR_IFELSE;
6746 ret->edata = exprData_makeCond (pred, tclause, eclause);
6747
6748 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
6749 {
6750 exprNode_combineControl (ret, tclause, eclause);
6751 ret->loc = fileloc_update (ret->loc, eclause->loc);
6752 }
6753
6754 return ret;
6755}
6756
6757/*
6758** *allpaths <- TRUE iff all executions paths must go through the switch
6759*/
6760
6761static bool
6762checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
6763{
6764 exprNodeSList el = exprNode_flatten (e);
6765 bool mustReturn = TRUE; /* find a branch that doesn't */
6766 bool thisReturn = FALSE;
6767 bool hasDefault = FALSE;
6768 bool hasAllMembers = FALSE;
6769 bool inSwitch = FALSE;
6770 bool isEnumSwitch = FALSE;
6771 bool canBreak = FALSE;
6772 bool fallThrough = FALSE;
6773 ctype ct = ctype_unknown;
6774 enumNameSList usedEnums;
6775 enumNameList enums;
6776
6777 if (exprNode_isDefined (test))
6778 {
6779 ctype ttype;
6780
6781 ct = test->typ;
6782 ttype = ctype_realType (ct);
6783
6784 if (ctype_isEnum (ttype))
6785 {
6786 isEnumSwitch = TRUE;
6787 enums = ctype_elist (ttype);
6788 usedEnums = enumNameSList_new ();
6789 }
6790 }
6791
6792 exprNodeSList_elements (el, current)
6793 {
6794 if (exprNode_isDefined (current))
6795 {
6796 switch (current->kind)
6797 {
6798 case XPR_FTDEFAULT:
6799 case XPR_DEFAULT:
6800 if (hasDefault)
6801 {
6802 voptgenerror
6803 (FLG_CONTROL,
6804 message ("Duplicate default cases in switch"),
6805 exprNode_loc (current));
6806 }
6807 /*@fallthrough@*/
6808 case XPR_FTCASE:
6809 case XPR_CASE:
6810 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
6811 {
6812 hasDefault = TRUE;
6813 }
6814 else
6815 {
6816 if (isEnumSwitch)
6817 {
6818 exprNode st = exprData_getSingle (current->edata);
6819 uentry ue = exprNode_getUentry (st);
6820
6821 if (uentry_isValid (ue))
6822 {
6823 cstring cname = uentry_rawName (ue);
6824
6825 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
6826 {
6827 if (enumNameSList_member
6828 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
6829 {
6830 voptgenerror
6831 (FLG_CONTROL,
6832 message ("Duplicate case in switch: %s",
6833 cname),
6834 current->loc);
6835 }
6836 else
6837 {
6838 enumNameSList_addh (usedEnums, cname);
6839 }
6840 }
6841 else
6842 {
6843 voptgenerror
6844 (FLG_TYPE,
6845 message ("Case in switch not %s member: %s",
6846 ctype_unparse (ct), cname),
6847 current->loc);
6848 }
6849 }
6850 }
6851 }
6852
6853 if (inSwitch && !fallThrough)
6854 {
6855 if (!thisReturn || canBreak)
6856 {
6857 mustReturn = FALSE;
6858 }
6859 }
6860
6861 fallThrough = TRUE;
6862 inSwitch = TRUE;
6863 thisReturn = FALSE;
6864 canBreak = FALSE;
6865 /*@switchbreak@*/ break;
6866 default:
6867 thisReturn = thisReturn || exprNode_mustEscape (current);
6868 canBreak = canBreak || current->canBreak;
6869 if (canBreak) fallThrough = FALSE;
6870 }
6871 }
6872 } end_exprNodeSList_elements;
6873
6874 if (inSwitch) /* check the last one! */
6875 {
6876 if (!thisReturn || canBreak)
6877 {
6878 mustReturn = FALSE;
6879 }
6880 }
6881
6882 if (isEnumSwitch)
6883 {
6884 if (!hasDefault
6885 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
6886 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
6887 {
6888 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
6889
6890 voptgenerror (FLG_MISSCASE,
6891 message ("Missing case%s in switch: %q",
6892 cstring_makeLiteralTemp
6893 ((enumNameSList_size (unused) > 1) ? "s" : ""),
6894 enumNameSList_unparse (unused)),
6895 g_currentloc);
6896
6897 enumNameSList_free (unused);
6898 }
6899 else
6900 {
6901 hasAllMembers = TRUE;
6902 *allpaths = TRUE;
6903 }
6904
6905 enumNameSList_free (usedEnums);
6906 }
6907 else
6908 {
6909 *allpaths = hasDefault;
6910 }
6911
6912 exprNodeSList_free (el);
6913 return ((hasDefault || hasAllMembers) && mustReturn);
6914}
6915
6916exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
6917{
6918 exprNode ret = exprNode_createPartialCopy (e);
6919 bool allpaths;
6920
6921 DPRINTF (("Switch: %s", exprNode_unparse (s)));
6922
6923 ret->kind = XPR_SWITCH;
6924 ret->edata = exprData_makePair (e, s);
6925
6926 if (!exprNode_isError (s))
6927 {
6928 exprNode fs = exprNode_firstStatement (s);
6929 ret->loc = fileloc_update (ret->loc, s->loc);
6930
6931 if (exprNode_isUndefined (fs)
6932 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
6933 || exprNode_isDefaultMarker (fs)) {
6934 ;
6935 } else {
6936 voptgenerror (FLG_FIRSTCASE,
6937 message
6938 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
6939 fs->loc);
6940 }
6941 }
6942
6943 if (!exprNode_isError (e))
6944 {
6945 if (checkSwitchExpr (e, s, &allpaths))
6946 {
6947 ret->exitCode = XK_MUSTRETURN;
6948 }
6949 else
6950 {
6951 ret->exitCode = e->exitCode;
6952 }
6953
6954 ret->canBreak = e->canBreak;
6955 ret->mustBreak = e->mustBreak;
6956 }
6957 /*
6958 ** forgot this!
6959 ** exprNode.c:3883,32: Variable allpaths used before definition
6960 */
6961 else
6962 {
6963 allpaths = FALSE;
6964 }
6965
6966 DPRINTF (("Context exit switch!"));
6967 context_exitSwitch (ret, allpaths);
6968 DPRINTF (("Context exit switch done!"));
6969
6970 return ret;
6971}
6972
6973static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
6974 /*@notnull@*/ exprNode body)
6975{
6976 sRefSet tuses = test->uses;
6977
6978 if (!sRefSet_isEmpty (test->uses))
6979 {
6980 sRefSet sets = sRefSet_newCopy (body->sets);
6981 bool hasError = TRUE;
6982 bool innerState = FALSE;
6983 sRefSet tuncon = sRefSet_undefined;
6984
6985 sets = sRefSet_union (sets, test->sets);
6986 sets = sRefSet_union (sets, body->msets);
6987 sets = sRefSet_union (sets, test->msets);
6988
6989 sRefSet_allElements (tuses, el)
6990 {
6991 if (sRef_isUnconstrained (el))
6992 {
6993 tuncon = sRefSet_insert (tuncon, el);
6994 }
6995 else
6996 {
6997 if (sRefSet_member (sets, el))
6998 {
6999 hasError = FALSE;
7000 break;
7001 }
7002 }
7003
7004 if (sRef_isInternalState (el)
7005 || sRef_isFileStatic (sRef_getRootBase (el)))
7006 {
7007 innerState = TRUE;
7008 }
7009 } end_sRefSet_allElements ;
7010
7011 if (hasError)
7012 {
7013 sRefSet suncon = sRefSet_undefined;
7014 bool sinner = FALSE;
7015
7016 sRefSet_allElements (sets, el)
7017 {
7018 if (sRef_isUnconstrained (el))
7019 {
7020 suncon = sRefSet_insert (suncon, el);
7021 }
7022 else if (sRef_isInternalState (el))
7023 {
7024 sinner = TRUE;
7025 }
7026 else
7027 {
7028 ;
7029 }
7030 } end_sRefSet_allElements ;
7031
7032 if (sinner && innerState)
7033 {
7034 ;
7035 }
7036 else if (sRefSet_isEmpty (tuncon)
7037 && sRefSet_isEmpty (suncon))
7038 {
7039 voptgenerror
7040 (FLG_INFLOOPS,
7041 message
7042 ("Suspected infinite loop. No value used in loop test (%q) "
7043 "is modified by test or loop body.",
7044 sRefSet_unparsePlain (tuses)),
7045 test->loc);
7046 }
7047 else
7048 {
7049 if (sRefSet_isEmpty (tuncon))
7050 {
7051 voptgenerror
7052 (FLG_INFLOOPSUNCON,
7053 message ("Suspected infinite loop. No condition values "
7054 "modified. Modification possible through "
7055 "unconstrained calls: %q",
7056 sRefSet_unparsePlain (suncon)),
7057 test->loc);
7058 }
7059 else
7060 {
7061 voptgenerror
7062 (FLG_INFLOOPSUNCON,
7063 message ("Suspected infinite loop. No condition values "
7064 "modified. Possible undetected dependency through "
7065 "unconstrained calls in loop test: %q",
7066 sRefSet_unparsePlain (tuncon)),
7067 test->loc);
7068 }
7069 }
7070 }
7071
7072 sRefSet_free (sets);
7073 }
7074}
7075
7076exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7077{
7078 exprNode ret;
7079 bool emptyErr = FALSE;
616915dd 7080
7081 if (context_maybeSet (FLG_WHILEEMPTY))
7082 {
7083 if (exprNode_isEmptyStatement (b))
7084 {
7085 emptyErr = optgenerror
7086 (FLG_WHILEEMPTY,
7087 cstring_makeLiteral
7088 ("Body of while statement is empty"),
7089 exprNode_loc (b));
7090 }
7091 }
7092
7093 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7094 {
7095 if (exprNode_isDefined (b)
7096 && !exprNode_isBlock (b))
7097 {
7098 if (context_inIterDef ()
7099 && (b->kind == XPR_STMTLIST
7100 || b->kind == XPR_TOK))
7101 {
7102 ; /* no error */
7103 }
7104 else
7105 {
7106 voptgenerror (FLG_WHILEBLOCK,
7107 message
7108 ("Body of while statement is not a block: %s",
7109 exprNode_unparse (b)),
7110 exprNode_loc (b));
7111 }
7112 }
7113 }
7114
7115 if (exprNode_isError (t))
7116 {
7117 if (exprNode_isError (b))
7118 {
7ebcc5bb 7119 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
616915dd 7120 }
7121 else
7122 {
7123 ret = exprNode_createPartialCopy (b);
7124 }
7125 }
7126 else
7127 {
7128 exprNode test;
7129
7130 ret = exprNode_createPartialCopy (t);
7131
7132 llassert (t->kind == XPR_WHILEPRED);
7133
7134 test = exprData_getSingle (t->edata);
7135
7136 if (!exprNode_isError (b) && exprNode_isDefined (test))
7137 {
7138 if (context_maybeSet (FLG_INFLOOPS)
7139 || context_maybeSet (FLG_INFLOOPSUNCON))
7140 {
7141 /*
7142 ** check that some variable in the predicate is set by the body
7143 ** if the predicate uses any variables
7144 */
7145
7146 checkInfiniteLoop (test, b);
7147 }
7148
7149 exprNode_mergeUSs (ret, b);
7150
7151 if (exprNode_isDefined (b))
7152 {
7153 ret->exitCode = exitkind_makeConditional (b->exitCode);
7154 }
7155 }
7156 }
7157
7158 ret->edata = exprData_makePair (t, b);
7159 ret->kind = XPR_WHILE;
7160
7161 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7162 {
7163 voptgenerror
7164 (FLG_CONTROL,
7165 message ("Predicate always exits: %s", exprNode_unparse (t)),
7166 exprNode_loc (t));
7167 }
7168
7169 ret->exitCode = XK_NEVERESCAPE;
7170
7171 /*
7172 ** If loop is infinite, and there is no break inside,
7173 ** exit code is never reach.
7174 */
7175
7176 if (exprNode_knownIntValue (t))
7177 {
7178 if (!exprNode_isZero (t))
7179 {
7180 if (exprNode_isDefined (b))
7181 {
7182 if (!b->canBreak)
7183 {
7184 /* Really, it means never reached. */
7185 ret->exitCode = XK_MUSTEXIT;
7186 }
7187 }
7188 }
7189 }
7190 else
7191 {
7192 ;
7193 }
7194
7195 ret->canBreak = FALSE;
7196 ret->mustBreak = FALSE;
7197
7198 return ret;
7199}
7200
7201/*
7202** do { b } while (t);
7203**
7204** note: body passed as first argument
7205*/
7206
7207exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7208{
7209 exprNode ret;
7210
7211 if (exprNode_isError (t))
7212 {
7213 if (exprNode_isError (b))
7214 {
7ebcc5bb 7215 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
616915dd 7216 }
7217 else
7218 {
7219 ret = exprNode_createPartialCopy (b);
7220
7221 ret->exitCode = exitkind_makeConditional (b->exitCode);
7222 exprNode_checkUse (ret, b->sref, b->loc);
7223 ret->exitCode = b->exitCode;
7224 ret->canBreak = b->canBreak;
7225 ret->mustBreak = b->mustBreak;
7226 }
7227 }
7228 else
7229 {
7230 ret = exprNode_createPartialCopy (t);
7231 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7232
7233 if (!exprNode_isError (b))
7234 {
7235 /*
7236 ** forgot the copy's --- why wasn't this detected??
7237 */
7238
28bf4b0b 7239 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7240 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7241 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
616915dd 7242
7243 /* left this out --- causes and aliasing bug (infinite loop)
7244 should be detected?? */
7245
7246 exprNode_checkUse (ret, b->sref, b->loc);
7247 exprNode_mergeUSs (ret, t);
7248 exprNode_checkUse (ret, t->sref, t->loc);
7249
7250 ret->exitCode = b->exitCode;
7251 ret->canBreak = b->canBreak;
7252 ret->mustBreak = b->mustBreak;
7253 }
7254 }
7255
7256 context_exitDoWhileClause (t);
7257
7258 ret->kind = XPR_DOWHILE;
7259 ret->edata = exprData_makePair (t, b);
7ebcc5bb 7260 return ret;
616915dd 7261}
7262
7263exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7264{
7265 exprNode ret;
7266 bool emptyErr = FALSE;
7267
7268 if (context_maybeSet (FLG_FOREMPTY))
7269 {
7270 if (exprNode_isEmptyStatement (body))
7271 {
7272 emptyErr = optgenerror
7273 (FLG_FOREMPTY,
7274 cstring_makeLiteral
7275 ("Body of for statement is empty"),
7276 exprNode_loc (body));
7277 }
7278 }
7279
7280 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7281 {
7282 if (exprNode_isDefined (body)
7283 && !exprNode_isBlock (body))
7284 {
7285 if (context_inIterDef ()
7286 && (body->kind == XPR_STMTLIST
7287 || body->kind == XPR_TOK))
7288 {
7289 ; /* no error */
7290 }
7291 else
7292 {
7293 voptgenerror (FLG_FORBLOCK,
7294 message
7295 ("Body of for statement is not a block: %s",
7296 exprNode_unparse (body)),
7297 exprNode_loc (body));
7298 }
7299 }
7300 }
7301
7302 /*
7303 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7304 */
7305
7306 if (exprNode_isError (body))
7307 {
7308 ret = exprNode_createPartialCopy (inc);
7309 }
7310 else
7311 {
7312 ret = exprNode_createPartialCopy (body);
7313
7314 ret->exitCode = exitkind_makeConditional (body->exitCode);
7315
7316 exprNode_mergeUSs (inc, body);
7317
7318 if (exprNode_isDefined (inc))
7319 {
7320 exprNode tmp;
7321
7322 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7323
7324
7325 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7326 exprNode_freeShallow (tmp);
7327
7328 context_clearMessageAnnote ();
7329 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7330
7331 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7332 exprNode_freeShallow (tmp);
7333
7334 context_clearMessageAnnote ();
7335
28bf4b0b 7336 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7337 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7338 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
616915dd 7339 }
7340 }
7341
7342 ret->kind = XPR_FOR;
7343 ret->edata = exprData_makePair (inc, body);
7344
7345 if (exprNode_isDefined (inc)) {
7346 exprNode test = exprData_getTripleTest (inc->edata);
7347
7348 if (exprNode_isUndefined (test)) {
7349 if (exprNode_isDefined (body)) {
7350 if (!body->canBreak) {
7351 /* Really, it means never reached. */
7352 ret->exitCode = XK_MUSTEXIT;
7353 }
7354 }
7355 }
7356 }
7357
7358 return (ret);
7359}
7360
7361/*
7362** for (init; test; inc)
7363** ==>
7364** init;
7365** while (test) { body; inc; }
7366**
7367** Now: check use of init (may set vars for test)
7368** check use of test
7369** no checks on inc
7370_*/
7371
7372/*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7373{
7374 exprNode test;
7375
7376 if (exprNode_isError (pred)) return guardSet_undefined;
7377
7378 llassert (pred->kind == XPR_FORPRED);
7379
7380 test = exprData_getTripleTest (pred->edata);
7381
7382 if (!exprNode_isError (test))
7383 {
7384 return (test->guards);
7385 }
7386
7387 return guardSet_undefined;
7388}
7389
7390exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7391{
7392 exprNode ret = exprNode_createSemiCopy (test);
7393
7394 if (exprNode_isDefined (test))
7395 {
7396 exprNode_copySets (ret, test);
7397 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7398 exprNode_checkUse (ret, test->sref, test->loc);
7399
7400 exprNode_produceGuards (test);
7401
7402 ret->guards = guardSet_copy (test->guards);
7403 }
7404
7405 ret->edata = exprData_makeSingle (test);
7406 ret->kind = XPR_WHILEPRED;
7407 return ret;
7408}
7409
7410exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7411 /*@only@*/ exprNode inc)
7412{
7413 exprNode ret;
7414
7415 /*
7416 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7417 */
7418
7419 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7420
7421 if (!exprNode_isError (inc))
7422 {
7423 ret = exprNode_createPartialCopy (inc);
7424 }
7425 else
7426 {
7427 if (!exprNode_isError (init))
7428 {
7429 ret = exprNode_createPartialCopy (init);
7430 }
7431 else if (!exprNode_isError (test))
7432 {
7433 ret = exprNode_createPartialCopy (test);
7434 }
7435 else
7436 {
7437 ret = exprNode_createUnknown ();
7438 }
7439 }
7440
7441 exprNode_mergeUSs (ret, init);
7442
7443 if (exprNode_isDefined (init))
7444 {
7445 exprNode_checkUse (ret, init->sref, init->loc);
7446 }
7447
7448 exprNode_mergeUSs (ret, test);
7449
7450 if (exprNode_isDefined (test))
7451 {
7452 exprNode_checkUse (ret, test->sref, test->loc);
7453 }
7454
7455 ret->kind = XPR_FORPRED;
7456 ret->edata = exprData_makeFor (init, test, inc);
7457 return (ret);
7458}
7459
7460/*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7461{
7462 exprNode ret = exprNode_createUnknown ();
7463
7464 if (context_inMacro ())
7465 {
7466 voptgenerror (FLG_MACROSTMT,
7467 message ("Macro %s uses goto (not functional)",
7468 context_inFunctionName ()),
7469 g_currentloc);
7470 }
7471
7472 ret->kind = XPR_GOTO;
7473 ret->edata = exprData_makeLiteral (label);
7474 ret->mustBreak = TRUE;
7475 ret->exitCode = XK_GOTO;
7476 ret->canBreak = TRUE;
7477 return ret;
7478}
7479
7480exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7481{
7482 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7483
7484 ret->kind = XPR_CONTINUE;
7485 ret->edata = exprData_makeTok (l);
7486 ret->canBreak = TRUE;
7487 ret->mustBreak = TRUE;
7488
7489 if (qcontinue == QSAFEBREAK)
7490 {
7491 ; /* no checking */
7492 }
7493 else if (qcontinue == QINNERCONTINUE)
7494 {
7495 if (!context_inDeepLoop ())
7496 {
7497 voptgenerror
7498 (FLG_LOOPLOOPCONTINUE,
7499 cstring_makeLiteral ("Continue statement marked with innercontinue "
7500 "is not inside a nested loop"),
7501 exprNode_loc (ret));
7502 }
7503 }
7504 else if (qcontinue == BADTOK)
7505 {
7506 if (context_inDeepLoop ())
7507 {
7508 voptgenerror
7509 (FLG_LOOPLOOPCONTINUE,
7510 cstring_makeLiteral ("Continue statement in nested loop"),
7511 exprNode_loc (ret));
7512 }
7513 }
7514 else
7515 {
7516 llbuglit ("exprNode_continue: bad qcontinue");
7517 }
7518
7519 return ret;
7520}
7521
7522exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
7523{
7524 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7525 clause breakClause = context_breakClause ();
7526
7527 ret->kind = XPR_BREAK;
7528 ret->edata = exprData_makeTok (l);
7529 ret->canBreak = TRUE;
7530 ret->mustBreak = TRUE;
7531
7532 if (breakClause == NOCLAUSE)
7533 {
7534 voptgenerror
7535 (FLG_SYNTAX,
7536 cstring_makeLiteral ("Break not inside while, for or switch statement"),
7537 exprNode_loc (ret));
7538 }
7539 else
7540 {
7541 if (bqual != BADTOK)
7542 {
7543 switch (bqual)
7544 {
7545 case QSAFEBREAK:
7546 break;
7547 case QINNERBREAK:
7548 if (breakClause == SWITCHCLAUSE)
7549 {
7550 if (!context_inDeepSwitch ())
7551 {
7552 voptgenerror (FLG_SYNTAX,
7553 cstring_makeLiteral
7554 ("Break preceded by innerbreak is not in a deep switch"),
7555 exprNode_loc (ret));
7556 }
7557 }
7558 else
7559 {
7560 if (!context_inDeepLoop ())
7561 {
7562 voptgenerror (FLG_SYNTAX,
7563 cstring_makeLiteral
7564 ("Break preceded by innerbreak is not in a deep loop"),
7565 exprNode_loc (ret));
7566 }
7567 }
7568 break;
7569 case QLOOPBREAK:
7570 if (breakClause == SWITCHCLAUSE)
7571 {
7572 voptgenerror (FLG_SYNTAX,
7573 cstring_makeLiteral
7574 ("Break preceded by loopbreak is breaking a switch"),
7575 exprNode_loc (ret));
7576 }
7577 break;
7578 case QSWITCHBREAK:
7579 if (breakClause != SWITCHCLAUSE)
7580 {
7581 voptgenerror
7582 (FLG_SYNTAX,
7583 message ("Break preceded by switchbreak is breaking %s",
7584 cstring_makeLiteralTemp
7585 ((breakClause == WHILECLAUSE
7586 || breakClause == DOWHILECLAUSE) ? "a while loop"
7587 : (breakClause == FORCLAUSE) ? "a for loop"
7588 : (breakClause == ITERCLAUSE) ? "an iterator"
7589 : "<error loop>")),
7590 exprNode_loc (ret));
7591 }
7592 break;
7593 BADDEFAULT;
7594 }
7595 }
7596 else
7597 {
7598 if (breakClause == SWITCHCLAUSE)
7599 {
7600 clause nextBreakClause = context_nextBreakClause ();
7601
7602 switch (nextBreakClause)
7603 {
7604 case NOCLAUSE: break;
7605 case WHILECLAUSE:
7606 case DOWHILECLAUSE:
7607 case FORCLAUSE:
7608 case ITERCLAUSE:
7609 voptgenerror
7610 (FLG_LOOPSWITCHBREAK,
7611 cstring_makeLiteral ("Break statement in switch inside loop"),
7612 exprNode_loc (ret));
7613 break;
7614 case SWITCHCLAUSE:
7615 voptgenerror
7616 (FLG_SWITCHSWITCHBREAK,
7617 cstring_makeLiteral ("Break statement in switch inside switch"),
7618 exprNode_loc (ret));
7619 break;
7620 BADDEFAULT;
7621 }
7622 }
7623 else
7624 {
7625 if (context_inDeepLoop ())
7626 {
7627 voptgenerror
7628 (FLG_LOOPLOOPBREAK,
7629 cstring_makeLiteral ("Break statement in nested loop"),
7630 exprNode_loc (ret));
7631 }
7632 else
7633 {
7634 if (context_inDeepLoopSwitch ())
7635 {
7636 voptgenerror
7637 (FLG_SWITCHLOOPBREAK,
7638 cstring_makeLiteral ("Break statement in loop inside switch"),
7639 exprNode_loc (ret));
7640 }
7641 }
7642 }
7643 }
7644 }
7645
7646 return ret;
7647}
7648
7649exprNode exprNode_nullReturn (/*@only@*/ lltok t)
7650{
7651 fileloc loc = lltok_getLoc (t);
7652 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
7653
7654 context_returnFunction ();
7655 exprChecks_checkNullReturn (loc);
7656
7657 ret->kind = XPR_NULLRETURN;
7658 ret->edata = exprData_makeTok (t);
7659 ret->exitCode = XK_MUSTRETURN;
7660 return ret;
7661}
7662
7663exprNode exprNode_return (/*@only@*/ exprNode e)
7664{
7665 exprNode ret;
7666
7667 if (exprNode_isError (e))
7668 {
7669 ret = exprNode_createUnknown ();
7670 }
7671 else
7672 {
7673 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
7674
7675 exprNode_checkUse (ret, e->sref, e->loc);
7676 exprNode_checkReturn (e);
7677 }
7678
7679 context_returnFunction ();
7680 ret->kind = XPR_RETURN;
7681 ret->edata = exprData_makeSingle (e);
7682 ret->exitCode = XK_MUSTRETURN;
7683
7684 return (ret);
7685}
7686
7687exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
7688{
7689 exprNode ret;
7690
7691 if (exprNode_isError (e1))
7692 {
7693 if (exprNode_isError (e2))
7694 {
7ebcc5bb 7695 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
616915dd 7696 }
7697 else
7698 {
7699 ret = exprNode_createPartialCopy (e2);
7700 exprNode_checkUse (ret, e2->sref, e2->loc);
7701 ret->sref = e2->sref;
7702 }
7703 }
7704 else
7705 {
7706 ret = exprNode_createPartialCopy (e1);
7707
7708 exprNode_checkUse (ret, e1->sref, e1->loc);
7709
7710 if (!exprNode_isError (e2))
7711 {
7712 exprNode_mergeUSs (ret, e2);
7713 exprNode_checkUse (ret, e2->sref, e2->loc);
7714 ret->sref = e2->sref;
7715 }
7716 }
7717
7718 ret->kind = XPR_COMMA;
7719 ret->edata = exprData_makePair (e1, e2);
7720
7721 if (exprNode_isDefined (e1))
7722 {
7723 if (exprNode_isDefined (e2))
7724 {
7725 ret->typ = e2->typ;
7726
7727 if (exprNode_mustEscape (e1) || e1->mustBreak)
7728 {
7729 voptgenerror
7730 (FLG_UNREACHABLE,
7731 message ("Second clause of comma expression is unreachable: %s",
7732 exprNode_unparse (e2)),
7733 exprNode_loc (e2));
7734 }
7735
7736 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
7737 ret->mustBreak = e1->mustBreak || e2->mustBreak;
7738 ret->canBreak = e1->canBreak || e2->canBreak;
7739 }
7740 else
7741 {
7742 if (exprNode_mustEscape (e1) || e1->mustBreak)
7743 {
7744 voptgenerror
7745 (FLG_UNREACHABLE,
7746 message ("Second clause of comma expression is unreachable: %s",
7747 exprNode_unparse (e2)),
7748 exprNode_loc (e2));
7749 }
7750
7751 ret->exitCode = e1->exitCode;
7752 ret->canBreak = e1->canBreak;
7753 }
7754 }
7755 else
7756 {
7757 if (exprNode_isDefined (e2))
7758 {
7759 ret->exitCode = e2->exitCode;
7760 ret->mustBreak = e2->mustBreak;
7761 ret->canBreak = e2->canBreak;
7762 }
7763 }
7764
7765 return (ret);
7766}
7767
7768static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
7769{
7770 ctype t1 = exprNode_getType (el);
7771 ctype t2 = exprNode_getType (val);
7772 bool hasError = FALSE;
7773
7774 if (ctype_isUnknown (t1))
7775 {
7776 voptgenerror (FLG_IMPTYPE,
7777 message ("Variable has unknown (implicitly int) type: %s",
7778 exprNode_unparse (el)),
7779 el->loc);
7780
7781 t1 = ctype_int;
7782 el->typ = ctype_int;
7783 }
7784
7785 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
7786 {
7787 exprNodeList vals = exprData_getArgs (val->edata);
7788
7789 if (ctype_isRealAP (t1))
7790 {
7791 int i = 0;
7792 int nerrors = 0;
7793
b072092f 7794 /*@i423 check number of entries int a[3] = { 1, 2, 3, 4 } ; */
7795
616915dd 7796 exprNodeList_elements (vals, oneval)
7797 {
7798 cstring istring = message ("%d", i);
7799 exprNode newel =
7800 exprNode_arrayFetch
7801 (exprNode_fakeCopy (el),
7802 exprNode_numLiteral (ctype_int, istring,
7803 fileloc_copy (el->loc), i));
7804
7805 if (exprNode_isDefined (newel))
7806 {
7807 if (exprNodeList_size (vals) == 1
7808 && ctype_isString (exprNode_getType (oneval))
7809 && ctype_isChar (exprNode_getType (newel)))
7810 {
7811 exprNode_freeIniter (newel);
7812 }
7813 else
7814 {
7815 if (exprNode_checkOneInit (newel, oneval))
7816 {
7817 hasError = TRUE;
7818 nerrors++;
7819
7820 if (nerrors > 3 && exprNodeList_size (vals) > 6)
7821 {
7822 llgenmsg
7823 (message ("Additional initialization errors "
7824 "for %s not reported",
7825 exprNode_unparse (el)),
7826 exprNode_loc (el));
7827 exprNode_freeIniter (newel);
7828 break;
7829 }
7830 else
7831 {
7832 exprNode_freeIniter (newel);
7833 }
7834 }
7835 else
7836 {
7837 exprNode_freeIniter (newel);
7838 }
7839 }
7840 }
7841
7842 cstring_free (istring);
7843 i++;
7844 /*@-branchstate@*/
7845 } end_exprNodeList_elements;
7846 /*@=branchstate@*/
7847 }
7848 else if (ctype_isStruct (ctype_realType (t1)))
7849 {
7850 uentryList fields = ctype_getFields (t1);
7851 int i = 0;
7852
7853 if (uentryList_size (fields) != exprNodeList_size (vals))
7854 {
7855 if (uentryList_size (fields) > exprNodeList_size (vals))
7856 {
7857 hasError = optgenerror
7858 (FLG_FULLINITBLOCK,
7859 message ("Initializer block for "
28bf4b0b 7860 "%s has %d field%&, but %s has %d field%&: %q",
616915dd 7861 exprNode_unparse (el),
7862 exprNodeList_size (vals),
7863 ctype_unparse (t1),
7864 uentryList_size (fields),
7865 exprNodeList_unparse (vals)),
7866 val->loc);
7867 }
7868 else
7869 {
7870 hasError = optgenerror
7871 (FLG_TYPE,
7872 message ("Initializer block for "
28bf4b0b 7873 "%s has %d field%&, but %s has %d field%&: %q",
616915dd 7874 exprNode_unparse (el),
7875 exprNodeList_size (vals),
7876 ctype_unparse (t1),
7877 uentryList_size (fields),
7878 exprNodeList_unparse (vals)),
7879 val->loc);
7880 }
7881 }
7882 else
7883 {
7884 exprNodeList_elements (vals, oneval)
7885 {
7886 uentry thisfield = uentryList_getN (fields, i);
7887 exprNode newel =
28bf4b0b 7888 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
7889 exprNode_loc (el),
7890 uentry_getName (thisfield));
616915dd 7891
7892 if (exprNode_isDefined (newel))
7893 {
7894 if (exprNode_checkOneInit (newel, oneval))
7895 {
7896 hasError = TRUE;
7897 }
7898
7899 exprNode_freeIniter (newel);
7900 }
7901
7902 i++;
7903 } end_exprNodeList_elements;
7904 }
7905 }
7906 else
7907 {
7908 hasError = optgenerror
7909 (FLG_TYPE,
7910 message ("Initializer block used for "
7911 "%s where %t is expected: %s",
7912 exprNode_unparse (el), t1, exprNode_unparse (val)),
7913 val->loc);
7914 }
7915 }
7916 else
7917 {
7918 if (exprNode_isDefined (val))
7919 {
7920 doAssign (el, val, TRUE);
7921
7922 if (!exprNode_matchType (t1, val))
7923 {
7924 hasError = gentypeerror
7925 (t1, val, t2, el,
7926 message ("Initial value of %s is type %t, "
7927 "expects %t: %s",
7928 exprNode_unparse (el),
7929 t2, t1, exprNode_unparse (val)),
7930 val->loc);
7931 }
7932 }
7933 }
7934
7935 return hasError;
7936}
7937
28bf4b0b 7938static exprNode
7939exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
7940{
7941 exprNode ret;
7942
7943 if (usymtab_exists (idDecl_observeId (t)))
7944 {
7945 uentry ue = usymtab_lookup (idDecl_observeId (t));
7946 ret = exprNode_createId (ue);
7947
7948 /*@i723 don't do this...but why? */
7949# if 0
7950 ct = ctype_realishType (ret->typ);
7951
7952 DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
7953
7954 if (ctype_isUnknown (ct))
7955 {
7956 if (uentry_isAnyTag (ue))
7957 {
7958 voptgenerror
7959 (FLG_IMPTYPE,
7960 message ("%s used but not previously declared: %s",
7961 uentry_ekindName (ue),
7962 idDecl_getName (t)),
7963 g_currentloc);
7964
7965 }
7966 else
7967 {
7968 voptgenerror
7969 (FLG_IMPTYPE,
7970 message ("Variable has unknown (implicitly int) type: %s",
7971 idDecl_getName (t)),
7972 g_currentloc);
7973 }
7974
7975 ct = ctype_int;
7976 }
7977# endif
7978 }
7979 else
7980 {
7ebcc5bb 7981 uentry ue;
7982
7983 DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
7984
7985 ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
7986 /*!! fileloc_copy (g_currentloc)); */
7987 /*@i32!!! should get error without this */
28bf4b0b 7988 ret = exprNode_fromIdentifierAux (ue);
7989
7990 /*
7991 ** No error - this happens in old style declarations:
7992
7993 voptgenerror
7994 (FLG_UNRECOG,
7995 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
7996 g_currentloc);
7997
7998 **
7999 */
8000 }
8001
8002 exprData_free (ret->edata, ret->kind);
8003 ret->edata = exprData_undefined;
8004 ret->exitCode = XK_NEVERESCAPE;
8005 ret->mustBreak = FALSE;
8006 ret->kind = XPR_INIT;
8007 return ret;
8008}
8009
8010exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8011{
8012 exprNode ret = exprNode_makeInitializationAux (t);
8013 llassert (ret->edata == exprData_undefined);
8014 ret->edata = exprData_makeInit (t, exprNode_undefined);
8015 return ret;
8016}
8017
616915dd 8018exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8019 /*@only@*/ exprNode e)
8020{
8021 uentry ue = usymtab_lookup (idDecl_observeId (t));
28bf4b0b 8022 exprNode ret = exprNode_makeInitializationAux (t);
8023 fileloc loc = exprNode_loc (e);
b072092f 8024
616915dd 8025 if (exprNode_isError (e))
8026 {
8027 e = exprNode_createUnknown ();
28bf4b0b 8028 idDecl_free (t);
616915dd 8029
8030 /* error: assume initializer is defined */
28bf4b0b 8031 sRef_setDefined (ret->sref, g_currentloc);
616915dd 8032 }
8033 else
8034 {
28bf4b0b 8035 ctype ct = ctype_realishType (ret->typ);
8036
616915dd 8037 /*
8038 ** evs - 9 Apr 1995
8039 **
8040 ** was addSafeUse --- what's the problem?
8041 **
8042 ** int x = 3, y = x ?
8043 */
8044
28bf4b0b 8045 exprData_free (ret->edata, ret->kind);
8046 ret->edata = exprData_makeInit (t, e);
8047
616915dd 8048 exprNode_checkUse (ret, e->sref, e->loc);
8049
8050 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8051 {
8052 exprNode lhs = exprNode_createId (ue);
8053
8054 /*
8055 ** static storage should be undefined before initializing
8056 */
8057
8058 if (uentry_isStatic (ue))
8059 {
8060 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8061 }
8062
8063 (void) exprNode_checkOneInit (lhs, e);
8064
8065 if (uentry_isStatic (ue))
8066 {
8067 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8068 }
8069
8070 exprNode_free (lhs);
8071 }
8072 else
8073 {
8074 if (!exprNode_matchType (ct, e))
8075 {
8076 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
8077 {
8078 ;
8079 }
8080 else
8081 {
8082 (void) gentypeerror
8083 (exprNode_getType (e), e, exprNode_getType (ret), ret,
8084 message
28bf4b0b 8085 ("Variable %q initialized to type %t, expects %t: %s",
8086 uentry_getName (ue), exprNode_getType (e),
616915dd 8087 exprNode_getType (ret),
8088 exprNode_unparse (e)),
8089 e->loc);
8090 }
8091 }
8092 }
8093
8094 if (uentry_isStatic (ue))
8095 {
8096 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8097 }
8098
8099 doAssign (ret, e, TRUE);
8100
8101 if (uentry_isStatic (ue))
8102 {
8103 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8104 }
8105 }
8106
8107 if (context_inIterDef ())
8108 {
8109 /* should check if it is yield */
8110 uentry_setUsed (ue, loc);
8111 }
8112 else
8113 {
28bf4b0b 8114 ;
616915dd 8115 }
8116
616915dd 8117 exprNode_mergeUSs (ret, e);
8118 return ret;
8119}
8120
8121exprNode exprNode_iter (/*@observer@*/ uentry name,
8122 /*@only@*/ exprNodeList alist,
8123 /*@only@*/ exprNode body,
8124 /*@observer@*/ uentry end)
8125{
8126 exprNode ret;
8127 cstring iname;
8128
8129 llassert (uentry_isValid (name));
8130
8131 uentry_setUsed (name, exprNode_loc (body));
8132
8133 ret = exprNode_createPartialCopy (body);
8134 iname = uentry_getName (name);
8135
8136 if (uentry_isInvalid (end))
8137 {
8138 llerror (FLG_ITER,
8139 message ("Iter %s not balanced with end_%s", iname, iname));
8140 }
8141 else
8142 {
8143 cstring ename = uentry_getName (end);
8144
8145 if (!cstring_equalPrefix (ename, "end_"))
8146 {
8147 llerror (FLG_ITER, message ("Iter %s not balanced with end_%s: %s",
8148 iname, iname, ename));
8149 }
8150 else
8151 {
8152 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8153 {
8154 llerror (FLG_ITER,
8155 message ("Iter %s not balanced with end_%s: %s",
8156 iname, iname, ename));
8157 }
8158 }
8159
8160 cstring_free (ename);
8161 }
8162
8163 context_exitIterClause (body);
8164
8165 ret->kind = XPR_ITER;
8166 ret->edata = exprData_makeIter (name, alist, body, end);
8167
8168 if (uentry_isIter (name))
8169 {
8170 (void) checkArgsReal (name, body,
8171 uentry_getParams (name), alist, TRUE, ret);
8172 }
8173
8174 cstring_free (iname);
8175
8176 return ret;
8177}
8178
8179exprNode
8180exprNode_iterNewId (/*@only@*/ cstring s)
8181{
8182 exprNode e = exprNode_new ();
8183 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8184
8185 llassert (processingIterVars ());
8186
8187 e->loc = context_getSaveLocation ();
8188
8189 if (fileloc_isUndefined (e->loc))
8190 {
8191 fileloc_free (e->loc);
8192 e->loc = fileloc_copy (g_currentloc);
8193 }
8194
8195 e->uses = sRefSet_new ();
8196 e->sets = sRefSet_new ();
8197 e->msets = sRefSet_new ();
8198 e->kind = XPR_VAR;
8199 e->val = multiVal_unknown ();
8200 e->guards = guardSet_new ();
8201 e->sref = defref;
8202 e->isJumpPoint = FALSE;
8203 e->exitCode = XK_NEVERESCAPE;
8204
8205 /*> missing fields, detected by lclint <*/
8206 e->canBreak = FALSE;
8207 e->mustBreak = FALSE;
8208 e->etext = cstring_undefined;
8209
8210 if (uentry_isYield (ue))
8211 {
8212 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8213 fileloc_copy (e->loc),
8214 FALSE);
8215 sRef sr;
8216
8217 uue = usymtab_supEntrySrefReturn (uue);
8218
8219 sr = uentry_getSref (uue);
8220 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8221 sr = uentry_getSref (uue);
8222 sRef_setDefined (sr, e->loc);
8223
8224 e->typ = uentry_getType (uue);
8225 e->sref = sr;
8226 e->edata = exprData_makeId (uue);
8227 uentry_setUsed (uue, g_currentloc);
8228 }
8229 else
8230 {
8231 uentry uue;
8232
8233 sRef_setGlobalScope ();
8234 uue = uentry_makeVariableLoc (s, ctype_unknown);
8235
8236 e->typ = ctype_unknown;
8237 e->edata = exprData_makeId (uue);
8238
8239 uentry_setUsed (uue, e->loc);
8240 uentry_setHasNameError (uue);
8241
8242 if (context_getFlag (FLG_REPEATUNRECOG))
8243 {
8244 uentry_markOwned (uue);
8245 }
8246 else
8247 {
8248 usymtab_supGlobalEntry (uue);
8249 }
8250
8251 sRef_clearGlobalScope ();
8252
8253 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8254 e->loc);
8255 }
8256
8257
8258 cstring_free (s);
84c9ffbf 8259
8260 exprNode_defineConstraints(e);
616915dd 8261 return (e);
8262}
8263
8264exprNode
8265exprNode_iterExpr (/*@returned@*/ exprNode e)
8266{
8267 if (!processingIterVars ())
8268 {
8269 llcontbuglit ("checkIterParam: not in iter");
8270 return e;
8271 }
8272
8273 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8274 iterParamNo ())))
8275 {
8276 if (exprNode_isDefined (e))
8277 {
8278 if (fileloc_isDefined (e->loc))
8279 {
8280 voptgenerror
8281 (FLG_ITER,
8282 message ("Yield parameter is not simple identifier: %s",
8283 exprNode_unparse (e)),
8284 e->loc);
8285 }
8286 else
8287 {
8288 voptgenerror
8289 (FLG_ITER,
8290 message ("Yield parameter is not simple identifier: %s",
8291 exprNode_unparse (e)),
8292 g_currentloc);
8293
8294 }
8295 }
8296 }
8297 return e;
8298}
8299
8300exprNode
8301exprNode_iterId (/*@observer@*/ uentry c)
8302{
8303 uentry ue;
8304
8305 llassert (processingIterVars ());
8306
8307 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8308 iterParamNo ());
8309
8310 if (uentry_isYield (ue))
8311 {
8312 ctype ct = uentry_getType (ue);
8313 exprNode e = exprNode_createPlain (ct);
8314 cstring name = uentry_getName (c);
8315 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8316
8317 uentry_setUsed (ue, g_currentloc);
8318 uentry_setHasNameError (ue);
8319
8320 cstring_free (name);
8321
8322 e->kind = XPR_VAR;
8323 e->edata = exprData_makeId (le);
8324 e->loc = context_getSaveLocation ();
8325 e->sref = uentry_getSref (le);
8326
8327 usymtab_supEntrySref (le);
8328
8329 if (!context_inHeader ())
8330 {
8331 if (optgenerror
8332 (FLG_ITER,
8333 message ("Yield parameter shadows local declaration: %q",
8334 uentry_getName (c)),
8335 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8336 {
8337 uentry_showWhereDeclared (c);
8338 }
8339 }
8340
8341 return e;
8342 }
8343
8344 return (exprNode_fromIdentifierAux (c));
8345}
8346
8347exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8348{
8349 exprNode ret = exprNode_create (ctype_unknown);
8350
8351 ret->kind = XPR_ITERCALL;
8352 ret->edata = exprData_makeIterCall (name, alist);
8353
8354 if (uentry_isIter (name))
8355 {
8356 uentryList params = uentry_getParams (name);
8357
8358 if (context_inIterDef ()
8359 && uentryList_size (params) == exprNodeList_size (alist))
8360 {
8361 int i = 0;
8362
8363 exprNodeList_elements (alist, arg)
8364 {
8365 uentry parg = uentryList_getN (params, i);
8366
8367 if (uentry_isYield (parg))
8368 {
8369 uentry ue = exprNode_getUentry (arg);
8370
8371 if (uentry_isValid (ue))
8372 {
8373 ;
8374 }
8375 }
8376
8377 i++;
8378 } end_exprNodeList_elements;
8379 }
8380
8381 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8382 checkUnspecCall (ret, params, alist);
8383 }
8384
8385 return ret;
8386}
8387
8388/*@exposed@*/ sRef exprNode_getSref (exprNode e)
8389{
8390 if (exprNode_isDefined (e))
8391 {
8392 /*@access sRef@*/
8393 if (e->sref == defref) /*@noaccess sRef@*/
8394 {
8395 /*@-mods@*/
8396 e->sref = sRef_makeUnknown ();
8397 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8398 /*@=mods@*/
8399 return e->sref;
8400 }
8401 else
8402 {
8403 return e->sref;
8404 }
8405 }
8406 else
8407 {
8408 return sRef_undefined;
8409 }
8410}
8411
8412/*@observer@*/ cstring
8413exprNode_unparseFirst (exprNode e)
8414{
8415 if (exprNode_isDefined (e))
8416 {
8417 cstring ret;
8418
8419 if (e->kind == XPR_STMTLIST
8420 || e->kind == XPR_COMMA || e->kind == XPR_COND)
8421 {
8422 exprNode first = exprData_getPairA (e->edata);
8423
8424 if (exprNode_isDefined (first))
8425 {
8426 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8427 }
8428 else
8429 {
8430 return (cstring_makeLiteralTemp ("..."));
8431 }
8432 }
8433
8434 ret = cstring_elide (exprNode_unparse (e), 20);
8435 cstring_markOwned (ret);
8436
8437 return (ret);
8438 }
8439 else
8440 {
8441 return cstring_makeLiteralTemp ("<error>");
8442 }
8443}
8444
8445/*@observer@*/ cstring
28bf4b0b 8446exprNode_unparse (/*@temp@*/ exprNode e)
616915dd 8447{
8448 if (exprNode_isError (e))
8449 {
8450 return cstring_makeLiteralTemp ("<error>");
8451 }
8452
8453 if (cstring_isDefined (e->etext))
8454 {
8455 return e->etext;
8456 }
8457 else
8458 {
8459 cstring ret = exprNode_doUnparse (e);
8460
8461 /*@-modifies@*/ /* benevolent */
8462 e->etext = ret;
8463 /*@=modifies@*/
8464 return ret;
8465 }
8466}
8467
8468/*@observer@*/ fileloc
8469exprNode_loc (exprNode e)
8470{
8471 if (exprNode_isError (e))
8472 {
8473 return (g_currentloc);
8474 }
8475 else
8476 {
8477 return (e->loc);
8478 }
8479}
8480
8481/*
8482** executes exprNode e
8483** recursively rexecutes as though in original parse using
8484** information in e->edata
8485*/
8486
8487static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
8488{
8489 exprNodeList ret = exprNodeList_new ();
8490
8491 exprNodeList_elements (e, current)
8492 {
8493 exprNodeList_addh (ret, exprNode_effect (current));
8494 } end_exprNodeList_elements;
8495
8496 return ret;
8497}
8498
8499static /*@only@*/ exprNode exprNode_effect (exprNode e)
8500 /*@globals internalState@*/
8501{
8502 bool innerEffect = inEffect;
8503 exprNode ret;
8504 exprData data;
8505
8506 inEffect = TRUE;
8507
8508 context_clearJustPopped ();
8509
8510 if (exprNode_isError (e))
8511 {
8512 ret = exprNode_undefined;
8513 }
8514 else
8515 {
8516 /*
8517 ** Turn off expose and dependent transfer checking.
8518 ** Need to pass exposed internal nodes,
8519 ** [ copying would be a waste! ]
8520 ** [ Actually, I think I wasted a lot more time than its worth ]
8521 ** [ trying to do this. ]
8522 */
8523
8524 /*@-exposetrans@*/
8525 /*@-observertrans@*/
8526 /*@-dependenttrans@*/
8527
8528 data = e->edata;
8529
8530 switch (e->kind)
8531 {
8532 case XPR_PARENS:
8533 ret = exprNode_addParens (exprData_getUopTok (data),
8534 exprNode_effect (exprData_getUopNode (data)));
8535 break;
8536 case XPR_ASSIGN:
8537 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
8538 exprNode_effect (exprData_getOpB (data)),
8539 exprData_getOpTok (data));
8540 break;
8541 case XPR_INITBLOCK:
8542 ret = exprNode_undefined;
8543 break;
8544 case XPR_CALL:
8545 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
8546 exprNodeList_effect (exprData_getArgs (data)));
8547 break;
8548 case XPR_EMPTY:
8549 ret = e;
8550 break;
8551
8552 case XPR_LABEL:
8553 ret = e;
8554 break;
8555
8556 case XPR_CONST:
8557 case XPR_VAR:
8558 {
8559 cstring id = exprData_getId (data);
8560 uentry ue = usymtab_lookupSafe (id);
8561
8562 ret = exprNode_fromIdentifierAux (ue);
8563 ret->loc = fileloc_update (ret->loc, e->loc);
8564 break;
8565 }
8566 case XPR_BODY:
8567 ret = e;
8568 break;
8569 case XPR_FETCH:
8570 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
8571 exprNode_effect (exprData_getPairB (data)));
8572 break;
8573 case XPR_OP:
8574 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
8575 exprNode_effect (exprData_getOpB (data)),
8576 exprData_getOpTok (data));
8577 break;
8578
8579 case XPR_POSTOP:
8580 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
8581 exprData_getUopTok (data));
8582 break;
8583 case XPR_PREOP:
8584 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
8585 exprData_getUopTok (data));
8586 break;
8587
8588 case XPR_OFFSETOF:
8589 case XPR_SIZEOFT:
8590 case XPR_SIZEOF:
8591 case XPR_ALIGNOFT:
8592 case XPR_ALIGNOF:
8593 ret = e;
8594 break;
8595
8596 case XPR_VAARG:
8597 ret = exprNode_vaArg (exprData_getCastTok (data),
8598 exprNode_effect (exprData_getCastNode (data)),
8599 exprData_getCastType (data));
8600 break;
8601
8602 case XPR_CAST:
8603 ret = exprNode_cast (exprData_getCastTok (data),
8604 exprNode_effect (exprData_getCastNode (data)),
8605 exprData_getCastType (data));
8606 break;
8607 case XPR_ITERCALL:
8608 ret = exprNode_iterStart (exprData_getIterCallIter (data),
8609 exprNodeList_effect
8610 (exprData_getIterCallArgs (data)));
8611 break;
8612
8613 case XPR_ITER:
8614 ret = exprNode_iter (exprData_getIterSname (data),
8615 exprNodeList_effect (exprData_getIterAlist (data)),
8616 exprNode_effect (exprData_getIterBody (data)),
8617 exprData_getIterEname (data));
8618 break;
8619
8620 case XPR_FOR:
8621 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
8622 exprNode_effect (exprData_getPairB (data)));
8623 break;
8624
8625 case XPR_FORPRED:
8626 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
8627 exprNode_effect (exprData_getTripleTest (data)),
8628 exprNode_effect (exprData_getTripleInc (data)));
8629 break;
8630
8631 case XPR_TOK:
8632 ret = exprNode_createTok (exprData_getTok (data));
8633 break;
8634
8635 case XPR_GOTO:
8636 ret = exprNode_goto (exprData_getLiteral (data));
8637 ret->loc = fileloc_update (ret->loc, e->loc);
8638 break;
8639
8640 case XPR_CONTINUE:
8641 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
8642 break;
8643
8644 case XPR_BREAK:
8645 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
8646 break;
8647
8648 case XPR_RETURN:
8649 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
8650 break;
8651
8652 case XPR_NULLRETURN:
8653 ret = exprNode_nullReturn (exprData_getTok (data));
8654 break;
8655
8656 case XPR_COMMA:
8657 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
8658 exprNode_effect (exprData_getPairB (data)));
8659 break;
8660
8661 case XPR_COND:
8662 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
8663 exprNode_effect (exprData_getTripleTrue (data)),
8664 exprNode_effect (exprData_getTripleFalse (data)));
8665 break;
8666 case XPR_IF:
8667 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
8668 exprNode_effect (exprData_getPairB (data)));
8669 break;
8670
8671 case XPR_IFELSE:
8672 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
8673 exprNode_effect (exprData_getTripleTrue (data)),
8674 exprNode_effect (exprData_getTripleFalse (data)));
8675 break;
8676 case XPR_WHILEPRED:
8677 ret = exprNode_whilePred (exprData_getSingle (data));
8678 break;
8679
8680 case XPR_WHILE:
8681 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
8682 exprNode_effect (exprData_getPairB (data)));
8683 break;
8684
8685 case XPR_DOWHILE:
8686 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
8687 exprNode_effect (exprData_getPairB (data)));
8688 break;
8689
8690 case XPR_BLOCK:
8691 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
8692 break;
8693
8694 case XPR_STMT:
8695 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
8696 exprData_getUopTok (data));
8697 break;
8698
8699 case XPR_STMTLIST:
8700 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
8701 exprNode_effect (exprData_getPairB (data)));
8702 break;
8703
8704 case XPR_FTCASE:
8705 case XPR_CASE:
8706 ret = exprNode_caseMarker
8707 (exprNode_effect (exprData_getSingle (data)),
8708 TRUE);
8709 break;
8710
8711 case XPR_FTDEFAULT:
8712 case XPR_DEFAULT:
8713 ret = exprNode_createTok (exprData_getTok (data));
8714 break;
8715
8716 case XPR_SWITCH:
8717 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
8718 exprNode_effect (exprData_getPairB (data)));
8719 break;
8720
8721 case XPR_INIT:
8722 ret = exprNode_makeInitialization
8723 (exprData_getInitId (data),
8724 exprNode_effect (exprData_getInitNode (data)));
8725 break;
8726
8727 case XPR_FACCESS:
28bf4b0b 8728 ret = exprNode_fieldAccessAux
8729 (exprNode_effect (exprData_getFieldNode (data)),
8730 exprNode_loc (exprData_getFieldNode (data)),
8731 cstring_copy (exprData_getFieldName (data)));
616915dd 8732 break;
8733
8734 case XPR_ARROW:
28bf4b0b 8735 ret = exprNode_arrowAccessAux
8736 (exprNode_effect (exprData_getFieldNode (data)),
8737 exprNode_loc (exprData_getFieldNode (data)),
8738 cstring_copy (exprData_getFieldName (data)));
616915dd 8739 break;
8740
8741 case XPR_STRINGLITERAL:
8742 ret = e;
8743 break;
8744
8745 case XPR_NUMLIT:
8746 ret = e;
8747 break;
8748
8749 case XPR_NODE:
8750 ret = e;
8751 break;
8752 /*@-branchstate@*/
8753 }
8754 /*@=branchstate@*/
8755 /*@=observertrans@*/
8756 /*@=exposetrans@*/
8757 /*@=dependenttrans@*/
8758 }
8759
8760 if (!innerEffect)
8761 {
8762 inEffect = FALSE;
8763 }
8764
8765 return ret;
8766}
8767
8768static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
8769{
8770 cstring ret;
8771 exprData data;
8772
8773 if (exprNode_isError (e))
8774 {
8775 return cstring_undefined;
8776 }
8777
8778 data = e->edata;
8779
8780 switch (e->kind)
8781 {
8782 case XPR_PARENS:
8783 ret = exprNode_rootVarName (exprData_getUopNode (data));
8784 break;
8785 case XPR_ASSIGN:
8786 ret = exprNode_rootVarName (exprData_getOpA (data));
8787 break;
8788 case XPR_CONST:
8789 case XPR_VAR:
8790 ret = exprData_getId (data);
8791 break;
8792 case XPR_LABEL:
8793 case XPR_TOK:
8794 case XPR_ITERCALL:
8795 case XPR_EMPTY:
8796 case XPR_CALL:
8797 case XPR_INITBLOCK:
8798 case XPR_BODY:
8799 case XPR_FETCH:
8800 case XPR_OP:
8801 case XPR_POSTOP:
8802 case XPR_PREOP:
8803 case XPR_OFFSETOF:
8804 case XPR_ALIGNOFT:
8805 case XPR_ALIGNOF:
8806 case XPR_SIZEOFT:
8807 case XPR_SIZEOF:
8808 case XPR_VAARG:
8809 case XPR_CAST:
8810 case XPR_ITER:
8811 case XPR_FOR:
8812 case XPR_FORPRED:
8813 case XPR_BREAK:
8814 case XPR_RETURN:
8815 case XPR_NULLRETURN:
8816 case XPR_COMMA:
8817 case XPR_COND:
8818 case XPR_IF:
8819 case XPR_IFELSE:
8820 case XPR_WHILE:
8821 case XPR_WHILEPRED:
8822 case XPR_DOWHILE:
8823 case XPR_GOTO:
8824 case XPR_CONTINUE:
8825 case XPR_FTDEFAULT:
8826 case XPR_DEFAULT:
8827 case XPR_SWITCH:
8828 case XPR_FTCASE:
8829 case XPR_CASE:
8830 case XPR_BLOCK:
8831 case XPR_STMT:
8832 case XPR_STMTLIST:
8833 case XPR_INIT:
8834 case XPR_FACCESS:
8835 case XPR_ARROW:
8836 case XPR_NODE:
8837 case XPR_NUMLIT:
8838 case XPR_STRINGLITERAL:
8839 ret = cstring_undefined;
8840 break;
8841 }
8842
8843 return ret;
8844}
8845
616915dd 8846static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
8847{
8848 cstring ret;
8849 exprData data;
8850
8851 if (exprNode_isError (e))
8852 {
8853 static /*@only@*/ cstring error = cstring_undefined;
8854
8855 if (!cstring_isDefined (error))
8856 {
8857 error = cstring_makeLiteral ("<error>");
8858 }
8859
8860 return error;
8861 }
8862
8863 data = e->edata;
8864
8865 switch (e->kind)
8866 {
8867 case XPR_PARENS:
8868 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
8869 break;
8870 case XPR_ASSIGN:
8871 ret = message ("%s %s %s",
8872 exprNode_unparse (exprData_getOpA (data)),
8873 lltok_unparse (exprData_getOpTok (data)),
8874 exprNode_unparse (exprData_getOpB (data)));
8875 break;
8876 case XPR_CALL:
8877 ret = message ("%s(%q)",
8878 exprNode_unparse (exprData_getFcn (data)),
8879 exprNodeList_unparse (exprData_getArgs (data)));
8880 break;
8881 case XPR_INITBLOCK:
8882 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
8883 break;
8884 case XPR_EMPTY:
8885 ret = cstring_undefined;
8886 break;
8887 case XPR_LABEL:
8888 ret = message ("%s:", exprData_getId (data));
8889 break;
8890 case XPR_CONST:
8891 case XPR_VAR:
8892 ret = cstring_copy (exprData_getId (data));
8893 break;
8894 case XPR_FETCH:
8895 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
8896 exprNode_unparse (exprData_getPairB (data)));
8897 break;
8898 case XPR_BODY:
8899 ret = message ("<body>");
8900 break;
8901 case XPR_OP:
8902 ret = message ("%s %s %s",
8903 exprNode_unparse (exprData_getOpA (data)),
8904 lltok_unparse (exprData_getOpTok (data)),
8905 exprNode_unparse (exprData_getOpB (data)));
8906 break;
8907
8908 case XPR_PREOP:
8909 ret = message ("%s%s",
8910 lltok_unparse (exprData_getUopTok (data)),
8911 exprNode_unparse (exprData_getUopNode (data)));
8912 break;
8913
8914 case XPR_POSTOP:
8915 ret = message ("%s%s",
8916 exprNode_unparse (exprData_getUopNode (data)),
8917 lltok_unparse (exprData_getUopTok (data)));
8918 break;
8919
8920 case XPR_OFFSETOF:
8921 ret = message ("offsetof(%s,%q)",
8922 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
8923 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
8924 break;
8925
8926 case XPR_SIZEOFT:
8927 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8928 break;
8929
8930 case XPR_SIZEOF:
8931 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
8932 break;
8933
8934 case XPR_ALIGNOFT:
8935 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8936 break;
8937
8938 case XPR_ALIGNOF:
8939 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
8940 break;
8941
8942 case XPR_VAARG:
8943 ret = message ("va_arg(%s, %q)",
8944 exprNode_unparse (exprData_getCastNode (data)),
8945 qtype_unparse (exprData_getCastType (data)));
8946 break;
8947
8948 case XPR_ITERCALL:
8949 ret = message ("%q(%q)",
8950 uentry_getName (exprData_getIterCallIter (data)),
8951 exprNodeList_unparse (exprData_getIterCallArgs (data)));
8952 break;
8953 case XPR_ITER:
8954 ret = message ("%q(%q) %s %q",
8955 uentry_getName (exprData_getIterSname (data)),
8956 exprNodeList_unparse (exprData_getIterAlist (data)),
8957 exprNode_unparse (exprData_getIterBody (data)),
8958 uentry_getName (exprData_getIterEname (data)));
8959 break;
8960 case XPR_CAST:
8961 ret = message ("(%q)%s",
8962 qtype_unparse (exprData_getCastType (data)),
8963 exprNode_unparse (exprData_getCastNode (data)));
8964 break;
8965
8966 case XPR_FOR:
8967 ret = message ("%s %s",
8968 exprNode_unparse (exprData_getPairA (data)),
8969 exprNode_unparse (exprData_getPairB (data)));
8970 break;
8971
8972 case XPR_FORPRED:
8973 ret = message ("for (%s; %s; %s)",
8974 exprNode_unparse (exprData_getTripleInit (data)),
8975 exprNode_unparse (exprData_getTripleTest (data)),
8976 exprNode_unparse (exprData_getTripleInc (data)));
8977 break;
8978
8979 case XPR_GOTO:
8980 ret = message ("goto %s", exprData_getLiteral (data));
8981 break;
8982
8983 case XPR_CONTINUE:
8984 ret = cstring_makeLiteral ("continue");
8985 break;
8986
8987 case XPR_BREAK:
8988 ret = cstring_makeLiteral ("break");
8989 break;
8990
8991 case XPR_RETURN:
8992 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
8993 break;
8994
8995 case XPR_NULLRETURN:
8996 ret = cstring_makeLiteral ("return");
8997 break;
8998
8999 case XPR_COMMA:
9000 ret = message ("%s, %s",
9001 exprNode_unparse (exprData_getPairA (data)),
9002 exprNode_unparse (exprData_getPairB (data)));
9003 break;
9004
9005 case XPR_COND:
9006 ret = message ("%s ? %s : %s",
9007 exprNode_unparse (exprData_getTriplePred (data)),
9008 exprNode_unparse (exprData_getTripleTrue (data)),
9009 exprNode_unparse (exprData_getTripleFalse (data)));
9010 break;
9011 case XPR_IF:
9012 ret = message ("if (%s) %s",
9013 exprNode_unparse (exprData_getPairA (data)),
9014 exprNode_unparse (exprData_getPairB (data)));
9015 break;
9016
9017 case XPR_IFELSE:
9018 ret = message ("if (%s) %s else %s",
9019 exprNode_unparse (exprData_getTriplePred (data)),
9020 exprNode_unparse (exprData_getTripleTrue (data)),
9021 exprNode_unparse (exprData_getTripleFalse (data)));
9022 break;
9023 case XPR_WHILE:
9024 ret = message ("while (%s) %s",
9025 exprNode_unparse (exprData_getPairA (data)),
9026 exprNode_unparse (exprData_getPairB (data)));
9027 break;
9028
9029 case XPR_WHILEPRED:
9030 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9031 break;
9032
9033 case XPR_TOK:
9034 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9035 break;
9036
9037 case XPR_DOWHILE:
9038 ret = message ("do { %s } while (%s)",
9039 exprNode_unparse (exprData_getPairB (data)),
9040 exprNode_unparse (exprData_getPairA (data)));
9041 break;
9042
9043 case XPR_BLOCK:
9044 ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
9045 break;
9046
9047 case XPR_STMT:
9048 ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
9049 break;
9050
9051 case XPR_STMTLIST:
9052 ret = message ("%s; %s",
9053 exprNode_unparse (exprData_getPairA (data)),
9054 exprNode_unparse (exprData_getPairB (data)));
9055 break;
9056
9057 case XPR_FTDEFAULT:
9058 case XPR_DEFAULT:
9059 ret = cstring_makeLiteral ("default:");
9060 break;
9061
9062 case XPR_SWITCH:
9063 ret = message ("switch (%s) %s",
9064 exprNode_unparse (exprData_getPairA (data)),
9065 exprNode_unparse (exprData_getPairB (data)));
9066 break;
9067
9068 case XPR_FTCASE:
9069 case XPR_CASE:
9070 ret = message ("case %s:",
9071 exprNode_unparse (exprData_getSingle (data)));
9072 break;
9073
9074 case XPR_INIT:
28bf4b0b 9075 if (exprNode_isError (exprData_getInitNode (data)))
9076 {
9077 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9078 }
9079 else
9080 {
9081 ret = message ("%q = %s",
9082 idDecl_unparseC (exprData_getInitId (data)),
9083 exprNode_unparse (exprData_getInitNode (data)));
9084 }
616915dd 9085 break;
9086
9087 case XPR_FACCESS:
9088 ret = message ("%s.%s",
9089 exprNode_unparse (exprData_getFieldNode (data)),
9090 exprData_getFieldName (data));
9091 break;
9092
9093 case XPR_ARROW:
9094 ret = message ("%s->%s",
9095 exprNode_unparse (exprData_getFieldNode (data)),
9096 exprData_getFieldName (data));
9097 break;
9098
9099 case XPR_STRINGLITERAL:
28bf4b0b 9100 ret = message ("\"%s\"", exprData_getLiteral (data));
616915dd 9101 break;
9102
9103 case XPR_NUMLIT:
9104 ret = cstring_copy (exprData_getLiteral (data));
9105 break;
9106
9107 case XPR_NODE:
9108 ret = cstring_makeLiteral ("<node>");
9109 break;
9110 }
9111
9112 return ret;
9113}
9114
28bf4b0b 9115bool
9116exprNode_isInitializer (exprNode e)
9117{
9118 return (exprNode_isDefined (e)
9119 && e->kind == XPR_INIT);
9120}
9121
616915dd 9122bool
9123exprNode_isCharLit (exprNode e)
9124{
9125 if (exprNode_isDefined (e))
9126 {
9127 return (multiVal_isChar (exprNode_getValue (e)));
9128 }
9129 else
9130 {
9131 return FALSE;
9132 }
9133}
9134
9135bool
9136exprNode_isNumLit (exprNode e)
9137{
9138 if (exprNode_isDefined (e))
9139 {
9140 return (multiVal_isInt (exprNode_getValue (e)));
9141 }
9142 else
9143 {
9144 return FALSE;
9145 }
9146}
9147
9148static bool
9149exprNode_isFalseConstant (exprNode e)
9150{
9151 if (exprNode_isDefined (e))
9152 {
9153 cstring s = exprNode_rootVarName (e);
9154
9155 if (cstring_equal (s, context_getFalseName ()))
9156 {
9157 return TRUE;
9158 }
9159 }
9160
9161 return FALSE;
9162}
9163
9164bool
9165exprNode_matchLiteral (ctype expected, exprNode e)
9166{
9167 if (exprNode_isDefined (e))
9168 {
9169 multiVal m = exprNode_getValue (e);
9170
9171 if (multiVal_isDefined (m))
9172 {
9173 if (multiVal_isInt (m))
9174 {
9175 long int val = multiVal_forceInt (m);
9176
9177 if (ctype_isDirectBool (ctype_realishType (expected)))
9178 {
9179 if (val == 0)
9180 {
9181 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9182 }
9183 else
9184 {
9185 return FALSE;
9186 }
9187 }
9188
9189 if (ctype_isRealInt (expected))
9190 {
9191 /*
9192 ** unsigned <- [ constant >= 0 is okay ]
9193 */
9194
9195 if (ctype_isUnsigned (expected))
9196 {
9197 if (val < 0)
9198 {
9199 return FALSE;
9200 }
9201 }
9202
9203 /*
9204 ** No checks on sizes of integers...maybe add
9205 ** these later.
9206 */
9207
9208 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9209 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9210 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9211
9212 if (context_getFlag (FLG_NUMLITERAL)
9213 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9214 return TRUE;
9215 } else {
9216 if (val == 0) {
9217 return TRUE;
9218 } else {
9219 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9220 }
9221 }
9222 }
9223 else if (ctype_isChar (expected))
9224 {
9225 return FALSE;
9226 }
9227 else if (ctype_isArrayPtr (expected))
9228 {
9229 return (val == 0);
9230 }
9231 else if (ctype_isAnyFloat (expected))
9232 {
9233 return (context_getFlag (FLG_NUMLITERAL));
9234 }
9235 else
9236 {
9237 return FALSE;
9238 }
9239 }
9240 else if (multiVal_isDouble (m))
9241 {
9242 if (ctype_isAnyFloat (expected))
9243 {
9244 return TRUE;
9245 }
9246 }
9247 else if (multiVal_isChar (m))
9248 {
9249 char val = multiVal_forceChar (m);
9250
9251 if (ctype_isChar (expected))
9252 {
9253 if (ctype_isUnsigned (expected) && ((int)val) < 0)
9254 {
9255 return FALSE;
9256 }
9257 else
9258 {
9259 return TRUE;
9260 }
9261 }
9262 }
9263 else
9264 {
9265 return FALSE;
9266 }
9267 }
9268 }
9269
9270 return FALSE;
9271}
9272
9273bool
9274exprNode_matchType (ctype expected, exprNode e)
9275{
9276 ctype actual;
9277
9278 if (!exprNode_isDefined (e)) return TRUE;
9279
9280 actual = ctype_realishType (exprNode_getType (e));
9281
9282 if (ctype_match (ctype_realishType (expected), actual))
9283 {
9284 return TRUE;
9285 }
9286
9287 llassert (!exprNode_isError (e));
9288 return (exprNode_matchLiteral (expected, e));
9289}
9290
9291static bool
9292exprNode_matchTypes (exprNode e1, exprNode e2)
9293{
9294 ctype t1;
9295 ctype t2;
9296
9297 if (!exprNode_isDefined (e1)) return TRUE;
9298 if (!exprNode_isDefined (e2)) return TRUE;
9299
9300 /*
9301 ** realish type --- keep bools, bools
9302 */
9303
9304 t1 = ctype_realishType (exprNode_getType (e1));
9305 t2 = ctype_realishType (exprNode_getType (e2));
9306
9307 if (ctype_match (t1, t2))
9308 {
9309 return TRUE;
9310 }
9311
9312 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9313}
9314
9315/*
9316** pass e as ct
9317*/
9318
9319static bool
9320 exprNode_matchArgType (ctype ct, exprNode e)
9321{
9322 ctype et;
9323
9324 if (!exprNode_isDefined (e))
9325 {
9326 return TRUE;
9327 }
9328
9329 et = ctype_realType (exprNode_getType (e));
9330
9331 if (ctype_matchArg (ct, et)) return TRUE;
9332
9333 llassert (!exprNode_isError (e));
9334 return (exprNode_matchLiteral (ct, e));
9335}
9336
9337static /*@only@*/ exprNodeSList
9338 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9339{
9340 if (exprNode_isDefined (e))
9341 {
9342 if (e->kind == XPR_STMTLIST)
9343 {
9344 return (exprNodeSList_append
9345 (exprNode_flatten (exprData_getPairA (e->edata)),
9346 exprNode_flatten (exprData_getPairB (e->edata))));
9347 }
9348 else if (e->kind == XPR_BLOCK)
9349 {
9350 return (exprNode_flatten (exprData_getSingle (e->edata)));
9351 }
9352 else
9353 {
9354 return (exprNodeSList_singleton (e));
9355 }
9356 }
9357
9358 return exprNodeSList_new ();
9359}
9360
9361static /*@exposed@*/ exprNode
9362exprNode_lastStatement (/*@returned@*/ exprNode e)
9363{
9364 if (exprNode_isDefined (e))
9365 {
9366 if (e->kind == XPR_STMTLIST)
9367 {
9368 exprNode b = exprData_getPairB (e->edata);
9369
9370 if (exprNode_isDefined (b))
9371 {
9372 return exprNode_lastStatement (b);
9373 }
9374 else
9375 {
9376 return exprNode_lastStatement (exprData_getPairA (e->edata));
9377 }
9378 }
9379 else if (e->kind == XPR_BLOCK)
9380 {
9381 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
9382 }
9383 else
9384 {
9385 return (e);
9386 }
9387 }
9388
9389 return exprNode_undefined;
9390}
9391
9392static /*@exposed@*/ exprNode
9393exprNode_firstStatement (/*@returned@*/ exprNode e)
9394{
9395 if (exprNode_isDefined (e))
9396 {
9397 if (e->kind == XPR_STMTLIST)
9398 {
9399 exprNode b = exprData_getPairA (e->edata);
9400
9401 if (exprNode_isDefined (b))
9402 {
9403 return exprNode_firstStatement (b);
9404 }
9405 else
9406 {
9407 return exprNode_firstStatement (exprData_getPairB (e->edata));
9408 }
9409 }
9410 else if (e->kind == XPR_BLOCK)
9411 {
9412 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
9413 }
9414 else
9415 {
9416 return (e);
9417 }
9418 }
9419
9420 return exprNode_undefined;
9421}
9422
9423static void
9424exprNode_mergeUSs (exprNode res, exprNode other)
9425{
9426 if (exprNode_isDefined (res) && exprNode_isDefined (other))
9427 {
9428 res->msets = sRefSet_union (res->msets, other->msets);
9429 res->sets = sRefSet_union (res->sets, other->sets);
9430 res->uses = sRefSet_union (res->uses, other->uses);
9431 }
9432}
9433
9434static void
9435exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
9436{
9437 if (exprNode_isDefined (res))
9438 {
9439 if (exprNode_isDefined (other1))
9440 {
9441 res->sets = sRefSet_union (res->sets, other1->sets);
9442 res->msets = sRefSet_union (res->msets, other1->msets);
9443 res->uses = sRefSet_union (res->uses, other1->uses);
9444 }
9445 if (exprNode_isDefined (other2))
9446 {
9447 res->sets = sRefSet_union (res->sets, other2->sets);
9448 res->msets = sRefSet_union (res->msets, other2->msets);
9449 res->uses = sRefSet_union (res->uses, other2->uses);
9450 }
9451 }
9452}
9453
9454/*
9455** modifies e->uses
9456**
9457** Reports errors is s is not defined.
9458*/
9459
9460static void
28bf4b0b 9461exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
616915dd 9462{
9463 if (exprNode_isDefined (e))
9464 {
9465 e->uses = sRefSet_insert (e->uses, s);
9466 }
9467}
9468
9469void
28bf4b0b 9470exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
616915dd 9471{
9472 if (sRef_isKnown (s) && !sRef_isConst (s))
9473 {
9474 /*
9475 ** need to check all outer types are useable
9476 */
9477
9478 DPRINTF (("Check use: %s / %s",
9479 exprNode_unparse (e), sRef_unparse (s)));
28bf4b0b 9480
616915dd 9481 exprNode_addUse (e, s);
9482
9483 if (!context_inProtectVars ())
9484 {
9485 /*
9486 ** only report the deepest error
9487 */
9488
9489 sRef errorRef = sRef_undefined;
9490 sRef lastRef = sRef_undefined;
9491 bool deadRef = FALSE;
9492 bool unuseable = FALSE;
9493 bool errorMaybe = FALSE;
9494
9495 while (sRef_isValid (s) && sRef_isKnown (s))
9496 {
9497 ynm readable = sRef_isReadable (s);
9498
28bf4b0b 9499 DPRINTF (("Readable: %s / %s",
9500 sRef_unparseFull (s), ynm_unparse (readable)));
9501
616915dd 9502 if (!(ynm_toBoolStrict (readable)))
9503 {
9504 if (ynm_isMaybe (readable))
9505 {
9506 lastRef = errorRef;
9507 errorRef = s;
cd7d9b17 9508 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
616915dd 9509 deadRef = sRef_isPossiblyDead (errorRef);
9510 unuseable = sRef_isUnuseable (errorRef);
9511 errorMaybe = TRUE;
9512 }
9513 else
9514 {
9515 lastRef = errorRef;
9516 errorRef = s;
9517 deadRef = sRef_isDead (errorRef);
9518 unuseable = sRef_isUnuseable (errorRef);
9519 errorMaybe = FALSE;
9520 }
9521
9522 if (!sRef_isPartial (s))
9523 {
cd7d9b17 9524 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
616915dd 9525 sRef_setDefined (s, fileloc_undefined);
9526 }
9527 }
9528
9529 s = sRef_getBaseSafe (s);
9530 } /* end while */
9531
9532 if (sRef_isValid (errorRef))
9533 {
9534 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
9535 && sRef_isPointer (errorRef))
9536 {
9537 errorRef = lastRef;
9538 }
9539
9540 if (deadRef)
9541 {
9542 if (sRef_isThroughArrayFetch (errorRef))
9543 {
9544 if (optgenerror
9545 (FLG_STRICTUSERELEASED,
9546 message ("%q %q may be used after being released",
9547 sRef_unparseKindNamePlain (errorRef),
9548 sRef_unparse (errorRef)),
9549 loc))
9550 {
9551 sRef_showRefKilled (errorRef);
9552
9553 if (sRef_isKept (errorRef))
9554 {
9555 sRef_clearAliasState (errorRef, loc);
9556 }
9557 }
9558 }
9559 else
9560 {
9561 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
9562
9563 if (optgenerror
9564 (FLG_USERELEASED,
9565 message ("%q %q %qused after being released",
9566 sRef_unparseKindNamePlain (errorRef),
9567 sRef_unparse (errorRef),
9568 cstring_makeLiteral (errorMaybe
9569 ? "may be " : "")),
9570 loc))
9571 {
9572 sRef_showRefKilled (errorRef);
9573
9574 if (sRef_isKept (errorRef))
9575 {
9576 sRef_clearAliasState (errorRef, loc);
9577 }
9578 }
9579 }
9580 }
9581 else if (unuseable)
9582 {
9583 if (optgenerror
9584 (FLG_USEDEF,
9585 message ("%q %q%qused in inconsistent state",
9586 sRef_unparseKindName (errorRef),
9587 sRef_unparseOpt (errorRef),
9588 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9589 loc))
9590 {
9591 sRef_showStateInconsistent (errorRef);
9592 }
9593 }
9594 else
9595 {
28bf4b0b 9596 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
616915dd 9597
9598 voptgenerror
9599 (FLG_USEDEF,
9600 message ("%q %q%qused before definition",
9601 sRef_unparseKindName (errorRef),
9602 sRef_unparseOpt (errorRef),
9603 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9604 loc);
cd7d9b17 9605
9606 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
616915dd 9607 }
9608
9609 sRef_setDefined (errorRef, loc);
9610
9611 if (sRef_isAddress (errorRef))
9612 {
9613 sRef_setDefined (sRef_getRootBase (errorRef), loc);
9614 }
9615 } /* end is error */
9616 }
9617 }
9618
9619 setCodePoint ();
9620}
9621
9622static void
28bf4b0b 9623checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
616915dd 9624{
9625 if (exprNode_isDefined (e) && sRef_isKnown (s))
9626 {
9627 e->uses = sRefSet_insert (e->uses, s);
9628 }
9629}
9630
9631static void
9632exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
9633{
9634 if (exprNode_isDefined (e))
9635 {
9636 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
9637 }
9638}
9639
9640void
28bf4b0b 9641exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
616915dd 9642{
9643 sRef defines = sRef_undefined;
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",
9658 sRef_unparse (s)),
9659 exprNode_loc (e));
9660 }
9661
9662 if (sRef_isMeaningful (s))
9663 {
9664
9665 if (sRef_isDead (s))
9666 {
9667 sRef base = sRef_getBaseSafe (s);
9668
9669 if (sRef_isValid (base)
9670 && sRef_isDead (base))
9671 {
9672 sRef_setPartial (s, exprNode_loc (e));
9673 }
9674
9675 defines = s; /* okay - modifies for only param */
9676 }
9677 else if (sRef_isPartial (s))
9678 {
9679 sRef eref = exprNode_getSref (e);
9680
9681 if (!sRef_isPartial (eref))
9682 {
9683 /*
9684 ** should do something different here???
9685 */
9686
9687 sRef_setDefinedComplete (eref, exprNode_loc (e));
9688 }
9689 else
9690 {
9691 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
9692 }
9693
9694 if (sRef_isMeaningful (eref))
9695 {
9696 defines = eref;
9697 }
9698 else
9699 {
9700 defines = s;
9701 }
9702 }
9703 else if (sRef_isAllocated (s))
9704 {
9705 sRef eref = exprNode_getSref (e);
9706
9707
9708 if (!sRef_isAllocated (eref))
9709 {
9710 sRef_setDefinedComplete (eref, exprNode_loc (e));
9711 }
9712 else
9713 {
9714 sRef base = sRef_getBaseSafe (eref);
9715
9716 if (sRef_isValid (base))
9717 {
9718 sRef_setPdefined (base, exprNode_loc (e));
9719 }
9720 }
9721
9722 defines = s;
9723 }
9724 else
9725 {
9726 sRef_setDefinedNCComplete (s, exprNode_loc (e));
9727 defines = s;
9728 }
9729
9730 }
9731 else /* not meaningful...but still need to insert it */
9732 {
9733 defines = s;
9734 }
9735 }
9736
9737 if (exprNode_isDefined (e) && sRef_isValid (defines))
9738 {
9739 e->sets = sRefSet_insert (e->sets, defines);
9740 }
9741}
9742
9743void
28bf4b0b 9744exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
616915dd 9745{
9746 if (sRef_isValid (s) && !sRef_isNothing (s))
9747 {
9748 uentry ue = sRef_getBaseUentry (s);
9749
9750 if (uentry_isValid (ue))
9751 {
9752 uentry_setLset (ue);
9753 }
9754
9755 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9756 {
9757 voptgenerror (FLG_USEDEF,
9758 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
9759 exprNode_loc (e));
9760 }
9761
9762 if (sRef_isMeaningful (s))
9763 {
9764 sRef_setDefinedComplete (s, exprNode_loc (e));
9765 }
9766
9767 if (exprNode_isDefined (e))
9768 {
9769 e->msets = sRefSet_insert (e->msets, s);
9770 }
9771 }
9772}
9773
9774static void
9775checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
9776{
9777 checkAnyCall (fcn, cstring_undefined, params, args,
9778 FALSE, sRefSet_undefined, FALSE, 0);
9779}
9780
9781static void
9782checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
9783 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
9784{
9785 setCodePoint ();
9786
9787 if (uentry_isYield (ucurrent))
9788 {
9789 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
9790 exprNode_checkSet (current, current->sref);
9791 }
9792 else
9793 {
9794 if (uentry_isSefParam (ucurrent))
9795 {
9796 sRefSet sets = current->sets;
9797 sRef ref = exprNode_getSref (current);
9798
9799 if (sRef_isMacroParamRef (ref))
9800 {
9801 uentry ue = sRef_getUentry (ref);
9802
9803 if (!uentry_isSefParam (ue))
9804 {
9805 voptgenerror
9806 (FLG_SEFPARAMS,
9807 message
9808 ("Parameter %d to %s is declared sef, but "
9809 "the argument is a macro parameter declared "
9810 "without sef: %s",
9811 argno, exprNode_unparse (fcn),
9812 exprNode_unparse (current)),
9813 exprNode_loc (current));
9814 }
9815 }
9816
9817 if (!sRefSet_isEmpty (sets))
9818 {
9819 sRefSet reported = sRefSet_undefined;
9820
9821 sRefSet_realElements (current->sets, el)
9822 {
9823 if (sRefSet_isSameNameMember (reported, el))
9824 {
9825 ; /* don't report again */
9826 }
9827 else
9828 {
9829 if (sRef_isUnconstrained (el))
9830 {
9831 voptgenerror
9832 (FLG_SEFUNSPEC,
9833 message
9834 ("Parameter %d to %s is declared sef, but "
9835 "the argument calls unconstrained function %s "
9836 "(no guarantee it will not modify something): %s",
9837 argno, exprNode_unparse (fcn),
9838 sRef_unconstrainedName (el),
9839 exprNode_unparse (current)),
9840 exprNode_loc (current));
9841 }
9842 else
9843 {
9844 voptgenerror
9845 (FLG_SEFPARAMS,
9846 message
9847 ("Parameter %d to %s is declared sef, but "
9848 "the argument may modify %q: %s",
9849 argno, exprNode_unparse (fcn),
9850 sRef_unparse (el),
9851 exprNode_unparse (current)),
9852 exprNode_loc (current));
9853 }
9854 }
9855 } end_sRefSet_realElements;
9856 }
9857 }
9858
9859 checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs);
9860 exprNode_mergeUSs (fcn, current);
9861 }
9862}
9863
9864static void
9865 checkAnyCall (/*@dependent@*/ exprNode fcn,
9866 /*@dependent@*/ cstring fname,
9867 uentryList pn,
9868 exprNodeList args,
9869 bool hasMods, sRefSet mods,
9870 bool isSpec,
9871 int specialArgs)
9872{
9873 int paramno = 0;
9874 int nargs = exprNodeList_size (args);
9875
9876 setCodePoint ();
9877
9878 /*
9879 ** concat all args ud's to f, add each arg sref as a use unless
9880 ** it was specified as "out", in which case it is a def.
9881 */
9882
9883 uentryList_reset (pn);
9884
9885 /*
9886 ** aliasing checks:
9887 **
9888 ** if paramn is only or unique, no other arg may alias argn
9889 */
9890
9891 exprNodeList_elements (args, current)
9892 {
9893 paramno++;
9894
9895 if (exprNode_isDefined (current))
9896 {
9897 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
9898 {
9899 uentry ucurrent = uentryList_current (pn);
9900
9901 if (specialArgs == 0
9902 || (paramno < specialArgs))
9903 {
28bf4b0b 9904 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
616915dd 9905
9906 if (context_maybeSet (FLG_ALIASUNIQUE))
9907 {
9908 if (uentry_isOnly (ucurrent)
9909 || uentry_isUnique (ucurrent))
9910 {
9911 checkUniqueParams (fcn, current, args,
9912 paramno, ucurrent);
9913 }
9914 }
9915 }
9916 }
9917 else /* uentry is undefined */
9918 {
9919 if (specialArgs == 0)
9920 {
9921 exprNode_checkUseParam (current);
9922 }
9923
9924 exprNode_mergeUSs (fcn, current);
9925 }
9926 }
9927 uentryList_advanceSafe (pn);
9928 } end_exprNodeList_elements;
9929
9930 if (hasMods)
9931 {
9932 setCodePoint ();
9933
9934 sRefSet_allElements (mods, s)
9935 {
9936 sRef fb;
9937 sRef rb = sRef_getRootBase (s);
9938
28bf4b0b 9939 if (sRef_isFileOrGlobalScope (rb))
616915dd 9940 {
9941 context_usedGlobal (rb);
9942 }
9943
9944 fb = sRef_fixBaseParam (s, args);
9945
9946 if (!sRef_isMacroParamRef (fb))
9947 {
9948 if (sRef_isNothing (fb))
9949 {
9950 ;
9951 }
9952 else
9953 {
9954 if (sRef_isValid (fb))
9955 {
9956 uentry ue = sRef_getBaseUentry (s);
9957
9958 if (uentry_isValid (ue))
9959 {
9960 uentry_setLset (ue);
9961 }
9962 }
9963
9964 fcn->sets = sRefSet_insert (fcn->sets, fb);
9965 }
9966 }
9967 sRef_clearDerivedComplete (s);
9968 } end_sRefSet_allElements;
9969
9970 setCodePoint ();
9971 }
9972 else
9973 {
9974 if (context_hasMods ())
9975 {
9976 if (context_maybeSet (FLG_MODUNCON))
9977 {
9978 voptgenerror
9979 (FLG_MODUNCON,
9980 message ("Undetected modification possible "
9981 "from call to unconstrained function %s: %s",
9982 fname,
9983 exprNode_unparse (fcn)),
9984 exprNode_loc (fcn));
9985 }
9986 }
9987 else
9988 {
9989 if (context_maybeSet (FLG_MODUNCONNOMODS)
9990 && !(context_inIterDef () || context_inIterEnd ()))
9991 {
9992 voptgenerror
9993 (FLG_MODUNCONNOMODS,
9994 message ("Undetected modification possible "
9995 "from call to unconstrained function %s: %s",
9996 fname,
9997 exprNode_unparse (fcn)),
9998 exprNode_loc (fcn));
9999 }
10000 }
10001
10002 exprNode_checkSetAny (fcn, fname);
10003 }
10004}
10005
10006void exprNode_checkUseParam (exprNode current)
10007{
10008 if (exprNode_isDefined (current))
10009 {
10010 exprNode_checkUse (current, current->sref, current->loc);
10011 }
10012}
10013
10014static ctype
10015 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10016 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10017 lltok op)
10018{
10019 ctype ret = tr1;
10020
10021 if (!ctype_match (tr1, tr2))
10022 {
10023 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10024 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10025 {
10026 ;
10027 }
10028 else
10029 {
10030 (void) gentypeerror
10031 (tr1, e1, tr2, e2,
10032 message ("Incompatible types for %s (%s, %s): %s %s %s",
10033 lltok_unparse (op),
10034 ctype_unparse (te1),
10035 ctype_unparse (te2),
10036 exprNode_unparse (e1), lltok_unparse (op),
10037 exprNode_unparse (e2)),
10038 e1->loc);
10039 }
10040 ret = ctype_unknown;
10041 }
10042 else
10043 {
10044 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
10045 {
10046 ret = ctype_resolveNumerics (tr1, tr2);
10047 }
10048 else if (!context_msgStrictOps ())
10049 {
10050 if (ctype_isPointer (tr1))
10051 {
10052 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10053 {
10054 ret = ctype_int;
10055 }
10056 else if (ctype_isInt (tr2))
10057 {
10058 ret = te1;
10059 }
10060 else
10061 {
10062 ret = ctype_unknown;
10063 }
10064 }
10065 else if (ctype_isPointer (tr2))
10066 {
10067 if (ctype_isPointer (tr1))
10068 {
10069 ret = ctype_int;
10070 }
10071 else if (ctype_isInt (tr1))
10072 {
10073 ret = te2;
10074 }
10075 else
10076 {
10077 ret = ctype_unknown;
10078 }
10079 }
10080 else
10081 {
10082 ret = ctype_resolveNumerics (tr1, tr2);
10083 }
10084 }
10085 else
10086 {
10087 int opid = lltok_getTok (op);
10088 bool comparop = (opid == EQ_OP || opid == NE_OP
10089 || opid == TLT || opid == TGT
10090 || opid == LE_OP || opid == GE_OP);
10091
10092 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10093 {
10094 if (comparop
10095 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10096 || (ctype_isBool (tr1) && ctype_isBool (tr2))
10097 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10098 {
10099 ; /* no error */
10100 }
10101 else
10102 {
10103 if (ctype_sameName (te1, te2))
10104 {
10105 voptgenerror
10106 (FLG_STRICTOPS,
10107 message ("Operands of %s are non-numeric (%t): %s %s %s",
10108 lltok_unparse (op), te1,
10109 exprNode_unparse (e1), lltok_unparse (op),
10110 exprNode_unparse (e2)),
10111 e1->loc);
10112 }
10113 else
10114 {
10115 voptgenerror
10116 (FLG_STRICTOPS,
10117 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10118 lltok_unparse (op), te1, te2,
10119 exprNode_unparse (e1), lltok_unparse (op),
10120 exprNode_unparse (e2)),
10121 e1->loc);
10122 }
10123 }
10124 }
10125 else if (!ctype_isNumeric (tr1))
10126 {
10127 voptgenerror
10128 (FLG_STRICTOPS,
10129 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10130 lltok_unparse (op), te1,
10131 exprNode_unparse (e1), lltok_unparse (op),
10132 exprNode_unparse (e2)),
10133 e1->loc);
10134 }
10135 else
10136 {
10137 if (!ctype_isNumeric (tr2))
10138 {
10139 voptgenerror
10140 (FLG_STRICTOPS,
10141 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10142 lltok_unparse (op), te2,
10143 exprNode_unparse (e1), lltok_unparse (op),
10144 exprNode_unparse (e2)),
10145 e2->loc);
10146 }
10147 }
10148
10149 ret = ctype_unknown;
10150 }
10151 }
10152
10153 return ret;
10154}
10155
10156static void
10157abstractOpError (ctype tr1, ctype tr2, lltok op,
10158 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10159 fileloc loc1, fileloc loc2)
10160{
10161 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10162 {
10163 if (ctype_match (tr1, tr2))
10164 {
10165 voptgenerror
10166 (FLG_ABSTRACT,
10167 message ("Operands of %s are abstract type (%t): %s %s %s",
10168 lltok_unparse (op), tr1,
10169 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10170 loc1);
10171 }
10172 else
10173 {
10174 voptgenerror
10175 (FLG_ABSTRACT,
10176 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10177 lltok_unparse (op), tr1, tr2,
10178 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10179 loc1);
10180 }
10181 }
10182 else if (ctype_isRealAbstract (tr1))
10183 {
10184 voptgenerror
10185 (FLG_ABSTRACT,
10186 message ("Left operand of %s is abstract type (%t): %s %s %s",
10187 lltok_unparse (op), tr1,
10188 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10189 loc1);
10190 }
10191 else
10192 {
10193 if (ctype_isRealAbstract (tr2))
10194 {
10195 voptgenerror
10196 (FLG_ABSTRACT,
10197 message ("Right operand of %s is abstract type (%t): %s %s %s",
10198 lltok_unparse (op), tr2,
10199 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10200 loc2);
10201 }
10202 }
10203}
10204
10205/*
10206** e1 <= e2
10207**
10208** requies e1 and e2 and not error exprNode's.
10209**
10210** Checks:
10211**
10212** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10213** the rep of the abstract type is exposed.
10214**
10215** The order is very important:
10216**
10217** check rep expose (move into check transfer)
10218** check transfer
10219** setup aliases
10220*/
10221
10222/*
10223** This isn't really a sensible procedure, but the indententation
10224** was getting too deep.
10225*/
10226
10227static void
10228checkOneRepExpose (sRef ysr, sRef base,
10229 /*@notnull@*/ exprNode e1,
10230 /*@notnull@*/ exprNode e2, ctype ct,
10231 sRef s2b)
10232{
10233 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
08eb3d0e 10234 || sRef_isOwned (ysr)
10235 || sRef_isExposed (ysr)))
616915dd 10236 {
08eb3d0e 10237 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10238 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10239
616915dd 10240 {
10241 if (sRef_isIReference (ysr))
10242 {
10243 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10244 {
10245 voptgenerror
10246 (FLG_ASSIGNEXPOSE,
10247 message
10248 ("Assignment of mutable component of parameter %q "
10249 "to component of abstract "
10250 "type %s exposes rep: %s = %s",
10251 sRef_unparse (base),
10252 ctype_unparse (ct),
10253 exprNode_unparse (e1), exprNode_unparse (e2)),
10254 e1->loc);
10255 }
10256 else
10257 {
10258 voptgenerror
10259 (FLG_ASSIGNEXPOSE,
10260 message
10261 ("Assignment of mutable component of parameter %q "
10262 "(through alias %q) to component of abstract "
10263 "type %s exposes rep: %s = %s",
10264 sRef_unparse (base),
10265 sRef_unparse (e2->sref),
10266 ctype_unparse (ct),
10267 exprNode_unparse (e1), exprNode_unparse (e2)),
10268 e1->loc);
10269 }
10270 }
10271 else
10272 {
10273 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10274 {
10275 voptgenerror
10276 (FLG_ASSIGNEXPOSE,
10277 message ("Assignment of mutable parameter %q "
10278 "to component of abstract type %s "
10279 "exposes rep: %s = %s",
10280 sRef_unparse (base),
10281 ctype_unparse (ct),
10282 exprNode_unparse (e1),
10283 exprNode_unparse (e2)),
10284 e1->loc);
10285 }
10286 else
10287 {
10288 voptgenerror
10289 (FLG_ASSIGNEXPOSE,
10290 message ("Assignment of mutable parameter %q "
10291 "(through alias %q) to "
10292 "component of abstract type %s exposes "
10293 "rep: %s = %s",
10294 sRef_unparse (base),
10295 sRef_unparse (e2->sref),
10296 ctype_unparse (ct),
10297 exprNode_unparse (e1),
10298 exprNode_unparse (e2)),
10299 e1->loc);
10300 }
10301 }
10302 }
10303
28bf4b0b 10304 if (sRef_isFileOrGlobalScope (s2b))
616915dd 10305 {
10306 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10307 {
10308 voptgenerror
10309 (FLG_REPEXPOSE,
10310 message ("Assignment of global %q "
10311 "to component of "
10312 "abstract type %s exposes rep: %s = %s",
10313 sRef_unparse (base),
10314 ctype_unparse (ct),
10315 exprNode_unparse (e1), exprNode_unparse (e2)),
10316 e1->loc);
10317 }
10318 else
10319 {
10320 voptgenerror
10321 (FLG_REPEXPOSE,
10322 message ("Assignment of global %q (through alias %q) "
10323 "to component of "
10324 "abstract type %s exposes rep: %s = %s",
10325 sRef_unparse (base),
10326 sRef_unparse (e2->sref),
10327 ctype_unparse (ct),
10328 exprNode_unparse (e1), exprNode_unparse (e2)),
10329 e1->loc);
10330 }
10331 }
10332 }
10333}
10334
10335static void
10336doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
10337{
10338 if (ctype_isRealFunction (exprNode_getType (e1))
10339 && !ctype_isRealPointer (exprNode_getType (e1)))
10340 {
10341 voptgenerror
10342 (FLG_TYPE,
10343 message ("Invalid left-hand side of assignment (function type %s): %s",
10344 ctype_unparse (exprNode_getType (e1)),
10345 exprNode_unparse (e1)),
10346 e1->loc);
10347 }
10348
10349 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
10350 {
10351 ctype t2 = exprNode_getType (e2);
10352 sRef sr = sRef_getRootBase (e1->sref);
10353 ctype ct = sRef_getType (sr);
10354
10355 if (ctype_isAbstract (t2)
10356 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
10357 {
10358 /* it is immutable, okay to reference */
10359 goto donerepexpose;
10360 }
10361
10362 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
10363 {
10364 sRef s2b = sRef_getRootBase (e2->sref);
10365 sRef s1 = e1->sref;
10366 sRef s1b = sRef_getRootBase (s1);
10367 sRefSet aliases;
10368
10369 aliases = usymtab_canAlias (e2->sref);
10370
10371 if (!sRef_similar (s2b, s1b)
10372 && !sRef_isExposed (s1)
10373 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
10374 {
10375 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
10376 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
10377 && !sRef_isExposed (s2b))
10378 {
10379 if (sRef_isIReference (e2->sref))
10380 {
10381 voptgenerror
10382 (FLG_ASSIGNEXPOSE,
10383 message
10384 ("Assignment of mutable component of parameter %q "
10385 "to component of abstract type %s exposes rep: %s = %s",
10386 sRef_unparse (s2b),
10387 ctype_unparse (ct),
10388 exprNode_unparse (e1), exprNode_unparse (e2)),
10389 e1->loc);
10390 }
10391 else
10392 {
10393 voptgenerror
10394 (FLG_ASSIGNEXPOSE,
10395 message ("Assignment of mutable parameter %q to "
10396 "component of abstract type %s exposes rep: %s = %s",
10397 sRef_unparse (s2b),
10398 ctype_unparse (ct),
10399 exprNode_unparse (e1), exprNode_unparse (e2)),
10400 e1->loc);
10401 }
10402 }
10403
28bf4b0b 10404 if (sRef_isFileOrGlobalScope (s2b))
616915dd 10405 {
10406 voptgenerror
10407 (FLG_ASSIGNEXPOSE,
10408 message ("Assignment of global %q to component of "
10409 "abstract type %s exposes rep: %s = %s",
10410 sRef_unparse (s2b),
10411 ctype_unparse (ct),
10412 exprNode_unparse (e1), exprNode_unparse (e2)),
10413 e1->loc);
10414 }
10415
10416 sRefSet_realElements (aliases, ysr)
10417 {
10418 sRef base = sRef_getRootBase (ysr);
10419
10420 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
10421 || sRef_sameName (base, s1b))
10422 {
10423 ; /* error already reported or same sref */
10424 }
10425 else
10426 {
10427 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
10428 }
10429 } end_sRefSet_realElements;
10430 }
10431 sRefSet_free (aliases);
10432 }
10433 }
10434
10435 donerepexpose:
10436
10437 /*
10438 ** function variables don't really work...
10439 */
10440
10441 if (!ctype_isFunction (ctype_realType (e2->typ)))
10442 {
10443 if (isInit)
10444 {
28bf4b0b 10445 DPRINTF (("Check init: %s / %s",
10446 exprNode_unparse (e1), exprNode_unparse (e2)));
616915dd 10447 checkInitTransfer (e1, e2);
10448 }
10449 else
10450 {
10451 checkAssignTransfer (e1, e2);
10452 }
10453 }
10454 else
10455 {
10456 sRef fref = e2->sref;
10457
10458 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
10459 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
10460
10461 /* Need to typecheck the annotation on the parameters */
10462
10463 if (ctype_isRealFunction (e1->typ)) {
10464 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
10465 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
10466
10467 if (!uentryList_isMissingParams (e1p)
10468 && !uentryList_isMissingParams (e2p)
10469 && uentryList_size (e1p) > 0) {
10470 if (uentryList_size (e1p) == uentryList_size (e2p)) {
10471 int n = 0;
10472
10473 uentryList_elements (e1p, el1) {
10474 uentry el2;
10475
10476 el2 = uentryList_getN (e2p, n);
10477 n++;
10478 uentry_checkMatchParam (el1, el2, n, e2);
10479 } end_uentryList_elements;
10480 }
10481 }
10482 }
10483 }
10484
28bf4b0b 10485 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
616915dd 10486 {
10487 ;
10488 }
10489 else
10490 {
28bf4b0b 10491 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
616915dd 10492 updateAliases (e1, e2);
10493 }
616915dd 10494}
10495
10496static void
10497checkMacroParen (exprNode e)
10498{
10499 if (exprNode_isError (e) || e->kind == XPR_CAST)
10500 {
10501 ;
10502 }
10503 else
10504 {
10505 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
10506 {
10507 voptgenerror
10508 (FLG_MACROPARENS,
10509 message ("Macro parameter used without parentheses: %s",
10510 exprNode_unparse (e)),
10511 e->loc);
10512 }
10513 }
10514}
10515
10516static void
10517reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
10518{
10519 if (isnull)
10520 {
10521 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
10522 }
10523 else
10524 {
10525 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
10526 }
10527}
10528
10529/*
10530** e1 <= e2
10531**
10532** if e2 is a parameter or global derived location which
10533** can be modified (that is, e2 is a mutable abstract type,
10534** or a derived pointer), then e1 can alias e2.
10535**
10536** e1 can alias everything which e2 can alias.
10537**
10538** Also, if e1 is guarded, remove from guard sets!
10539*/
10540
10541static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
10542{
10543 if (!context_inProtectVars ())
10544 {
10545 /*
10546 ** depends on types of e1 and e2
10547 */
10548
10549 sRef s1 = e1->sref;
10550 sRef s2 = e2->sref;
10551 ctype t1 = exprNode_getType (e1);
10552
10553 /* handle pointer sRefs, record fields, arrays, etc... */
10554
10555 if (!ctype_isRealSU (t1))
10556 {
28bf4b0b 10557 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
616915dd 10558 sRef_copyRealDerivedComplete (s1, s2);
10559 }
28bf4b0b 10560 else
10561 {
10562 /*
10563 ** Fields should alias
10564 */
10565
10566 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
10567 }
616915dd 10568
10569 if (ctype_isMutable (t1) && sRef_isKnown (s1))
10570 {
10571 usymtab_clearAlias (s1);
10572 usymtab_addMustAlias (s1, s2);
28bf4b0b 10573 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
10574 }
10575 else
10576 {
10577 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
616915dd 10578 }
10579
10580 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
10581 {
10582 usymtab_unguard (s1);
10583 }
10584 }
10585}
10586
10587exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
10588{
10589 if (exprNode_isDefined (e))
10590 {
10591 e->loc = fileloc_update (e->loc, loc);
10592 }
10593 else
10594 {
10595 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
10596 }
10597
10598 return (e);
10599}
10600
10601static void checkUniqueParams (exprNode fcn,
10602 /*@notnull@*/ exprNode current,
10603 exprNodeList args,
10604 int paramno, uentry ucurrent)
10605{
10606 int iparamno = 0;
10607 sRef thisref = exprNode_getSref (current);
10608
10609 /*
10610 ** Check if any argument could match this argument.
10611 */
10612
10613 exprNodeList_elements (args, icurrent)
10614 {
10615 iparamno++;
10616
10617 if (iparamno != paramno)
10618 {
10619 sRef sr = exprNode_getSref (icurrent);
10620
10621 if (sRef_similarRelaxed (thisref, sr))
10622 {
10623 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
10624 {
10625 voptgenerror
10626 (FLG_ALIASUNIQUE,
10627 message
10628 ("Parameter %d (%s) to function %s is declared %s but "
10629 "is aliased by parameter %d (%s)",
10630 paramno,
10631 exprNode_unparse (current),
10632 exprNode_unparse (fcn),
10633 alkind_unparse (uentry_getAliasKind (ucurrent)),
10634 iparamno, exprNode_unparse (icurrent)),
10635 current->loc);
10636 }
10637 }
10638 else
10639 {
10640 sRefSet aliases = usymtab_canAlias (sr);
10641
10642 sRefSet_allElements (aliases, asr)
10643 {
10644 if (ctype_isUnknown (sRef_getType (thisref)))
10645 {
10646 sRef_setType (thisref, uentry_getType (ucurrent));
10647 }
10648
10649 if (sRef_similarRelaxed (thisref, asr))
10650 {
10651 if (sRef_isExternal (asr))
10652 {
10653 if (sRef_isLocalState (thisref))
10654 {
10655 ; /* okay */
10656 }
10657 else
10658 {
10659 sRef base = sRef_getRootBase (asr);
10660
10661 if (!sRef_similar (sRef_getBase (asr), thisref))
10662 {
10663 if (sRef_isUnique (base) || sRef_isOnly (base)
10664 || sRef_isKept (base)
10665 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
10666 || (sRef_isAddress (thisref)
10667 && sRef_isLocalVar (sRef_getRootBase (thisref))))
10668 {
10669 ; /* okay, no error */
10670 }
10671 else
10672 {
10673 voptgenerror
10674 (FLG_MAYALIASUNIQUE,
10675 message
10676 ("Parameter %d (%s) to function %s is declared %s but "
10677 "may be aliased externally by parameter %d (%s)",
10678 paramno,
10679 exprNode_unparse (current),
10680 exprNode_unparse (fcn),
10681 alkind_unparse (uentry_getAliasKind (ucurrent)),
10682 iparamno, exprNode_unparse (icurrent)),
10683 current->loc);
10684 }
10685 }
10686 }
10687 }
10688 else
10689 {
10690 voptgenerror
10691 (FLG_ALIASUNIQUE,
10692 message
10693 ("Parameter %d (%s) to function %s is declared %s but "
10694 "is aliased externally by parameter %d (%s) through "
10695 "alias %q",
10696 paramno,
10697 exprNode_unparse (current),
10698 exprNode_unparse (fcn),
10699 alkind_unparse (uentry_getAliasKind (ucurrent)),
10700 iparamno, exprNode_unparse (icurrent),
10701 sRef_unparse (asr)),
10702 current->loc);
10703 }
10704 }
10705 } end_sRefSet_allElements;
10706 sRefSet_free (aliases);
10707 }
10708 }
10709 } end_exprNodeList_elements;
10710}
10711
10712long exprNode_getLongValue (exprNode e) {
10713 long value;
10714
10715 if (exprNode_hasValue (e)
10716 && multiVal_isInt (exprNode_getValue (e)))
10717 {
10718 value = multiVal_forceInt (exprNode_getValue (e));
10719 }
10720 else
10721 {
10722 value = 0;
10723 }
10724
10725 return value;
10726}
10727
d46ce6a4 10728/*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
616915dd 10729{
84c9ffbf 10730 if (exprNode_isDefined (p_e) )
d46ce6a4 10731 return ( p_e->loc );
616915dd 10732 else
10733 return fileloc_undefined;
10734}
10735
bb25bea6 10736/*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
616915dd 10737{
10738 /*
10739 ** Returns the location of the sequence point following e.
10740 **
10741 ** Only works for statements (for now).
10742 */
10743
10744 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
10745 lltok t = exprData_getUopTok (e->edata);
bb25bea6 10746 return fileloc_copy(lltok_getLoc (t));
616915dd 10747 } else {
28bf4b0b 10748 //drl possible problem : warning fix
616915dd 10749 // llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
10750 return fileloc_undefined;
10751 }
10752 }
10753
9280addf 10754exprNode exprNode_createNew(ctype c)
10755{
10756 exprNode ret;
10757
10758 ret = exprNode_createPlain (c);
10759
10760 return ret;
10761}
d30bc0c7 10762
10763bool exprNode_isInitBlock (exprNode e)
10764{
10765 return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);
10766}
This page took 5.341535 seconds and 5 git commands to generate.