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