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