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