2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
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.
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.
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.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
28 # include <ctype.h> /* for isdigit */
29 # include "splintMacros.nf"
31 # include "cgrammar.h"
32 # include "cscanner.h"
33 # include "cscannerHelp.h"
34 # include "cgrammar_tokens.h"
36 # include "exprChecks.h"
37 # include "transferChecks.h"
38 # include "exprNodeSList.h"
40 static bool exprNode_sameStorage (exprNode p_e1, exprNode p_e2) /*@*/ ;
41 static bool exprNode_isEmptyStatement (exprNode p_e);
42 static /*@exposed@*/ exprNode exprNode_firstStatement (/*@returned@*/ exprNode p_e);
43 static bool exprNode_isFalseConstant (exprNode p_e) /*@*/ ;
44 static bool exprNode_isStatement (exprNode p_e);
45 static void checkGlobUse (uentry p_glob, bool p_isCall, /*@notnull@*/ exprNode p_e);
46 static void exprNode_addUse (exprNode p_e, /*@exposed@*/ sRef p_s);
47 static bool exprNode_matchArgType (ctype p_ct, exprNode p_e);
48 static exprNode exprNode_fakeCopy (exprNode p_e) /*@*/ ;
49 static exprNode exprNode_statementError (/*@only@*/ exprNode p_e, /*@only@*/ lltok p_t);
50 static bool exprNode_matchTypes (exprNode p_e1, exprNode p_e2);
51 static void checkUniqueParams (exprNode p_fcn,
52 /*@notnull@*/ exprNode p_current, exprNodeList p_args,
53 int p_paramno, uentry p_ucurrent);
54 static void updateAliases (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2);
55 static bool abstractOpError (ctype p_tr1, ctype p_tr2, lltok p_op,
56 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2,
57 fileloc p_loc1, fileloc p_loc2)
58 /*@modifies g_warningstream@*/ ;
59 static ctype checkNumerics (ctype p_tr1, ctype p_tr2, ctype p_te1, ctype p_te2,
60 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, lltok p_op);
61 static void doAssign (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, bool p_isInit);
62 static void checkSafeUse (exprNode p_e, /*@exposed@*/ sRef p_s);
63 static void reflectNullTest (/*@notnull@*/ exprNode p_e, bool p_isnull);
64 static void checkMacroParen (exprNode p_e);
65 static exprNodeSList exprNode_flatten (/*@dependent@*/ exprNode p_e);
66 static void exprNode_checkSetAny (exprNode p_e, /*@dependent@*/ cstring p_name);
67 static void exprNode_checkUse (exprNode p_e, /*@exposed@*/ sRef p_s, fileloc p_loc);
68 static void exprNode_mergeUSs (exprNode p_res, exprNode p_other);
69 static void exprNode_mergeCondUSs (exprNode p_res, exprNode p_other1, exprNode p_other2);
70 static /*@only@*/ /*@notnull@*/ exprNode exprNode_fromIdentifierAux (/*@observer@*/ uentry p_c);
71 static void checkAnyCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn,
72 /*@dependent@*/ cstring p_fname,
73 uentryList p_pn, exprNodeList p_args,
74 bool p_hasMods, sRefSet p_mods, bool p_isSpec,
76 static void checkOneArg (uentry p_ucurrent, /*@notnull@*/ exprNode p_current,
77 /*@dependent@*/ exprNode p_fcn, bool p_isSpec, int p_argno, int p_totargs);
79 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn, uentryList p_params, exprNodeList p_args);
81 static /*@only@*/ exprNode exprNode_effect (exprNode p_e)
82 /*@globals internalState@*/ ;
83 static /*@only@*/ cstring exprNode_doUnparse (exprNode p_e);
84 static /*@observer@*/ cstring exprNode_rootVarName (exprNode p_e);
85 static /*@exposed@*/ exprNode
86 exprNode_lastStatement (/*@returned@*/ exprNode p_e);
88 static /*@only@*/ exprNode s_mustExitNode = exprNode_undefined;
90 static int checkArgsReal (uentry p_fcn, /*@dependent@*/ exprNode p_f,
92 exprNodeList p_args, bool p_isIter, exprNode p_ret);
94 static bool inEffect = FALSE;
95 static int nowalloc = 0;
96 static int totalloc = 0;
97 static int maxalloc = 0;
99 static /*@only@*/ uentry regArg;
100 static /*@only@*/ uentry outArg;
101 static /*@only@*/ uentry outStringArg;
102 static /*@exposed@*/ sRef stdinRef;
103 static /*@exposed@*/ sRef stdoutRef;
104 static /*@only@*/ uentry csArg;
105 static /*@only@*/ uentry csOnlyArg;
106 static ctype cstringType;
107 static ctype ctypeType;
108 static ctype filelocType;
109 static bool initMod = FALSE;
111 /*@function void exprNode_swap (sef exprNode, sef exprNode)@*/
113 # define exprNode_swap(e1,e2) do { exprNode m_tmp = (e1); (e1) = (e2); (e2) = m_tmp; } while (FALSE)
116 static void exprNode_defineConstraints(/*@sef@*/ /*@special@*/ /*@notnull@*/ exprNode e)
117 /*@defines e->requiresConstraints, e->ensuresConstraints,
118 e->trueEnsuresConstraints, e->falseEnsuresConstraints @*/
120 e->requiresConstraints = constraintList_makeNew ();
121 e->ensuresConstraints = constraintList_makeNew ();
122 e->trueEnsuresConstraints = constraintList_makeNew ();
123 e->falseEnsuresConstraints = constraintList_makeNew ();
127 ** must occur after library has been read
130 void exprNode_initMod (void)
131 /*@globals undef regArg, undef outArg, undef outStringArg,
132 undef csOnlyArg, undef csArg;
139 cstringType = ctype_unknown;
140 ctypeType = ctype_unknown;
141 filelocType = ctype_unknown;
143 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
145 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
148 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
150 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
153 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
155 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
158 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdin")))
160 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdin"));
162 else /* define stdin */
164 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdin"),
166 fileloc_getBuiltin (),
168 uentry_setHasNameError (ue);
169 ue = usymtab_supGlobalEntryReturn (ue);
172 stdinRef = sRef_makePointer (uentry_getSref (ue));
174 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdout")))
176 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdout"));
180 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdout"),
182 fileloc_getBuiltin (),
184 uentry_setHasNameError (ue);
185 ue = usymtab_supGlobalEntryReturn (ue);
188 stdoutRef = sRef_makePointer (uentry_getSref (ue));
190 tmp = idDecl_create (cstring_undefined, qtype_create (ctype_unknown));
192 regArg = uentry_makeParam (tmp, PARAMUNKNOWN);
195 qtype_addQual (qtype_create (ctype_makePointer (ctype_unknown)),
198 outArg = uentry_makeParam (tmp, PARAMUNKNOWN);
200 idDecl_setTyp (tmp, qtype_addQual (qtype_create (ctype_string),
203 outStringArg = uentry_makeParam (tmp, PARAMUNKNOWN);
205 idDecl_setTyp (tmp, qtype_addQual (qtype_addQual (qtype_create (cstringType),
207 qual_createNull ()));
209 csOnlyArg = uentry_makeParam (tmp, PARAMUNKNOWN);
211 idDecl_setTyp (tmp, qtype_addQual (qtype_create (cstringType), qual_createNull ()));
212 csArg = uentry_makeParam (tmp, PARAMUNKNOWN);
218 exprNode_destroyMod (void)
219 /*@globals killed regArg, killed outArg, killed outStringArg,
220 killed s_mustExitNode, initMod @*/
224 /* evans 2002-07-12: changed uentry_free to uentry_freeComplete */
225 uentry_freeComplete (regArg);
226 uentry_freeComplete (outArg);
227 uentry_freeComplete (outStringArg);
229 exprNode_free (s_mustExitNode);
236 static void exprNode_resetSref (/*@notnull@*/ exprNode e)
238 e->sref = sRef_undefined;
241 exprNode exprNode_fakeCopy (exprNode e)
243 /*@-temptrans@*/ /*@-retalias@*/
245 /*@=temptrans@*/ /*@=retalias@*/
248 static bool isFlagKey (char key)
250 return (key == '-' || key == '+' || key == ' ' || key == '#');
253 static void exprNode_combineControl (/*@notnull@*/ exprNode ret,
254 /*@notnull@*/ exprNode ifclause,
255 /*@notnull@*/ exprNode elseclause)
257 ret->canBreak = ifclause->canBreak || elseclause->canBreak;
260 (ifclause->mustBreak || exprNode_mustEscape (ifclause))
261 && (elseclause->mustBreak || exprNode_mustEscape (elseclause));
263 ret->exitCode = exitkind_combine (ifclause->exitCode,
264 elseclause->exitCode);
269 ** For exprNode's returned by exprNode_effect.
272 static bool shallowKind (exprKind kind)
274 return (kind == XPR_STRINGLITERAL
275 || kind == XPR_NUMLIT
278 || kind == XPR_NODE);
282 exprNode_freeIniter (/*@only@*/ exprNode e)
284 if (!exprNode_isError (e))
290 ** Its a fake copy, don't free the field->rec and field->field
295 sfree (e->edata->field);
301 exprNode_free (e->edata->op->b);
302 /*@-compdestroy@*/ sfree (e->edata->op); /*@=compdestroy@*/
306 llbug (message ("other: %s", exprNode_unparse (e)));
309 multiVal_free (e->val);
310 cstring_free (e->etext);
311 fileloc_free (e->loc);
312 sRefSet_free (e->uses);
313 sRefSet_free (e->sets);
314 sRefSet_free (e->msets);
315 guardSet_free (e->guards);
317 constraintList_free(e->requiresConstraints);
318 constraintList_free(e->ensuresConstraints);
319 constraintList_free(e->trueEnsuresConstraints);
320 constraintList_free(e->falseEnsuresConstraints);
322 e->requiresConstraints = NULL;
323 e->ensuresConstraints = NULL;
324 e->trueEnsuresConstraints = NULL;
325 e->falseEnsuresConstraints = NULL;
332 exprNode_freeShallow (/*@only@*/ exprNode e)
334 if (!exprNode_isError (e))
336 if (shallowKind (e->kind))
343 if (e->kind == XPR_EMPTY
344 || e->kind == XPR_BODY
345 || e->kind == XPR_STRINGLITERAL
346 || e->kind == XPR_NUMLIT
347 || e->kind == XPR_NODE
348 || e->kind == XPR_OFFSETOF
349 || e->kind == XPR_ALIGNOFT
350 || e->kind == XPR_ALIGNOF
351 || e->kind == XPR_SIZEOFT
352 || e->kind == XPR_SIZEOF)
354 /* don't free anything */
358 /* multiVal_free (e->val); */
359 cstring_free (e->etext);
360 fileloc_free (e->loc);
361 sRefSet_free (e->uses);
362 sRefSet_free (e->sets);
363 sRefSet_free (e->msets);
364 guardSet_free (e->guards);
365 exprData_freeShallow (e->edata, e->kind);
367 /*@-compdestroy@*/ sfree (e); /*@=compdestroy@*/
376 exprNode_free (exprNode e)
378 if (!exprNode_isError (e))
382 multiVal_free (e->val);
383 cstring_free (e->etext);
384 fileloc_free (e->loc);
385 sRefSet_free (e->uses);
386 sRefSet_free (e->sets);
387 sRefSet_free (e->msets);
388 guardSet_free (e->guards);
389 exprData_free (e->edata, e->kind);
391 constraintList_free(e->requiresConstraints);
392 constraintList_free(e->ensuresConstraints);
393 constraintList_free(e->trueEnsuresConstraints);
394 constraintList_free(e->falseEnsuresConstraints);
396 e->requiresConstraints = NULL;
397 e->ensuresConstraints = NULL;
398 e->trueEnsuresConstraints = NULL;
399 e->falseEnsuresConstraints = NULL;
409 exprNode_makeError ()
411 return exprNode_undefined;
414 static /*@out@*/ /*@only@*/ /*@notnull@*/ exprNode
417 exprNode ret = (exprNode) dmalloc (sizeof (*ret));
418 /* static int lastexpnodes = 0; */
423 if (nowalloc > maxalloc)
431 static /*@notnull@*/ /*@special@*/ exprNode
432 exprNode_createPlain (ctype c)
434 /*@ensures isnull result->edata, result->loc, result->val, result->guards,
435 result->uses, result->sets, result->msets, result->etext @*/
438 exprNode e = exprNode_new ();
442 e->val = multiVal_undefined;
443 e->sref = sRef_undefined;
444 e->etext = cstring_undefined;
445 e->loc = fileloc_undefined;
446 e->guards = guardSet_undefined;
447 e->uses = sRefSet_undefined;
448 e->sets = sRefSet_undefined;
449 e->msets = sRefSet_undefined;
450 e->edata = exprData_undefined;
451 e->exitCode = XK_NEVERESCAPE;
453 e->mustBreak = FALSE;
454 e->isJumpPoint = FALSE;
456 exprNode_defineConstraints(e);
461 /*@observer@*/ exprNode exprNode_makeMustExit (void)
463 if (exprNode_isUndefined (s_mustExitNode))
465 s_mustExitNode = exprNode_createPlain (ctype_unknown);
466 s_mustExitNode->exitCode = XK_MUSTEXIT;
469 return s_mustExitNode;
473 static /*@notnull@*/ /*@special@*/ exprNode exprNode_create (ctype c)
475 /*@post:isnull result->edata, result->guards, result->val,
476 result->uses, result->sets, result->msets@*/
479 exprNode e = exprNode_createPlain (c);
480 e->loc = fileloc_copy (g_currentloc);
484 static /*@notnull@*/ /*@special@*/ exprNode exprNode_createUnknown (void)
486 /*@post:isnull result->edata, result->guards,
487 result->uses, result->sets, result->msets@*/
490 return (exprNode_create (ctype_unknown));
493 static /*@notnull@*/ /*@special@*/ exprNode
494 exprNode_createLoc (ctype c, /*@keep@*/ fileloc loc)
496 /*@post:isnull result->edata, result->guards, result->val,
497 result->uses, result->sets, result->msets@*/
500 exprNode e = exprNode_createPlain (c);
506 exprNode_copySets (/*@special@*/ /*@notnull@*/ exprNode ret, exprNode e)
507 /*@defines ret->guards, ret->uses, ret->sets, ret->msets@*/
509 if (exprNode_isDefined (e))
511 ret->guards = guardSet_copy (e->guards);
512 ret->uses = sRefSet_newCopy (e->uses);
513 ret->sets = sRefSet_newCopy (e->sets);
514 ret->msets = sRefSet_newCopy (e->msets);
518 ret->guards = guardSet_undefined;
519 ret->uses = sRefSet_undefined;
520 ret->sets = sRefSet_undefined;
521 ret->msets = sRefSet_undefined;
525 static /*@notnull@*/ /*@special@*/ exprNode
526 exprNode_createPartialLocCopy (exprNode e, /*@only@*/ fileloc loc)
528 /*@post:isnull result->edata, result->etext@*/
531 exprNode ret = exprNode_new ();
533 if (exprNode_isError (e))
535 ret->typ = ctype_unknown;
536 ret->val = multiVal_undefined;
538 ret->guards = guardSet_undefined;
539 ret->uses = sRefSet_undefined;
540 ret->sets = sRefSet_undefined;
541 ret->msets = sRefSet_undefined;
546 ret->val = multiVal_copy (e->val);
548 ret->guards = guardSet_copy (e->guards);
549 ret->uses = sRefSet_newCopy (e->uses);
550 ret->sets = sRefSet_newCopy (e->sets);
551 ret->msets = sRefSet_newCopy (e->msets);
554 ret->kind = XPR_EMPTY;
555 ret->sref = sRef_undefined;
556 ret->etext = cstring_undefined;
557 ret->exitCode = XK_NEVERESCAPE;
558 ret->canBreak = FALSE;
559 ret->mustBreak = FALSE;
560 ret->isJumpPoint = FALSE;
561 ret->edata = exprData_undefined;
563 exprNode_defineConstraints(ret);
569 static /*@notnull@*/ /*@special@*/ exprNode
570 exprNode_createPartialCopy (exprNode e)
572 /*@post:isnull result->edata, result->etext@*/
575 return (exprNode_createPartialLocCopy (e, fileloc_copy (exprNode_loc (e))));
578 static /*@notnull@*/ /*@special@*/ exprNode
579 exprNode_createPartialNVCopy (exprNode e)
581 /*@post:isnull result->edata, result->etext, result->val @*/
584 exprNode ret = exprNode_new ();
586 if (exprNode_isError (e))
588 ret->typ = ctype_unknown;
589 ret->loc = fileloc_undefined;
590 ret->guards = guardSet_undefined;
591 ret->uses = sRefSet_undefined;
592 ret->sets = sRefSet_undefined;
593 ret->msets = sRefSet_undefined;
598 ret->loc = fileloc_copy (e->loc);
599 ret->guards = guardSet_copy (e->guards);
600 ret->uses = sRefSet_newCopy (e->uses);
601 ret->sets = sRefSet_newCopy (e->sets);
602 ret->msets = sRefSet_newCopy (e->msets);
605 ret->val = multiVal_undefined;
606 ret->kind = XPR_EMPTY;
607 ret->sref = sRef_undefined;
608 ret->etext = cstring_undefined;
609 ret->exitCode = XK_NEVERESCAPE;
610 ret->canBreak = FALSE;
611 ret->mustBreak = FALSE;
612 ret->isJumpPoint = FALSE;
613 ret->edata = exprData_undefined;
615 exprNode_defineConstraints(ret);
620 static /*@notnull@*/ /*@special@*/ exprNode
621 exprNode_createSemiCopy (exprNode e)
623 /*@post:isnull result->edata, result->etext, result->sets,
624 result->msets, result->uses, result->guards@*/
627 if (exprNode_isError (e))
629 return exprNode_createPlain (ctype_unknown);
633 exprNode ret = exprNode_new ();
636 ret->val = multiVal_copy (e->val);
637 ret->loc = fileloc_copy (e->loc);
638 ret->guards = guardSet_undefined;
639 ret->uses = sRefSet_undefined;
640 ret->sets = sRefSet_undefined;
641 ret->msets = sRefSet_undefined;
643 ret->kind = XPR_EMPTY;
644 ret->sref = sRef_undefined;
645 ret->etext = cstring_undefined;
646 ret->exitCode = XK_NEVERESCAPE;
647 ret->canBreak = FALSE;
648 ret->mustBreak = FALSE;
649 ret->isJumpPoint = FALSE;
650 ret->edata = exprData_undefined;
652 exprNode_defineConstraints(ret);
659 exprNode_isNullValue (exprNode e)
661 if (exprNode_isDefined (e))
663 multiVal m = exprNode_getValue (e);
665 if (multiVal_isInt (m))
667 return (multiVal_forceInt (m) == 0);
675 exprNode_isUnknownConstant (/*@notnull@*/ exprNode e)
677 while (e->kind == XPR_PARENS)
679 e = exprData_getUopNode (e->edata);
681 if (!exprNode_isDefined (e))
686 /* evans 2002-02-05: was llassert (exprNode_isDefined (e)); but this can fail */
689 if (e->kind == XPR_CONST)
691 multiVal m = exprNode_getValue (e);
693 if (multiVal_isUnknown (m))
703 exprNode_numLiteral (ctype c, /*@temp@*/ cstring t,
704 /*@only@*/ fileloc loc, long val)
706 exprNode e = exprNode_createLoc (c, loc);
708 e->kind = XPR_NUMLIT;
710 llassert (multiVal_isUndefined (e->val));
711 e->val = multiVal_makeInt (val);
712 e->edata = exprData_makeLiteral (cstring_copy (t));
716 e->sref = sRef_makeUnknown ();
717 sRef_setDefNull (e->sref, e->loc);
720 DPRINTF (("Num lit: %s / %s", exprNode_unparse (e), ctype_unparse (exprNode_getType (e))));
725 exprNode_charLiteral (char c, cstring text, /*@only@*/ fileloc loc)
727 exprNode e = exprNode_createLoc (ctype_char, loc);
729 if (context_getFlag (FLG_CHARINTLITERAL))
731 e->typ = ctype_makeConj (ctype_char, ctype_int);
734 e->kind = XPR_NUMLIT;
735 e->val = multiVal_makeChar (c);
737 e->edata = exprData_makeLiteral (cstring_copy (text));
742 exprNode_floatLiteral (double d, ctype ct, cstring text, /*@only@*/ fileloc loc)
744 exprNode e = exprNode_createLoc (ct, loc);
746 e->kind = XPR_NUMLIT;
747 e->val = multiVal_makeDouble (d);
748 e->edata = exprData_makeLiteral (cstring_copy (text));
752 multiVal exprNode_getValue (exprNode e)
754 while (exprNode_isInParens (e)) {
755 if (e->edata != NULL) {
756 e = exprData_getUopNode (e->edata);
762 if (exprNode_isDefined (e)) {
765 return multiVal_undefined;
770 exprNode_combineLiterals (exprNode e, exprNode rest)
774 /* Both must be string literals. */
776 if (exprNode_isUndefined (rest) || exprNode_isUndefined (e))
778 exprNode_free (rest);
782 if (!exprNode_isStringLiteral (e))
786 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e),
787 exprNode_unparse (rest)),
789 exprNode_free (rest);
793 if (!exprNode_isStringLiteral (rest))
797 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e), exprNode_unparse (rest)),
800 exprNode_free (rest);
804 ns = cstring_concat (multiVal_forceString (exprNode_getValue (e)),
805 multiVal_forceString (exprNode_getValue (rest)));
807 multiVal_free (e->val);
808 exprData_free (e->edata, e->kind);
809 e->edata = exprData_makeLiteral (cstring_copy (ns));
810 e->val = multiVal_makeString (ns);
811 exprNode_free (rest);
816 exprNode_rawStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
818 exprNode e = exprNode_createLoc (ctype_string, loc);
819 size_t len = cstring_length (t);
821 if (context_getFlag (FLG_STRINGLITERALLEN))
823 if (len > size_fromInt (context_getValue (FLG_STRINGLITERALLEN)))
825 voptgenerror (FLG_STRINGLITERALLEN,
827 ("String literal length (%d) exceeds maximum "
828 "length (%d): \"%s\"",
830 context_getValue (FLG_STRINGLITERALLEN),
836 e->kind = XPR_STRINGLITERAL;
837 e->val = multiVal_makeString (cstring_copy (t));
838 e->edata = exprData_makeLiteral (t);
839 e->sref = sRef_makeConst (ctype_string);
841 if (context_getFlag (FLG_READONLYSTRINGS))
843 sRef_setAliasKind (e->sref, AK_STATIC, fileloc_undefined);
844 sRef_setExKind (e->sref, XO_OBSERVER, loc);
848 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
851 return (e); /* s released */
855 exprNode_wideStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
857 exprNode res = exprNode_stringLiteral (t, loc);
858 res->typ = ctype_makeWideString ();
863 exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
865 size_t len = size_fromInt (size_toInt (cstring_length (t)) - 2);
866 char *ts = cstring_toCharsSafe (t);
867 char *s = cstring_toCharsSafe (cstring_create (len + 1));
869 llassert (*ts == '\"' && *(ts + len + 1) == '\"');
870 strncpy (s, ts+1, len);
873 return exprNode_rawStringLiteral (cstring_fromCharsO (s), loc);
876 exprNode exprNode_fromUIO (cstring c)
878 fileloc loc = context_getSaveLocation ();
879 exprNode e = exprNode_createPlain (ctype_unknown);
883 if (fileloc_isUndefined (loc))
885 loc = fileloc_copy (g_currentloc);
888 e->loc = loc; /* save loc was mangled */
889 e->sref = sRef_undefined;
891 if (usymtab_exists (c))
893 uentry ue = usymtab_lookupEither (c);
895 if (uentry_isDatatype (ue)
896 && uentry_isSpecified (ue))
899 (message ("%q: Specified datatype %s used in code, but not defined. "
900 "(Cannot continue reasonably from this error.)",
901 fileloc_unparse (e->loc), c));
909 llassertprint (!usymtab_exists (c), ("Entry exists: %s", c));
912 ** was supercedeGlobalEntry...is this better?
915 if (!context_inIterEnd ())
917 if (context_inMacro ())
919 if (context_getFlag (FLG_UNRECOG))
923 message ("Unrecognized identifier in macro definition: %s", c), e->loc);
927 flagcode_recordSuppressed (FLG_UNRECOG);
933 (FLG_UNRECOG, message ("Unrecognized identifier: %s", c), e->loc);
937 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
939 /* No alias errors for unrecognized identifiers */
940 sRef_setAliasKind (e->sref, AK_ERROR, loc);
945 exprNode exprNode_makeConstantString (cstring c, /*@only@*/ fileloc loc)
947 exprNode e = exprNode_createPlain (ctype_unknown);
950 e->sref = sRef_makeConst (ctype_string);
951 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
952 e->typ = ctype_string;
954 /* No alias errors for unrecognized identifiers */
955 sRef_setAliasKind (e->sref, AK_STATIC, loc);
956 sRef_setExKind (e->sref, XO_OBSERVER, loc);
961 exprNode exprNode_createId (/*@observer@*/ uentry c)
963 if (uentry_isValid (c))
965 exprNode e = exprNode_new ();
967 DPRINTF (("create id: %s", uentry_unparse (c)));
969 e->typ = uentry_getType (c);
971 if (uentry_isFunction (c)
972 && !sRef_isLocalVar (uentry_getSref (c)))
974 e->sref = sRef_undefined;
978 e->sref = uentry_getSref (c);
981 if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
983 sRef_setDefined (e->sref, fileloc_undefined);
987 ** yoikes! leaving this out was a heinous bug...that would have been
988 ** caught if i had splint working first. gag!
991 e->etext = cstring_undefined;
993 if (uentry_isEitherConstant (c))
996 e->val = multiVal_copy (uentry_getConstantValue (c));
1001 e->val = multiVal_unknown ();
1004 e->edata = exprData_makeId (c);
1005 e->loc = context_getSaveLocation ();
1007 if (fileloc_isUndefined (e->loc))
1009 fileloc_free (e->loc);
1010 e->loc = fileloc_copy (g_currentloc);
1013 e->guards = guardSet_new ();
1014 e->sets = sRefSet_new ();
1015 e->msets = sRefSet_new ();
1016 e->uses = sRefSet_new ();
1018 /*> missing fields, detected by splint <*/
1019 e->exitCode = XK_NEVERESCAPE;
1020 e->isJumpPoint = FALSE;
1021 e->canBreak = FALSE;
1022 e->mustBreak = FALSE;
1024 exprNode_defineConstraints (e);
1029 return exprNode_createUnknown ();
1033 /*@notnull@*/ exprNode
1034 exprNode_fromIdentifier (/*@observer@*/ uentry c)
1038 if (context_justPopped ()) /* watch out! c could be dead */
1040 uentry ce = usymtab_lookupSafe (cscannerHelp_observeLastIdentifier ());
1042 if (uentry_isValid (ce))
1048 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
1052 ret = exprNode_fromIdentifierAux (c);
1056 static void exprNode_checkStringLiteralLength (ctype t1, exprNode e2)
1058 multiVal mval = exprNode_getValue (e2);
1062 if (ctype_isFixedArray (t1))
1064 size_t nelements = ctype_getArraySize (t1);
1066 llassert (multiVal_isString (mval));
1067 slit = multiVal_forceString (mval);
1069 len = cstring_lengthExpandEscapes (slit);
1071 llassert (exprNode_isDefined (e2));
1073 if (len == nelements)
1077 temp = cstring_expandEscapes (slit);
1079 if (temp[len-1] == '\0')
1082 (FLG_STRINGLITNOROOMFINALNULL,
1083 message ("String literal with %d character%& "
1084 "is assigned to %s (no room for final null terminator): %s",
1085 size_toInt (len + 1),
1087 exprNode_unparse (e2)),
1093 (FLG_STRINGLITNOROOM,
1094 message ("String literal with %d character%& "
1095 "is assigned to %s (no room for null terminator): %s",
1096 size_toInt (len + 1),
1098 exprNode_unparse (e2)),
1102 else if (len > nelements)
1105 (FLG_STRINGLITTOOLONG,
1106 message ("String literal with %d character%& (counting null terminator) "
1107 "is assigned to %s (insufficient storage available): %s",
1108 size_toInt (len + 1),
1110 exprNode_unparse (e2)),
1113 else if (len < nelements - 1)
1116 (FLG_STRINGLITSMALLER,
1117 message ("String literal with %d character%& is assigned to %s (possible waste of storage): %s",
1118 size_toInt (len + 1),
1120 exprNode_unparse (e2)),
1130 static /*@only@*/ /*@notnull@*/ exprNode
1131 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
1133 exprNode e = exprNode_createId (c);
1136 uentry_setUsed (c, e->loc);
1138 if (uentry_isVar (c) && sRef_isFileOrGlobalScope (sr))
1140 checkGlobUse (c, FALSE, e);
1147 exprNode_isZero (exprNode e)
1149 if (exprNode_isDefined (e))
1151 multiVal m = exprNode_getValue (e);
1153 if (multiVal_isInt (m))
1155 return (multiVal_forceInt (m) == 0);
1163 exprNode_isNonNegative (exprNode e)
1165 if (exprNode_isDefined (e))
1167 multiVal m = exprNode_getValue (e);
1169 if (multiVal_isInt (m))
1171 return (multiVal_forceInt (m) >= 0);
1175 ** This is not always true if programmer defines enum
1176 ** values, but then the constant should be known.
1179 if (ctype_isEnum (ctype_realType (e->typ)))
1189 ** a[x] - uses a but NOT a[]
1190 ** result sref = a[] (set/use in assignment)
1192 ** The syntax x[a] is also legal in C, and has the same
1193 ** semantics. If ind is an array, and arr is an int, flip
1198 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
1201 ** error in arr, error propagates (no new messages)
1202 ** error in ind, assume valid and continue
1205 DPRINTF (("Array fetch: %s / %s",
1206 exprNode_unparse (e1), exprNode_unparse (e2)));
1208 if (exprNode_isError (e1))
1211 return (exprNode_makeError ());
1217 ctype carr = exprNode_getType (e1);
1218 ctype crarr = ctype_realType (carr);
1221 ** this sets up funny aliasing, that leads to spurious
1222 ** splint errors. Hence, the i2 comments.
1225 /* evans 2001-09-09 added ctype_isKnown so there is no swap when e1 type is unknown */
1226 if (ctype_isKnown (crarr)
1227 && !ctype_isRealArray (crarr)
1228 && ctype_isRealNumeric (crarr)
1229 && !exprNode_isError (e2)
1230 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1235 carr = exprNode_getType (arr);
1236 crarr = ctype_realType (carr);
1244 DPRINTF (("arr: %s", exprNode_unparse (arr)));
1246 if (sRef_possiblyNull (arr->sref))
1248 if (!usymtab_isGuarded (arr->sref))
1250 if (!context_inSizeof() )
1252 if (optgenerror (FLG_NULLDEREF,
1253 message ("Index of %s pointer %q: %s",
1254 sRef_nullMessage (arr->sref),
1255 sRef_unparse (arr->sref),
1256 exprNode_unparse (arr)),
1259 DPRINTF (("ref: %s", sRef_unparseFull (arr->sref)));
1260 sRef_showNullInfo (arr->sref);
1262 /* suppress future messages */
1263 sRef_setNullError (arr->sref);
1269 if (exprNode_isError (ind))
1271 if ((ctype_isArrayPtr (crarr)
1272 && !ctype_isFunction (crarr))
1273 || ctype_isUnknown (carr))
1275 exprNode ret = exprNode_createPartialCopy (arr);
1277 if (ctype_isKnown (carr))
1279 ret->typ = ctype_baseArrayPtr (crarr);
1283 ret->typ = ctype_unknown;
1286 ret->sref = sRef_makeArrayFetch (arr->sref);
1288 ret->kind = XPR_FETCH;
1291 ** Because of funny aliasing (when arr and ind are
1292 ** flipped) spurious errors would be reported here.
1295 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1296 checkSafeUse (ret, arr->sref);
1301 voptgenerror (FLG_TYPE,
1302 message ("Array fetch from non-array (%t): %s[%s]", carr,
1303 exprNode_unparse (e1), exprNode_unparse (e2)),
1305 exprNode_free (arr);
1306 return (exprNode_makeError ());
1311 if (!ctype_isForceRealInt (&(ind->typ)))
1313 ctype rt = ctype_realType (ind->typ);
1315 if (ctype_isChar (rt))
1319 message ("Array fetch using non-integer, %t: %s[%s]",
1321 exprNode_unparse (e1), exprNode_unparse (e2)),
1324 else if (ctype_isEnum (rt))
1328 message ("Array fetch using non-integer, %t: %s[%s]",
1330 exprNode_unparse (e1), exprNode_unparse (e2)),
1337 message ("Array fetch using non-integer, %t: %s[%s]",
1339 exprNode_unparse (e1), exprNode_unparse (e2)),
1343 multiVal_free (ind->val);
1344 ind->val = multiVal_unknown ();
1347 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1349 exprNode ret = exprNode_createSemiCopy (arr);
1350 multiVal m = exprNode_getValue (ind);
1352 ret->typ = ctype_baseArrayPtr (crarr);
1353 ret->kind = XPR_FETCH;
1355 if (multiVal_isInt (m))
1357 int i = (int) multiVal_forceInt (m);
1359 if (sRef_isValid (arr->sref)) {
1360 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1362 ret->sref = sRef_undefined;
1367 ret->sref = sRef_makeArrayFetch (arr->sref);
1370 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1371 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1372 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1374 /* (see comment on spurious errors above) */
1375 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1377 exprNode_checkUse (ret, ind->sref, ind->loc);
1378 exprNode_checkUse (ret, arr->sref, arr->loc);
1384 if (ctype_isUnknown (carr))
1386 exprNode ret = exprNode_createPartialCopy (arr);
1388 ret->kind = XPR_FETCH;
1389 ret->typ = ctype_unknown;
1390 ret->sets = sRefSet_union (ret->sets, ind->sets);
1391 ret->msets = sRefSet_union (ret->msets, ind->msets);
1392 ret->uses = sRefSet_union (ret->uses, ind->uses);
1394 /* (see comment on spurious errors above) */
1395 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1397 exprNode_checkUse (ret, ind->sref, ind->loc);
1398 exprNode_checkUse (ret, arr->sref, arr->loc);
1405 message ("Array fetch from non-array (%t): %s[%s]", carr,
1406 exprNode_unparse (e1), exprNode_unparse (e2)),
1409 exprNode_free (arr);
1410 exprNode_free (ind);
1412 return (exprNode_makeError ());
1422 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1423 exprNodeList args, exprNode ret)
1425 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1429 ** checkPrintfArgs --- checks arguments for printf-like functions
1430 ** Arguments before ... have already been checked.
1431 ** The argument before the ... is a char *.
1432 ** argno is the format string argument.
1436 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1437 exprNodeList args, exprNode ret, int argno)
1440 ** the last argument before the elips is the format string
1445 int nargs = exprNodeList_size (args);
1446 uentryList params = uentry_getParams (fcn);
1450 ** These should be ensured by checkSpecialFunction
1453 llassert (uentryList_size (params) == argno + 1);
1454 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1456 a = exprNodeList_getN (args, argno - 1);
1457 formatloc = fileloc_copy (exprNode_loc (a));
1459 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1460 && exprNode_knownStringValue (a))
1462 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1463 char *code = format;
1466 nargs = exprNodeList_size (args);
1468 while ((code = strchr (code, '%')) != NULL)
1470 char *origcode = code;
1471 cstring codetext = cstring_newEmpty ();
1472 char key = *(++code);
1473 ctype modtype = ctype_int;
1474 bool modified = FALSE;
1476 fileloc_addColumn (formatloc, code - ocode);
1478 codetext = cstring_appendChar (codetext, key);
1481 while (isFlagKey (key))
1484 codetext = cstring_appendChar (codetext, key);
1485 fileloc_incColumn (formatloc);
1488 if (key == 'm') /* skipped in syslog */
1493 /* ignore field width */
1494 while (isdigit ((int) key) != 0)
1497 codetext = cstring_appendChar (codetext, key);
1498 fileloc_incColumn (formatloc);
1501 /* ignore precision */
1505 codetext = cstring_appendChar (codetext, key);
1506 fileloc_incColumn (formatloc);
1509 ** In printf, '*' means: read the next arg as an int for the
1510 ** field width. This seems to be missing from my copy of the
1511 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1512 ** later) but never does.
1517 ; /* don't do anything --- handle later */
1521 while (isdigit ((int) key) != 0)
1524 codetext = cstring_appendChar (codetext, key);
1525 fileloc_incColumn (formatloc);
1532 modtype = ctype_sint; /* short */
1534 codetext = cstring_appendChar (codetext, key);
1535 fileloc_incColumn (formatloc);
1537 else if (key == 'l' || key == 'L')
1539 modtype = ctype_lint; /* long */
1541 codetext = cstring_appendChar (codetext, key);
1542 fileloc_incColumn (formatloc);
1544 if (key == 'l' || key == 'L') {
1545 modtype = ctype_llint; /* long long */
1547 codetext = cstring_appendChar (codetext, key);
1548 fileloc_incColumn (formatloc);
1556 /* now, key = type of conversion to apply */
1558 fileloc_incColumn (formatloc);
1566 message ("No argument corresponding to %q format "
1567 "code %d (%%%s): \"%s\"",
1568 uentry_getName (fcn),
1570 cstring_fromChars (format)),
1573 if (fileloc_isDefined (formatloc)
1574 && context_getFlag (FLG_SHOWCOL))
1576 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1584 a = exprNodeList_getN (args, i);
1587 if (!exprNode_isError (a))
1593 case '*': /* int argument for fieldwidth */
1594 expecttype = ctype_int;
1595 *(--code) = '%'; /* convert it for next code */
1596 fileloc_subColumn (formatloc, 1);
1597 /*@switchbreak@*/ break;
1600 expecttype = ctype_combine (ctype_uint, modtype);
1601 /*@switchbreak@*/ break;
1603 case 'i': /* int argument */
1605 expecttype = ctype_combine (ctype_int, modtype);
1606 /*@switchbreak@*/ break;
1608 case 'x': /* unsigned int */
1610 expecttype = ctype_combine (ctype_uint, modtype);
1612 /*@switchbreak@*/ break;
1618 case 'f': /* double */
1619 expecttype = ctype_combine (ctype_double, modtype);
1620 /*@switchbreak@*/ break;
1622 case 'c': /* int converted to char (check its a char?) */
1623 expecttype = ctype_makeConj (ctype_int,
1624 ctype_makeConj (ctype_char,
1627 /* evans 2001-10-05 - changed to reflect correct ISO spec:
1628 int converted to char */
1630 /* expecttype = ctype_makeConj (ctype_char, ctype_uchar); */
1631 /*@switchbreak@*/ break;
1633 case 's': /* string */
1634 expecttype = ctype_string;
1635 /*@switchbreak@*/ break;
1638 while (((key = *(++code)) != ']')
1641 codetext = cstring_appendChar (codetext, key);
1642 fileloc_incColumn (formatloc);
1648 (message ("Bad character set format: %s",
1649 cstring_fromChars (origcode)));
1652 expecttype = ctype_string;
1653 /*@switchbreak@*/ break;
1655 case 'p': /* pointer */
1656 expecttype = ctype_makePointer (ctype_void);
1657 /* need not be defined */
1658 uentry_setDefState (regArg, SS_RELDEF);
1659 sRef_setPosNull (uentry_getSref (regArg),
1662 /*@switchbreak@*/ break;
1664 case 'n': /* pointer to int, modified by call! */
1665 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1667 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1668 /*@switchbreak@*/ break;
1670 case 'm': /* in a syslog, it doesn't consume an argument */
1671 /* should check we're really doing syslog */
1673 /*@switchbreak@*/ break;
1677 expecttype = ctype_unknown;
1681 message ("Unrecognized format code: %s",
1682 cstring_fromChars (origcode)),
1683 fileloc_isDefined (formatloc)
1684 ? formatloc : g_currentloc);
1686 /*@switchbreak@*/ break;
1689 if (!(exprNode_matchArgType (expecttype, a)))
1691 if (ctype_isVoidPointer (expecttype)
1692 && ctype_isRealAbstract (a->typ)
1693 && (context_getFlag (FLG_ABSTVOIDP)))
1699 if (llgenformattypeerror
1700 (expecttype, exprNode_undefined,
1702 message ("Format argument %d to %q (%%%s) expects "
1705 uentry_getName (fcn),
1708 a->typ, exprNode_unparse (a)),
1711 if (fileloc_isDefined (formatloc)
1712 && context_getFlag (FLG_SHOWCOL))
1715 (cstring_makeLiteral
1716 ("Corresponding format code"),
1723 uentry_setType (regArg, expecttype);
1724 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1726 if (ctype_equal (expecttype, ctype_string))
1728 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1731 uentry_setType (regArg, ctype_unknown);
1732 uentry_fixupSref (regArg);
1736 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1747 cstring_free (codetext);
1752 voptgenerror (FLG_TYPE,
1753 message ("Format string for %q has %d arg%&, given %d",
1754 uentry_getName (fcn), i - argno, nargs - argno),
1760 /* no checking possible for compile-time unknown format strings */
1761 if (exprNode_isDefined (a))
1765 message ("Format string parameter to %s is not a compile-time constant: %s",
1766 exprNode_unparse (f),
1767 exprNode_unparse (a)),
1772 fileloc_free (formatloc);
1776 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1777 exprNodeList args, exprNode ret, int argno)
1781 int nargs = exprNodeList_size (args);
1782 uentryList params = uentry_getParams (fcn);
1786 ** These should be ensured by checkSpecialFunction
1789 llassert (uentryList_size (params) == argno + 1);
1790 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1792 a = exprNodeList_getN (args, argno - 1);
1793 formatloc = fileloc_copy (exprNode_loc (a));
1795 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1796 && exprNode_knownStringValue (a))
1798 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1799 char *code = format;
1802 nargs = exprNodeList_size (args);
1804 while ((code = strchr (code, '%')) != NULL)
1806 char *origcode = code;
1807 char key = *(++code);
1808 cstring codetext = cstring_newEmpty ();
1809 ctype modtype = ctype_int;
1810 char modifier = '\0';
1811 bool modified = TRUE;
1812 bool ignore = FALSE;
1814 codetext = cstring_appendChar (codetext, key);
1815 fileloc_addColumn (formatloc, code - ocode);
1818 ** this is based on ANSI standard library description of fscanf
1819 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1822 /* '*' suppresses assignment (does not need match argument) */
1827 codetext = cstring_appendChar (codetext, key);
1830 fileloc_incColumn (formatloc);
1833 /* ignore field width */
1834 while (isdigit ((int) key) != 0)
1837 codetext = cstring_appendChar (codetext, key);
1838 fileloc_incColumn (formatloc);
1843 modtype = ctype_sint; /* short */
1845 codetext = cstring_appendChar (codetext, key);
1846 fileloc_incColumn (formatloc);
1848 else if (key == 'l' || key == 'L')
1850 modtype = ctype_lint; /* long */
1854 codetext = cstring_appendChar (codetext, key);
1856 fileloc_incColumn (formatloc);
1858 if (key == 'l' || key == 'L') {
1859 modtype = ctype_llint; /* long long */
1861 codetext = cstring_appendChar (codetext, key);
1862 fileloc_incColumn (formatloc);
1870 /* now, key = type of conversion to apply */
1872 fileloc_incColumn (formatloc);
1886 message ("No argument corresponding to %q format "
1887 "code %d (%%%s): \"%s\"",
1888 uentry_getName (fcn),
1890 cstring_fromChars (format)),
1893 if (fileloc_isDefined (formatloc)
1894 && context_getFlag (FLG_SHOWCOL))
1897 (cstring_makeLiteral ("Corresponding format code"),
1905 a = exprNodeList_getN (args, i);
1908 if (!exprNode_isError (a))
1914 case '*': /* int argument for fieldwidth */
1915 expecttype = ctype_makePointer (ctype_int);
1916 *(--code) = '%'; /* convert it for next code */
1917 fileloc_subColumn (formatloc, 1);
1918 /*@switchbreak@*/ break;
1921 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1922 /*@switchbreak@*/ break;
1927 case 'X': /* unsigned int */
1928 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1929 /*@switchbreak@*/ break;
1936 /* printf is double, scanf is float! */
1938 if (modifier == 'l')
1940 expecttype = ctype_makePointer (ctype_double);
1942 else if (modifier == 'L')
1944 expecttype = ctype_makePointer (ctype_ldouble);
1948 llassert (modifier == '\0');
1949 expecttype = ctype_makePointer (ctype_float);
1951 /*@switchbreak@*/ break;
1953 case 'c': /* int converted to char (check its a char?) */
1954 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1955 /*@switchbreak@*/ break;
1957 case 's': /* string */
1958 expecttype = ctype_string;
1959 /*@switchbreak@*/ break;
1963 while (((key = *(++code)) != ']')
1966 codetext = cstring_appendChar (codetext, key);
1967 fileloc_incColumn (formatloc);
1973 (message ("Bad character set format: %s",
1974 cstring_fromChars (origcode)));
1977 expecttype = ctype_string;
1978 /*@switchbreak@*/ break;
1981 case 'p': /* pointer */
1984 message ("Format code should not be used in scanf: %s",
1985 cstring_fromChars (origcode)),
1986 fileloc_isDefined (formatloc)
1987 ? formatloc : g_currentloc);
1989 expecttype = ctype_unknown;
1990 /*@switchbreak@*/ break;
1992 case 'n': /* pointer to int, modified by call! */
1993 expecttype = ctype_makePointer (ctype_int);
1994 /*@switchbreak@*/ break;
1997 expecttype = ctype_unknown;
2001 message ("Unrecognized format code: %s",
2002 cstring_fromChars (origcode)),
2003 fileloc_isDefined (formatloc)
2004 ? formatloc : g_currentloc);
2006 /*@switchbreak@*/ break;
2009 if (!(exprNode_matchArgType (expecttype, a)))
2011 if (ctype_isVoidPointer (expecttype)
2012 && ctype_isRealAbstract (a->typ)
2013 && (context_getFlag (FLG_ABSTVOIDP)))
2019 if (llgenformattypeerror
2020 (expecttype, exprNode_undefined,
2022 message ("Format argument %d to %q (%%%s) expects "
2025 uentry_getName (fcn),
2026 codetext, expecttype,
2027 a->typ, exprNode_unparse (a)),
2030 if (fileloc_isDefined (formatloc)
2031 && context_getFlag (FLG_SHOWCOL))
2034 (cstring_makeLiteral
2035 ("Corresponding format code"),
2042 uentry_setType (outArg, expecttype);
2043 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
2044 uentry_setType (outArg, ctype_unknown);
2045 uentry_fixupSref (outArg);
2049 exprNode_checkCallModifyVal (a->sref, args, f, ret);
2054 /* a->sref = sRef_undefined; */
2061 cstring_free (codetext);
2066 voptgenerror (FLG_TYPE,
2067 message ("Format string for %q has %d arg%&, given %d",
2068 uentry_getName (fcn), i - argno, nargs - argno),
2074 /* no checking possible for compile-time unknown format strings */
2077 fileloc_free (formatloc);
2081 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
2084 /*@unused@*/ int argno)
2087 ** the last argument before the elips is the format string
2090 int nargs = exprNodeList_size (args);
2095 a = exprNodeList_getN (args, argno - 1);
2096 formatloc = fileloc_copy (exprNode_loc (a));
2098 if (ctype_isUnknown (cstringType)) {
2099 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
2101 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
2105 if (ctype_isUnknown (ctypeType)) {
2106 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
2108 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
2112 if (ctype_isUnknown (filelocType)) {
2113 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
2115 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
2119 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
2120 && exprNode_knownStringValue (a))
2122 cstring format = multiVal_forceString (exprNode_getValue (a));
2123 char *code = cstring_toCharsSafe (format);
2126 nargs = exprNodeList_size (args);
2128 while ((code = strchr (code, '%')) != NULL)
2130 char *origcode = code;
2131 char key = *(++code);
2132 cstring codetext = cstring_newEmpty ();
2133 bool isOnly = FALSE;
2135 codetext = cstring_appendChar (codetext, key);
2137 fileloc_addColumn (formatloc, code - ocode);
2139 while (key >= '0' && key <= '9')
2142 codetext = cstring_appendChar (codetext, key);
2143 fileloc_incColumn (formatloc);
2147 fileloc_incColumn (formatloc);
2151 if (key == '&') /* plural marker */
2160 message ("Message missing format arg %d (%%%s): \"%s\"",
2161 i + 1, codetext, format),
2167 a = exprNodeList_getN (args, i);
2171 if (!exprNode_isError (a))
2175 /*@-loopswitchbreak@*/
2181 expecttype = ctype_char; break;
2183 expecttype = cstringType; break;
2185 expecttype = cstringType; isOnly = TRUE; break;
2187 expecttype = cstringType; isOnly = TRUE; break;
2188 case 'd': expecttype = ctype_int; break;
2189 case 'u': expecttype = ctype_uint; break;
2190 case 'w': expecttype = ctype_ulint; break;
2191 case 'f': expecttype = ctype_float; break;
2192 case 'b': expecttype = ctype_bool; break;
2193 case 't': expecttype = ctypeType; break;
2195 expecttype = ctype_makePointer (ctype_void);
2196 /* need not be defined */
2197 uentry_setDefState (regArg, SS_RELDEF);
2198 sRef_setPosNull (uentry_getSref (regArg),
2201 /*@switchbreak@*/ break;
2202 case 'l': expecttype = filelocType; break;
2203 case '&': /* a wee bit of a hack methinks */
2204 expecttype = ctype_int;
2206 case 'r': expecttype = ctype_bool; break;
2208 expecttype = ctype_unknown;
2211 message ("Unrecognized format code: %s",
2212 cstring_fromChars (origcode)),
2213 fileloc_isDefined (formatloc)
2214 ? formatloc : g_currentloc);
2217 /*@=loopswitchbreak@*/
2219 if (!(exprNode_matchArgType (expecttype, a)))
2221 if (ctype_isVoidPointer (expecttype)
2222 && ctype_isRealAbstract (a->typ)
2223 && (context_getFlag (FLG_ABSTVOIDP)))
2229 if (llgenformattypeerror
2230 (expecttype, exprNode_undefined,
2232 message ("Format argument %d to %q (%%%s) expects "
2235 uentry_getName (fcn),
2236 codetext, expecttype,
2237 a->typ, exprNode_unparse (a)),
2240 if (fileloc_isDefined (formatloc)
2241 && context_getFlag (FLG_SHOWCOL))
2244 (cstring_makeLiteral
2245 ("Corresponding format code"),
2252 if (ctype_equal (expecttype, cstringType))
2256 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2257 uentry_fixupSref (csOnlyArg);
2261 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2262 uentry_fixupSref (csArg);
2267 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2268 uentry_fixupSref (regArg);
2274 cstring_free (codetext);
2279 voptgenerror (FLG_TYPE,
2280 message ("Format string for %q has %d arg%&, given %d",
2281 uentry_getName (fcn), i - argno, nargs -argno),
2287 /* no checking possible for compile-time unknown format strings */
2290 fileloc_free (formatloc);
2294 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2295 /*@notnull@*/ exprNode e2,
2301 bool hadUncon = FALSE;
2303 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
2304 sRefSet_hasUnconstrained (sets2))
2307 (FLG_EVALORDERUNCON,
2309 ("Expression may have undefined behavior (%q used in right operand "
2310 "may set global variable %q used in left operand): %s %s %s",
2311 sRefSet_unparseUnconstrained (sets2),
2312 sRef_unparse (sRef_getRootBase (e1->sref)),
2313 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2317 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
2318 sRefSet_hasUnconstrained (sets1))
2321 (FLG_EVALORDERUNCON,
2323 ("Expression has undefined behavior (%q used in left operand "
2324 "may set global variable %q used in right operand): %s %s %s",
2325 sRefSet_unparseUnconstrained (sets1),
2326 sRef_unparse (e2->sref),
2327 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2331 sRefSet_realElements (e1->uses, sr)
2333 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2338 ("Expression has undefined behavior (left operand uses %q, "
2339 "modified by right operand): %s %s %s",
2341 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2344 } end_sRefSet_realElements;
2346 sRefSet_realElements (sets1, sr)
2348 if (sRef_isMeaningful (sr))
2350 if (sRef_same (sr, e2->sref))
2355 ("Expression has undefined behavior (value of right operand "
2356 "modified by left operand): %s %s %s",
2357 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2360 else if (sRefSet_member (e2->uses, sr))
2365 ("Expression has undefined behavior (left operand modifies %q, "
2366 "used by right operand): %s %s %s",
2368 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2373 if (sRefSet_member (sets2, sr))
2375 if (sRef_isUnconstrained (sr))
2383 hadUncon = optgenerror
2384 (FLG_EVALORDERUNCON,
2386 ("Expression may have undefined behavior. Left operand "
2387 "calls %q; right operand calls %q. The unconstrained "
2388 "functions may modify global state used by "
2389 "the other operand): %s %s %s",
2390 sRefSet_unparseUnconstrained (sets1),
2391 sRefSet_unparseUnconstrained (sets2),
2392 exprNode_unparse (e1), lltok_unparse (op),
2393 exprNode_unparse (e2)),
2402 ("Expression has undefined behavior (both "
2403 "operands modify %q): %s %s %s",
2405 exprNode_unparse (e1),
2406 lltok_unparse (op), exprNode_unparse (e2)),
2412 } end_sRefSet_realElements;
2415 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2417 bool hasError = FALSE;
2419 if (exprNode_isError (e1) || exprNode_isError (e2))
2424 if (sRefSet_member (e2->sets, e1->sref))
2426 if (e2->kind == XPR_CALL)
2432 hasError = optgenerror
2434 message ("Expression has undefined behavior "
2435 "(value of left operand %s is modified "
2436 "by right operand %s): %s %s %s",
2437 exprNode_unparse (e1),
2438 exprNode_unparse (e2),
2439 exprNode_unparse (e1), lltok_unparse (op),
2440 exprNode_unparse (e2)),
2445 if (context_getFlag (FLG_EVALORDERUNCON))
2447 if (sRefSet_member (e2->msets, e1->sref))
2449 if (e2->kind == XPR_CALL)
2455 hasError = optgenerror
2458 ("Expression has undefined behavior (value of left "
2459 "operand may be modified by right operand): %s %s %s",
2460 exprNode_unparse (e1), lltok_unparse (op),
2461 exprNode_unparse (e2)),
2469 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2471 if (context_maybeSet (FLG_EVALORDERUNCON))
2473 checkExpressionDefinedAux (e1, e2, e1->msets,
2474 e2->msets, op, FLG_EVALORDERUNCON);
2479 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2482 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2483 exprNodeList args, bool isIter, exprNode ret)
2487 if (!exprNode_isError (f))
2489 if (!uentryList_isMissingParams (cl))
2491 int nargs = exprNodeList_size (args);
2492 int expectargs = uentryList_size (cl);
2496 if (expectargs == 0)
2504 message ("Iter %q invoked with %d args, "
2506 uentry_getName (fcn),
2514 message ("Function %s called with %d args, "
2516 exprNode_unparse (f), nargs),
2523 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2525 exprNodeList_reset (args);
2527 uentryList_elements (cl, current)
2529 ctype ct = uentry_getType (current);
2532 if (ctype_isElips (ct))
2535 ** do special checking for printf/scanf library functions
2537 ** this is kludgey code, just for handling the special case
2541 if (uentry_isPrintfLike (fcn))
2543 checkPrintfArgs (f, fcn, args, ret, i);
2546 else if (uentry_isScanfLike (fcn))
2548 checkScanfArgs (f, fcn, args, ret, i);
2551 else if (uentry_isMessageLike (fcn))
2553 checkMessageArgs (f, fcn, args, i);
2558 llassert (!uentry_isSpecialFunction (fcn));
2561 nargs = expectargs; /* avoid errors */
2566 if (i >= nargs) break;
2568 a = exprNodeList_current (args);
2569 exprNodeList_advance (args);
2573 if (exprNode_isError (a))
2580 probably necessary? I'm not sure about this one
2581 checkMacroParen (a);
2584 f->guards = guardSet_union (f->guards, a->guards);
2586 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2588 if (!(exprNode_matchArgType (ct, a)))
2590 DPRINTF (("Args mismatch!"));
2592 if (ctype_isVoidPointer (ct)
2593 && (ctype_isPointer (a->typ)
2594 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2599 ("Pointer to abstract type (%t) used "
2601 "(arg %d to %q): %s",
2603 uentry_getName (fcn),
2604 exprNode_unparse (a)),
2612 (ct, exprNode_undefined,
2615 ("Iter %q expects arg %d to "
2616 "be %t gets %t: %s",
2617 uentry_getName (fcn),
2618 i, ct, a->typ, exprNode_unparse (a)),
2629 ("Function %q expects arg %d to be %t gets %t: %s",
2630 uentry_getName (fcn),
2631 i, ct, a->typ, exprNode_unparse (a)),
2634 DPRINTF (("Types: %s / %s",
2636 ctype_unparse (a->typ)));
2640 ** Clear null marker for abstract types.
2641 ** (It is not revealed, so suppress future messages.)
2644 if (ctype_isAbstract (a->typ))
2646 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2653 } end_uentryList_elements ;
2656 if (expectargs != nargs) /* note: not != since we may have ... */
2658 if (ctype_isElips (last))
2662 message ("Function %s called with %d args, expects at least %d",
2663 exprNode_unparse (f),
2664 nargs, expectargs - 1),
2673 message ("Iter %q invoked with %d args, expects %d",
2674 uentry_getName (fcn), nargs, expectargs),
2681 message ("Function %s called with %d args, expects %d",
2682 exprNode_unparse (f),
2695 ** Check for undefined code sequences in function arguments:
2697 ** one parameter sets something used by another parameter
2698 ** one parameter sets something set by another parameter
2702 checkSequencingOne (exprNode f, exprNodeList args,
2703 /*@notnull@*/ exprNode el, int argno)
2706 ** Do second loop, iff +undefunspec
2710 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2712 for (checkloop = 0; checkloop < numloops; checkloop++)
2718 thissets = el->sets;
2722 llassert (checkloop == 1);
2723 thissets = el->msets;
2726 sRefSet_realElements (thissets, thisset)
2730 /*@access exprNodeList@*/
2731 for (j = 0; j < args->nelements; j++)
2733 exprNode jl = args->elements[j];
2734 int thisargno = j + 1;
2736 if (thisargno != argno && exprNode_isDefined (jl))
2738 sRefSet otheruses = jl->uses;
2740 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
2741 sRefSet_hasUnconstrained (thissets))
2744 (FLG_EVALORDERUNCON,
2747 ("%q used in argument %d may set "
2748 "global variable %q used by argument %d: %s(%q)",
2749 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2752 sRef_unparse (sRef_getRootBase (jl->sref)),
2754 exprNode_unparse (f), exprNodeList_unparse (args)),
2758 if (sRefSet_member (otheruses, thisset))
2760 if (sRef_isUnconstrained (thisset))
2763 (FLG_EVALORDERUNCON,
2765 ("Unconstrained functions used in arguments %d (%q) "
2766 "and %d (%s) may modify "
2767 "or use global state in undefined way: %s(%q)",
2769 sRefSet_unparseUnconstrainedPlain (otheruses),
2771 sRef_unconstrainedName (thisset),
2772 exprNode_unparse (f),
2773 exprNodeList_unparse (args)),
2781 ("Argument %d modifies %q, used by argument %d "
2782 "(order of evaluation of actual parameters is "
2783 "undefined): %s(%q)",
2784 argno, sRef_unparse (thisset), thisargno,
2785 exprNode_unparse (f), exprNodeList_unparse (args)),
2791 sRefSet othersets = jl->sets;
2793 if (sRefSet_member (othersets, thisset))
2795 if (sRef_isUnconstrained (thisset))
2798 (FLG_EVALORDERUNCON,
2800 ("Unconstrained functions used in "
2801 "arguments %d (%q) and %d (%s) may modify "
2802 "or use global state in undefined way: %s(%q)",
2804 sRefSet_unparseUnconstrainedPlain (othersets),
2806 sRef_unconstrainedName (thisset),
2807 exprNode_unparse (f), exprNodeList_unparse (args)),
2815 ("Argument %d modifies %q, set by argument %d (order of"
2816 " evaluation of actual parameters is undefined): %s(%q)",
2817 argno, sRef_unparse (thisset), thisargno,
2818 exprNode_unparse (f), exprNodeList_unparse (args)),
2825 /*@noaccess exprNodeList@*/
2826 } end_sRefSet_realElements;
2831 checkSequencing (exprNode f, exprNodeList args)
2833 if (exprNodeList_size (args) > 1)
2838 /*@access exprNodeList*/
2840 for (i = 0; i < args->nelements; i++)
2842 el = args->elements[i];
2844 if (!exprNode_isError (el))
2846 checkSequencingOne (f, args, el, i + 1);
2849 /*@noaccess exprNodeList*/
2854 ** requires le = exprNode_getUentry (f)
2858 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2859 uentry le, exprNodeList args,
2860 /*@notnull@*/ exprNode ret, int specialArgs)
2862 bool isSpec = FALSE;
2863 bool hasMods = FALSE;
2865 globSet usesGlobs = globSet_undefined;
2866 sRefSet mods = sRefSet_undefined;
2867 bool freshMods = FALSE;
2868 uentryList params = uentryList_undefined;
2870 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2873 ** check globals and modifies
2878 if (!uentry_isValid (le))
2880 ctype fr = ctype_realType (f->typ);
2882 if (ctype_isFunction (fr))
2884 params = ctype_argsFunction (fr);
2888 params = uentryList_missingParams;
2891 if (!context_getFlag (FLG_MODNOMODS)
2892 && !context_getFlag (FLG_GLOBUNSPEC))
2894 checkUnspecCall (f, params, args);
2900 fname = uentry_rawName (le);
2904 if (uentry_isFunction (le))
2906 params = uentry_getParams (le);
2907 mods = uentry_getMods (le);
2908 hasMods = uentry_hasMods (le);
2909 usesGlobs = uentry_getGlobs (le);
2910 isSpec = uentry_isSpecified (le);
2912 else /* not a function */
2914 ctype ct = ctype_realType (uentry_getType (le));
2916 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2917 ("checkModGlobs: uentry not a function: %s",
2918 uentry_unparse (le)));
2920 params = ctype_argsFunction (ct);
2921 return; /*@32 ! remove this? */
2930 globSet_allElements (usesGlobs, el)
2932 if (sRef_isValid (el))
2934 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2936 context_usedGlobal (el);
2937 exprNode_checkUse (f, el, f->loc);
2939 if (context_checkInternalUse ())
2941 if (!context_globAccess (el))
2943 if (sRef_isSystemState (el)
2944 && !context_getFlag (FLG_MODFILESYSTEM))
2953 ("Called procedure %s may access %q, but "
2954 "globals list does not include globals %s",
2955 exprNode_unparse (f),
2957 cstring_makeLiteralTemp (sRef_isInternalState (el)
2965 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2971 uentry gle = sRef_getUentry (el);
2972 sRef sr = sRef_updateSref (el);
2974 if (sRef_isUndefGlob (el))
2976 sRef_setDefined (sr, f->loc);
2977 exprNode_checkSet (f, sr);
2985 if (sRef_isAllocated (el))
2987 exprNode_checkSet (f, sr);
2991 if (sRef_isStateUndefined (sr))
2996 ("%s %q used by function undefined before call: %s",
2997 sRef_getScopeName (sr),
2999 exprNode_unparse (f)),
3001 sRef_setDefined (sr, f->loc);
3003 exprNode_checkUse (f, sr, f->loc);
3006 checkGlobUse (gle, TRUE, f);
3009 if (sRef_isKilledGlob (el))
3011 sRef_kill (sr, f->loc);
3012 context_usedGlobal (sr);
3016 } end_globSet_allElements;
3022 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
3024 sRefSet smods = sRefSet_undefined;
3027 ** NEED to check for modifies anything
3031 ** check each sRef that called function modifies (ml), is
3037 sRefSet_allElements (mods, s) /* s is something which may be modified */
3039 DPRINTF (("Check modify: %s", sRef_unparse (s)));
3041 if (sRef_isKindSpecial (s))
3043 if (sRef_isSpecInternalState (s))
3045 if (context_getFlag (FLG_MODINTERNALSTRICT))
3047 exprNode_checkCallModifyVal (s, args, f, ret);
3051 sRefSet mmods = context_modList ();
3053 sRefSet_allElements (mmods, el)
3055 if (sRef_isInternalState (el))
3057 sRef_setModified (el);
3059 } end_sRefSet_allElements ;
3064 exprNode_checkCallModifyVal (s, args, f, ret);
3069 sRef rb = sRef_getRootBase (s);
3071 if (sRef_isFileOrGlobalScope (rb))
3073 context_usedGlobal (rb);
3076 if (sRef_isFileStatic (s)
3077 && !fileId_equal (fileloc_fileId (f->loc),
3078 fileloc_fileId (uentry_whereDefined (le))))
3080 smods = sRefSet_insert (smods, s);
3084 exprNode_checkCallModifyVal (s, args, f, ret);
3087 } end_sRefSet_allElements;
3092 ** Static elements in modifies set can have nasty consequences.
3093 ** (I think...have not been able to reproduce a possible bug.)
3096 if (!sRefSet_isDefined (smods))
3098 mods = sRefSet_newCopy (mods);
3101 sRefSet_allElements (smods, el)
3103 bool res = sRefSet_delete (mods, el);
3106 } end_sRefSet_allElements;
3108 sRefSet_free (smods);
3113 else if (sRefSet_isDefined (mods))
3114 { /* just check observers */
3117 sRefSet_allElements (mods, s) /* s is something which may be modified */
3119 sRef rb = sRef_getRootBase (s);
3123 if (sRef_isParam (rb))
3125 sRef b = sRef_fixBaseParam (s, args);
3127 if (sRef_isObserver (b))
3129 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
3133 message ("Function call may modify observer%q: %s",
3134 sRef_unparsePreOpt (b), exprNode_unparse (e)),
3137 sRef_showExpInfo (b);
3141 } end_sRefSet_allElements;
3145 if (!hasMods) /* no specified modifications */
3147 if (context_getFlag (FLG_MODOBSERVERUNCON))
3149 exprNodeList_elements (args, e)
3151 if (exprNode_isDefined (e))
3153 sRef s = exprNode_getSref (e);
3155 if (sRef_isObserver (s)
3156 && ctype_isMutable (sRef_getType (s)))
3159 (FLG_MODOBSERVERUNCON,
3161 ("Call to unconstrained function %s may modify observer%q: %s",
3162 exprNode_unparse (f),
3163 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3166 sRef_showExpInfo (s);
3170 } end_exprNodeList_elements;
3175 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3177 ret->uses = sRefSet_union (ret->uses, f->uses);
3178 ret->sets = sRefSet_union (ret->sets, f->sets);
3179 ret->msets = sRefSet_union (ret->msets, f->msets);
3184 ** Spurious errors reported, because splint can't tell
3185 ** mods must be fresh if freshMods is true.
3188 /*@i@*/ sRefSet_free (mods);
3194 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3196 if (uentry_isVar (glob))
3198 if (context_inFunctionLike ())
3200 sRef sr = uentry_getSref (glob);
3202 context_usedGlobal (sr);
3204 if (context_checkGlobUse (glob))
3206 if (!context_globAccess (sr))
3212 message ("Called procedure %s may access %s %q",
3213 exprNode_unparse (e),
3214 sRef_unparseScope (sr),
3215 uentry_getName (glob)),
3222 message ("Undocumented use of %s %s",
3223 sRef_unparseScope (sr),
3224 exprNode_unparse (e)),
3233 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3238 reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
3240 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3241 exprNode_unparse (f), exprNodeList_unparse (args),
3242 uentry_unparseFull (le),
3243 stateClauseList_unparse (uentry_getStateClauseList (le))));
3245 if (uentry_isValid (le) && uentry_isFunction (le))
3247 stateClauseList sclauses = uentry_getStateClauseList (le);
3249 if (stateClauseList_isDefined (sclauses))
3251 DPRINTF (("Reflect ensures: %s / %s / %s",
3252 uentry_unparse (le),
3253 exprNode_unparse (f), exprNodeList_unparse (args)));
3255 stateClauseList_elements (sclauses, cl)
3257 if (stateClause_hasEnsures (cl))
3259 /* Same in usymtab.c:1904 */
3260 if (stateClause_setsMetaState (cl))
3262 qual q = stateClause_getMetaQual (cl);
3263 annotationInfo ainfo = qual_getAnnotationInfo (q);
3264 metaStateInfo minfo = annotationInfo_getState (ainfo);
3265 cstring key = metaStateInfo_getName (minfo);
3266 int mvalue = annotationInfo_getValue (ainfo);
3268 sRefSet osrs = sRefSet_undefined;
3271 if (stateClause_isGlobal (cl))
3273 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3278 srs = stateClause_getRefs (cl);
3281 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3284 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3286 sRefSet_elements (srs, sel)
3290 if (sRef_isResult (sRef_getRootBase (sel)))
3292 s = exprNode_getSref (ret);
3296 s = sRef_fixBaseParam (sel, args);
3299 DPRINTF (("Reflecting state clause on: %s / %s",
3300 sRef_unparse (sel), sRef_unparse (s)));
3302 sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3303 } end_sRefSet_elements;
3305 sRefSet_free (osrs);
3309 sRefSet srs = stateClause_getRefs (cl);
3310 sRefModVal modf = stateClause_getEnsuresFunction (cl);
3311 int eparam = stateClause_getStateParameter (cl);
3313 llassert (modf != NULL);
3315 DPRINTF (("Reflect after clause: %s / %s",
3316 stateClause_unparse (cl),
3317 sRefSet_unparse (srs)));
3319 sRefSet_elements (srs, sel)
3323 DPRINTF (("elements: %s", sRef_unparse (sel)));
3324 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3326 if (sRef_isResult (sRef_getRootBase (sel)))
3328 DPRINTF (("Fix base: %s / %s",
3329 sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
3330 s = sRef_fixBase (sel, exprNode_getSref (ret));
3331 DPRINTF (("==> %s", sRef_unparseFull (s)));
3335 s = sRef_fixBaseParam (sel, args);
3338 DPRINTF (("elements: %s", sRef_unparse (s)));
3339 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3341 DPRINTF (("Reflecting state clause on: %s / %s",
3342 sRef_unparseFull (sel), sRef_unparseFull (s)));
3344 /* evans 2001-08-24 - added aliasSetCompleteParam */
3345 sRef_aliasSetCompleteParam (modf, s, eparam, exprNode_loc (f));
3347 DPRINTF (("After reflecting state clause on: %s / %s",
3348 sRef_unparseFull (sel), sRef_unparseFull (s)));
3349 } end_sRefSet_elements;
3352 } end_stateClauseList_elements ;
3355 DPRINTF (("Here: %s / %s",
3356 uentry_unparseFull (le),
3357 bool_unparse (uentry_hasMetaStateEnsures (le))));
3359 if (uentry_hasMetaStateEnsures (le))
3361 fileloc loc = exprNode_loc (f);
3363 metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3365 metaStateConstraintList_elements (mscl, msc)
3367 metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3368 metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3369 metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
3370 cstring key = metaStateInfo_getName (msinfo);
3371 sRef mlsr = metaStateSpecifier_getSref (msspec);
3373 sRef lastref = sRef_undefined;
3374 stateValue sval = stateValue_undefined;
3376 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3377 metaStateConstraint_unparse (msc)));
3378 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3380 if (sRef_isResult (sRef_getRootBase (mlsr)))
3382 s = exprNode_getSref (ret);
3386 s = sRef_fixBaseParam (mlsr, args);
3389 DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3391 while (metaStateExpression_isDefined (msexpr))
3393 metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
3394 metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
3397 DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3399 if (metaStateExpression_isMerge (msexpr))
3401 msexpr = metaStateExpression_getRest (msexpr);
3405 msexpr = metaStateExpression_undefined;
3408 if (metaStateInfo_isDefined (msi))
3410 /* Must match lhs state */
3411 llassert (metaStateInfo_equal (msinfo, msi));
3414 if (metaStateSpecifier_isElipsis (ms))
3417 ** For elipsis, we need to merge all the relevant elipsis parameters
3421 uentryList params = uentry_getParams (le);
3422 int paramno = uentryList_size (params) - 1;
3424 if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
3428 message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3429 uentry_getName (le)),
3430 uentry_whereLast (le));
3431 /*@innerbreak@*/ break;
3434 while (paramno < exprNodeList_size (args))
3436 exprNode arg = exprNodeList_getN (args, paramno);
3437 fs = exprNode_getSref (arg);
3438 DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3440 /* cut and pasted... gack*/
3441 if (stateValue_isDefined (sval))
3443 /* Use combination table to merge old state value with new one: */
3444 stateValue tval = sRef_getMetaStateValue (fs, key);
3446 if (stateValue_isDefined (tval))
3448 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3449 cstring msg = cstring_undefined;
3450 int nval = stateCombinationTable_lookup (sctable,
3451 stateValue_getValue (sval),
3452 stateValue_getValue (tval),
3454 DPRINTF (("Combining: %s + %s -> %d",
3455 stateValue_unparseValue (sval, msinfo),
3456 stateValue_unparseValue (tval, msinfo),
3459 if (nval == stateValue_error)
3464 ("Attributes merged in ensures clause in states that "
3465 "cannot be combined (%q is %q, %q is %q)%q",
3466 sRef_unparse (lastref),
3467 stateValue_unparseValue (sval, msinfo),
3469 stateValue_unparseValue (tval, msinfo),
3470 cstring_isDefined (msg) ?
3471 message (": %s", msg) : cstring_undefined),
3474 sRef_showMetaStateInfo (fs, key);
3478 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3479 loc = exprNode_loc (arg);
3483 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3488 sval = sRef_getMetaStateValue (fs, key);
3493 if (stateValue_isError (sval))
3495 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3504 msr = metaStateSpecifier_getSref (ms);
3507 llassert (sRef_isParam (sRef_getRootBase (msr)));
3508 fs = sRef_fixBaseParam (msr, args);
3510 if (stateValue_isDefined (sval))
3512 /* Use combination table to merge old state value with new one: */
3513 stateValue tval = sRef_getMetaStateValue (fs, key);
3515 if (stateValue_isDefined (tval))
3517 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3518 cstring msg = cstring_undefined;
3519 int nval = stateCombinationTable_lookup (sctable,
3520 stateValue_getValue (sval),
3521 stateValue_getValue (tval),
3523 DPRINTF (("Combining: %s + %s -> %d",
3524 stateValue_unparseValue (sval, msinfo),
3525 stateValue_unparseValue (tval, msinfo),
3528 if (nval == stateValue_error)
3533 ("Attributes merged in ensures clause in states that "
3534 "cannot be combined (%q is %q, %q is %q)%q",
3535 sRef_unparse (lastref),
3536 stateValue_unparseValue (sval, msinfo),
3538 stateValue_unparseValue (tval, msinfo),
3539 cstring_isDefined (msg)
3540 ? message (": %s", msg) : cstring_undefined),
3543 sRef_showMetaStateInfo (fs, key);
3547 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3551 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3556 sval = sRef_getMetaStateValue (fs, key);
3561 if (stateValue_isError (sval))
3563 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3568 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3570 if (stateValue_isDefined (sval))
3572 sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
3576 DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
3578 } end_metaStateConstraintList_elements ;
3580 metaStateConstraintList_free (mscl);
3586 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3588 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3589 exprNode_unparse (f), exprNodeList_unparse (args),
3590 uentry_unparseFull (le),
3591 stateClauseList_unparse (uentry_getStateClauseList (le))));
3593 if (uentry_isValid (le) && uentry_isFunction (le))
3595 stateClauseList sclauses = uentry_getStateClauseList (le);
3597 if (stateClauseList_isDefined (sclauses))
3599 DPRINTF (("Check requires: %s / %s / %s",
3600 uentry_unparse (le),
3601 exprNode_unparse (f), exprNodeList_unparse (args)));
3603 stateClauseList_elements (sclauses, cl)
3605 DPRINTF (("Check clause: %s / %s",
3606 stateClause_unparse (cl),
3607 bool_unparse (stateClause_hasRequires (cl))));
3609 if (stateClause_hasRequires (cl))
3611 sRefSet osrs = sRefSet_undefined;
3614 if (stateClause_isGlobal (cl))
3616 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3621 srs = stateClause_getRefs (cl);
3624 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3626 if (stateClause_setsMetaState (cl))
3628 qual q = stateClause_getMetaQual (cl);
3629 annotationInfo ainfo = qual_getAnnotationInfo (q);
3630 metaStateInfo minfo = annotationInfo_getState (ainfo);
3631 cstring key = metaStateInfo_getName (minfo);
3632 int mvalue = annotationInfo_getValue (ainfo);
3634 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3636 sRefSet_elements (srs, sel)
3638 sRef s = sRef_fixBaseParam (sel, args);
3640 if (sRef_isResult (sRef_getRootBase (sel)))
3646 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3647 sRef_unparseFull (sel), sRef_unparseFull (s),
3650 if (!sRef_checkMetaStateValue (s, key, mvalue))
3652 DPRINTF (("HERE: %s", sRef_unparse (s)));
3656 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3657 uentry_getName (le),
3658 sRef_isGlobalMarker (s)
3660 : message (" by %q", sRef_unparse (s)),
3661 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3663 stateClause_unparse (cl)),
3666 sRef_showAliasInfo (s);
3670 DPRINTF (("Error supressed!"));
3671 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3672 DPRINTF (("Context supress: %s",
3673 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3677 } end_sRefSet_elements;
3681 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3682 int eparam = stateClause_getStateParameter (cl);
3684 DPRINTF (("Reflect after clause: %s / %s",
3685 stateClause_unparse (cl),
3686 sRefSet_unparse (srs)));
3688 llassert (modf != NULL);
3690 sRefSet_elements (srs, sel)
3694 DPRINTF (("elements: %s", sRef_unparse (sel)));
3695 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3697 s = sRef_fixBaseParam (sel, args);
3699 DPRINTF (("elements: %s", sRef_unparse (s)));
3700 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3702 if (sRef_isResult (sRef_getRootBase (sel)))
3704 ; /*@i423 what do we do about results */
3708 DPRINTF (("Reflecting state clause on: %s / %s",
3709 sRef_unparse (sel), sRef_unparse (s)));
3711 modf (s, eparam, exprNode_loc (f));
3713 } end_sRefSet_elements;
3716 sRefSet_free (osrs);
3718 } end_stateClauseList_elements ;
3723 static /*@only@*/ exprNode
3724 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3725 ctype t, /*@keep@*/ exprNodeList args)
3727 /* requires f is a non-error exprNode, with type function */
3728 cstring fname = exprNode_unparse (f);
3729 uentry le = exprNode_getUentry (f);
3730 exprNode ret = exprNode_createPartialCopy (f);
3735 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3737 ret->typ = ctype_getReturnType (t);
3738 ret->kind = XPR_CALL;
3740 ret->edata = exprData_makeCall (f, args);
3743 ** Order of these steps is very important!
3745 ** Must check for argument dependencies before messing up uses and sets.
3748 if (context_getFlag (FLG_EVALORDER))
3750 exprNodeList_elements (args, current)
3752 if (exprNode_isDefined (current))
3754 exprNode_addUse (current, current->sref);
3756 } end_exprNodeList_elements;
3758 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3760 checkSequencing (f, args);
3763 exprNodeList_elements (args, current)
3765 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3767 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3769 } end_exprNodeList_elements ;
3772 special = checkArgs (le, f, t, args, ret);
3773 checkGlobMods (f, le, args, ret, special);
3774 checkRequiresClause (le, f, args);
3777 if (uentry_isValid (le)
3778 && (uentry_isFunction (le)
3779 || (uentry_isVariable (le)
3780 && ctype_isFunction (uentry_getType (le)))))
3782 exitkind exk = uentry_getExitCode (le);
3784 /* f->typ is already set to the return type */
3786 DPRINTF (("Function: %s", uentry_unparseFull (le)));
3787 ret->sref = uentry_returnedRef (le, args, exprNode_loc (f));
3788 DPRINTF (("Returned: %s / %s",
3789 uentry_unparseFull (le),
3790 sRef_unparseFull (ret->sref)));
3792 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3794 qual nullPred = uentry_nullPred (le);
3796 if (qual_isTrueNull (nullPred))
3798 exprNode arg = exprNodeList_head (args);
3800 if (exprNode_isDefined (arg))
3802 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3805 else if (qual_isFalseNull (nullPred))
3807 exprNode arg = exprNodeList_head (args);
3809 if (exprNode_isDefined (arg))
3811 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3816 llassert (qual_isUnknown (nullPred));
3820 if (exitkind_isConditionalExit (exk))
3824 ** if (arg0) then { exit! } else { ; }
3826 ** if (arg0) then { ; } else { exit! }
3831 llassert (!exprNodeList_isEmpty (args));
3832 firstArg = exprNodeList_head (args);
3834 if (exprNode_isDefined (firstArg)
3835 && !guardSet_isEmpty (firstArg->guards))
3837 usymtab_trueBranch (guardSet_undefined);
3838 usymtab_altBranch (guardSet_undefined);
3840 if (exitkind_isTrueExit (exk))
3842 usymtab_popBranches (firstArg,
3843 exprNode_makeMustExit (),
3845 TRUE, TRUEEXITCLAUSE);
3849 usymtab_popBranches (firstArg,
3851 exprNode_makeMustExit (),
3852 TRUE, FALSEEXITCLAUSE);
3856 ret->exitCode = XK_MAYEXIT;
3858 else if (exitkind_mustExit (exk))
3860 ret->exitCode = XK_MUSTEXIT;
3862 else if (exitkind_couldExit (exk))
3864 ret->exitCode = XK_MAYEXIT;
3871 if (cstring_equalLit (fname, "exit"))
3873 if (exprNodeList_size (args) == 1)
3875 exprNode arg = exprNodeList_head (args);
3877 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3879 long int val = multiVal_forceInt (exprNode_getValue (arg));
3886 ("Argument to exit has implementation defined behavior: %s",
3887 exprNode_unparse (arg)),
3888 exprNode_loc (arg));
3896 ret->sref = sRef_undefined;
3897 exprNode_checkSetAny (ret, uentry_rawName (le));
3900 DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3901 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3902 reflectEnsuresClause (ret, le, f, args);
3905 DPRINTF (("Here: %s", sRef_unparseFull (ret->sref)));
3910 ** this is yucky! should keep the uentry as part of exprNode!
3913 uentry exprNode_getUentry (exprNode e)
3915 if (exprNode_isError (e))
3917 return uentry_undefined;
3921 cstring s = exprNode_rootVarName (e);
3922 uentry ue = usymtab_lookupSafe (s);
3929 ** Returns true iff e1 and e2 are both exactly the same storage
3933 static bool exprNode_sameStorage (exprNode e1, exprNode e2)
3935 sRef s1 = exprNode_getSref (e1);
3936 sRef s2 = exprNode_getSref (e2);
3938 return (sRef_realSame (s1, s2));
3942 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3944 exprNode ret = exprNode_createPlain (ctype_unknown);
3946 ret->kind = XPR_INITBLOCK;
3947 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3948 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3954 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3959 usymtab_checkAllValid ();
3962 if (exprNode_isUndefined (f))
3965 exprNodeList_free (args);
3966 return exprNode_undefined;
3969 t = exprNode_getType (f);
3971 if (sRef_isLocalVar (f->sref))
3973 exprNode_checkUse (f, f->sref, f->loc);
3975 if (sRef_possiblyNull (f->sref))
3977 if (!usymtab_isGuarded (f->sref))
3979 if (optgenerror (FLG_NULLDEREF,
3980 message ("Function call using %s pointer %q",
3981 sRef_nullMessage (f->sref),
3982 sRef_unparse (f->sref)),
3985 sRef_showNullInfo (f->sref);
3986 sRef_setNullError (f->sref);
3994 if (ctype_isRealFunction (t))
3996 exprNode ret = functionCallSafe (f, t, args);
4000 else if (ctype_isUnknown (t))
4002 exprNode ret = exprNode_createPartialCopy (f);
4008 exprNodeList_elements (args, current)
4010 if (exprNode_isDefined (current))
4012 exprNode_checkUse (ret, current->sref, ret->loc);
4015 ** also, anything derivable from current->sref may be used
4018 exprNode_addUse (ret, sRef_makeDerived (current->sref));
4019 exprNode_mergeUSs (ret, current);
4021 } end_exprNodeList_elements;
4023 ret->edata = exprData_makeCall (f, args);
4024 ret->kind = XPR_CALL;
4026 tstring = cstring_copy (exprNode_unparse (f));
4028 cstring_markOwned (tstring);
4029 exprNode_checkSetAny (ret, tstring);
4035 voptgenerror (FLG_TYPE,
4036 message ("Call to non-function (type %t): %s", t,
4037 exprNode_unparse (f)),
4040 exprNodeList_free (args);
4042 return (exprNode_makeError ());
4047 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4048 /*@only@*/ cstring f)
4050 exprNode ret = exprNode_createPartialCopy (s);
4052 ret->kind = XPR_FACCESS;
4054 if (exprNode_isError (s))
4056 ret->edata = exprData_makeField (s, f);
4061 ctype t = exprNode_getType (s);
4062 ctype tr = ctype_realType (t);
4064 checkMacroParen (s);
4066 ret->edata = exprData_makeField (s, f);
4068 if (ctype_isStructorUnion (tr))
4070 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
4072 if (uentry_isUndefined (tf))
4074 voptgenerror (FLG_TYPE,
4075 message ("Access non-existent field %s of %t: %s", f, t,
4076 exprNode_unparse (ret)),
4078 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
4083 uentry_setUsed (tf, exprNode_loc (ret));
4085 ret->typ = uentry_getType (tf);
4086 checkSafeUse (ret, s->sref);
4088 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
4089 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
4093 else /* isStructorUnion */
4095 if (ctype_isRealAbstract (tr))
4099 message ("Access field of abstract type (%t): %s.%s",
4100 t, exprNode_unparse (s), f),
4102 ret->typ = ctype_unknown;
4106 if (ctype_isKnown (tr))
4111 ("Access field of non-struct or union (%t): %s.%s",
4112 t, exprNode_unparse (s), f),
4115 ret->typ = ctype_unknown;
4119 cstring sn = cstring_copy (f);
4121 checkSafeUse (ret, s->sref);
4122 cstring_markOwned (sn);
4123 ret->sref = sRef_makeField (s->sref, sn);
4135 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
4136 /*@only@*/ cstring f)
4138 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
4144 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
4146 exprNode ret = exprNode_createPartialCopy (e);
4148 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
4149 ret->kind = XPR_PARENS;
4150 ret->edata = exprData_makeUop (e, lpar);
4152 if (!exprNode_isError (e))
4154 ret->exitCode = e->exitCode;
4155 ret->canBreak = e->canBreak;
4156 ret->mustBreak = e->mustBreak;
4157 ret->isJumpPoint = e->isJumpPoint;
4158 ret->sref = e->sref;
4165 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4166 /*@only@*/ cstring f)
4168 exprNode ret = exprNode_createPartialCopy (s);
4170 ret->edata = exprData_makeField (s, f);
4171 ret->kind = XPR_ARROW;
4173 if (exprNode_isError (s))
4179 ctype t = exprNode_getType (s);
4180 ctype tr = ctype_realType (t);
4182 checkMacroParen (s);
4184 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4186 if (ctype_isRealPointer (tr))
4188 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4190 if (ctype_isStructorUnion (b))
4192 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4194 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4196 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4200 message ("Arrow access from %s pointer%q: %s",
4201 sRef_nullMessage (s->sref),
4202 sRef_unparsePreOpt (s->sref),
4203 exprNode_unparse (ret)),
4206 sRef_showNullInfo (s->sref);
4207 sRef_setNullError (s->sref);
4212 if (uentry_isUndefined (fentry))
4216 message ("Access non-existent field %s of %t: %s",
4217 f, t, exprNode_unparse (ret)),
4219 ret->typ = ctype_unknown;
4225 ** was safeUse: shouldn't be safe!
4228 ** rec must be defined,
4229 ** *rec must be allocated
4230 ** rec->field need only be defined it if is an rvalue
4233 uentry_setUsed (fentry, exprNode_loc (ret));
4234 ret->typ = uentry_getType (fentry);
4236 exprNode_checkUse (ret, s->sref, s->loc);
4238 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4239 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4243 else /* Pointer to something that is not a struct or union*/
4245 if (ctype_isRealAbstract (tr))
4247 ctype xrt = ctype_forceRealType (tr);
4251 message ("Arrow access field of abstract type (%t): %s->%s",
4252 t, exprNode_unparse (s), f),
4256 ** Set the state correctly, as if the abstraction is broken.
4259 if (ctype_isRealPointer (xrt) &&
4260 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4261 ctype_isStructorUnion (b)))
4263 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4264 ret->typ = uentry_getType (fentry);
4265 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4269 ret->typ = ctype_unknown;
4270 ret->sref = sRef_undefined;
4273 else /* not a struct, union or abstract */
4275 if (ctype_isUnknown (tr)) {
4276 cstring sn = cstring_copy (f);
4278 DPRINTF (("Here: %s", exprNode_unparse (s)));
4280 exprNode_checkUse (ret, s->sref, s->loc);
4281 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4283 cstring_markOwned (sn);
4284 ret->sref = sRef_makeArrow (s->sref, sn);
4286 ret->kind = XPR_ARROW;
4291 message ("Arrow access field of non-struct or union "
4292 "pointer (%t): %s->%s",
4293 t, exprNode_unparse (s), f),
4296 ret->typ = ctype_unknown;
4297 ret->sref = sRef_undefined;
4302 else /* its not a pointer */
4304 if (!ctype_isUnknown (tr))
4308 message ("Arrow access of non-pointer (%t): %s->%s",
4309 t, exprNode_unparse (s), f),
4312 ret->typ = ctype_unknown;
4313 ret->sref = sRef_undefined;
4317 cstring sn = cstring_copy (f);
4319 DPRINTF (("Here: %s", exprNode_unparse (s)));
4321 exprNode_checkUse (ret, s->sref, s->loc);
4322 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4324 cstring_markOwned (sn);
4325 ret->sref = sRef_makeArrow (s->sref, sn);
4327 ret->kind = XPR_ARROW;
4338 exprNode_arrowAccess (/*@only@*/ exprNode s,
4339 /*@only@*/ lltok arrow,
4340 /*@only@*/ cstring f)
4342 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4348 ** only postOp's in C: i++ and i--
4352 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4354 /* check modification also */
4355 /* cstring opname = lltok_unparse (op);*/
4357 exprNode ret = exprNode_createPartialCopy (e);
4359 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4360 ret->kind = XPR_POSTOP;
4361 ret->edata = exprData_makeUop (e, op);
4363 if (!exprNode_isDefined (e))
4368 checkMacroParen (e);
4370 exprNode_checkUse (ret, e->sref, e->loc);
4371 exprNode_checkSet (ret, e->sref);
4373 t = exprNode_getType (e);
4375 if (sRef_isUnsafe (e->sref))
4377 voptgenerror (FLG_MACROPARAMS,
4378 message ("Operand of %s is macro parameter (non-functional): %s%s",
4379 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4381 sRef_makeSafe (e->sref);
4382 sRef_makeSafe (ret->sref);
4385 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4391 if (ctype_isRealAbstract (t))
4393 if (ctype_isRealNumAbstract (t)) {
4394 ; /* Allow operations on numabstract types */
4398 message ("Operand of %s is abstract type (%t): %s",
4399 lltok_unparse (op), t, exprNode_unparse (e)),
4407 message ("Operand of %s is non-numeric (%t): %s",
4408 lltok_unparse (op), t, exprNode_unparse (e)),
4411 ret->typ = ctype_unknown;
4414 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4416 exprNode_checkModify (e, ret);
4418 /* added 7/11/2000 D.L */
4420 /*DRL 6/8/01 I decided to disable all Splint warnings here since the code
4421 probably needs a rewrite any way */
4424 /* updateEnvironmentForPostOp (e); */
4426 /* start modifications */
4427 /* added by Seejo on 4/16/2000 */
4429 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4431 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4433 ret->sref = sRef_copy (e->sref);
4436 if (lltok_getTok (op) == INC_OP) {
4437 if (sRef_getSize(e->sref) > 0) {
4439 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4441 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4442 /* Assumption: there is only 1 \0 in the buffer */
4443 /* This will not be correct if there are 2 \0's in the buffer */
4444 sRef_setNotNullTerminatedState(ret->sref);
4445 sRef_resetLen(ret->sref);
4447 sRef_setNullTerminatedState(ret->sref);
4448 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4450 if (sRef_isNullTerminated (ret->sref))
4451 printf ("ret->sref is Null Terminated\n");
4452 else if (sRef_isPossiblyNullTerminated (ret->sref))
4453 printf ("ret->sref is Possibly Null Terminated\n");
4454 else if (sRef_isNotNullTerminated (ret->sref))
4455 printf ("ret->sref is Not Null Terminated\n");
4462 if (lltok_getTok (op) == DEC_OP) {
4463 if (sRef_getSize(e->sref) >= 0) {
4464 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4465 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4469 /* end modifications */
4475 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4477 bool checkMod = FALSE;
4479 int opid = lltok_getTok (op);
4480 exprNode ret = exprNode_createSemiCopy (e);
4482 exprNode_copySets (ret, e);
4484 multiVal_free (ret->val);
4485 ret->val = multiVal_undefined;
4486 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4487 ret->kind = XPR_PREOP;
4488 ret->edata = exprData_makeUop (e, op);
4490 if (exprNode_isError (e))
4495 checkMacroParen (e);
4497 te = exprNode_getType (e);
4498 tr = ctype_realType (te);
4500 if (opid != TAMPERSAND)
4502 exprNode_checkUse (ret, e->sref, e->loc);
4504 if (ctype_isRealAbstract (tr)
4505 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4507 if (ctype_isRealNumAbstract (tr))
4509 ; /* no warning for numabstract types */
4513 if (optgenerror (FLG_ABSTRACT,
4514 message ("Operand of %s is abstract type (%t): %s",
4515 lltok_unparse (op), tr,
4516 exprNode_unparse (ret)),
4519 tr = te = ctype_unknown;
4520 ret->typ = ctype_unknown;
4521 sRef_setNullError (e->sref);
4530 case DEC_OP: /* should also check modification! */
4531 if (sRef_isMacroParamRef (e->sref))
4535 message ("Operand of %s is macro parameter (non-functional): %s",
4536 lltok_unparse (op), exprNode_unparse (ret)),
4541 exprNode_checkSet (ret, e->sref);
4544 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4549 if (context_msgStrictOps ())
4553 message ("Operand of %s is non-numeric (%t): %s",
4554 lltok_unparse (op), te, exprNode_unparse (ret)),
4557 ret->typ = ctype_int;
4560 /* start modifications */
4561 /* added by Seejo on 4/16/2000 */
4563 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4565 if ((sRef_isPossiblyNullTerminated (e->sref))
4566 || (sRef_isNullTerminated(e->sref))) {
4567 ret->sref = sRef_copy (e->sref);
4570 if (lltok_getTok (op) == INC_OP) {
4571 if (sRef_getSize(e->sref) > 0) {
4573 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4575 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4576 /* Assumption: there is only 1 \0 in the buffer */
4577 /* This will not be correct if there are 2 \0's in the buffer */
4578 sRef_setNotNullTerminatedState(ret->sref);
4579 sRef_resetLen (ret->sref);
4581 sRef_setNullTerminatedState(ret->sref);
4582 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4588 if (lltok_getTok (op) == DEC_OP) {
4589 if (sRef_getSize(e->sref) >= 0) {
4590 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4591 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4596 /* end modifications */
4603 if (ctype_isForceRealNumeric (&tr))
4607 ret->val = multiVal_invert (exprNode_getValue (e));
4611 ret->val = multiVal_copy (exprNode_getValue (e));
4616 if (context_msgStrictOps ())
4620 message ("Operand of %s is non-numeric (%t): %s",
4621 lltok_unparse (op), te, exprNode_unparse (ret)),
4625 ret->typ = ctype_int;
4629 case TEXCL: /* maybe this should be restricted */
4630 guardSet_flip (ret->guards);
4632 if (ctype_isRealBool (te) || ctype_isUnknown (te))
4638 if (ctype_isRealPointer (tr))
4640 if (sRef_isKnown (e->sref))
4642 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4646 (FLG_BOOLOPS, FLG_PTRNEGATE,
4647 message ("Operand of %s is non-boolean (%t): %s",
4648 lltok_unparse (op), te, exprNode_unparse (ret)),
4655 message ("Operand of %s is non-boolean (%t): %s",
4656 lltok_unparse (op), te, exprNode_unparse (ret)),
4660 ret->typ = ctype_bool;
4665 if (ctype_isForceRealInt (&tr))
4670 if (context_msgStrictOps ())
4674 message ("Operand of %s is non-integer (%t): %s",
4675 lltok_unparse (op), te, exprNode_unparse (ret)),
4679 if (ctype_isInt (e->typ))
4685 ret->typ = ctype_int;
4691 ret->typ = ctype_makePointer (e->typ);
4693 if (sRef_isKnown (e->sref))
4695 ret->sref = sRef_makeAddress (e->sref);
4702 if (ctype_isAP (tr))
4704 ret->typ = ctype_baseArrayPtr (e->typ);
4708 if (ctype_isKnown (te))
4710 if (ctype_isFunction (te))
4716 message ("Dereference of function type (%t): %s",
4717 te, exprNode_unparse (ret)),
4722 voptgenerror (FLG_TYPE,
4723 message ("Dereference of non-pointer (%t): %s",
4724 te, exprNode_unparse (ret)),
4726 ret->typ = ctype_unknown;
4731 ret->typ = ctype_unknown;
4736 if (sRef_isKnown (e->sref))
4738 DPRINTF (("Checking possibly null: %s", sRef_unparseFull (e->sref)));
4740 if (sRef_possiblyNull (e->sref))
4742 DPRINTF (("Checking possibly null: %s", sRef_unparse (e->sref)));
4743 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4747 message ("Dereference of %s pointer %q: %s",
4748 sRef_nullMessage (e->sref),
4749 sRef_unparse (e->sref),
4750 exprNode_unparse (ret)),
4753 sRef_showNullInfo (e->sref);
4754 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4759 ret->sref = sRef_makePointer (e->sref);
4764 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4769 exprNode_checkModify (e, ret);
4776 ** any reason to disallow sizeof (abstract type) ?
4780 ** used by both sizeof
4784 ctype sizeof_resultType (void)
4786 static ctype sizet = ctype_unknown;
4788 if (ctype_isUnknown (sizet))
4790 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4792 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4796 sizet = ctype_ulint;
4803 exprNode_sizeofType (/*@only@*/ qtype qt)
4805 exprNode ret = exprNode_create (sizeof_resultType ());
4806 ctype ct = qtype_getType (qt);
4808 ret->kind = XPR_SIZEOFT;
4809 ret->edata = exprData_makeSizeofType (qt);
4811 voptgenerror (FLG_SIZEOFTYPE,
4812 message ("Parameter to sizeof is type %s: %s",
4814 exprNode_unparse (ret)),
4821 exprNode_alignofType (/*@only@*/ qtype qt)
4823 exprNode ret = exprNode_create (sizeof_resultType ());
4824 ctype ct = qtype_getType (qt);
4826 ret->kind = XPR_ALIGNOFT;
4827 ret->edata = exprData_makeSizeofType (qt);
4829 voptgenerror (FLG_SIZEOFTYPE,
4830 message ("Parameter to alignof is type %s: %s",
4832 exprNode_unparse (ret)),
4838 exprNode exprNode_offsetof (qtype qt, cstringList s)
4840 exprNode ret = exprNode_create (sizeof_resultType ());
4841 ctype ct = qtype_getType (qt);
4843 ret->kind = XPR_OFFSETOF;
4844 ret->edata = exprData_makeOffsetof (qt, s);
4846 if (!ctype_isRealSU (ct))
4848 voptgenerror (FLG_TYPE,
4849 message ("First parameter to offsetof is not a "
4850 "struct or union type (type %s): %s",
4852 exprNode_unparse (ret)),
4859 cstringList_elements (s, el) {
4863 if (ctype_isUndefined (lt))
4867 else if (!ctype_isRealSU (lt))
4869 voptgenerror (FLG_TYPE,
4870 message ("Inner offsetof type is not a "
4871 "struct or union type (type %s before field %s): %s",
4872 ctype_unparse (lt), el,
4873 exprNode_unparse (ret)),
4879 fields = ctype_getFields (ctype_realType (lt));
4880 fld = uentryList_lookupField (fields, el);
4881 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4883 if (uentry_isUndefined (fld))
4885 if (ctype_equal (lt, ct)) {
4886 voptgenerror (FLG_TYPE,
4887 message ("Field %s in offsetof is not the "
4888 "name of a field of %s: %s",
4891 exprNode_unparse (ret)),
4894 voptgenerror (FLG_TYPE,
4895 message ("Deep field %s in offsetof is not the "
4896 "name of a field of %s: %s",
4899 exprNode_unparse (ret)),
4905 lt = uentry_getType (fld);
4908 } end_cstringList_elements;
4910 /* Should report error if its a bit field - behavior is undefined! */
4917 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4921 if (exprNode_isUndefined (e))
4923 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4924 ret->edata = exprData_makeSingle (e);
4925 ret->typ = sizeof_resultType ();
4926 ret->kind = XPR_SIZEOF;
4930 uentry u = exprNode_getUentry (e);
4932 ret = exprNode_createPartialCopy (e);
4933 ret->edata = exprData_makeSingle (e);
4935 ret->typ = sizeof_resultType ();
4936 ret->kind = XPR_SIZEOF;
4938 if (uentry_isValid (u)
4939 && uentry_isRefParam (u)
4940 && ctype_isRealArray (uentry_getType (u)))
4943 (FLG_SIZEOFFORMALARRAY,
4944 message ("Parameter to sizeof is an array-type function parameter: %s",
4945 exprNode_unparse (ret)),
4951 ** sizeof (x) doesn't "really" use x
4958 exprNode_alignofExpr (/*@only@*/ exprNode e)
4962 if (exprNode_isUndefined (e))
4964 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4968 ret = exprNode_createPartialCopy (e);
4971 ret->edata = exprData_makeSingle (e);
4972 ret->typ = sizeof_resultType ();
4973 ret->kind = XPR_ALIGNOF;
4976 ** sizeof (x) doesn't "really" use x
4983 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4989 if (exprNode_isError (e))
4993 return exprNode_undefined;
4996 checkMacroParen (e);
4998 c = qtype_getType (q);
4999 t = exprNode_getType (e);
5001 ret = exprNode_createPartialCopy (e);
5003 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
5005 ret->kind = XPR_CAST;
5006 ret->edata = exprData_makeCast (tok, e, q);
5008 ret->sref = sRef_copy (e->sref);
5010 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
5012 if (!sRef_isConst (e->sref))
5014 usymtab_addForceMustAlias (ret->sref, e->sref);
5017 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
5018 sRef_setTypeFull (ret->sref, c);
5019 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
5025 ** void * <-> abstract * (if FLG_ABSTVOIDP)
5026 ** abstract * <-> void * (if FLG_ABSTVOIDP)
5029 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
5031 /* evans 2002-07-19: added this warning */
5032 DPRINTF (("Checking: %s / %s", exprNode_unparse (ret), sRef_unparseFull (ret->sref)));
5033 if (sRef_isFresh (ret->sref))
5037 message ("New fresh storage %q(type %s) cast to void (not released): %s",
5038 sRef_unparseOpt (ret->sref),
5039 ctype_unparse (exprNode_getType (ret)),
5040 exprNode_unparse (ret)),
5041 exprNode_loc (ret));
5044 else if (ctype_isRealAP (c)) /* casting to array or pointer */
5046 ctype bc = ctype_getBaseType (c);
5047 ctype bt = ctype_getBaseType (t);
5048 ctype rt = ctype_realType (t);
5050 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
5051 && (ctype_isArrayPtr (rt)
5052 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5056 message ("Cast from function pointer type (%t) to "
5057 "non-function pointer (%t): %s",
5058 c, t, exprNode_unparse (ret)),
5062 if (!ctype_isFunction (ctype_baseArrayPtr (c))
5063 && (ctype_isArrayPtr (rt)
5064 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5068 message ("Cast from non-function pointer type (%t) to "
5069 "function pointer (%t): %s",
5070 c, t, exprNode_unparse (ret)),
5074 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
5075 !(ctype_isRealAbstract (bc)
5076 && context_hasAccess (ctype_typeId (bc))))
5078 ; /* okay to cast zero */
5082 if (ctype_isRealAbstract (bc)
5083 && !context_hasAccess (ctype_typeId (bc)))
5085 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
5089 message ("Cast to underlying abstract type %t: %s",
5090 c, exprNode_unparse (ret)),
5097 message ("Cast to underlying abstract type %t: %s",
5098 c, exprNode_unparse (ret)),
5103 if (ctype_isRealAbstract (bt)
5104 && !context_hasAccess (ctype_typeId (bt)))
5106 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
5110 message ("Cast from underlying abstract type %t: %s",
5111 t, exprNode_unparse (ret)),
5118 message ("Cast from underlying abstract type %t: %s",
5119 t, exprNode_unparse (ret)),
5127 ctype bt = ctype_realType (ctype_getBaseType (t));
5128 ctype bc = ctype_realType (ctype_getBaseType (c));
5130 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
5132 if (ctype_match (c, t))
5134 if (ctype_equal (c, t))
5138 message ("Redundant cast involving abstract type %t: %s",
5139 bt, exprNode_unparse (ret)),
5147 message ("Cast from abstract type %t: %s",
5148 bt, exprNode_unparse (ret)),
5153 if (ctype_isAbstract (bc)
5154 && !context_hasAccess (ctype_typeId (bc)))
5156 if (ctype_match (c, t))
5162 if (ctype_isNumAbstract (bc))
5164 if (exprNode_isNumLiteral (e))
5167 (FLG_NUMABSTRACTCAST,
5168 message ("Cast from literal to numabstract type %t: %s", bc,
5169 exprNode_unparse (ret)),
5176 message ("Cast to numabstract type %t: %s", bc,
5177 exprNode_unparse (ret)),
5183 DPRINTF (("No access to: %s / %d",
5184 ctype_unparse (bc), ctype_typeId (bc)));
5185 DPRINTF (("Context %s %s",
5186 bool_unparse (context_inFunctionLike ()),
5187 context_unparse ()));
5190 message ("Cast to abstract type %t: %s", bc,
5191 exprNode_unparse (ret)),
5198 if (ctype_isAbstract (c))
5200 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
5202 /* okay, cast exposed to abstract */
5203 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
5207 if (ctype_isVisiblySharable (t)
5208 && sRef_isExternallyVisible (e->sref)
5209 && !(ctype_isAbstract (t)
5210 && context_hasAccess (ctype_typeId (t))))
5214 message ("Cast to abstract type from externally visible "
5215 "mutable storage exposes rep of %s: %s",
5217 exprNode_unparse (e)),
5227 evaluationOrderUndefined (lltok op)
5229 int opid = lltok_getTok (op);
5231 return (opid != AND_OP && opid != OR_OP);
5234 static bool checkIntegral (/*@notnull@*/ exprNode e1,
5235 /*@notnull@*/ exprNode e2,
5236 /*@notnull@*/ exprNode ret,
5241 ctype te1 = exprNode_getType (e1);
5242 ctype te2 = exprNode_getType (e2);
5244 ctype tr1 = ctype_realishType (te1);
5245 ctype tr2 = ctype_realishType (te2);
5247 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5253 if (context_msgStrictOps ())
5255 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5257 if (ctype_sameName (te1, te2))
5261 message ("Operands of %s are non-integer (%t): %s",
5262 lltok_unparse (op), te1,
5263 exprNode_unparse (ret)),
5270 message ("Operands of %s are non-integers (%t, %t): %s",
5271 lltok_unparse (op), te1, te2,
5272 exprNode_unparse (ret)),
5276 else if (!ctype_isInt (tr1))
5280 message ("Left operand of %s is non-integer (%t): %s",
5281 lltok_unparse (op), te1, exprNode_unparse (ret)),
5285 /* !ctype_isInt (te2) */
5289 message ("Right operand of %s is non-integer (%t): %s",
5290 lltok_unparse (op), te2, exprNode_unparse (ret)),
5300 ** returns exprNode representing e1 op e2
5302 ** uses msg if there are errors
5303 ** can be used for both assignment ops and regular ops
5308 static /*@only@*/ /*@notnull@*/ exprNode
5309 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
5310 /*@keep@*/ lltok op)
5312 ctype te1, te2, tr1, tr2, tret;
5313 int opid = lltok_getTok (op);
5314 bool hasError = FALSE;
5317 if (exprNode_isError (e1))
5319 ret = exprNode_createPartialNVCopy (e2);
5323 ret = exprNode_createPartialNVCopy (e1);
5326 ret->val = multiVal_undefined;
5329 ret->edata = exprData_makeOp (e1, e2, op);
5331 if (exprNode_isError (e1) || exprNode_isError (e2))
5333 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5334 || opid == EQ_OP || opid == NE_OP
5335 || opid == AND_OP || opid == OR_OP)
5337 ret->typ = ctype_bool;
5340 if (exprNode_isDefined (e1))
5342 exprNode_checkUse (ret, e1->sref, e1->loc);
5345 if (exprNode_isDefined (e2))
5347 exprNode_mergeUSs (ret, e2);
5348 exprNode_checkUse (ret, e2->sref, e2->loc);
5354 tret = ctype_unknown;
5355 te1 = exprNode_getType (e1);
5357 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5359 te2 = exprNode_getType (e2);
5361 tr1 = ctype_realishType (te1);
5362 tr2 = ctype_realishType (te2);
5366 ret->guards = guardSet_or (ret->guards, e2->guards);
5368 else if (opid == AND_OP)
5370 ret->guards = guardSet_and (ret->guards, e2->guards);
5377 if (opid == EQ_OP || opid == NE_OP)
5379 exprNode temp1 = e1, temp2 = e2;
5381 /* could do NULL == x */
5383 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5385 temp1 = e2; temp2 = e1;
5388 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5390 reflectNullTest (temp1, (opid == NE_OP));
5391 guardSet_free (ret->guards);
5392 ret->guards = guardSet_copy (temp1->guards);
5396 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5397 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5402 if (anyAbstract (tr1, tr2) &&
5403 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
5404 (opid == AND_OP || opid == OR_OP
5405 || opid == EQ_OP || opid == NE_OP))))
5407 if (abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc))
5409 tret = ctype_unknown;
5414 if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5416 /* unknown types, no comparisons possible */
5422 case TMULT: /* multiplication and division: */
5424 case MUL_ASSIGN: /* numeric, numeric -> numeric */
5425 case DIV_ASSIGN: /* */
5426 if (opid == TMULT || opid == MUL_ASSIGN)
5428 ret->val = multiVal_multiply (exprNode_getValue (e1),
5429 exprNode_getValue (e2));
5433 ret->val = multiVal_divide (exprNode_getValue (e1),
5434 exprNode_getValue (e2));
5437 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5440 case TPLUS: /* addition and subtraction: */
5441 case TMINUS: /* pointer, int -> pointer */
5442 case SUB_ASSIGN: /* int, pointer -> pointer */
5443 case ADD_ASSIGN: /* numeric, numeric -> numeric */
5444 if (opid == TPLUS || opid == ADD_ASSIGN)
5446 ret->val = multiVal_add (exprNode_getValue (e1),
5447 exprNode_getValue (e2));
5451 ret->val = multiVal_subtract (exprNode_getValue (e1),
5452 exprNode_getValue (e2));
5455 tr1 = ctype_fixArrayPtr (tr1);
5457 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5458 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5462 if (context_msgPointerArith ())
5466 message ("Pointer arithmetic (%t, %t): %s",
5467 te1, te2, exprNode_unparse (ret)),
5472 ** Swap terms so e1 is always the pointer
5475 if (ctype_isRealPointer (tr1))
5481 exprNode_swap (e1, e2);
5484 if (sRef_possiblyNull (e1->sref)
5485 && !usymtab_isGuarded (e1->sref))
5488 (FLG_NULLPOINTERARITH,
5489 message ("Pointer arithmetic involving possibly "
5490 "null pointer %s: %s",
5491 exprNode_unparse (e1),
5492 exprNode_unparse (ret)),
5496 ret->sref = sRef_copy (e1->sref);
5498 /* start modifications */
5499 /* added by Seejo on 4/16/2000 */
5501 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5503 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5506 added ugly fixed to stop
5507 program from crashing on point + int +int
5508 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5510 if (!multiVal_isInt (e2->val) )
5514 val = (int) multiVal_forceInt (e2->val);
5516 /* Operator : + or += */
5517 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5518 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5519 val should not result in a
5520 size < 0 (size = 0 is ok !) */
5522 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5524 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5525 sRef_setNotNullTerminatedState(ret->sref);
5526 sRef_resetLen (ret->sref);
5528 sRef_setNullTerminatedState(ret->sref);
5529 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5534 /* Operator : - or -= */
5535 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5536 if (sRef_getSize(e1->sref) >= 0) {
5537 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5538 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5543 /* end modifications */
5545 sRef_setNullError (ret->sref);
5548 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5549 ** since is points to storage that should not be deallocated
5550 ** through this pointer.
5553 if (sRef_isOnly (ret->sref)
5554 || sRef_isFresh (ret->sref))
5556 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5561 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5562 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5564 if (context_msgPointerArith ())
5568 message ("Pointer arithmetic (%t, %t): %s",
5569 te1, te2, exprNode_unparse (ret)),
5573 if (sRef_possiblyNull (e1->sref)
5574 && !usymtab_isGuarded (e1->sref))
5577 (FLG_NULLPOINTERARITH,
5578 message ("Pointer arithmetic involving possibly "
5579 "null pointer %s: %s",
5580 exprNode_unparse (e2),
5581 exprNode_unparse (ret)),
5585 ret->sref = sRef_copy (e2->sref);
5587 /* start modifications */
5588 /* added by Seejo on 4/16/2000 */
5590 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5593 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5594 int val = (int) multiVal_forceInt (e1->val);
5596 /* Operator : + or += */
5597 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5598 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5599 val should not result in a
5600 size < 0 (size = 0 is ok !) */
5602 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5604 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5605 sRef_setNotNullTerminatedState(ret->sref);
5606 sRef_resetLen (ret->sref);
5608 sRef_setNullTerminatedState(ret->sref);
5609 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5614 /* Operator : - or -= */
5615 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5616 if (sRef_getSize(e2->sref) >= 0) {
5617 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5618 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5622 /* end modifications */
5624 sRef_setNullError (ret->sref);
5627 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5628 ** since is points to storage that should not be deallocated
5629 ** through this pointer.
5632 if (sRef_isOnly (ret->sref)
5633 || sRef_isFresh (ret->sref)) {
5634 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5638 ret->sref = e2->sref;
5642 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5651 case TAMPERSAND: /* bitwise & */
5653 case TCIRC: /* ^ (XOR) */
5658 bool reported = FALSE;
5664 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5665 || opid == RIGHT_OP || opid == RIGHT_ASSIGN)
5668 ** evans 2002-01-01: fixed this to follow ISO 6.5.7.
5671 if (!ctype_isUnsigned (tr2)
5672 && !exprNode_isNonNegative (e2))
5674 reported = optgenerror
5676 message ("Right operand of %s may be negative (%t): %s",
5677 lltok_unparse (op), te2,
5678 exprNode_unparse (ret)),
5682 if (!ctype_isUnsigned (tr1)
5683 && !exprNode_isNonNegative (e1))
5685 reported = optgenerror
5686 (FLG_SHIFTIMPLEMENTATION,
5687 message ("Left operand of %s may be negative (%t): %s",
5688 lltok_unparse (op), te1,
5689 exprNode_unparse (ret)),
5694 ** Should check size of right operand also...
5700 if (!ctype_isUnsigned (tr1))
5702 if (exprNode_isNonNegative (e1)) {
5705 reported = optgenerror
5707 message ("Left operand of %s is not unsigned value (%t): %s",
5708 lltok_unparse (op), te1,
5709 exprNode_unparse (ret)),
5719 if (!ctype_isUnsigned (tr2))
5721 if (!exprNode_isNonNegative (e2)) {
5722 reported = optgenerror
5724 message ("Right operand of %s is not unsigned value (%t): %s",
5725 lltok_unparse (op), te2,
5726 exprNode_unparse (ret)),
5735 if (!checkIntegral (e1, e2, ret, op)) {
5736 te1 = ctype_unknown;
5740 DPRINTF (("Set: %s", ctype_unparse (te1)));
5743 ** tret is the widest type of te1 and te2
5746 tret = ctype_widest (te1, te2);
5751 if (checkIntegral (e1, e2, ret, op)) {
5754 tret = ctype_unknown;
5759 case TLT: /* comparisons */
5760 case TGT: /* numeric, numeric -> bool */
5762 DPRINTF (("Here we go: %s / %s",
5763 ctype_unparse (tr1), ctype_unparse (tr2)));
5765 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5766 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5769 bool fepsilon = FALSE;
5771 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5776 if (opid == TLT || opid == TGT)
5778 uentry ue1 = exprNode_getUentry (e1);
5779 uentry ue2 = exprNode_getUentry (e2);
5782 ** FLT_EPSILON, etc. really is a variable, not
5786 if (uentry_isVariable (ue1))
5788 cstring uname = uentry_rawName (ue1);
5790 if (cstring_equalLit (uname, "FLT_EPSILON")
5791 || cstring_equalLit (uname, "DBL_EPSILON")
5792 || cstring_equalLit (uname, "LDBL_EPSILON"))
5798 if (uentry_isVariable (ue2))
5800 cstring uname = uentry_rawName (ue2);
5802 if (cstring_equalLit (uname, "FLT_EPSILON")
5803 || cstring_equalLit (uname, "DBL_EPSILON")
5804 || cstring_equalLit (uname, "LDBL_EPSILON"))
5813 ; /* Don't complain. */
5819 message ("Dangerous comparison involving %s types: %s",
5820 ctype_unparse (rtype),
5821 exprNode_unparse (ret)),
5830 ** Types should match.
5833 DPRINTF (("Match types: %s / %s", exprNode_unparse (e1),
5834 exprNode_unparse (e2)));
5836 if (!exprNode_matchTypes (e1, e2))
5838 hasError = gentypeerror
5840 message ("Operands of %s have incompatible types (%t, %t): %s",
5841 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5847 || (ctype_isForceRealNumeric (&tr1)
5848 && ctype_isForceRealNumeric (&tr2)) ||
5849 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5855 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5856 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5860 message ("Comparison of pointer and numeric (%t, %t): %s",
5861 te1, te2, exprNode_unparse (ret)),
5866 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5871 /* certain comparisons on unsigned's and zero look suspicious */
5873 if (opid == TLT || opid == LE_OP || opid == GE_OP)
5875 if ((ctype_isUnsigned (tr1) && exprNode_isZero (e2))
5876 || (ctype_isUnsigned (tr2) && exprNode_isZero (e1)))
5879 (FLG_UNSIGNEDCOMPARE,
5880 message ("Comparison of unsigned value involving zero: %s",
5881 exprNode_unparse (ret)),
5886 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5888 if ((opid == EQ_OP || opid == NE_OP) &&
5889 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5892 ** is one a variable?
5895 if (uentry_isVariable (exprNode_getUentry (e1))
5896 || uentry_isVariable (exprNode_getUentry (e2)))
5899 ** comparisons with FALSE are okay
5902 if (exprNode_isFalseConstant (e1)
5903 || exprNode_isFalseConstant (e2))
5912 ("Use of %q with %s variables (risks inconsistency because "
5913 "of multiple true values): %s",
5914 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5915 context_printBoolName (), exprNode_unparse (ret)),
5922 case AND_OP: /* bool, bool -> bool */
5924 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5930 if (context_maybeSet (FLG_BOOLOPS))
5932 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5934 if (ctype_sameName (te1, te2))
5938 message ("Operands of %s are non-boolean (%t): %s",
5939 lltok_unparse (op), te1,
5940 exprNode_unparse (ret)),
5948 ("Operands of %s are non-booleans (%t, %t): %s",
5949 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5953 else if (!ctype_isRealBool (te1))
5957 message ("Left operand of %s is non-boolean (%t): %s",
5958 lltok_unparse (op), te1, exprNode_unparse (ret)),
5961 else if (!ctype_isRealBool (te2))
5965 message ("Right operand of %s is non-boolean (%t): %s",
5966 lltok_unparse (op), te2, exprNode_unparse (ret)),
5979 (cstring_makeLiteral
5980 ("There has been a problem in the parser. This is believed to result "
5981 "from a problem with bison v. 1.25. Please try rebuidling Splint "
5982 "using the pre-compiled grammar files by commenting out the "
5983 "BISON= line in the top-level Makefile."));
5988 DPRINTF (("Return type %s: %s", exprNode_unparse (ret), ctype_unparse (tret)));
5990 exprNode_checkUse (ret, e1->sref, e1->loc);
5991 exprNode_mergeUSs (ret, e2);
5992 exprNode_checkUse (ret, e2->sref, e2->loc);
5998 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5999 /*@only@*/ lltok op)
6003 checkMacroParen (e1);
6004 checkMacroParen (e2);
6006 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
6008 checkExpressionDefined (e1, e2, op);
6011 ret = exprNode_makeOp (e1, e2, op);
6016 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
6019 ** This is somewhat bogus!
6021 ** Assigning to a nested observer in a non-observer datatype
6022 ** should not produce an error.
6025 sRef ref = exprNode_getSref (e1);
6027 DPRINTF (("Check assign mod: %s",
6028 sRef_unparseFull (ref)));
6030 if (sRef_isObserver (ref)
6031 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
6032 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
6034 sRef base = sRef_getBase (ref);
6036 if (sRef_isValid (base) && sRef_isObserver (base))
6038 exprNode_checkModify (e1, ret);
6042 exprNode_checkModifyVal (e1, ret);
6047 exprNode_checkModify (e1, ret);
6052 exprNode_assign (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2, /*@only@*/ lltok op)
6054 bool isalloc = FALSE;
6055 bool isjustalloc = FALSE;
6056 bool noalias = FALSE;
6059 DPRINTF (("%s [%s] <- %s [%s]",
6060 exprNode_unparse (e1),
6061 ctype_unparse (e1->typ),
6062 exprNode_unparse (e2),
6063 ctype_unparse (e2->typ)));
6065 if (lltok_getTok (op) != TASSIGN)
6067 ret = exprNode_makeOp (e1, e2, op);
6069 DPRINTF (("Here goes: %s %s",
6070 ctype_unparse (e1->typ),
6071 ctype_unparse (e2->typ)));
6073 if (exprNode_isDefined (e1)
6074 && exprNode_isDefined (e2))
6076 if (ctype_isNumeric (e2->typ)
6077 || ctype_isNumeric (e1->typ))
6079 /* Its a pointer arithmetic expression like ptr += i */
6086 ret = exprNode_createPartialCopy (e1);
6087 ret->kind = XPR_ASSIGN;
6088 ret->edata = exprData_makeOp (e1, e2, op);
6090 if (!exprNode_isError (e2))
6092 ret->sets = sRefSet_union (ret->sets, e2->sets);
6093 ret->msets = sRefSet_union (ret->msets, e2->msets);
6094 ret->uses = sRefSet_union (ret->uses, e2->uses);
6098 checkExpressionDefined (e1, e2, op);
6100 if (exprNode_isError (e1))
6102 if (!exprNode_isError (e2))
6104 ret->loc = fileloc_update (ret->loc, e2->loc);
6108 ret->loc = fileloc_update (ret->loc, g_currentloc);
6112 if (!exprNode_isError (e2))
6114 checkMacroParen (e2);
6117 if (exprNode_isDefined (e1))
6119 if (sRef_isMacroParamRef (e1->sref))
6121 if (context_inIterDef ())
6123 uentry ue = sRef_getUentry (e1->sref);
6125 if (uentry_isYield (ue))
6131 if (fileloc_isDefined (e1->loc))
6135 message ("Assignment to non-yield iter parameter: %q",
6136 sRef_unparse (e1->sref)),
6143 message ("Assignment to non-yield iter parameter: %q",
6144 sRef_unparse (e1->sref)),
6151 if (fileloc_isDefined (e1->loc))
6155 message ("Assignment to macro parameter: %q",
6156 sRef_unparse (e1->sref)),
6163 message ("Assignment to macro parameter: %q",
6164 sRef_unparse (e1->sref)),
6168 exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
6173 exprNode_checkAssignMod (e1, ret);
6176 if (exprNode_isDefined (e2))
6178 if (lltok_getTok (op) == TASSIGN)
6180 ctype te1 = exprNode_getType (e1);
6181 ctype te2 = exprNode_getType (e2);
6183 if (ctype_isVoid (te2))
6187 message ("Assignment of void value to %t: %s %s %s",
6188 te1, exprNode_unparse (e1),
6190 exprNode_unparse (e2)),
6193 else if (!ctype_forceMatch (te1, te2))
6195 if (exprNode_matchLiteral (te1, e2))
6197 DPRINTF (("Literals match: %s / %s",
6198 ctype_unparse (te1), exprNode_unparse (e2)));
6199 if (ctype_isNumAbstract (te1)) {
6200 if (!context_flagOn (FLG_NUMABSTRACTLIT, e1->loc)) {
6201 (void) llgenhinterror
6204 ("Assignment of %t literal to numabstract type %t: %s %s %s",
6206 exprNode_unparse (e1),
6208 exprNode_unparse (e2)),
6210 ("Use +numabstractlit to allow numeric literals to be used as numabstract values"),
6219 message ("Assignment of %t to %t: %s %s %s",
6220 te2, te1, exprNode_unparse (e1),
6222 exprNode_unparse (e2)),
6228 /* Type checks okay */
6232 exprNode_mergeUSs (ret, e2);
6233 exprNode_checkUse (ret, e2->sref, e2->loc);
6235 DPRINTF (("Do assign! %s %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6242 doAssign (e1, e2, FALSE);
6245 ret->sref = e1->sref;
6249 if (exprNode_isDefined (e2))
6251 exprNode_mergeUSs (ret, e2);
6252 exprNode_checkUse (ret, e2->sref, e2->loc);
6256 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
6258 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
6261 isjustalloc = sRef_isJustAllocated (e1->sref);
6262 isalloc = sRef_isAllocated (e1->sref);
6264 if (sRef_isField (e1->sref))
6266 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
6268 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
6270 exprNode_checkUse (ret, root, e1->loc);
6276 ** be careful! this defines e1->sref.
6279 /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
6281 DPRINTF (("Setting: %s -> %s", exprNode_unparse (ret), sRef_unparse (e1->sref)));
6282 exprNode_checkSet (ret, e1->sref);
6286 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
6287 ? e2->loc : e1->loc);
6293 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
6302 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
6303 /*@keep@*/ exprNode elseclause)
6307 if (!exprNode_isError (pred))
6309 ret = exprNode_createPartialCopy (pred);
6310 checkMacroParen (pred);
6311 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
6313 if (!exprNode_isError (ifclause))
6315 checkMacroParen (ifclause); /* update macro counts! */
6317 if (!exprNode_isError (elseclause))
6319 checkMacroParen (elseclause);
6321 if (!exprNode_matchTypes (ifclause, elseclause))
6324 (exprNode_getType (ifclause),
6326 exprNode_getType (elseclause),
6328 message ("Conditional clauses are not of same type: "
6330 exprNode_unparse (ifclause),
6331 exprNode_getType (ifclause),
6332 exprNode_unparse (elseclause),
6333 exprNode_getType (elseclause)),
6336 ret->sref = sRef_undefined;
6337 ret->typ = ctype_unknown;
6342 /* for now...should merge the states */
6343 ret->sref = ifclause->sref;
6344 ret->typ = ifclause->typ;
6346 if (exprNode_isNullValue (ifclause))
6348 ret->typ = elseclause->typ;
6352 exprNode_checkUse (ret, pred->sref, pred->loc);
6353 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6354 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6356 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6361 ret->typ = ifclause->typ;
6363 exprNode_checkUse (pred, pred->sref, pred->loc);
6364 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6366 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6371 if (!exprNode_isError (elseclause))
6373 ret->typ = elseclause->typ;
6375 exprNode_checkUse (pred, pred->sref, pred->loc);
6376 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6378 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6382 else /* pred is error */
6384 if (!exprNode_isError (ifclause))
6386 ret = exprNode_createSemiCopy (ifclause);
6388 checkMacroParen (ifclause); /* update macro counts! */
6390 if (!exprNode_isError (elseclause))
6392 checkMacroParen (elseclause);
6394 ret->typ = ifclause->typ;
6396 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6399 (exprNode_getType (ifclause),
6401 exprNode_getType (elseclause),
6403 message ("Conditional clauses are not of same type: "
6405 exprNode_unparse (ifclause),
6406 exprNode_getType (ifclause),
6407 exprNode_unparse (elseclause),
6408 exprNode_getType (elseclause)),
6411 ret->typ = ctype_unknown;
6415 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6416 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6418 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6421 else if (!exprNode_isError (elseclause)) /* pred, if errors */
6423 ret = exprNode_createSemiCopy (ifclause);
6425 ret->typ = elseclause->typ;
6426 checkMacroParen (elseclause);
6428 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6429 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6431 else /* all errors! */
6433 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6437 ret->kind = XPR_COND;
6438 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
6440 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6442 exprNode_combineControl (ret, ifclause, elseclause);
6449 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6451 ctype totype = qtype_getType (qt);
6453 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6457 ** check use of va_arg : <valist>, type -> type
6460 if (exprNode_isError (arg))
6465 targ = exprNode_getType (arg);
6468 ** arg should have be a pointer
6471 if (!ctype_isUA (targ) ||
6472 (!usymId_equal (ctype_typeId (targ),
6473 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6477 message ("First argument to va_arg is not a va_list (type %t): %s",
6478 targ, exprNode_unparse (arg)),
6482 exprNode_checkSet (ret, arg->sref);
6486 ** return type is totype
6490 ret->kind = XPR_VAARG;
6491 ret->edata = exprData_makeCast (tok, arg, qt);
6496 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6498 exprNode ret = exprNode_createPlain (ctype_undefined);
6499 ret->kind = XPR_LABEL;
6500 ret->edata = exprData_makeLiteral (label);
6501 ret->isJumpPoint = TRUE;
6503 return (ret); /* for now, ignore label */
6506 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6508 if (exprNode_isDefined (stmt))
6510 stmt->isJumpPoint = TRUE;
6512 /* This prevent stray no return path errors, etc. */
6513 stmt->exitCode = XK_MUSTEXIT;
6519 bool exprNode_isDefaultMarker (exprNode e)
6521 if (exprNode_isDefined (e))
6523 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6529 bool exprNode_isCaseMarker (exprNode e)
6531 if (exprNode_isDefined (e))
6533 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6539 bool exprNode_isLabelMarker (exprNode e)
6541 if (exprNode_isDefined (e))
6543 return (e->kind == XPR_LABEL);
6549 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6551 exprNode ret = exprNode_createPartialCopy (test);
6553 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6555 if (exprNode_isError (test)) {
6559 exprNode_checkUse (ret, test->sref, test->loc);
6561 usymtab_setExitCode (ret->exitCode);
6565 usymtab_setMustBreak ();
6568 ret->edata = exprData_makeSingle (test);
6569 ret->isJumpPoint = TRUE;
6575 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6577 exprNode ret = exprNode_createPartialCopy (test);
6579 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6580 ret->edata = exprData_makePair (test, stmt);
6581 ret->isJumpPoint = TRUE;
6583 if (exprNode_isError (test))
6588 exprNode_checkUse (ret, test->sref, test->loc);
6590 if (exprNode_isError (stmt))
6595 exprNode_mergeUSs (ret, stmt);
6597 ret->exitCode = stmt->exitCode;
6598 ret->mustBreak = stmt->mustBreak;
6599 ret->canBreak = stmt->canBreak;
6601 usymtab_setExitCode (ret->exitCode);
6605 usymtab_setMustBreak ();
6612 /*@notnull@*/ /*@only@*/ exprNode
6613 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6615 exprNode ret = exprNode_createTok (def);
6617 ret->isJumpPoint = TRUE;
6618 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6623 exprNode_mayEscape (exprNode e)
6625 if (exprNode_isDefined (e))
6627 return exitkind_couldEscape (e->exitCode);
6633 exprNode_mustBreak (exprNode e)
6635 if (exprNode_isDefined (e))
6637 return e->mustBreak;
6644 exprNode_mustEscape (exprNode e)
6646 if (exprNode_isDefined (e))
6648 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6655 exprNode_errorEscape (exprNode e)
6657 if (exprNode_isDefined (e))
6659 return exitkind_isError (e->exitCode);
6665 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6667 exprNode ret = exprNode_createPartialCopy (e1);
6669 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6671 ret->edata = exprData_makePair (e1, e2);
6672 ret->kind = XPR_STMTLIST;
6674 if (exprNode_isDefined (e1))
6676 ret->isJumpPoint = e1->isJumpPoint;
6677 ret->canBreak = e1->canBreak;
6681 if (exprNode_isDefined (e2))
6683 ret->loc = fileloc_update (ret->loc, e2->loc);
6687 if (exprNode_isDefined (e2))
6689 ret->exitCode = e2->exitCode;
6690 ret->mustBreak = e2->mustBreak;
6691 if (e2->canBreak) ret->canBreak = TRUE;
6695 ** if e1 must return, then e2 is unreachable!
6698 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6700 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6701 && !(e2->isJumpPoint))
6703 if (context_getFlag (FLG_UNREACHABLE))
6707 if (e2->kind == XPR_STMT)
6709 nr = exprData_getUopNode (e2->edata);
6712 if ((nr->kind == XPR_TOK
6713 && lltok_isSemi (exprData_getTok (nr->edata))))
6715 /* okay to have unreachable ";" */
6716 ret->exitCode = XK_MUSTEXIT;
6717 ret->canBreak = TRUE;
6721 if (optgenerror (FLG_UNREACHABLE,
6722 message ("Unreachable code: %s",
6723 exprNode_unparseFirst (nr)),
6726 ret->isJumpPoint = TRUE;
6727 ret->mustBreak = FALSE;
6728 ret->exitCode = XK_ERROR;
6729 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6733 ret->exitCode = XK_MUSTEXIT;
6734 ret->canBreak = TRUE;
6742 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6745 ** We want a warning anytime we have:
6747 ** yyy; <<<- no break or return
6751 exprNode lastStmt = exprNode_lastStatement (e1);
6753 if (exprNode_isDefined (lastStmt)
6754 && !exprNode_mustEscape (lastStmt)
6755 && !exprNode_mustBreak (lastStmt)
6756 && !exprNode_isCaseMarker (lastStmt)
6757 && !exprNode_isDefaultMarker (lastStmt)
6758 && !exprNode_isLabelMarker (lastStmt))
6760 voptgenerror (FLG_CASEBREAK,
6762 ("Fall through case (no preceding break)"),
6769 exprNode_mergeUSs (ret, e2);
6771 usymtab_setExitCode (ret->exitCode);
6775 usymtab_setMustBreak ();
6778 DPRINTF (("==> %s", exprNode_unparse (ret)));
6782 exprNode exprNode_createTok (/*@only@*/ lltok t)
6784 exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6785 ret = exprNode_create (ctype_unknown);
6786 ret->kind = XPR_TOK;
6787 ret->edata = exprData_makeTok (t);
6791 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6793 if (!exprNode_isError (e))
6795 exprChecks_checkStatementEffect(e);
6798 return (exprNode_statementError (e, t));
6801 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6803 exprNode ret = exprNode_createPartialCopy (e);
6805 if (!exprNode_isError (e))
6807 if (e->kind != XPR_ASSIGN)
6809 exprNode_checkUse (ret, e->sref, e->loc);
6812 ret->exitCode = e->exitCode;
6813 ret->canBreak = e->canBreak;
6814 ret->mustBreak = e->mustBreak;
6817 ret->edata = exprData_makeUop (e, t);
6818 ret->kind = XPR_STMT;
6823 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6825 if (!exprNode_isError (e))
6827 if (e->kind != XPR_ASSIGN)
6829 exprNode_checkUse (e, e->sref, e->loc);
6836 void exprNode_produceGuards (exprNode pred)
6838 if (!exprNode_isError (pred))
6840 if (ctype_isRealPointer (pred->typ))
6842 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6845 exprNode_checkUse (pred, pred->sref, pred->loc);
6846 exprNode_resetSref (pred);
6850 exprNode exprNode_compoundStatementExpression (/*@only@*/ lltok tlparen, /*@only@*/ exprNode e)
6854 DPRINTF (("Compound: %s", exprNode_unparse (e)));
6856 if (!context_flagOn (FLG_GNUEXTENSIONS, exprNode_loc (e)))
6858 (void) llgenhinterror
6860 message ("Compound statement expressions is not supported by ISO C99"),
6861 message ("Use +gnuextensions to allow compound statement expressions (and other GNU language extensions) "
6862 "without this warning"),
6867 ** The type of a compoundStatementExpression is the type of the last statement
6870 llassert (exprNode_isBlock (e));
6871 laststmt = exprNode_lastStatement (e);
6873 DPRINTF (("Last statement: %s / %s", exprNode_unparse (laststmt), ctype_unparse (exprNode_getType (laststmt))));
6874 DPRINTF (("e: %s", exprNode_unparse (e)));
6875 e->typ = exprNode_getType (laststmt);
6876 return exprNode_addParens (tlparen, e);
6880 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6882 exprNode ret = exprNode_createPartialCopy (e);
6884 if (!exprNode_isError (e))
6886 ret->exitCode = e->exitCode;
6887 ret->canBreak = e->canBreak;
6888 ret->mustBreak = e->mustBreak;
6891 DPRINTF (("Block e: %s", exprNode_unparse (e)));
6892 ret->edata = exprData_makeSingle (e);
6893 ret->kind = XPR_BLOCK;
6894 DPRINTF (("Block: %s", exprNode_unparse (ret)));
6898 bool exprNode_isBlock (exprNode e)
6900 return (exprNode_isDefined (e)
6901 && ((e)->kind == XPR_BLOCK));
6904 bool exprNode_isStatement (exprNode e)
6906 return (exprNode_isDefined (e)
6907 && ((e)->kind == XPR_STMT));
6910 bool exprNode_isAssign (exprNode e)
6912 if (exprNode_isDefined (e))
6914 return (e->kind == XPR_ASSIGN);
6920 bool exprNode_isEmptyStatement (exprNode e)
6922 return (exprNode_isDefined (e)
6923 && (e->kind == XPR_TOK)
6924 && (lltok_isSemi (exprData_getTok (e->edata))));
6927 bool exprNode_isMultiStatement (exprNode e)
6929 return (exprNode_isDefined (e)
6930 && ((e->kind == XPR_FOR)
6931 || (e->kind == XPR_FORPRED)
6932 || (e->kind == XPR_IF)
6933 || (e->kind == XPR_IFELSE)
6934 || (e->kind == XPR_WHILE)
6935 || (e->kind == XPR_WHILEPRED)
6936 || (e->kind == XPR_DOWHILE)
6937 || (e->kind == XPR_BLOCK)
6938 || (e->kind == XPR_STMT)
6939 || (e->kind == XPR_STMTLIST)
6940 || (e->kind == XPR_SWITCH)));
6943 void exprNode_checkIfPred (exprNode pred)
6945 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6948 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6951 bool emptyErr = FALSE;
6953 if (context_maybeSet (FLG_IFEMPTY))
6955 if (exprNode_isEmptyStatement (tclause))
6957 emptyErr = optgenerror (FLG_IFEMPTY,
6959 ("Body of if statement is empty"),
6960 exprNode_loc (tclause));
6964 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6966 if (exprNode_isDefined (tclause)
6967 && !exprNode_isBlock (tclause))
6969 voptgenerror (FLG_IFBLOCK,
6971 ("Body of if statement is not a block: %s",
6972 exprNode_unparse (tclause)),
6973 exprNode_loc (tclause));
6977 if (exprNode_isError (pred))
6979 if (exprNode_isError (tclause))
6981 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6985 ret = exprNode_createPartialCopy (tclause);
6990 if (exprNode_mustEscape (pred))
6994 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6995 exprNode_loc (pred));
6998 /*! exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred); */ /*@i523@*/
6999 exprNode_checkUse (pred, pred->sref, pred->loc);
7001 if (!exprNode_isError (tclause))
7003 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
7006 ret = exprNode_createPartialCopy (pred);
7010 ret->edata = exprData_makePair (pred, tclause);
7012 ret->exitCode = XK_UNKNOWN;
7014 if (exprNode_isDefined (tclause))
7016 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
7017 ret->canBreak = tclause->canBreak;
7018 ret->sets = sRefSet_union (ret->sets, tclause->sets);
7019 ret->msets = sRefSet_union (ret->msets, tclause->msets);
7020 ret->uses = sRefSet_union (ret->uses, tclause->uses);
7023 ret->mustBreak = FALSE;
7028 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
7029 /*@only@*/ exprNode tclause,
7030 /*@only@*/ exprNode eclause)
7033 bool tEmptyErr = FALSE;
7034 bool eEmptyErr = FALSE;
7036 if (context_maybeSet (FLG_IFEMPTY))
7038 if (exprNode_isEmptyStatement (tclause))
7040 tEmptyErr = optgenerror
7043 ("Body of if clause of if statement is empty"),
7044 exprNode_loc (tclause));
7047 if (exprNode_isEmptyStatement (eclause))
7049 eEmptyErr = optgenerror
7052 ("Body of else clause of if statement is empty"),
7053 exprNode_loc (eclause));
7057 if (context_maybeSet (FLG_IFBLOCK))
7060 && exprNode_isDefined (tclause)
7061 && !exprNode_isBlock (tclause))
7063 voptgenerror (FLG_IFBLOCK,
7065 ("Body of if clause of if statement is not a block: %s",
7066 exprNode_unparse (tclause)),
7067 exprNode_loc (tclause));
7071 && exprNode_isDefined (eclause)
7072 && !exprNode_isBlock (eclause)
7073 && !(eclause->kind == XPR_IF)
7074 && !(eclause->kind == XPR_IFELSE))
7079 ("Body of else clause of if statement is not a block: %s",
7080 exprNode_unparse (eclause)),
7081 exprNode_loc (eclause));
7085 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
7087 if (exprNode_isDefined (eclause)
7088 && (eclause->kind == XPR_IF))
7090 voptgenerror (FLG_ELSEIFCOMPLETE,
7091 message ("Incomplete else if logic (no final else): %s",
7092 exprNode_unparse (eclause)),
7093 exprNode_loc (eclause));
7097 if (exprNode_isError (pred))
7099 if (exprNode_isError (tclause))
7101 if (exprNode_isError (eclause))
7103 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7107 ret = exprNode_createPartialCopy (eclause);
7112 ret = exprNode_createPartialCopy (tclause);
7115 else /* pred is okay */
7117 ret = exprNode_createPartialCopy (pred);
7119 if (exprNode_mustEscape (pred))
7123 message ("Predicate always exits: %s", exprNode_unparse (pred)),
7124 exprNode_loc (pred));
7127 /*@i3423 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);*/
7128 exprNode_checkUse (ret, pred->sref, pred->loc);
7130 exprNode_mergeCondUSs (ret, tclause, eclause);
7133 ret->kind = XPR_IFELSE;
7134 ret->edata = exprData_makeCond (pred, tclause, eclause);
7136 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
7138 exprNode_combineControl (ret, tclause, eclause);
7139 ret->loc = fileloc_update (ret->loc, eclause->loc);
7146 ** *allpaths <- TRUE iff all executions paths must go through the switch
7150 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
7152 exprNodeSList el = exprNode_flatten (e);
7153 bool mustReturn = TRUE; /* find a branch that doesn't */
7154 bool thisReturn = FALSE;
7155 bool hasDefault = FALSE;
7156 bool hasAllMembers = FALSE;
7157 bool inSwitch = FALSE;
7158 bool isEnumSwitch = FALSE;
7159 bool canBreak = FALSE;
7160 bool fallThrough = FALSE;
7161 ctype ct = ctype_unknown;
7162 enumNameSList usedEnums;
7165 if (exprNode_isDefined (test))
7170 ttype = ctype_realType (ct);
7172 if (ctype_isEnum (ttype))
7174 isEnumSwitch = TRUE;
7175 enums = ctype_elist (ttype);
7176 usedEnums = enumNameSList_new ();
7180 exprNodeSList_elements (el, current)
7183 DPRINTF ((message("checkSwitchExpr current = %s ", exprNode_unparse(current) ) ));
7185 if (exprNode_isDefined (current))
7187 switch (current->kind)
7194 (FLG_DUPLICATECASES,
7195 message ("Duplicate default cases in switch"),
7196 exprNode_loc (current));
7201 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
7209 exprNode st = exprData_getSingle (current->edata);
7210 uentry ue = exprNode_getUentry (st);
7212 if (uentry_isValid (ue))
7214 cstring cname = uentry_rawName (ue);
7216 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
7218 if (enumNameSList_member
7219 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
7222 (FLG_DUPLICATECASES,
7223 message ("Duplicate case in switch: %s",
7229 enumNameSList_addh (usedEnums, cname);
7236 message ("Case in switch not %s member: %s",
7237 ctype_unparse (ct), cname),
7244 if (inSwitch && !fallThrough)
7246 if (!thisReturn || canBreak)
7256 /*@switchbreak@*/ break;
7258 thisReturn = thisReturn || exprNode_mustEscape (current);
7259 canBreak = canBreak || current->canBreak;
7260 if (canBreak) fallThrough = FALSE;
7263 } end_exprNodeSList_elements;
7265 if (inSwitch) /* check the last one! */
7267 if (!thisReturn || canBreak)
7276 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
7277 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
7279 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
7281 voptgenerror (FLG_MISSCASE,
7282 message ("Missing case%s in switch: %q",
7283 cstring_makeLiteralTemp
7284 ((enumNameSList_size (unused) > 1) ? "s" : ""),
7285 enumNameSList_unparse (unused)),
7288 enumNameSList_free (unused);
7289 *allpaths = FALSE; /* evans 2002-01-01 */
7293 hasAllMembers = TRUE;
7297 enumNameSList_free (usedEnums);
7301 *allpaths = hasDefault;
7304 exprNodeSList_free (el);
7305 return ((hasDefault || hasAllMembers) && mustReturn);
7308 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
7310 exprNode ret = exprNode_createPartialCopy (e);
7313 DPRINTF (("Switch: %s", exprNode_unparse (s)));
7315 ret->kind = XPR_SWITCH;
7316 ret->edata = exprData_makePair (e, s);
7318 if (!exprNode_isError (s))
7320 exprNode fs = exprNode_firstStatement (s);
7321 ret->loc = fileloc_update (ret->loc, s->loc);
7323 if (exprNode_isUndefined (fs)
7324 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
7325 || exprNode_isDefaultMarker (fs)) {
7328 voptgenerror (FLG_FIRSTCASE,
7330 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
7335 if (!exprNode_isError (e))
7337 if (checkSwitchExpr (e, s, &allpaths))
7339 ret->exitCode = XK_MUSTRETURN;
7343 ret->exitCode = e->exitCode;
7346 ret->canBreak = e->canBreak;
7347 ret->mustBreak = e->mustBreak;
7351 ** exprNode.c:3883,32: Variable allpaths used before definition
7358 DPRINTF (("Context exit switch!"));
7359 context_exitSwitch (ret, allpaths);
7360 DPRINTF (("Context exit switch done!"));
7365 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
7366 /*@notnull@*/ exprNode body)
7368 sRefSet tuses = test->uses;
7370 if (!sRefSet_isEmpty (test->uses))
7372 sRefSet sets = sRefSet_newCopy (body->sets);
7373 bool hasError = TRUE;
7374 bool innerState = FALSE;
7375 sRefSet tuncon = sRefSet_undefined;
7377 sets = sRefSet_union (sets, test->sets);
7378 sets = sRefSet_union (sets, body->msets);
7379 sets = sRefSet_union (sets, test->msets);
7381 sRefSet_allElements (tuses, el)
7383 if (sRef_isUnconstrained (el))
7385 tuncon = sRefSet_insert (tuncon, el);
7389 if (sRefSet_member (sets, el))
7396 if (sRef_isInternalState (el)
7397 || sRef_isFileStatic (sRef_getRootBase (el)))
7401 } end_sRefSet_allElements ;
7405 sRefSet suncon = sRefSet_undefined;
7406 bool sinner = FALSE;
7408 sRefSet_allElements (sets, el)
7410 if (sRef_isUnconstrained (el))
7412 suncon = sRefSet_insert (suncon, el);
7414 else if (sRef_isInternalState (el))
7422 } end_sRefSet_allElements ;
7424 if (sinner && innerState)
7428 else if (sRefSet_isEmpty (tuncon)
7429 && sRefSet_isEmpty (suncon))
7434 ("Suspected infinite loop. No value used in loop test (%q) "
7435 "is modified by test or loop body.",
7436 sRefSet_unparsePlain (tuses)),
7441 if (sRefSet_isEmpty (tuncon))
7445 message ("Suspected infinite loop. No condition values "
7446 "modified. Modification possible through "
7447 "unconstrained calls: %q",
7448 sRefSet_unparsePlain (suncon)),
7455 message ("Suspected infinite loop. No condition values "
7456 "modified. Possible undetected dependency through "
7457 "unconstrained calls in loop test: %q",
7458 sRefSet_unparsePlain (tuncon)),
7464 sRefSet_free (sets);
7468 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7471 bool emptyErr = FALSE;
7473 if (context_maybeSet (FLG_WHILEEMPTY))
7475 if (exprNode_isEmptyStatement (b))
7477 emptyErr = optgenerror
7480 ("Body of while statement is empty"),
7485 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7487 if (exprNode_isDefined (b)
7488 && !exprNode_isBlock (b))
7490 if (context_inIterDef ()
7491 && (b->kind == XPR_STMTLIST
7492 || b->kind == XPR_TOK))
7498 voptgenerror (FLG_WHILEBLOCK,
7500 ("Body of while statement is not a block: %s",
7501 exprNode_unparse (b)),
7507 if (exprNode_isError (t))
7509 if (exprNode_isError (b))
7511 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7515 ret = exprNode_createPartialCopy (b);
7522 ret = exprNode_createPartialCopy (t);
7524 llassert (t->kind == XPR_WHILEPRED);
7526 test = exprData_getSingle (t->edata);
7528 if (!exprNode_isError (b) && exprNode_isDefined (test))
7530 if (context_maybeSet (FLG_INFLOOPS)
7531 || context_maybeSet (FLG_INFLOOPSUNCON))
7534 ** check that some variable in the predicate is set by the body
7535 ** if the predicate uses any variables
7538 checkInfiniteLoop (test, b);
7541 exprNode_mergeUSs (ret, b);
7543 if (exprNode_isDefined (b))
7545 ret->exitCode = exitkind_makeConditional (b->exitCode);
7550 ret->edata = exprData_makePair (t, b);
7551 ret->kind = XPR_WHILE;
7553 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7557 message ("Predicate always exits: %s", exprNode_unparse (t)),
7561 ret->exitCode = XK_NEVERESCAPE;
7564 ** If loop is infinite, and there is no break inside,
7565 ** exit code is never reach.
7568 if (exprNode_knownIntValue (t))
7570 if (!exprNode_isZero (t))
7572 if (exprNode_isDefined (b))
7576 /* Really, it means never reached. */
7577 ret->exitCode = XK_MUSTEXIT;
7587 ret->canBreak = FALSE;
7588 ret->mustBreak = FALSE;
7594 ** do { b } while (t);
7596 ** note: body passed as first argument
7599 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7603 DPRINTF (("Do while: %s / %s",
7604 exprNode_unparse (b), exprNode_unparse (t)));
7606 if (exprNode_isError (t))
7608 if (exprNode_isError (b))
7610 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7614 ret = exprNode_createPartialCopy (b);
7616 ret->exitCode = exitkind_makeConditional (b->exitCode);
7617 exprNode_checkUse (ret, b->sref, b->loc);
7618 ret->exitCode = b->exitCode;
7619 ret->canBreak = b->canBreak;
7620 ret->mustBreak = FALSE;
7625 DPRINTF (("Do while: %s / %s",
7626 exitkind_unparse (t->exitCode),
7627 exitkind_unparse (b->exitCode)));
7629 ret = exprNode_createPartialCopy (t);
7630 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7632 if (!exprNode_isError (b))
7635 ** forgot the copy's --- why wasn't this detected??
7638 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7639 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7640 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
7642 /* left this out --- causes and aliasing bug (infinite loop)
7643 should be detected?? */
7645 exprNode_checkUse (ret, b->sref, b->loc);
7646 exprNode_mergeUSs (ret, t);
7647 exprNode_checkUse (ret, t->sref, t->loc);
7649 /* evans 2001-10-05: while loop can break */
7650 ret->exitCode = exitkind_makeConditional (b->exitCode);
7652 DPRINTF (("Do while: %s",
7653 exitkind_unparse (ret->exitCode)));
7655 ret->canBreak = b->canBreak;
7657 /* Always FALSE for doWhile loops - break's when test is false */
7658 ret->mustBreak = FALSE; /* b->mustBreak; */
7662 context_exitDoWhileClause (t);
7664 ret->kind = XPR_DOWHILE;
7665 ret->edata = exprData_makePair (t, b);
7669 bool exprNode_loopMustExec (exprNode forPred)
7672 ** Returns true if it is obvious that the loop always executes at least once
7674 ** For now, we only identify the most obvious cases. Should be true anytime
7675 ** we can prove init => !test.
7678 if (exprNode_isDefined (forPred))
7680 exprNode init, test, inc;
7683 llassert (forPred->kind == XPR_FORPRED);
7685 edata = forPred->edata;
7686 init = exprData_getTripleInit (edata);
7687 test = exprData_getTripleTest (edata);
7688 inc = exprData_getTripleInc (edata);
7690 if (exprNode_isAssign (init))
7692 exprNode loopVar = exprData_getOpA (init->edata);
7693 exprNode loopInit = exprData_getOpB (init->edata);
7695 if (exprNode_isDefined (test) && test->kind == XPR_OP)
7697 exprNode testVar = exprData_getOpA (test->edata);
7698 exprNode testVal = exprData_getOpB (test->edata);
7699 lltok comp = exprData_getOpTok (test->edata);
7700 int opid = lltok_getTok (comp);
7702 DPRINTF (("Same storage: %s / %s", exprNode_unparse (loopVar),
7703 exprNode_unparse (testVar)));
7705 if (exprNode_sameStorage (loopVar, testVar))
7707 multiVal valinit = exprNode_getValue (loopInit);
7708 multiVal valtest = exprNode_getValue (testVal);
7710 DPRINTF (("Values: %s / %s", multiVal_unparse (valinit),
7711 multiVal_unparse (valtest)));
7713 if (multiVal_isInt (valinit) && multiVal_isInt (valtest))
7715 long v1 = multiVal_forceInt (valinit);
7716 long v2 = multiVal_forceInt (valtest);
7718 DPRINTF (("Here: %ld %ld", v1, v2));
7720 if ((opid == EQ_OP && v1 < v2)
7721 || (opid == NE_OP && v1 != v2)
7722 || (opid == TLT && v1 <= v2)
7723 || (opid == TGT && v1 >= v2)
7724 || (opid == LE_OP && v1 < v2)
7725 || (opid == GE_OP && v1 > v2))
7727 DPRINTF (("mustexec if inc"));
7736 DPRINTF (("loop must exec: FALSE"));
7740 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7743 bool emptyErr = FALSE;
7745 if (context_maybeSet (FLG_FOREMPTY))
7747 if (exprNode_isEmptyStatement (body))
7749 emptyErr = optgenerror
7752 ("Body of for statement is empty"),
7753 exprNode_loc (body));
7757 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7759 if (exprNode_isDefined (body)
7760 && !exprNode_isBlock (body))
7762 if (context_inIterDef ()
7763 && (body->kind == XPR_STMTLIST
7764 || body->kind == XPR_TOK))
7770 voptgenerror (FLG_FORBLOCK,
7772 ("Body of for statement is not a block: %s",
7773 exprNode_unparse (body)),
7774 exprNode_loc (body));
7780 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7783 if (exprNode_isError (body))
7785 ret = exprNode_createPartialCopy (inc);
7789 ret = exprNode_createPartialCopy (body);
7791 ret->exitCode = exitkind_makeConditional (body->exitCode);
7793 exprNode_mergeUSs (inc, body);
7795 if (exprNode_isDefined (inc))
7799 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7801 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7802 exprNode_freeShallow (tmp);
7804 context_clearMessageAnnote ();
7805 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7807 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7808 exprNode_freeShallow (tmp);
7810 context_clearMessageAnnote ();
7812 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7813 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7814 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7818 ret->kind = XPR_FOR;
7819 ret->edata = exprData_makePair (inc, body);
7821 if (exprNode_isDefined (inc)) {
7822 exprNode test = exprData_getTripleTest (inc->edata);
7824 if (exprNode_isUndefined (test)) {
7825 if (exprNode_isDefined (body)) {
7826 if (!body->canBreak) {
7827 /* Really, it means never reached. */
7828 ret->exitCode = XK_MUSTEXIT;
7838 ** for (init; test; inc)
7841 ** while (test) { body; inc; }
7843 ** Now: check use of init (may set vars for test)
7844 ** check use of test
7848 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7852 if (exprNode_isError (pred)) return guardSet_undefined;
7854 llassert (pred->kind == XPR_FORPRED);
7856 test = exprData_getTripleTest (pred->edata);
7858 if (!exprNode_isError (test))
7860 return (test->guards);
7863 return guardSet_undefined;
7866 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7868 exprNode ret = exprNode_createSemiCopy (test);
7870 if (exprNode_isDefined (test))
7872 exprNode_copySets (ret, test);
7873 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7874 exprNode_checkUse (ret, test->sref, test->loc);
7876 exprNode_produceGuards (test);
7878 ret->guards = guardSet_copy (test->guards);
7881 ret->edata = exprData_makeSingle (test);
7882 ret->kind = XPR_WHILEPRED;
7886 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7887 /*@only@*/ exprNode inc)
7892 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7895 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7897 if (!exprNode_isError (inc))
7899 ret = exprNode_createPartialCopy (inc);
7903 if (!exprNode_isError (init))
7905 ret = exprNode_createPartialCopy (init);
7907 else if (!exprNode_isError (test))
7909 ret = exprNode_createPartialCopy (test);
7913 ret = exprNode_createUnknown ();
7917 exprNode_mergeUSs (ret, init);
7919 if (exprNode_isDefined (init))
7921 exprNode_checkUse (ret, init->sref, init->loc);
7924 exprNode_mergeUSs (ret, test);
7926 if (exprNode_isDefined (test))
7928 exprNode_checkUse (ret, test->sref, test->loc);
7931 ret->kind = XPR_FORPRED;
7932 ret->edata = exprData_makeFor (init, test, inc);
7936 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7938 exprNode ret = exprNode_createUnknown ();
7940 if (context_inMacro ())
7942 voptgenerror (FLG_MACROSTMT,
7943 message ("Macro %s uses goto (not functional)",
7944 context_inFunctionName ()),
7948 ret->kind = XPR_GOTO;
7949 ret->edata = exprData_makeLiteral (label);
7950 ret->mustBreak = TRUE;
7951 ret->exitCode = XK_GOTO;
7952 ret->canBreak = TRUE;
7956 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7958 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7960 ret->kind = XPR_CONTINUE;
7961 ret->edata = exprData_makeTok (l);
7962 ret->canBreak = TRUE;
7963 ret->mustBreak = TRUE;
7965 if (qcontinue == QSAFEBREAK)
7969 else if (qcontinue == QINNERCONTINUE)
7971 if (!context_inDeepLoop ())
7974 (FLG_LOOPLOOPCONTINUE,
7975 cstring_makeLiteral ("Continue statement marked with innercontinue "
7976 "is not inside a nested loop"),
7977 exprNode_loc (ret));
7980 else if (qcontinue == BADTOK)
7982 if (context_inDeepLoop ())
7985 (FLG_LOOPLOOPCONTINUE,
7986 cstring_makeLiteral ("Continue statement in nested loop"),
7987 exprNode_loc (ret));
7992 llbuglit ("exprNode_continue: bad qcontinue");
7998 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
8000 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
8001 clause breakClause = context_breakClause ();
8003 ret->kind = XPR_BREAK;
8004 ret->edata = exprData_makeTok (l);
8005 ret->canBreak = TRUE;
8006 ret->mustBreak = TRUE;
8008 if (breakClause == NOCLAUSE)
8012 cstring_makeLiteral ("Break not inside while, for or switch statement"),
8013 exprNode_loc (ret));
8017 if (bqual != BADTOK)
8024 if (breakClause == SWITCHCLAUSE)
8026 if (!context_inDeepSwitch ())
8028 voptgenerror (FLG_SYNTAX,
8030 ("Break preceded by innerbreak is not in a deep switch"),
8031 exprNode_loc (ret));
8036 if (!context_inDeepLoop ())
8038 voptgenerror (FLG_SYNTAX,
8040 ("Break preceded by innerbreak is not in a deep loop"),
8041 exprNode_loc (ret));
8046 if (breakClause == SWITCHCLAUSE)
8048 voptgenerror (FLG_SYNTAX,
8050 ("Break preceded by loopbreak is breaking a switch"),
8051 exprNode_loc (ret));
8055 if (breakClause != SWITCHCLAUSE)
8059 message ("Break preceded by switchbreak is breaking %s",
8060 cstring_makeLiteralTemp
8061 ((breakClause == WHILECLAUSE
8062 || breakClause == DOWHILECLAUSE) ? "a while loop"
8063 : (breakClause == FORCLAUSE) ? "a for loop"
8064 : (breakClause == ITERCLAUSE) ? "an iterator"
8066 exprNode_loc (ret));
8074 if (breakClause == SWITCHCLAUSE)
8076 clause nextBreakClause = context_nextBreakClause ();
8078 switch (nextBreakClause)
8080 case NOCLAUSE: break;
8086 (FLG_LOOPSWITCHBREAK,
8087 cstring_makeLiteral ("Break statement in switch inside loop"),
8088 exprNode_loc (ret));
8092 (FLG_SWITCHSWITCHBREAK,
8093 cstring_makeLiteral ("Break statement in switch inside switch"),
8094 exprNode_loc (ret));
8101 if (context_inDeepLoop ())
8105 cstring_makeLiteral ("Break statement in nested loop"),
8106 exprNode_loc (ret));
8110 if (context_inDeepLoopSwitch ())
8113 (FLG_SWITCHLOOPBREAK,
8114 cstring_makeLiteral ("Break statement in loop inside switch"),
8115 exprNode_loc (ret));
8125 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
8127 fileloc loc = lltok_getLoc (t);
8128 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
8130 context_returnFunction ();
8131 exprChecks_checkNullReturn (loc);
8133 ret->kind = XPR_NULLRETURN;
8134 ret->edata = exprData_makeTok (t);
8135 ret->exitCode = XK_MUSTRETURN;
8139 exprNode exprNode_return (/*@only@*/ exprNode e)
8143 if (exprNode_isError (e))
8145 ret = exprNode_createUnknown ();
8149 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
8151 exprNode_checkUse (ret, e->sref, e->loc);
8152 exprNode_checkReturn (e);
8155 context_returnFunction ();
8156 ret->kind = XPR_RETURN;
8157 ret->edata = exprData_makeSingle (e);
8158 ret->exitCode = XK_MUSTRETURN;
8163 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
8167 if (exprNode_isError (e1))
8169 if (exprNode_isError (e2))
8171 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
8175 ret = exprNode_createPartialCopy (e2);
8176 exprNode_checkUse (ret, e2->sref, e2->loc);
8177 ret->sref = e2->sref;
8182 ret = exprNode_createPartialCopy (e1);
8184 exprNode_checkUse (ret, e1->sref, e1->loc);
8186 if (!exprNode_isError (e2))
8188 exprNode_mergeUSs (ret, e2);
8189 exprNode_checkUse (ret, e2->sref, e2->loc);
8190 ret->sref = e2->sref;
8194 ret->kind = XPR_COMMA;
8195 ret->edata = exprData_makePair (e1, e2);
8197 if (exprNode_isDefined (e1))
8199 if (exprNode_isDefined (e2))
8203 if (exprNode_mustEscape (e1) || e1->mustBreak)
8207 message ("Second clause of comma expression is unreachable: %s",
8208 exprNode_unparse (e2)),
8212 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
8213 ret->mustBreak = e1->mustBreak || e2->mustBreak;
8214 ret->canBreak = e1->canBreak || e2->canBreak;
8218 if (exprNode_mustEscape (e1) || e1->mustBreak)
8222 message ("Second clause of comma expression is unreachable: %s",
8223 exprNode_unparse (e2)),
8227 ret->exitCode = e1->exitCode;
8228 ret->canBreak = e1->canBreak;
8233 if (exprNode_isDefined (e2))
8235 ret->exitCode = e2->exitCode;
8236 ret->mustBreak = e2->mustBreak;
8237 ret->canBreak = e2->canBreak;
8244 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
8246 ctype t1 = exprNode_getType (el);
8247 ctype t2 = exprNode_getType (val);
8248 bool hasError = FALSE;
8250 DPRINTF (("Check one init: %s / %s",
8251 exprNode_unparse (el),
8252 exprNode_unparse (val)));
8254 if (ctype_isUnknown (t1))
8256 voptgenerror (FLG_IMPTYPE,
8257 message ("Variable has unknown (implicitly int) type: %s",
8258 exprNode_unparse (el)),
8262 el->typ = ctype_int;
8265 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
8267 exprNodeList vals = exprData_getArgs (val->edata);
8269 DPRINTF (("Check one init: %s", exprNodeList_unparse (vals)));
8270 DPRINTF (("Type: %s", ctype_unparse (t1)));
8272 if (ctype_isRealAP (t1))
8277 if (ctype_isFixedArray (t1))
8279 size_t nelements = ctype_getArraySize (t1);
8281 DPRINTF (("Checked array: %s / %d",
8282 ctype_unparse (t1), nelements));
8284 if (exprNode_isStringLiteral (val))
8286 exprNode_checkStringLiteralLength (t1, val);
8290 if (exprNodeList_size (vals) != size_toInt (nelements))
8292 hasError = optgenerror
8293 (exprNodeList_size (vals) > size_toInt (nelements)
8294 ? FLG_INITSIZE : FLG_INITALLELEMENTS,
8295 message ("Initializer block for "
8296 "%s has %d element%&, but declared as %s: %q",
8297 exprNode_unparse (el),
8298 exprNodeList_size (vals),
8300 exprNodeList_unparse (vals)),
8306 exprNodeList_elements (vals, oneval)
8308 cstring istring = message ("%d", i);
8311 (exprNode_fakeCopy (el),
8312 exprNode_numLiteral (ctype_int, istring,
8313 fileloc_copy (el->loc), i));
8315 if (exprNode_isDefined (newel))
8317 if (exprNodeList_size (vals) == 1
8318 && ctype_isString (exprNode_getType (oneval))
8319 && ctype_isChar (exprNode_getType (newel)))
8321 exprNode_freeIniter (newel);
8325 if (exprNode_checkOneInit (newel, oneval))
8330 if (nerrors > 3 && exprNodeList_size (vals) > 6)
8333 (message ("Additional initialization errors "
8334 "for %s not reported",
8335 exprNode_unparse (el)),
8337 exprNode_freeIniter (newel);
8342 exprNode_freeIniter (newel);
8347 exprNode_freeIniter (newel);
8352 cstring_free (istring);
8355 } end_exprNodeList_elements;
8358 else if (ctype_isStruct (ctype_realType (t1)))
8360 uentryList fields = ctype_getFields (t1);
8363 if (uentryList_size (fields) != exprNodeList_size (vals))
8365 if (uentryList_size (fields) > exprNodeList_size (vals))
8367 hasError = optgenerror
8369 message ("Initializer block for "
8370 "%s has %d field%&, but %s has %d field%&: %q",
8371 exprNode_unparse (el),
8372 exprNodeList_size (vals),
8374 uentryList_size (fields),
8375 exprNodeList_unparse (vals)),
8380 hasError = optgenerror
8382 message ("Initializer block for "
8383 "%s has %d field%&, but %s has %d field%&: %q",
8384 exprNode_unparse (el),
8385 exprNodeList_size (vals),
8387 uentryList_size (fields),
8388 exprNodeList_unparse (vals)),
8394 exprNodeList_elements (vals, oneval)
8396 uentry thisfield = uentryList_getN (fields, i);
8398 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8400 uentry_getName (thisfield));
8402 if (exprNode_isDefined (newel))
8404 if (exprNode_checkOneInit (newel, oneval))
8409 exprNode_freeIniter (newel);
8413 } end_exprNodeList_elements;
8416 /* evans 2001-12-30: added to fix bug reported by Jim Zelenka */
8417 else if (ctype_isUnion (ctype_realType (t1)))
8419 uentryList fields = ctype_getFields (t1);
8423 ** Union initializers set the first member always.
8426 DPRINTF (("Union initializer: %s / %s",
8427 exprNode_unparse (el), ctype_unparse (ctype_realType (t1))));
8429 if (exprNodeList_size (vals) != 1)
8431 hasError = optgenerror
8433 message ("Initializer block for union "
8434 "%s has %d elements, union initializers should have one element: %q",
8435 exprNode_unparse (el),
8436 exprNodeList_size (vals),
8437 exprNodeList_unparse (vals)),
8442 exprNode oneval = exprNodeList_head (vals);
8443 uentry thisfield = uentryList_getN (fields, i);
8445 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8447 uentry_getName (thisfield));
8449 if (exprNode_isDefined (newel))
8451 if (exprNode_checkOneInit (newel, oneval))
8456 exprNode_freeIniter (newel);
8462 hasError = optgenerror
8464 message ("Initializer block used for "
8465 "%s where %t is expected: %s",
8466 exprNode_unparse (el), t1, exprNode_unparse (val)),
8472 if (exprNode_isDefined (val))
8474 doAssign (el, val, TRUE);
8476 if (!exprNode_matchType (t1, val))
8478 hasError = gentypeerror
8480 message ("Initial value of %s is type %t, "
8482 exprNode_unparse (el),
8483 t2, t1, exprNode_unparse (val)),
8492 static /*@notnull@*/ exprNode
8493 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
8497 DPRINTF (("Initialization: %s", idDecl_unparse (t)));
8499 if (usymtab_exists (idDecl_observeId (t)))
8501 uentry ue = usymtab_lookup (idDecl_observeId (t));
8502 ret = exprNode_createId (ue);
8504 /*@i723 don't do this...but why? */
8506 ct = ctype_realishType (ret->typ);
8508 DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
8510 if (ctype_isUnknown (ct))
8512 if (uentry_isAnyTag (ue))
8516 message ("%s used but not previously declared: %s",
8517 uentry_ekindName (ue),
8518 idDecl_getName (t)),
8526 message ("Variable has unknown (implicitly int) type: %s",
8527 idDecl_getName (t)),
8539 DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
8541 ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
8542 /*!! fileloc_copy (g_currentloc)); */
8543 /*@i32!!! should get error without this */
8545 ret = exprNode_fromIdentifierAux (ue);
8548 ** No error - this happens in old style declarations:
8552 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8559 exprData_free (ret->edata, ret->kind);
8560 ret->edata = exprData_undefined;
8561 ret->exitCode = XK_NEVERESCAPE;
8562 ret->mustBreak = FALSE;
8563 ret->kind = XPR_INIT;
8567 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8569 exprNode ret = exprNode_makeInitializationAux (t);
8570 llassert (ret->edata == exprData_undefined);
8571 ret->edata = exprData_makeInit (t, exprNode_undefined);
8575 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8576 /*@only@*/ exprNode e)
8578 uentry ue = usymtab_lookup (idDecl_observeId (t));
8579 exprNode ret = exprNode_makeInitializationAux (t);
8580 fileloc loc = exprNode_loc (e);
8582 DPRINTF (("initialization: %s = %s", idDecl_unparse (t), exprNode_unparse (e)));
8584 if (exprNode_isError (e))
8586 e = exprNode_createUnknown ();
8587 /* error: assume initializer is defined */
8588 sRef_setDefined (ret->sref, g_currentloc);
8589 ret->edata = exprData_makeInit (t, e);
8593 ctype ct = ctype_realishType (ret->typ);
8598 ** was addSafeUse --- what's the problem?
8600 ** int x = 3, y = x ?
8603 exprData_free (ret->edata, ret->kind);
8604 ret->edata = exprData_makeInit (t, e);
8605 DPRINTF (("ret: %s", exprNode_unparse (ret)));
8607 exprNode_checkUse (ret, e->sref, e->loc);
8609 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8611 exprNode lhs = exprNode_createId (ue);
8614 ** static storage should be undefined before initializing
8617 if (uentry_isStatic (ue))
8619 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8622 (void) exprNode_checkOneInit (lhs, e);
8624 if (uentry_isStatic (ue))
8626 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8629 exprNode_free (lhs);
8633 if (!exprNode_matchType (ct, e))
8635 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
8642 (exprNode_getType (e), e, exprNode_getType (ret), ret,
8644 ("Variable %q initialized to type %t, expects %t: %s",
8645 uentry_getName (ue), exprNode_getType (e),
8646 exprNode_getType (ret),
8647 exprNode_unparse (e)),
8653 if (uentry_isStatic (ue))
8655 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8658 if (exprNode_isStringLiteral (e)
8659 && (ctype_isArray (ct))
8660 && (ctype_isChar (ctype_realType (ctype_baseArrayPtr (ct)))))
8663 ** If t is a char [], the literal is copied.
8666 exprNode_checkStringLiteralLength (ct, e);
8667 sRef_setDefState (ret->sref, SS_DEFINED, e->loc);
8668 ret->val = multiVal_copy (e->val);
8670 sRef_setNullTerminatedState (ret->sref);
8672 if (multiVal_isDefined (e->val))
8674 cstring slit = multiVal_forceString (e->val);
8675 sRef_setLen (ret->sref, size_toInt (cstring_length (slit) + 1));
8678 if (ctype_isFixedArray (ct))
8680 sRef_setSize (ret->sref, size_toInt (ctype_getArraySize (ct)));
8685 doAssign (ret, e, TRUE);
8688 if (uentry_isStatic (ue))
8690 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8694 if (context_inIterDef ())
8696 /* should check if it is yield */
8697 uentry_setUsed (ue, loc);
8704 exprNode_mergeUSs (ret, e);
8705 DPRINTF (("Ret: %s %p %p",
8706 exprNode_unparse (ret),
8707 ret->requiresConstraints,
8708 ret->ensuresConstraints));
8710 DPRINTF (("Ret: %s %s %s",
8711 exprNode_unparse (ret),
8712 constraintList_unparse (ret->requiresConstraints),
8713 constraintList_unparse (ret->ensuresConstraints)));
8717 exprNode exprNode_iter (/*@observer@*/ uentry name,
8718 /*@only@*/ exprNodeList alist,
8719 /*@only@*/ exprNode body,
8720 /*@observer@*/ uentry end)
8725 llassert (uentry_isValid (name));
8727 uentry_setUsed (name, exprNode_loc (body));
8729 ret = exprNode_createPartialCopy (body);
8730 iname = uentry_getName (name);
8732 if (uentry_isInvalid (end))
8734 llerror (FLG_ITERBALANCE,
8735 message ("Iter %s not balanced with end_%s", iname, iname));
8739 cstring ename = uentry_getName (end);
8741 if (!cstring_equalPrefixLit (ename, "end_"))
8743 llerror (FLG_ITERBALANCE, message ("Iter %s not balanced with end_%s: %s",
8744 iname, iname, ename));
8748 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8750 llerror (FLG_ITERBALANCE,
8751 message ("Iter %s not balanced with end_%s: %s",
8752 iname, iname, ename));
8756 cstring_free (ename);
8759 context_exitIterClause (body);
8761 ret->kind = XPR_ITER;
8762 ret->edata = exprData_makeIter (name, alist, body, end);
8764 if (uentry_isIter (name))
8766 (void) checkArgsReal (name, body,
8767 uentry_getParams (name), alist, TRUE, ret);
8770 cstring_free (iname);
8776 exprNode_iterNewId (/*@only@*/ cstring s)
8778 exprNode e = exprNode_new ();
8779 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8781 llassert (processingIterVars ());
8783 e->loc = context_getSaveLocation ();
8785 if (fileloc_isUndefined (e->loc))
8787 fileloc_free (e->loc);
8788 e->loc = fileloc_copy (g_currentloc);
8791 e->uses = sRefSet_new ();
8792 e->sets = sRefSet_new ();
8793 e->msets = sRefSet_new ();
8795 e->val = multiVal_unknown ();
8796 e->guards = guardSet_new ();
8797 e->sref = sRef_undefined;
8798 e->isJumpPoint = FALSE;
8799 e->exitCode = XK_NEVERESCAPE;
8801 /*> missing fields, detected by splint <*/
8802 e->canBreak = FALSE;
8803 e->mustBreak = FALSE;
8804 e->etext = cstring_undefined;
8806 if (uentry_isYield (ue))
8808 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8809 fileloc_copy (e->loc),
8813 uue = usymtab_supEntrySrefReturn (uue);
8815 sr = uentry_getSref (uue);
8816 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8817 sr = uentry_getSref (uue);
8818 sRef_setDefined (sr, e->loc);
8820 e->typ = uentry_getType (uue);
8822 e->edata = exprData_makeId (uue);
8823 uentry_setUsed (uue, g_currentloc);
8829 sRef_setGlobalScope ();
8830 uue = uentry_makeVariableLoc (s, ctype_unknown);
8832 e->typ = ctype_unknown;
8833 e->edata = exprData_makeId (uue);
8835 uentry_setUsed (uue, e->loc);
8836 uentry_setHasNameError (uue);
8838 if (context_getFlag (FLG_REPEATUNRECOG))
8840 uentry_markOwned (uue);
8844 usymtab_supGlobalEntry (uue);
8847 sRef_clearGlobalScope ();
8849 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8856 exprNode_defineConstraints(e);
8861 exprNode_iterExpr (/*@returned@*/ exprNode e)
8863 if (!processingIterVars ())
8865 llcontbuglit ("checkIterParam: not in iter");
8869 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8872 if (exprNode_isDefined (e))
8874 if (fileloc_isDefined (e->loc))
8878 message ("Yield parameter is not simple identifier: %s",
8879 exprNode_unparse (e)),
8886 message ("Yield parameter is not simple identifier: %s",
8887 exprNode_unparse (e)),
8897 exprNode_iterId (/*@observer@*/ uentry c)
8901 llassert (processingIterVars ());
8903 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8906 if (uentry_isYield (ue))
8908 ctype ct = uentry_getType (ue);
8909 exprNode e = exprNode_createPlain (ct);
8910 cstring name = uentry_getName (c);
8911 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8913 uentry_setUsed (ue, g_currentloc);
8914 uentry_setHasNameError (ue);
8916 cstring_free (name);
8919 e->edata = exprData_makeId (le);
8920 e->loc = context_getSaveLocation ();
8921 e->sref = uentry_getSref (le);
8923 usymtab_supEntrySref (le);
8925 if (!context_inHeader ())
8929 message ("Yield parameter shadows local declaration: %q",
8930 uentry_getName (c)),
8931 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8933 uentry_showWhereDeclared (c);
8940 return (exprNode_fromIdentifierAux (c));
8943 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8945 exprNode ret = exprNode_create (ctype_unknown);
8947 ret->kind = XPR_ITERCALL;
8948 ret->edata = exprData_makeIterCall (name, alist);
8950 if (uentry_isIter (name))
8952 uentryList params = uentry_getParams (name);
8954 if (context_inIterDef ()
8955 && uentryList_size (params) == exprNodeList_size (alist))
8959 exprNodeList_elements (alist, arg)
8961 uentry parg = uentryList_getN (params, i);
8963 if (uentry_isYield (parg))
8965 uentry ue = exprNode_getUentry (arg);
8967 if (uentry_isValid (ue))
8974 } end_exprNodeList_elements;
8977 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8978 checkUnspecCall (ret, params, alist);
8984 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8986 if (exprNode_isDefined (e))
8988 if (sRef_isInvalid (e->sref))
8991 e->sref = sRef_makeUnknown ();
8992 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
9003 return sRef_undefined;
9007 /*@observer@*/ cstring
9008 exprNode_unparseFirst (exprNode e)
9010 if (exprNode_isDefined (e))
9014 if (e->kind == XPR_STMTLIST
9015 || e->kind == XPR_COMMA || e->kind == XPR_COND)
9017 exprNode first = exprData_getPairA (e->edata);
9019 if (exprNode_isDefined (first))
9021 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
9025 return (cstring_makeLiteralTemp ("..."));
9029 ret = cstring_elide (exprNode_unparse (e), 20);
9030 cstring_markOwned (ret);
9036 return cstring_makeLiteralTemp ("<error>");
9040 /*@observer@*/ cstring
9041 exprNode_unparse (/*@temp@*/ exprNode e)
9043 if (exprNode_isError (e))
9045 return cstring_makeLiteralTemp ("<error>");
9048 if (cstring_isDefined (e->etext))
9054 cstring ret = exprNode_doUnparse (e);
9056 /*@-modifies@*/ /* benevolent */
9063 /*@observer@*/ fileloc
9064 exprNode_loc (exprNode e)
9066 if (exprNode_isError (e))
9068 return (g_currentloc);
9077 ** executes exprNode e
9078 ** recursively rexecutes as though in original parse using
9079 ** information in e->edata
9082 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
9084 exprNodeList ret = exprNodeList_new ();
9086 exprNodeList_elements (e, current)
9088 exprNodeList_addh (ret, exprNode_effect (current));
9089 } end_exprNodeList_elements;
9094 static /*@only@*/ exprNode exprNode_effect (exprNode e)
9095 /*@globals internalState@*/
9097 bool innerEffect = inEffect;
9103 context_clearJustPopped ();
9105 if (exprNode_isError (e))
9107 ret = exprNode_undefined;
9112 ** Turn off expose and dependent transfer checking.
9113 ** Need to pass exposed internal nodes,
9114 ** [ copying would be a waste! ]
9115 ** [ Actually, I think I wasted a lot more time than its worth ]
9116 ** [ trying to do this. ]
9120 /*@-observertrans@*/
9121 /*@-dependenttrans@*/
9128 ret = exprNode_addParens (exprData_getUopTok (data),
9129 exprNode_effect (exprData_getUopNode (data)));
9132 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
9133 exprNode_effect (exprData_getOpB (data)),
9134 exprData_getOpTok (data));
9137 ret = exprNode_undefined;
9140 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
9141 exprNodeList_effect (exprData_getArgs (data)));
9154 cstring id = exprData_getId (data);
9155 uentry ue = usymtab_lookupSafe (id);
9157 ret = exprNode_fromIdentifierAux (ue);
9158 ret->loc = fileloc_update (ret->loc, e->loc);
9165 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
9166 exprNode_effect (exprData_getPairB (data)));
9170 ** evans 2002-03-15: for && and ||, need to do the guards also
9171 ** this is what cgrammar.y does - should be
9172 ** able to avoid duplication, but need to
9173 ** time with grammar productions.
9176 DPRINTF (("Effect: %s", exprNode_unparse (e)));
9178 if (lltok_getTok (exprData_getOpTok (data)) == AND_OP)
9180 exprNode e1 = exprNode_effect (exprData_getOpA (data));
9182 exprNode_produceGuards (e1);
9183 context_enterAndClause (e1);
9184 e2 = exprNode_effect (exprData_getOpB (data));
9186 ret = exprNode_op (e1, e2,
9187 exprData_getOpTok (data));
9189 context_exitAndClause (ret, e2);
9191 else if (lltok_getTok (exprData_getOpTok (data)) == OR_OP)
9193 exprNode e1 = exprNode_effect (exprData_getOpA (data));
9195 exprNode_produceGuards (e1);
9196 context_enterOrClause (e1);
9197 e2 = exprNode_effect (exprData_getOpB (data));
9199 ret = exprNode_op (e1, e2,
9200 exprData_getOpTok (data));
9202 context_exitOrClause (ret, e2);
9206 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
9207 exprNode_effect (exprData_getOpB (data)),
9208 exprData_getOpTok (data));
9213 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
9214 exprData_getUopTok (data));
9217 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
9218 exprData_getUopTok (data));
9230 ret = exprNode_vaArg (exprData_getCastTok (data),
9231 exprNode_effect (exprData_getCastNode (data)),
9232 exprData_getCastType (data));
9236 ret = exprNode_cast (exprData_getCastTok (data),
9237 exprNode_effect (exprData_getCastNode (data)),
9238 exprData_getCastType (data));
9241 ret = exprNode_iterStart (exprData_getIterCallIter (data),
9243 (exprData_getIterCallArgs (data)));
9247 ret = exprNode_iter (exprData_getIterSname (data),
9248 exprNodeList_effect (exprData_getIterAlist (data)),
9249 exprNode_effect (exprData_getIterBody (data)),
9250 exprData_getIterEname (data));
9254 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
9255 exprNode_effect (exprData_getPairB (data)));
9259 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
9260 exprNode_effect (exprData_getTripleTest (data)),
9261 exprNode_effect (exprData_getTripleInc (data)));
9265 ret = exprNode_createTok (exprData_getTok (data));
9269 ret = exprNode_goto (exprData_getLiteral (data));
9270 ret->loc = fileloc_update (ret->loc, e->loc);
9274 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
9278 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
9282 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
9285 case XPR_NULLRETURN:
9286 ret = exprNode_nullReturn (exprData_getTok (data));
9290 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
9291 exprNode_effect (exprData_getPairB (data)));
9295 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
9296 exprNode_effect (exprData_getTripleTrue (data)),
9297 exprNode_effect (exprData_getTripleFalse (data)));
9300 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
9301 exprNode_effect (exprData_getPairB (data)));
9305 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
9306 exprNode_effect (exprData_getTripleTrue (data)),
9307 exprNode_effect (exprData_getTripleFalse (data)));
9310 ret = exprNode_whilePred (exprData_getSingle (data));
9314 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
9315 exprNode_effect (exprData_getPairB (data)));
9319 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
9320 exprNode_effect (exprData_getPairB (data)));
9324 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
9328 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
9329 exprData_getUopTok (data));
9333 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
9334 exprNode_effect (exprData_getPairB (data)));
9339 ret = exprNode_caseMarker
9340 (exprNode_effect (exprData_getSingle (data)),
9346 ret = exprNode_createTok (exprData_getTok (data));
9350 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
9351 exprNode_effect (exprData_getPairB (data)));
9355 ret = exprNode_makeInitialization
9356 (exprData_getInitId (data),
9357 exprNode_effect (exprData_getInitNode (data)));
9361 ret = exprNode_fieldAccessAux
9362 (exprNode_effect (exprData_getFieldNode (data)),
9363 exprNode_loc (exprData_getFieldNode (data)),
9364 cstring_copy (exprData_getFieldName (data)));
9368 ret = exprNode_arrowAccessAux
9369 (exprNode_effect (exprData_getFieldNode (data)),
9370 exprNode_loc (exprData_getFieldNode (data)),
9371 cstring_copy (exprData_getFieldName (data)));
9374 case XPR_STRINGLITERAL:
9388 /*@=observertrans@*/
9390 /*@=dependenttrans@*/
9401 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
9406 if (exprNode_isError (e))
9408 return cstring_undefined;
9416 ret = exprNode_rootVarName (exprData_getUopNode (data));
9419 ret = exprNode_rootVarName (exprData_getOpA (data));
9423 ret = exprData_getId (data);
9426 ret = idDecl_getName (exprData_getInitId (data));
9451 case XPR_NULLRETURN:
9473 case XPR_STRINGLITERAL:
9474 ret = cstring_undefined;
9481 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
9486 if (exprNode_isError (e))
9488 static /*@only@*/ cstring error = cstring_undefined;
9490 if (!cstring_isDefined (error))
9492 error = cstring_makeLiteral ("<error>");
9503 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
9506 ret = message ("%s %s %s",
9507 exprNode_unparse (exprData_getOpA (data)),
9508 lltok_unparse (exprData_getOpTok (data)),
9509 exprNode_unparse (exprData_getOpB (data)));
9512 ret = message ("%s(%q)",
9513 exprNode_unparse (exprData_getFcn (data)),
9514 exprNodeList_unparse (exprData_getArgs (data)));
9517 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
9520 ret = cstring_undefined;
9523 ret = message ("%s:", exprData_getId (data));
9527 ret = cstring_copy (exprData_getId (data));
9530 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
9531 exprNode_unparse (exprData_getPairB (data)));
9534 ret = message ("<body>");
9537 ret = message ("%s %s %s",
9538 exprNode_unparse (exprData_getOpA (data)),
9539 lltok_unparse (exprData_getOpTok (data)),
9540 exprNode_unparse (exprData_getOpB (data)));
9544 ret = message ("%s%s",
9545 lltok_unparse (exprData_getUopTok (data)),
9546 exprNode_unparse (exprData_getUopNode (data)));
9550 ret = message ("%s%s",
9551 exprNode_unparse (exprData_getUopNode (data)),
9552 lltok_unparse (exprData_getUopTok (data)));
9556 ret = message ("offsetof(%s,%q)",
9557 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
9558 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
9562 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9566 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
9570 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9574 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
9578 ret = message ("va_arg(%s, %q)",
9579 exprNode_unparse (exprData_getCastNode (data)),
9580 qtype_unparse (exprData_getCastType (data)));
9584 ret = message ("%q(%q)",
9585 uentry_getName (exprData_getIterCallIter (data)),
9586 exprNodeList_unparse (exprData_getIterCallArgs (data)));
9589 ret = message ("%q(%q) %s %q",
9590 uentry_getName (exprData_getIterSname (data)),
9591 exprNodeList_unparse (exprData_getIterAlist (data)),
9592 exprNode_unparse (exprData_getIterBody (data)),
9593 uentry_getName (exprData_getIterEname (data)));
9596 ret = message ("(%q)%s",
9597 qtype_unparse (exprData_getCastType (data)),
9598 exprNode_unparse (exprData_getCastNode (data)));
9602 ret = message ("%s %s",
9603 exprNode_unparse (exprData_getPairA (data)),
9604 exprNode_unparse (exprData_getPairB (data)));
9608 ret = message ("for (%s; %s; %s)",
9609 exprNode_unparse (exprData_getTripleInit (data)),
9610 exprNode_unparse (exprData_getTripleTest (data)),
9611 exprNode_unparse (exprData_getTripleInc (data)));
9615 ret = message ("goto %s", exprData_getLiteral (data));
9619 ret = cstring_makeLiteral ("continue");
9623 ret = cstring_makeLiteral ("break");
9627 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
9630 case XPR_NULLRETURN:
9631 ret = cstring_makeLiteral ("return");
9635 ret = message ("%s, %s",
9636 exprNode_unparse (exprData_getPairA (data)),
9637 exprNode_unparse (exprData_getPairB (data)));
9641 ret = message ("%s ? %s : %s",
9642 exprNode_unparse (exprData_getTriplePred (data)),
9643 exprNode_unparse (exprData_getTripleTrue (data)),
9644 exprNode_unparse (exprData_getTripleFalse (data)));
9647 ret = message ("if (%s) %s",
9648 exprNode_unparse (exprData_getPairA (data)),
9649 exprNode_unparse (exprData_getPairB (data)));
9653 ret = message ("if (%s) %s else %s",
9654 exprNode_unparse (exprData_getTriplePred (data)),
9655 exprNode_unparse (exprData_getTripleTrue (data)),
9656 exprNode_unparse (exprData_getTripleFalse (data)));
9659 ret = message ("while (%s) %s",
9660 exprNode_unparse (exprData_getPairA (data)),
9661 exprNode_unparse (exprData_getPairB (data)));
9665 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9669 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9673 ret = message ("do { %s } while (%s)",
9674 exprNode_unparse (exprData_getPairB (data)),
9675 exprNode_unparse (exprData_getPairA (data)));
9679 ret = message ("{ %s }", exprNode_unparse (exprData_getSingle (data)));
9680 /* evans 2002-02-20 was unparseFirst! */
9684 ret = message ("%s;", exprNode_unparse (exprData_getUopNode (data)));
9688 if (exprNode_isStatement (exprData_getPairA (data)))
9691 ** statement expressions already print the ;
9694 ret = message ("%s %s",
9695 exprNode_unparse (exprData_getPairA (data)),
9696 exprNode_unparse (exprData_getPairB (data)));
9700 ret = message ("%s; %s",
9701 exprNode_unparse (exprData_getPairA (data)),
9702 exprNode_unparse (exprData_getPairB (data)));
9708 ret = cstring_makeLiteral ("default:");
9712 ret = message ("switch (%s) %s",
9713 exprNode_unparse (exprData_getPairA (data)),
9714 exprNode_unparse (exprData_getPairB (data)));
9719 ret = message ("case %s:",
9720 exprNode_unparse (exprData_getSingle (data)));
9724 if (exprNode_isError (exprData_getInitNode (data)))
9726 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9730 ret = message ("%q = %s",
9731 idDecl_unparseC (exprData_getInitId (data)),
9732 exprNode_unparse (exprData_getInitNode (data)));
9737 ret = message ("%s.%s",
9738 exprNode_unparse (exprData_getFieldNode (data)),
9739 exprData_getFieldName (data));
9743 ret = message ("%s->%s",
9744 exprNode_unparse (exprData_getFieldNode (data)),
9745 exprData_getFieldName (data));
9748 case XPR_STRINGLITERAL:
9749 if (ctype_isWideString (e->typ))
9751 ret = message ("L\"%s\"", exprData_getLiteral (data));
9755 ret = message ("\"%s\"", exprData_getLiteral (data));
9760 ret = cstring_copy (exprData_getLiteral (data));
9764 ret = cstring_makeLiteral ("<node>");
9772 exprNode_isInitializer (exprNode e)
9774 return (exprNode_isDefined (e)
9775 && e->kind == XPR_INIT);
9779 exprNode_isCharLiteral (exprNode e)
9781 if (exprNode_isDefined (e))
9783 return (multiVal_isChar (exprNode_getValue (e)));
9792 exprNode_isNumLiteral (exprNode e)
9794 if (exprNode_isDefined (e))
9796 return (multiVal_isInt (exprNode_getValue (e)));
9805 exprNode_isFalseConstant (exprNode e)
9807 if (exprNode_isDefined (e))
9809 cstring s = exprNode_rootVarName (e);
9811 if (cstring_equal (s, context_getFalseName ()))
9821 exprNode_matchLiteral (ctype expected, exprNode e)
9823 if (exprNode_isDefined (e))
9825 multiVal m = exprNode_getValue (e);
9827 if (multiVal_isDefined (m))
9829 if (multiVal_isInt (m))
9831 long int val = multiVal_forceInt (m);
9833 if (ctype_isNumAbstract (expected)
9834 && context_flagOn (FLG_NUMABSTRACTLIT, exprNode_loc (e)))
9839 if (ctype_isDirectBool (ctype_realishType (expected)))
9843 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9851 if (ctype_isRealInt (expected))
9854 ** unsigned <- [ constant >= 0 is okay ]
9857 if (ctype_isUnsigned (expected))
9866 ** No checks on sizes of integers...maybe add
9870 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9871 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9872 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9874 if (context_getFlag (FLG_NUMLITERAL)
9875 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9881 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9885 else if (ctype_isChar (expected))
9889 else if (ctype_isArrayPtr (expected))
9892 ** evans 2001-10-14: We allow 0 to match any pointer, but only if the type matches or is void *.
9897 if (ctype_match (exprNode_getType (e), expected)
9898 || ctype_isVoidPointer (exprNode_getType (e)))
9908 else if (ctype_isAnyFloat (expected))
9910 return (context_getFlag (FLG_NUMLITERAL));
9917 else if (multiVal_isDouble (m))
9919 if (ctype_isAnyFloat (expected))
9924 else if (multiVal_isChar (m))
9926 char val = multiVal_forceChar (m);
9928 if (ctype_isChar (expected))
9930 if (ctype_isUnsigned (expected) && ((int)val) < 0)
9951 exprNode_matchType (ctype expected, exprNode e)
9955 if (!exprNode_isDefined (e)) return TRUE;
9957 actual = ctype_realishType (exprNode_getType (e));
9959 if (ctype_match (ctype_realishType (expected), actual))
9964 llassert (!exprNode_isError (e));
9965 return (exprNode_matchLiteral (expected, e));
9969 exprNode_matchTypes (exprNode e1, exprNode e2)
9974 if (!exprNode_isDefined (e1)) return TRUE;
9975 if (!exprNode_isDefined (e2)) return TRUE;
9978 ** realish type --- keep bools, bools
9981 t1 = ctype_realishType (exprNode_getType (e1));
9982 t2 = ctype_realishType (exprNode_getType (e2));
9984 if (ctype_match (t1, t2))
9989 DPRINTF (("Matching literal! %s %s %s %s",
9990 ctype_unparse (t1), exprNode_unparse (e2),
9991 ctype_unparse (t2), exprNode_unparse (e1)));
9993 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
10001 exprNode_matchArgType (ctype ct, exprNode e)
10005 if (!exprNode_isDefined (e))
10010 et = ctype_realType (exprNode_getType (e));
10012 if (ctype_matchArg (ct, et)) return TRUE;
10014 llassert (!exprNode_isError (e));
10015 return (exprNode_matchLiteral (ct, e));
10018 static /*@only@*/ exprNodeSList
10019 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
10021 if (exprNode_isDefined (e))
10023 if (e->kind == XPR_STMTLIST)
10025 return (exprNodeSList_append
10026 (exprNode_flatten (exprData_getPairA (e->edata)),
10027 exprNode_flatten (exprData_getPairB (e->edata))));
10029 else if (e->kind == XPR_BLOCK)
10031 return (exprNode_flatten (exprData_getSingle (e->edata)));
10035 return (exprNodeSList_singleton (e));
10039 return exprNodeSList_new ();
10042 static /*@exposed@*/ exprNode
10043 exprNode_lastStatement (/*@returned@*/ exprNode e)
10045 if (exprNode_isDefined (e))
10047 if (e->kind == XPR_STMTLIST)
10049 exprNode b = exprData_getPairB (e->edata);
10051 if (exprNode_isDefined (b))
10053 return exprNode_lastStatement (b);
10057 return exprNode_lastStatement (exprData_getPairA (e->edata));
10060 else if (e->kind == XPR_BLOCK)
10062 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
10070 return exprNode_undefined;
10073 static /*@exposed@*/ exprNode
10074 exprNode_firstStatement (/*@returned@*/ exprNode e)
10076 if (exprNode_isDefined (e))
10078 if (e->kind == XPR_STMTLIST)
10080 exprNode b = exprData_getPairA (e->edata);
10082 if (exprNode_isDefined (b))
10084 return exprNode_firstStatement (b);
10088 return exprNode_firstStatement (exprData_getPairB (e->edata));
10091 else if (e->kind == XPR_BLOCK)
10093 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
10101 return exprNode_undefined;
10105 exprNode_mergeUSs (exprNode res, exprNode other)
10107 if (exprNode_isDefined (res) && exprNode_isDefined (other))
10109 res->msets = sRefSet_union (res->msets, other->msets);
10110 res->sets = sRefSet_union (res->sets, other->sets);
10111 res->uses = sRefSet_union (res->uses, other->uses);
10116 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
10118 if (exprNode_isDefined (res))
10120 if (exprNode_isDefined (other1))
10122 res->sets = sRefSet_union (res->sets, other1->sets);
10123 res->msets = sRefSet_union (res->msets, other1->msets);
10124 res->uses = sRefSet_union (res->uses, other1->uses);
10126 if (exprNode_isDefined (other2))
10128 res->sets = sRefSet_union (res->sets, other2->sets);
10129 res->msets = sRefSet_union (res->msets, other2->msets);
10130 res->uses = sRefSet_union (res->uses, other2->uses);
10136 ** modifies e->uses
10138 ** Reports errors is s is not defined.
10142 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
10144 if (exprNode_isDefined (e))
10146 e->uses = sRefSet_insert (e->uses, s);
10151 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
10153 if (sRef_isKnown (s) && !sRef_isConst (s))
10156 ** need to check all outer types are useable
10159 DPRINTF (("Check use: %s / %s",
10160 exprNode_unparse (e), sRef_unparse (s)));
10162 exprNode_addUse (e, s);
10164 if (!context_inProtectVars ())
10167 ** only report the deepest error
10170 sRef errorRef = sRef_undefined;
10171 sRef lastRef = sRef_undefined;
10172 bool deadRef = FALSE;
10173 bool unuseable = FALSE;
10174 bool errorMaybe = FALSE;
10176 while (sRef_isValid (s) && sRef_isKnown (s))
10178 ynm readable = sRef_isValidLvalue (s);
10180 DPRINTF (("Readable: %s / %s",
10181 sRef_unparseFull (s), ynm_unparse (readable)));
10183 if (!(ynm_toBoolStrict (readable)))
10185 if (ynm_isMaybe (readable))
10187 lastRef = errorRef;
10189 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
10190 deadRef = sRef_isPossiblyDead (errorRef);
10191 unuseable = sRef_isUnuseable (errorRef);
10196 lastRef = errorRef;
10198 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
10199 deadRef = sRef_isDead (errorRef);
10200 unuseable = sRef_isUnuseable (errorRef);
10201 errorMaybe = FALSE;
10205 if (!sRef_isPartial (s))
10207 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
10208 sRef_setDefined (s, loc);
10209 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
10214 s = sRef_getBaseSafe (s);
10217 if (sRef_isValid (errorRef))
10219 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
10220 && sRef_isPointer (errorRef))
10222 errorRef = lastRef;
10223 DPRINTF (("errorRef: %s", sRef_unparseFull (errorRef)));
10228 if (sRef_isThroughArrayFetch (errorRef))
10231 (FLG_STRICTUSERELEASED,
10232 message ("%q %q may be used after being released",
10233 sRef_unparseKindNamePlain (errorRef),
10234 sRef_unparse (errorRef)),
10237 sRef_showRefKilled (errorRef);
10239 if (sRef_isKept (errorRef))
10241 sRef_clearAliasState (errorRef, loc);
10247 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
10251 message ("%q %q %qused after being released",
10252 sRef_unparseKindNamePlain (errorRef),
10253 sRef_unparse (errorRef),
10254 cstring_makeLiteral (errorMaybe
10255 ? "may be " : "")),
10258 sRef_showRefKilled (errorRef);
10260 if (sRef_isKept (errorRef))
10262 sRef_clearAliasState (errorRef, loc);
10267 else if (unuseable)
10271 message ("%q %q%qused in inconsistent state",
10272 sRef_unparseKindName (errorRef),
10273 sRef_unparseOpt (errorRef),
10274 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10277 sRef_showStateInconsistent (errorRef);
10282 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
10286 message ("%q %q%qused before definition",
10287 sRef_unparseKindName (errorRef),
10288 sRef_unparseOpt (errorRef),
10289 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10295 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
10298 sRef_setDefined (errorRef, loc);
10300 if (sRef_isAddress (errorRef))
10302 sRef_setDefined (sRef_getRootBase (errorRef), loc);
10304 } /* end is error */
10312 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
10314 if (exprNode_isDefined (e) && sRef_isKnown (s))
10316 e->uses = sRefSet_insert (e->uses, s);
10321 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
10323 if (exprNode_isDefined (e))
10325 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
10330 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
10332 sRef defines = sRef_undefined;
10334 if (sRef_isValid (s) && !sRef_isNothing (s))
10336 uentry ue = sRef_getBaseUentry (s);
10338 if (uentry_isValid (ue))
10340 uentry_setLset (ue);
10343 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10345 voptgenerror (FLG_USEDEF,
10346 message ("Attempt to set unuseable storage: %q",
10351 if (sRef_isMeaningful (s))
10353 if (sRef_isDead (s))
10355 sRef base = sRef_getBaseSafe (s);
10357 if (sRef_isValid (base)
10358 && sRef_isDead (base))
10360 sRef_setPartial (s, exprNode_loc (e));
10363 defines = s; /* okay - modifies for only param */
10365 else if (sRef_isPartial (s))
10367 sRef eref = exprNode_getSref (e);
10369 if (!sRef_isPartial (eref))
10372 ** should do something different here???
10375 sRef_setDefinedComplete (eref, exprNode_loc (e));
10379 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
10382 if (sRef_isMeaningful (eref))
10391 else if (sRef_isAllocated (s))
10393 sRef eref = exprNode_getSref (e);
10396 if (!sRef_isAllocated (eref))
10398 sRef_setDefinedComplete (eref, exprNode_loc (e));
10402 sRef base = sRef_getBaseSafe (eref);
10404 if (sRef_isValid (base))
10406 sRef_setPdefined (base, exprNode_loc (e));
10414 sRef_setDefinedNCComplete (s, exprNode_loc (e));
10419 else /* not meaningful...but still need to insert it */
10425 if (exprNode_isDefined (e) && sRef_isValid (defines))
10427 e->sets = sRefSet_insert (e->sets, defines);
10432 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
10434 if (sRef_isValid (s) && !sRef_isNothing (s))
10436 uentry ue = sRef_getBaseUentry (s);
10438 if (uentry_isValid (ue))
10440 uentry_setLset (ue);
10443 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10445 voptgenerror (FLG_USEDEF,
10446 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
10450 if (sRef_isMeaningful (s))
10452 sRef_setDefinedComplete (s, exprNode_loc (e));
10455 if (exprNode_isDefined (e))
10457 e->msets = sRefSet_insert (e->msets, s);
10463 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
10465 checkAnyCall (fcn, cstring_undefined, params, args,
10466 FALSE, sRefSet_undefined, FALSE, 0);
10470 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
10471 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
10475 if (uentry_isYield (ucurrent))
10477 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
10478 exprNode_checkSet (current, current->sref);
10482 if (uentry_isSefParam (ucurrent))
10484 sRefSet sets = current->sets;
10485 sRef ref = exprNode_getSref (current);
10487 if (sRef_isMacroParamRef (ref))
10489 uentry ue = sRef_getUentry (ref);
10491 if (!uentry_isSefParam (ue))
10496 ("Parameter %d to %s is declared sef, but "
10497 "the argument is a macro parameter declared "
10499 argno, exprNode_unparse (fcn),
10500 exprNode_unparse (current)),
10501 exprNode_loc (current));
10505 if (!sRefSet_isEmpty (sets))
10507 sRefSet reported = sRefSet_undefined;
10509 sRefSet_realElements (current->sets, el)
10511 if (sRefSet_isSameNameMember (reported, el))
10513 ; /* don't report again */
10517 if (sRef_isUnconstrained (el))
10522 ("Parameter %d to %s is declared sef, but "
10523 "the argument calls unconstrained function %s "
10524 "(no guarantee it will not modify something): %s",
10525 argno, exprNode_unparse (fcn),
10526 sRef_unconstrainedName (el),
10527 exprNode_unparse (current)),
10528 exprNode_loc (current));
10535 ("Parameter %d to %s is declared sef, but "
10536 "the argument may modify %q: %s",
10537 argno, exprNode_unparse (fcn),
10539 exprNode_unparse (current)),
10540 exprNode_loc (current));
10543 } end_sRefSet_realElements;
10547 transferChecks_passParam (current, ucurrent, isSpec, fcn, argno, totargs);
10548 exprNode_mergeUSs (fcn, current);
10553 checkAnyCall (/*@dependent@*/ exprNode fcn,
10554 /*@dependent@*/ cstring fname,
10557 bool hasMods, sRefSet mods,
10562 int nargs = exprNodeList_size (args);
10567 ** concat all args ud's to f, add each arg sref as a use unless
10568 ** it was specified as "out", in which case it is a def.
10571 uentryList_reset (pn);
10574 ** aliasing checks:
10576 ** if paramn is only or unique, no other arg may alias argn
10579 exprNodeList_elements (args, current)
10583 if (exprNode_isDefined (current))
10585 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
10587 uentry ucurrent = uentryList_current (pn);
10589 if (specialArgs == 0
10590 || (paramno < specialArgs))
10592 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
10594 if (context_maybeSet (FLG_ALIASUNIQUE))
10596 if (uentry_isOnly (ucurrent)
10597 || uentry_isUnique (ucurrent))
10599 checkUniqueParams (fcn, current, args,
10600 paramno, ucurrent);
10605 else /* uentry is undefined */
10607 if (specialArgs == 0)
10609 exprNode_checkUseParam (current);
10612 exprNode_mergeUSs (fcn, current);
10615 uentryList_advanceSafe (pn);
10616 } end_exprNodeList_elements;
10622 sRefSet_allElements (mods, s)
10625 sRef rb = sRef_getRootBase (s);
10627 if (sRef_isFileOrGlobalScope (rb))
10629 context_usedGlobal (rb);
10632 fb = sRef_fixBaseParam (s, args);
10634 if (!sRef_isMacroParamRef (fb))
10636 if (sRef_isNothing (fb))
10642 if (sRef_isValid (fb))
10644 uentry ue = sRef_getBaseUentry (s);
10646 if (uentry_isValid (ue))
10648 uentry_setLset (ue);
10652 fcn->sets = sRefSet_insert (fcn->sets, fb);
10655 sRef_clearDerivedComplete (s);
10656 } end_sRefSet_allElements;
10662 if (context_hasMods ())
10664 if (context_maybeSet (FLG_MODUNCON))
10668 message ("Undetected modification possible "
10669 "from call to unconstrained function %s: %s",
10671 exprNode_unparse (fcn)),
10672 exprNode_loc (fcn));
10677 if (context_maybeSet (FLG_MODUNCONNOMODS)
10678 && !(context_inIterDef () || context_inIterEnd ()))
10681 (FLG_MODUNCONNOMODS,
10682 message ("Undetected modification possible "
10683 "from call to unconstrained function %s: %s",
10685 exprNode_unparse (fcn)),
10686 exprNode_loc (fcn));
10690 exprNode_checkSetAny (fcn, fname);
10694 void exprNode_checkUseParam (exprNode current)
10696 if (exprNode_isDefined (current))
10698 exprNode_checkUse (current, current->sref, current->loc);
10703 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10704 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10709 if (!ctype_match (tr1, tr2))
10711 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10712 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10714 DPRINTF (("No error: [%s] %s / [%s] %s",
10715 exprNode_unparse (e1), ctype_unparse (tr1),
10716 exprNode_unparse (e2), ctype_unparse (tr2)));
10718 ret = ctype_biggerType (tr1, tr2);
10722 if (ctype_isNumAbstract (tr1)
10723 && exprNode_isNumLiteral (e2)
10724 && context_flagOn (FLG_NUMABSTRACTLIT, e1->loc))
10726 ret = tr1; /* No error */
10728 else if (ctype_isNumAbstract (tr2)
10729 && exprNode_isNumLiteral (e1)
10730 && context_flagOn (FLG_NUMABSTRACTLIT, e1->loc))
10738 message ("Incompatible types for %s (%s, %s): %s %s %s",
10739 lltok_unparse (op),
10740 ctype_unparse (te1),
10741 ctype_unparse (te2),
10742 exprNode_unparse (e1), lltok_unparse (op),
10743 exprNode_unparse (e2)),
10746 ret = ctype_unknown;
10750 ret = ctype_biggerType (tr1, tr2);
10757 if (ctype_isNumAbstract (tr1))
10761 else if (ctype_isForceRealNumeric (&tr1)
10762 && ctype_isForceRealNumeric (&tr2))
10764 ret = ctype_resolveNumerics (tr1, tr2);
10766 else if (!context_msgStrictOps ())
10768 if (ctype_isPointer (tr1))
10770 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10774 else if (ctype_isInt (tr2))
10780 ret = ctype_unknown;
10783 else if (ctype_isPointer (tr2))
10785 if (ctype_isPointer (tr1))
10789 else if (ctype_isInt (tr1))
10795 ret = ctype_unknown;
10800 ret = ctype_resolveNumerics (tr1, tr2);
10805 int opid = lltok_getTok (op);
10806 bool comparop = (opid == EQ_OP || opid == NE_OP
10807 || opid == TLT || opid == TGT
10808 || opid == LE_OP || opid == GE_OP);
10810 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10813 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10814 || (ctype_isBool (tr1) && ctype_isBool (tr2))
10815 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10821 if (ctype_sameName (te1, te2))
10825 message ("Operands of %s are non-numeric (%t): %s %s %s",
10826 lltok_unparse (op), te1,
10827 exprNode_unparse (e1), lltok_unparse (op),
10828 exprNode_unparse (e2)),
10835 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10836 lltok_unparse (op), te1, te2,
10837 exprNode_unparse (e1), lltok_unparse (op),
10838 exprNode_unparse (e2)),
10843 else if (!ctype_isNumeric (tr1))
10847 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10848 lltok_unparse (op), te1,
10849 exprNode_unparse (e1), lltok_unparse (op),
10850 exprNode_unparse (e2)),
10855 if (!ctype_isNumeric (tr2))
10859 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10860 lltok_unparse (op), te2,
10861 exprNode_unparse (e1), lltok_unparse (op),
10862 exprNode_unparse (e2)),
10867 ret = ctype_unknown;
10875 abstractOpError (ctype tr1, ctype tr2, lltok op,
10876 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10877 fileloc loc1, fileloc loc2)
10879 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10881 if (ctype_match (tr1, tr2))
10883 if (ctype_isRealNumAbstract (tr1))
10885 ; /* No warning for numabstract types */
10889 if (lltok_isEqOp (op) || lltok_isNotEqOp (op))
10892 (FLG_ABSTRACTCOMPARE,
10893 message ("Object equality comparison (%s) on objects of abstract type (%t): %s %s %s",
10894 lltok_unparse (op), tr1,
10895 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10902 message ("Operands of %s are abstract type (%t): %s %s %s",
10903 lltok_unparse (op), tr1,
10904 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10911 if (ctype_isRealNumAbstract (tr1) && ctype_isRealNumAbstract (tr2))
10916 ("Operands of %s are different numabstract types (%t, %t): %s %s %s",
10917 lltok_unparse (op), tr1, tr2,
10918 exprNode_unparse (e1),
10919 lltok_unparse (op), exprNode_unparse (e2)),
10926 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10927 lltok_unparse (op), tr1, tr2,
10928 exprNode_unparse (e1), lltok_unparse (op),
10929 exprNode_unparse (e2)),
10934 else if (ctype_isRealAbstract (tr1) && !ctype_isRealNumAbstract (tr1))
10938 message ("Left operand of %s is abstract type (%t): %s %s %s",
10939 lltok_unparse (op), tr1,
10940 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10945 if (ctype_isRealAbstract (tr2) && !ctype_isRealNumAbstract (tr2))
10949 message ("Right operand of %s is abstract type (%t): %s %s %s",
10950 lltok_unparse (op), tr2,
10951 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10962 ** requies e1 and e2 and not error exprNode's.
10966 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10967 ** the rep of the abstract type is exposed.
10969 ** The order is very important:
10971 ** check rep expose (move into check transfer)
10977 ** This isn't really a sensible procedure, but the indententation
10978 ** was getting too deep.
10982 checkOneRepExpose (sRef ysr, sRef base,
10983 /*@notnull@*/ exprNode e1,
10984 /*@notnull@*/ exprNode e2, ctype ct,
10987 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
10988 || sRef_isOwned (ysr)
10989 || sRef_isExposed (ysr)))
10991 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10992 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10995 if (sRef_isIReference (ysr))
10997 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
11002 ("Assignment of mutable component of parameter %q "
11003 "to component of abstract "
11004 "type %s exposes rep: %s = %s",
11005 sRef_unparse (base),
11006 ctype_unparse (ct),
11007 exprNode_unparse (e1), exprNode_unparse (e2)),
11015 ("Assignment of mutable component of parameter %q "
11016 "(through alias %q) to component of abstract "
11017 "type %s exposes rep: %s = %s",
11018 sRef_unparse (base),
11019 sRef_unparse (e2->sref),
11020 ctype_unparse (ct),
11021 exprNode_unparse (e1), exprNode_unparse (e2)),
11027 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
11031 message ("Assignment of mutable parameter %q "
11032 "to component of abstract type %s "
11033 "exposes rep: %s = %s",
11034 sRef_unparse (base),
11035 ctype_unparse (ct),
11036 exprNode_unparse (e1),
11037 exprNode_unparse (e2)),
11044 message ("Assignment of mutable parameter %q "
11045 "(through alias %q) to "
11046 "component of abstract type %s exposes "
11048 sRef_unparse (base),
11049 sRef_unparse (e2->sref),
11050 ctype_unparse (ct),
11051 exprNode_unparse (e1),
11052 exprNode_unparse (e2)),
11058 if (sRef_isFileOrGlobalScope (s2b))
11060 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
11064 message ("Assignment of global %q "
11066 "abstract type %s exposes rep: %s = %s",
11067 sRef_unparse (base),
11068 ctype_unparse (ct),
11069 exprNode_unparse (e1), exprNode_unparse (e2)),
11076 message ("Assignment of global %q (through alias %q) "
11078 "abstract type %s exposes rep: %s = %s",
11079 sRef_unparse (base),
11080 sRef_unparse (e2->sref),
11081 ctype_unparse (ct),
11082 exprNode_unparse (e1), exprNode_unparse (e2)),
11090 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
11092 DPRINTF (("Do assign: %s <- %s",
11093 exprNode_unparse (e1), exprNode_unparse (e2)));
11094 DPRINTF (("Ctype: %s", ctype_unparse (exprNode_getType (e1))));
11096 if (ctype_isRealFunction (exprNode_getType (e1))
11097 && !ctype_isRealPointer (exprNode_getType (e1)))
11101 message ("Invalid left-hand side of assignment (function type %s): %s",
11102 ctype_unparse (exprNode_getType (e1)),
11103 exprNode_unparse (e1)),
11107 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
11109 ctype t2 = exprNode_getType (e2);
11110 sRef sr = sRef_getRootBase (e1->sref);
11111 ctype ct = sRef_getType (sr);
11113 if (ctype_isAbstract (t2)
11114 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
11116 /* it is immutable, okay to reference */
11117 goto donerepexpose;
11120 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
11122 sRef s2b = sRef_getRootBase (e2->sref);
11123 sRef s1 = e1->sref;
11124 sRef s1b = sRef_getRootBase (s1);
11127 aliases = usymtab_canAlias (e2->sref);
11129 if (!sRef_similar (s2b, s1b)
11130 && !sRef_isExposed (s1)
11131 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
11133 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
11134 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
11135 && !sRef_isExposed (s2b))
11137 if (sRef_isIReference (e2->sref))
11142 ("Assignment of mutable component of parameter %q "
11143 "to component of abstract type %s exposes rep: %s = %s",
11144 sRef_unparse (s2b),
11145 ctype_unparse (ct),
11146 exprNode_unparse (e1), exprNode_unparse (e2)),
11153 message ("Assignment of mutable parameter %q to "
11154 "component of abstract type %s exposes rep: %s = %s",
11155 sRef_unparse (s2b),
11156 ctype_unparse (ct),
11157 exprNode_unparse (e1), exprNode_unparse (e2)),
11162 if (sRef_isFileOrGlobalScope (s2b))
11166 message ("Assignment of global %q to component of "
11167 "abstract type %s exposes rep: %s = %s",
11168 sRef_unparse (s2b),
11169 ctype_unparse (ct),
11170 exprNode_unparse (e1), exprNode_unparse (e2)),
11174 sRefSet_realElements (aliases, ysr)
11176 sRef base = sRef_getRootBase (ysr);
11178 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
11179 || sRef_sameName (base, s1b))
11181 ; /* error already reported or same sref */
11185 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
11187 } end_sRefSet_realElements;
11189 sRefSet_free (aliases);
11196 ** function variables don't really work...
11199 if (!ctype_isFunction (ctype_realType (e2->typ)))
11203 DPRINTF (("Check init: %s / %s",
11204 exprNode_unparse (e1), exprNode_unparse (e2)));
11205 transferChecks_initialization (e1, e2);
11209 transferChecks_assign (e1, e2);
11214 sRef fref = e2->sref;
11216 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
11217 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
11219 /* Need to typecheck the annotation on the parameters */
11221 if (ctype_isRealFunction (e1->typ)) {
11222 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
11223 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
11225 if (!uentryList_isMissingParams (e1p)
11226 && !uentryList_isMissingParams (e2p)
11227 && uentryList_size (e1p) > 0) {
11228 if (uentryList_size (e1p) == uentryList_size (e2p)) {
11231 uentryList_elements (e1p, el1) {
11234 el2 = uentryList_getN (e2p, n);
11236 uentry_checkMatchParam (el1, el2, n, e2);
11237 } end_uentryList_elements;
11243 if (exprNode_isStringLiteral (e2))
11245 exprNode_checkStringLiteralLength (exprNode_getType (e1), e2);
11248 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
11254 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
11255 updateAliases (e1, e2);
11260 checkMacroParen (exprNode e)
11262 if (exprNode_isError (e) || e->kind == XPR_CAST)
11268 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
11272 message ("Macro parameter used without parentheses: %s",
11273 exprNode_unparse (e)),
11280 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
11284 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
11288 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
11295 ** if e2 is a parameter or global derived location which
11296 ** can be modified (that is, e2 is a mutable abstract type,
11297 ** or a derived pointer), then e1 can alias e2.
11299 ** e1 can alias everything which e2 can alias.
11301 ** Also, if e1 is guarded, remove from guard sets!
11304 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
11306 if (!context_inProtectVars ())
11309 ** depends on types of e1 and e2
11312 sRef s1 = e1->sref;
11313 sRef s2 = e2->sref;
11314 ctype t1 = exprNode_getType (e1);
11316 /* handle pointer sRefs, record fields, arrays, etc... */
11318 if (!ctype_isRealSU (t1))
11320 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
11321 sRef_copyRealDerivedComplete (s1, s2);
11326 ** Fields should alias
11329 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
11332 if (ctype_isMutable (t1) && sRef_isKnown (s1))
11334 usymtab_clearAlias (s1);
11335 usymtab_addMustAlias (s1, s2);
11336 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
11340 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
11343 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
11345 usymtab_unguard (s1);
11350 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
11352 if (exprNode_isDefined (e))
11354 e->loc = fileloc_update (e->loc, loc);
11358 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
11364 static void checkUniqueParams (exprNode fcn,
11365 /*@notnull@*/ exprNode current,
11367 int paramno, uentry ucurrent)
11370 sRef thisref = exprNode_getSref (current);
11373 ** Check if any argument could match this argument.
11376 exprNodeList_elements (args, icurrent)
11380 if (iparamno != paramno)
11382 sRef sr = exprNode_getSref (icurrent);
11384 if (sRef_similarRelaxed (thisref, sr))
11386 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
11391 ("Parameter %d (%s) to function %s is declared %s but "
11392 "is aliased by parameter %d (%s)",
11394 exprNode_unparse (current),
11395 exprNode_unparse (fcn),
11396 alkind_unparse (uentry_getAliasKind (ucurrent)),
11397 iparamno, exprNode_unparse (icurrent)),
11403 sRefSet aliases = usymtab_canAlias (sr);
11405 sRefSet_allElements (aliases, asr)
11407 if (ctype_isUnknown (sRef_getType (thisref)))
11409 sRef_setType (thisref, uentry_getType (ucurrent));
11412 if (sRef_similarRelaxed (thisref, asr))
11414 if (sRef_isExternal (asr))
11416 if (sRef_isLocalState (thisref))
11422 sRef base = sRef_getRootBase (asr);
11424 if (!sRef_similar (sRef_getBase (asr), thisref))
11426 if (sRef_isUnique (base) || sRef_isOnly (base)
11427 || sRef_isKept (base)
11428 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
11429 || (sRef_isAddress (thisref)
11430 && sRef_isLocalVar (sRef_getRootBase (thisref))))
11432 ; /* okay, no error */
11437 (FLG_MAYALIASUNIQUE,
11439 ("Parameter %d (%s) to function %s is declared %s but "
11440 "may be aliased externally by parameter %d (%s)",
11442 exprNode_unparse (current),
11443 exprNode_unparse (fcn),
11444 alkind_unparse (uentry_getAliasKind (ucurrent)),
11445 iparamno, exprNode_unparse (icurrent)),
11456 ("Parameter %d (%s) to function %s is declared %s but "
11457 "is aliased externally by parameter %d (%s) through "
11460 exprNode_unparse (current),
11461 exprNode_unparse (fcn),
11462 alkind_unparse (uentry_getAliasKind (ucurrent)),
11463 iparamno, exprNode_unparse (icurrent),
11464 sRef_unparse (asr)),
11468 } end_sRefSet_allElements;
11469 sRefSet_free (aliases);
11472 } end_exprNodeList_elements;
11475 long exprNode_getLongValue (exprNode e) {
11478 if (exprNode_hasValue (e)
11479 && multiVal_isInt (exprNode_getValue (e)))
11481 value = multiVal_forceInt (exprNode_getValue (e));
11492 /*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
11494 if (exprNode_isDefined (p_e) )
11495 return ( p_e->loc );
11497 return fileloc_undefined;
11500 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
11503 ** Returns the location of the sequence point following e.
11505 ** Only works for statements (for now).
11508 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
11509 lltok t = exprData_getUopTok (e->edata);
11510 return fileloc_copy(lltok_getLoc (t));
11512 /* drl possible problem : warning fix
11513 llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
11515 return fileloc_undefined;
11519 exprNode exprNode_createNew(ctype c)
11523 ret = exprNode_createPlain (c);
11528 bool exprNode_isInitBlock (exprNode e)
11530 return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);
11533 /*drl 3/2/2003 moved this function out of constraint.c */
11534 exprNode exprNode_copyConstraints (/*@returned@*/ exprNode dst, exprNode src)
11537 llassert (exprNode_isDefined (dst) );
11538 llassert (exprNode_isDefined (src) );
11540 constraintList_free (dst->ensuresConstraints);
11541 constraintList_free (dst->requiresConstraints);
11542 constraintList_free (dst->trueEnsuresConstraints);
11543 constraintList_free (dst->falseEnsuresConstraints);
11545 dst->ensuresConstraints = constraintList_copy (src->ensuresConstraints);
11546 dst->requiresConstraints = constraintList_copy (src->requiresConstraints);
11547 dst->trueEnsuresConstraints = constraintList_copy (src->trueEnsuresConstraints);
11548 dst->falseEnsuresConstraints = constraintList_copy (src->falseEnsuresConstraints);