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