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