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