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