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