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