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