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