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