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 ();
1015 e->sets = sRefSet_new ();
1016 e->msets = sRefSet_new ();
1017 e->uses = sRefSet_new ();
1019 /*> missing fields, detected by splint <*/
1020 e->exitCode = XK_NEVERESCAPE;
1021 e->isJumpPoint = FALSE;
1022 e->canBreak = FALSE;
1023 e->mustBreak = FALSE;
1025 exprNode_defineConstraints (e);
1030 return exprNode_createUnknown ();
1034 /*@notnull@*/ exprNode
1035 exprNode_fromIdentifier (/*@observer@*/ uentry c)
1039 if (context_justPopped ()) /* watch out! c could be dead */
1041 uentry ce = usymtab_lookupSafe (cscannerHelp_observeLastIdentifier ());
1043 if (uentry_isValid (ce))
1049 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
1053 ret = exprNode_fromIdentifierAux (c);
1057 static void exprNode_checkStringLiteralLength (ctype t1, exprNode e2)
1059 multiVal mval = exprNode_getValue (e2);
1063 if (ctype_isFixedArray (t1))
1065 size_t nelements = ctype_getArraySize (t1);
1067 llassert (multiVal_isString (mval));
1068 slit = multiVal_forceString (mval);
1070 len = cstring_lengthExpandEscapes (slit);
1072 llassert (exprNode_isDefined (e2));
1074 if (len == nelements)
1078 temp = cstring_expandEscapes (slit);
1080 if (temp[len-1] == '\0')
1083 (FLG_STRINGLITNOROOMFINALNULL,
1084 message ("String literal with %d character%& "
1085 "is assigned to %s (no room for final null terminator): %s",
1086 size_toInt (len + 1),
1088 exprNode_unparse (e2)),
1094 (FLG_STRINGLITNOROOM,
1095 message ("String literal with %d character%& "
1096 "is assigned to %s (no room for null terminator): %s",
1097 size_toInt (len + 1),
1099 exprNode_unparse (e2)),
1103 else if (len > nelements)
1106 (FLG_STRINGLITTOOLONG,
1107 message ("String literal with %d character%& (counting null terminator) "
1108 "is assigned to %s (insufficient storage available): %s",
1109 size_toInt (len + 1),
1111 exprNode_unparse (e2)),
1114 else if (len < nelements - 1)
1117 (FLG_STRINGLITSMALLER,
1118 message ("String literal with %d character%& is assigned to %s (possible waste of storage): %s",
1119 size_toInt (len + 1),
1121 exprNode_unparse (e2)),
1131 static /*@only@*/ /*@notnull@*/ exprNode
1132 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
1134 exprNode e = exprNode_createId (c);
1137 uentry_setUsed (c, e->loc);
1139 if (uentry_isVar (c) && sRef_isFileOrGlobalScope (sr))
1141 checkGlobUse (c, FALSE, e);
1148 exprNode_isZero (exprNode e)
1150 if (exprNode_isDefined (e))
1152 multiVal m = exprNode_getValue (e);
1154 if (multiVal_isInt (m))
1156 return (multiVal_forceInt (m) == 0);
1164 exprNode_isNonNegative (exprNode e)
1166 if (exprNode_isDefined (e))
1168 multiVal m = exprNode_getValue (e);
1170 if (multiVal_isInt (m))
1172 return (multiVal_forceInt (m) >= 0);
1176 ** This is not always true if programmer defines enum
1177 ** values, but then the constant should be known.
1180 if (ctype_isEnum (ctype_realType (e->typ)))
1190 ** a[x] - uses a but NOT a[]
1191 ** result sref = a[] (set/use in assignment)
1193 ** The syntax x[a] is also legal in C, and has the same
1194 ** semantics. If ind is an array, and arr is an int, flip
1199 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
1202 ** error in arr, error propagates (no new messages)
1203 ** error in ind, assume valid and continue
1206 DPRINTF (("Array fetch: %s / %s",
1207 exprNode_unparse (e1), exprNode_unparse (e2)));
1209 if (exprNode_isError (e1))
1212 return (exprNode_makeError ());
1218 ctype carr = exprNode_getType (e1);
1219 ctype crarr = ctype_realType (carr);
1222 ** this sets up funny aliasing, that leads to spurious
1223 ** splint errors. Hence, the i2 comments.
1226 /* evans 2001-09-09 added ctype_isKnown so there is no swap when e1 type is unknown */
1227 if (ctype_isKnown (crarr)
1228 && !ctype_isRealArray (crarr)
1229 && ctype_isRealNumeric (crarr)
1230 && !exprNode_isError (e2)
1231 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1236 carr = exprNode_getType (arr);
1237 crarr = ctype_realType (carr);
1245 DPRINTF (("arr: %s", exprNode_unparse (arr)));
1247 if (sRef_possiblyNull (arr->sref))
1249 if (!usymtab_isGuarded (arr->sref))
1251 if (!context_inSizeof() )
1253 if (optgenerror (FLG_NULLDEREF,
1254 message ("Index of %s pointer %q: %s",
1255 sRef_nullMessage (arr->sref),
1256 sRef_unparse (arr->sref),
1257 exprNode_unparse (arr)),
1260 DPRINTF (("ref: %s", sRef_unparseFull (arr->sref)));
1261 sRef_showNullInfo (arr->sref);
1263 /* suppress future messages */
1264 sRef_setNullError (arr->sref);
1270 if (exprNode_isError (ind))
1272 if ((ctype_isArrayPtr (crarr)
1273 && !ctype_isFunction (crarr))
1274 || ctype_isUnknown (carr))
1276 exprNode ret = exprNode_createPartialCopy (arr);
1278 if (ctype_isKnown (carr))
1280 ret->typ = ctype_baseArrayPtr (crarr);
1284 ret->typ = ctype_unknown;
1287 ret->sref = sRef_makeArrayFetch (arr->sref);
1289 ret->kind = XPR_FETCH;
1292 ** Because of funny aliasing (when arr and ind are
1293 ** flipped) spurious errors would be reported here.
1296 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1297 checkSafeUse (ret, arr->sref);
1302 voptgenerror (FLG_TYPE,
1303 message ("Array fetch from non-array (%t): %s[%s]", carr,
1304 exprNode_unparse (e1), exprNode_unparse (e2)),
1306 exprNode_free (arr);
1307 return (exprNode_makeError ());
1312 if (!ctype_isForceRealInt (&(ind->typ)))
1314 ctype rt = ctype_realType (ind->typ);
1316 if (ctype_isChar (rt))
1320 message ("Array fetch using non-integer, %t: %s[%s]",
1322 exprNode_unparse (e1), exprNode_unparse (e2)),
1325 else if (ctype_isEnum (rt))
1329 message ("Array fetch using non-integer, %t: %s[%s]",
1331 exprNode_unparse (e1), exprNode_unparse (e2)),
1334 else if (ctype_isNumAbstract (rt))
1337 (FLG_NUMABSTRACTINDEX,
1338 message ("Array fetch using numabstract type, %t: %s[%s]",
1340 exprNode_unparse (e1), exprNode_unparse (e2)),
1347 message ("Array fetch using non-integer, %t: %s[%s]",
1349 exprNode_unparse (e1), exprNode_unparse (e2)),
1353 multiVal_free (ind->val);
1354 ind->val = multiVal_unknown ();
1357 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1359 exprNode ret = exprNode_createSemiCopy (arr);
1360 multiVal m = exprNode_getValue (ind);
1362 ret->typ = ctype_baseArrayPtr (crarr);
1363 ret->kind = XPR_FETCH;
1365 if (multiVal_isInt (m))
1367 int i = (int) multiVal_forceInt (m);
1369 if (sRef_isValid (arr->sref)) {
1370 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1372 ret->sref = sRef_undefined;
1377 ret->sref = sRef_makeArrayFetch (arr->sref);
1380 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1381 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1382 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1384 /* (see comment on spurious errors above) */
1385 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1387 exprNode_checkUse (ret, ind->sref, ind->loc);
1388 exprNode_checkUse (ret, arr->sref, arr->loc);
1394 if (ctype_isUnknown (carr))
1396 exprNode ret = exprNode_createPartialCopy (arr);
1398 ret->kind = XPR_FETCH;
1399 ret->typ = ctype_unknown;
1400 ret->sets = sRefSet_union (ret->sets, ind->sets);
1401 ret->msets = sRefSet_union (ret->msets, ind->msets);
1402 ret->uses = sRefSet_union (ret->uses, ind->uses);
1404 /* (see comment on spurious errors above) */
1405 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1407 exprNode_checkUse (ret, ind->sref, ind->loc);
1408 exprNode_checkUse (ret, arr->sref, arr->loc);
1415 message ("Array fetch from non-array (%t): %s[%s]", carr,
1416 exprNode_unparse (e1), exprNode_unparse (e2)),
1419 exprNode_free (arr);
1420 exprNode_free (ind);
1422 return (exprNode_makeError ());
1432 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1433 exprNodeList args, exprNode ret)
1435 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1439 ** checkPrintfArgs --- checks arguments for printf-like functions
1440 ** Arguments before ... have already been checked.
1441 ** The argument before the ... is a char *.
1442 ** argno is the format string argument.
1446 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1447 exprNodeList args, exprNode ret, int argno)
1450 ** the last argument before the elips is the format string
1455 int nargs = exprNodeList_size (args);
1456 uentryList params = uentry_getParams (fcn);
1460 ** These should be ensured by checkSpecialFunction
1463 llassert (uentryList_size (params) == argno + 1);
1464 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1466 a = exprNodeList_getN (args, argno - 1);
1467 formatloc = fileloc_copy (exprNode_loc (a));
1469 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1470 && exprNode_knownStringValue (a))
1472 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1473 char *code = format;
1476 nargs = exprNodeList_size (args);
1478 while ((code = strchr (code, '%')) != NULL)
1480 char *origcode = code;
1481 cstring codetext = cstring_newEmpty ();
1482 char key = *(++code);
1483 ctype modtype = ctype_int;
1484 bool modified = FALSE;
1486 fileloc_addColumn (formatloc, code - ocode);
1488 codetext = cstring_appendChar (codetext, key);
1491 while (isFlagKey (key))
1494 codetext = cstring_appendChar (codetext, key);
1495 fileloc_incColumn (formatloc);
1498 if (key == 'm') /* skipped in syslog */
1503 /* ignore field width */
1504 while (isdigit ((int) key) != 0)
1507 codetext = cstring_appendChar (codetext, key);
1508 fileloc_incColumn (formatloc);
1511 /* ignore precision */
1515 codetext = cstring_appendChar (codetext, key);
1516 fileloc_incColumn (formatloc);
1519 ** In printf, '*' means: read the next arg as an int for the
1520 ** field width. This seems to be missing from my copy of the
1521 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1522 ** later) but never does.
1527 ; /* don't do anything --- handle later */
1531 while (isdigit ((int) key) != 0)
1534 codetext = cstring_appendChar (codetext, key);
1535 fileloc_incColumn (formatloc);
1542 modtype = ctype_sint; /* short */
1544 codetext = cstring_appendChar (codetext, key);
1545 fileloc_incColumn (formatloc);
1547 else if (key == 'l' || key == 'L')
1549 modtype = ctype_lint; /* long */
1551 codetext = cstring_appendChar (codetext, key);
1552 fileloc_incColumn (formatloc);
1554 if (key == 'l' || key == 'L') {
1555 modtype = ctype_llint; /* long long */
1557 codetext = cstring_appendChar (codetext, key);
1558 fileloc_incColumn (formatloc);
1566 /* now, key = type of conversion to apply */
1568 fileloc_incColumn (formatloc);
1576 message ("No argument corresponding to %q format "
1577 "code %d (%%%s): \"%s\"",
1578 uentry_getName (fcn),
1580 cstring_fromChars (format)),
1583 if (fileloc_isDefined (formatloc)
1584 && context_getFlag (FLG_SHOWCOL))
1586 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1594 a = exprNodeList_getN (args, i);
1597 if (!exprNode_isError (a))
1603 case '*': /* int argument for fieldwidth */
1604 expecttype = ctype_int;
1605 *(--code) = '%'; /* convert it for next code */
1606 fileloc_subColumn (formatloc, 1);
1607 /*@switchbreak@*/ break;
1610 expecttype = ctype_combine (ctype_uint, modtype);
1611 /*@switchbreak@*/ break;
1613 case 'i': /* int argument */
1615 expecttype = ctype_combine (ctype_int, modtype);
1616 /*@switchbreak@*/ break;
1618 case 'x': /* unsigned int */
1620 expecttype = ctype_combine (ctype_uint, modtype);
1622 /*@switchbreak@*/ break;
1628 case 'f': /* double */
1629 expecttype = ctype_combine (ctype_double, modtype);
1630 /*@switchbreak@*/ break;
1632 case 'c': /* int converted to char (check its a char?) */
1633 expecttype = ctype_makeConj (ctype_int,
1634 ctype_makeConj (ctype_char,
1636 /* evans 2001-10-05 - changed to reflect correct ISO spec:
1637 int converted to char */
1639 /*@switchbreak@*/ break;
1641 case 's': /* string */
1642 expecttype = ctype_string;
1643 /*@switchbreak@*/ break;
1646 while (((key = *(++code)) != ']')
1649 codetext = cstring_appendChar (codetext, key);
1650 fileloc_incColumn (formatloc);
1656 (message ("Bad character set format: %s",
1657 cstring_fromChars (origcode)));
1660 expecttype = ctype_string;
1661 /*@switchbreak@*/ break;
1663 case 'p': /* pointer */
1664 expecttype = ctype_makePointer (ctype_void);
1665 /* need not be defined */
1666 uentry_setDefState (regArg, SS_RELDEF);
1667 sRef_setPosNull (uentry_getSref (regArg),
1670 /*@switchbreak@*/ break;
1672 case 'n': /* pointer to int, modified by call! */
1673 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1675 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1676 /*@switchbreak@*/ break;
1678 case 'm': /* in a syslog, it doesn't consume an argument */
1679 /* should check we're really doing syslog */
1681 /*@switchbreak@*/ break;
1685 expecttype = ctype_unknown;
1689 message ("Unrecognized format code: %s",
1690 cstring_fromChars (origcode)),
1691 fileloc_isDefined (formatloc)
1692 ? formatloc : g_currentloc);
1694 /*@switchbreak@*/ break;
1697 if (!(exprNode_matchArgType (expecttype, a)))
1699 if (ctype_isVoidPointer (expecttype)
1700 && ctype_isRealAbstract (a->typ)
1701 && (context_getFlag (FLG_ABSTVOIDP)))
1707 if (llgenformattypeerror
1708 (expecttype, exprNode_undefined,
1710 message ("Format argument %d to %q (%%%s) expects "
1713 uentry_getName (fcn),
1716 a->typ, exprNode_unparse (a)),
1719 if (fileloc_isDefined (formatloc)
1720 && context_getFlag (FLG_SHOWCOL))
1723 (cstring_makeLiteral
1724 ("Corresponding format code"),
1731 uentry_setType (regArg, expecttype);
1732 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1734 if (ctype_equal (expecttype, ctype_string))
1736 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1739 uentry_setType (regArg, ctype_unknown);
1740 uentry_fixupSref (regArg);
1744 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1755 cstring_free (codetext);
1760 voptgenerror (FLG_TYPE,
1761 message ("Format string for %q has %d arg%&, given %d",
1762 uentry_getName (fcn), i - argno, nargs - argno),
1768 /* no checking possible for compile-time unknown format strings */
1769 if (exprNode_isDefined (a))
1773 message ("Format string parameter to %s is not a compile-time constant: %s",
1774 exprNode_unparse (f),
1775 exprNode_unparse (a)),
1780 fileloc_free (formatloc);
1784 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1785 exprNodeList args, exprNode ret, int argno)
1789 int nargs = exprNodeList_size (args);
1790 uentryList params = uentry_getParams (fcn);
1794 ** These should be ensured by checkSpecialFunction
1797 llassert (uentryList_size (params) == argno + 1);
1798 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1800 a = exprNodeList_getN (args, argno - 1);
1801 formatloc = fileloc_copy (exprNode_loc (a));
1803 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1804 && exprNode_knownStringValue (a))
1806 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1807 char *code = format;
1810 nargs = exprNodeList_size (args);
1812 while ((code = strchr (code, '%')) != NULL)
1814 char *origcode = code;
1815 char key = *(++code);
1816 cstring codetext = cstring_newEmpty ();
1817 ctype modtype = ctype_int;
1818 char modifier = '\0';
1819 bool modified = TRUE;
1820 bool ignore = FALSE;
1822 codetext = cstring_appendChar (codetext, key);
1823 fileloc_addColumn (formatloc, code - ocode);
1826 ** this is based on ANSI standard library description of fscanf
1827 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1830 /* '*' suppresses assignment (does not need match argument) */
1835 codetext = cstring_appendChar (codetext, key);
1838 fileloc_incColumn (formatloc);
1841 /* ignore field width */
1842 while (isdigit ((int) key) != 0)
1845 codetext = cstring_appendChar (codetext, key);
1846 fileloc_incColumn (formatloc);
1851 modtype = ctype_sint; /* short */
1853 codetext = cstring_appendChar (codetext, key);
1854 fileloc_incColumn (formatloc);
1856 else if (key == 'l' || key == 'L')
1858 modtype = ctype_lint; /* long */
1862 codetext = cstring_appendChar (codetext, key);
1864 fileloc_incColumn (formatloc);
1866 if (key == 'l' || key == 'L') {
1867 modtype = ctype_llint; /* long long */
1869 codetext = cstring_appendChar (codetext, key);
1870 fileloc_incColumn (formatloc);
1878 /* now, key = type of conversion to apply */
1880 fileloc_incColumn (formatloc);
1894 message ("No argument corresponding to %q format "
1895 "code %d (%%%s): \"%s\"",
1896 uentry_getName (fcn),
1898 cstring_fromChars (format)),
1901 if (fileloc_isDefined (formatloc)
1902 && context_getFlag (FLG_SHOWCOL))
1905 (cstring_makeLiteral ("Corresponding format code"),
1913 a = exprNodeList_getN (args, i);
1916 if (!exprNode_isError (a))
1922 case '*': /* int argument for fieldwidth */
1923 expecttype = ctype_makePointer (ctype_int);
1924 *(--code) = '%'; /* convert it for next code */
1925 fileloc_subColumn (formatloc, 1);
1926 /*@switchbreak@*/ break;
1929 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1930 /*@switchbreak@*/ break;
1934 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1935 /*@switchbreak@*/ break;
1938 case 'X': /* unsigned int */
1939 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1940 /*@switchbreak@*/ break;
1947 /* printf is double, scanf is float! */
1949 if (modifier == 'l')
1951 expecttype = ctype_makePointer (ctype_double);
1953 else if (modifier == 'L')
1955 expecttype = ctype_makePointer (ctype_ldouble);
1959 llassert (modifier == '\0');
1960 expecttype = ctype_makePointer (ctype_float);
1962 /*@switchbreak@*/ break;
1964 case 'c': /* int converted to char (check its a char?) */
1965 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1966 /*@switchbreak@*/ break;
1968 case 's': /* string */
1969 expecttype = ctype_string;
1970 /*@switchbreak@*/ break;
1974 while (((key = *(++code)) != ']')
1977 codetext = cstring_appendChar (codetext, key);
1978 fileloc_incColumn (formatloc);
1984 (message ("Bad character set format: %s",
1985 cstring_fromChars (origcode)));
1988 expecttype = ctype_string;
1989 /*@switchbreak@*/ break;
1992 case 'p': /* pointer */
1995 message ("Format code should not be used in scanf: %s",
1996 cstring_fromChars (origcode)),
1997 fileloc_isDefined (formatloc)
1998 ? formatloc : g_currentloc);
2000 expecttype = ctype_unknown;
2001 /*@switchbreak@*/ break;
2003 case 'n': /* pointer to int, modified by call! */
2004 expecttype = ctype_makePointer (ctype_int);
2005 /*@switchbreak@*/ break;
2008 expecttype = ctype_unknown;
2012 message ("Unrecognized format code: %s",
2013 cstring_fromChars (origcode)),
2014 fileloc_isDefined (formatloc)
2015 ? formatloc : g_currentloc);
2017 /*@switchbreak@*/ break;
2020 if (!(exprNode_matchArgType (expecttype, a)))
2022 if (ctype_isVoidPointer (expecttype)
2023 && ctype_isRealAbstract (a->typ)
2024 && (context_getFlag (FLG_ABSTVOIDP)))
2030 if (llgenformattypeerror
2031 (expecttype, exprNode_undefined,
2033 message ("Format argument %d to %q (%%%s) expects "
2036 uentry_getName (fcn),
2037 codetext, expecttype,
2038 a->typ, exprNode_unparse (a)),
2041 if (fileloc_isDefined (formatloc)
2042 && context_getFlag (FLG_SHOWCOL))
2045 (cstring_makeLiteral
2046 ("Corresponding format code"),
2053 uentry_setType (outArg, expecttype);
2054 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
2055 uentry_setType (outArg, ctype_unknown);
2056 uentry_fixupSref (outArg);
2060 exprNode_checkCallModifyVal (a->sref, args, f, ret);
2065 /* a->sref = sRef_undefined; */
2072 cstring_free (codetext);
2077 voptgenerror (FLG_TYPE,
2078 message ("Format string for %q has %d arg%&, given %d",
2079 uentry_getName (fcn), i - argno, nargs - argno),
2085 /* no checking possible for compile-time unknown format strings */
2088 fileloc_free (formatloc);
2092 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
2095 /*@unused@*/ int argno)
2098 ** the last argument before the elips is the format string
2101 int nargs = exprNodeList_size (args);
2106 a = exprNodeList_getN (args, argno - 1);
2107 formatloc = fileloc_copy (exprNode_loc (a));
2109 if (ctype_isUnknown (cstringType)) {
2110 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
2112 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
2116 if (ctype_isUnknown (ctypeType)) {
2117 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
2119 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
2123 if (ctype_isUnknown (filelocType)) {
2124 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
2126 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
2130 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
2131 && exprNode_knownStringValue (a))
2133 cstring format = multiVal_forceString (exprNode_getValue (a));
2134 char *code = cstring_toCharsSafe (format);
2137 nargs = exprNodeList_size (args);
2139 while ((code = strchr (code, '%')) != NULL)
2141 char *origcode = code;
2142 char key = *(++code);
2143 cstring codetext = cstring_newEmpty ();
2144 bool isOnly = FALSE;
2146 codetext = cstring_appendChar (codetext, key);
2148 fileloc_addColumn (formatloc, code - ocode);
2150 while (key >= '0' && key <= '9')
2153 codetext = cstring_appendChar (codetext, key);
2154 fileloc_incColumn (formatloc);
2158 fileloc_incColumn (formatloc);
2162 if (key == '&') /* plural marker */
2171 message ("Message missing format arg %d (%%%s): \"%s\"",
2172 i + 1, codetext, format),
2178 a = exprNodeList_getN (args, i);
2182 if (!exprNode_isError (a))
2186 /*@-loopswitchbreak@*/
2192 expecttype = ctype_char; break;
2194 expecttype = cstringType; break;
2196 expecttype = cstringType; isOnly = TRUE; break;
2198 expecttype = cstringType; isOnly = TRUE; break;
2199 case 'd': expecttype = ctype_int; break;
2200 case 'u': expecttype = ctype_uint; break;
2201 case 'w': expecttype = ctype_ulint; break;
2202 case 'f': expecttype = ctype_float; break;
2203 case 'b': expecttype = ctype_bool; break;
2204 case 't': expecttype = ctypeType; break;
2206 expecttype = ctype_makePointer (ctype_void);
2207 /* need not be defined */
2208 uentry_setDefState (regArg, SS_RELDEF);
2209 sRef_setPosNull (uentry_getSref (regArg),
2212 /*@switchbreak@*/ break;
2213 case 'l': expecttype = filelocType; break;
2214 case '&': /* a wee bit of a hack methinks */
2215 expecttype = ctype_int;
2217 case 'r': expecttype = ctype_bool; break;
2219 expecttype = ctype_unknown;
2222 message ("Unrecognized format code: %s",
2223 cstring_fromChars (origcode)),
2224 fileloc_isDefined (formatloc)
2225 ? formatloc : g_currentloc);
2228 /*@=loopswitchbreak@*/
2230 if (!(exprNode_matchArgType (expecttype, a)))
2232 if (ctype_isVoidPointer (expecttype)
2233 && ctype_isRealAbstract (a->typ)
2234 && (context_getFlag (FLG_ABSTVOIDP)))
2240 if (llgenformattypeerror
2241 (expecttype, exprNode_undefined,
2243 message ("Format argument %d to %q (%%%s) expects "
2246 uentry_getName (fcn),
2247 codetext, expecttype,
2248 a->typ, exprNode_unparse (a)),
2251 if (fileloc_isDefined (formatloc)
2252 && context_getFlag (FLG_SHOWCOL))
2255 (cstring_makeLiteral
2256 ("Corresponding format code"),
2263 if (ctype_equal (expecttype, cstringType))
2267 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2268 uentry_fixupSref (csOnlyArg);
2272 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2273 uentry_fixupSref (csArg);
2278 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2279 uentry_fixupSref (regArg);
2285 cstring_free (codetext);
2290 voptgenerror (FLG_TYPE,
2291 message ("Format string for %q has %d arg%&, given %d",
2292 uentry_getName (fcn), i - argno, nargs -argno),
2298 /* no checking possible for compile-time unknown format strings */
2301 fileloc_free (formatloc);
2305 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2306 /*@notnull@*/ exprNode e2,
2312 bool hadUncon = FALSE;
2314 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
2315 sRefSet_hasUnconstrained (sets2))
2318 (FLG_EVALORDERUNCON,
2320 ("Expression may have undefined behavior (%q used in right operand "
2321 "may set global variable %q used in left operand): %s %s %s",
2322 sRefSet_unparseUnconstrained (sets2),
2323 sRef_unparse (sRef_getRootBase (e1->sref)),
2324 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2328 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
2329 sRefSet_hasUnconstrained (sets1))
2332 (FLG_EVALORDERUNCON,
2334 ("Expression has undefined behavior (%q used in left operand "
2335 "may set global variable %q used in right operand): %s %s %s",
2336 sRefSet_unparseUnconstrained (sets1),
2337 sRef_unparse (e2->sref),
2338 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2342 sRefSet_realElements (e1->uses, sr)
2344 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2349 ("Expression has undefined behavior (left operand uses %q, "
2350 "modified by right operand): %s %s %s",
2352 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2355 } end_sRefSet_realElements;
2357 sRefSet_realElements (sets1, sr)
2359 if (sRef_isMeaningful (sr))
2361 if (sRef_same (sr, e2->sref))
2366 ("Expression has undefined behavior (value of right operand "
2367 "modified by left operand): %s %s %s",
2368 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2371 else if (sRefSet_member (e2->uses, sr))
2376 ("Expression has undefined behavior (left operand modifies %q, "
2377 "used by right operand): %s %s %s",
2379 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2384 if (sRefSet_member (sets2, sr))
2386 if (sRef_isUnconstrained (sr))
2394 hadUncon = optgenerror
2395 (FLG_EVALORDERUNCON,
2397 ("Expression may have undefined behavior. Left operand "
2398 "calls %q; right operand calls %q. The unconstrained "
2399 "functions may modify global state used by "
2400 "the other operand): %s %s %s",
2401 sRefSet_unparseUnconstrained (sets1),
2402 sRefSet_unparseUnconstrained (sets2),
2403 exprNode_unparse (e1), lltok_unparse (op),
2404 exprNode_unparse (e2)),
2413 ("Expression has undefined behavior (both "
2414 "operands modify %q): %s %s %s",
2416 exprNode_unparse (e1),
2417 lltok_unparse (op), exprNode_unparse (e2)),
2423 } end_sRefSet_realElements;
2426 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2428 bool hasError = FALSE;
2430 if (exprNode_isError (e1) || exprNode_isError (e2))
2435 if (sRefSet_member (e2->sets, e1->sref))
2437 if (e2->kind == XPR_CALL)
2443 hasError = optgenerror
2445 message ("Expression has undefined behavior "
2446 "(value of left operand %s is modified "
2447 "by right operand %s): %s %s %s",
2448 exprNode_unparse (e1),
2449 exprNode_unparse (e2),
2450 exprNode_unparse (e1), lltok_unparse (op),
2451 exprNode_unparse (e2)),
2456 if (context_getFlag (FLG_EVALORDERUNCON))
2458 if (sRefSet_member (e2->msets, e1->sref))
2460 if (e2->kind == XPR_CALL)
2466 hasError = optgenerror
2469 ("Expression has undefined behavior (value of left "
2470 "operand may be modified by right operand): %s %s %s",
2471 exprNode_unparse (e1), lltok_unparse (op),
2472 exprNode_unparse (e2)),
2480 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2482 if (context_maybeSet (FLG_EVALORDERUNCON))
2484 checkExpressionDefinedAux (e1, e2, e1->msets,
2485 e2->msets, op, FLG_EVALORDERUNCON);
2490 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2493 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2494 exprNodeList args, bool isIter, exprNode ret)
2498 if (!exprNode_isError (f))
2500 if (!uentryList_isMissingParams (cl))
2502 int nargs = exprNodeList_size (args);
2503 int expectargs = uentryList_size (cl);
2507 if (expectargs == 0)
2515 message ("Iter %q invoked with %d args, "
2517 uentry_getName (fcn),
2525 message ("Function %s called with %d args, "
2527 exprNode_unparse (f), nargs),
2534 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2536 exprNodeList_reset (args);
2538 uentryList_elements (cl, current)
2540 ctype ct = uentry_getType (current);
2543 if (ctype_isElips (ct))
2546 ** do special checking for printf/scanf library functions
2548 ** this is kludgey code, just for handling the special case
2552 if (uentry_isPrintfLike (fcn))
2554 checkPrintfArgs (f, fcn, args, ret, i);
2557 else if (uentry_isScanfLike (fcn))
2559 checkScanfArgs (f, fcn, args, ret, i);
2562 else if (uentry_isMessageLike (fcn))
2564 checkMessageArgs (f, fcn, args, i);
2569 llassert (!uentry_isSpecialFunction (fcn));
2572 nargs = expectargs; /* avoid errors */
2577 if (i >= nargs) break;
2579 a = exprNodeList_current (args);
2580 exprNodeList_advance (args);
2584 if (exprNode_isError (a))
2591 probably necessary? I'm not sure about this one
2592 checkMacroParen (a);
2595 f->guards = guardSet_union (f->guards, a->guards);
2597 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2599 if (!(exprNode_matchArgType (ct, a)))
2601 DPRINTF (("Args mismatch!"));
2603 if (ctype_isVoidPointer (ct)
2604 && (ctype_isPointer (a->typ)
2605 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2610 ("Pointer to abstract type (%t) used "
2612 "(arg %d to %q): %s",
2614 uentry_getName (fcn),
2615 exprNode_unparse (a)),
2623 (ct, exprNode_undefined,
2626 ("Iter %q expects arg %d to "
2627 "be %t gets %t: %s",
2628 uentry_getName (fcn),
2629 i, ct, a->typ, exprNode_unparse (a)),
2640 ("Function %q expects arg %d to be %t gets %t: %s",
2641 uentry_getName (fcn),
2642 i, ct, a->typ, exprNode_unparse (a)),
2645 DPRINTF (("Types: %s / %s",
2647 ctype_unparse (a->typ)));
2651 ** Clear null marker for abstract types.
2652 ** (It is not revealed, so suppress future messages.)
2655 if (ctype_isAbstract (a->typ))
2657 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2664 } end_uentryList_elements ;
2667 if (expectargs != nargs) /* note: not != since we may have ... */
2669 if (ctype_isElips (last))
2673 message ("Function %s called with %d args, expects at least %d",
2674 exprNode_unparse (f),
2675 nargs, expectargs - 1),
2684 message ("Iter %q invoked with %d args, expects %d",
2685 uentry_getName (fcn), nargs, expectargs),
2692 message ("Function %s called with %d args, expects %d",
2693 exprNode_unparse (f),
2706 ** Check for undefined code sequences in function arguments:
2708 ** one parameter sets something used by another parameter
2709 ** one parameter sets something set by another parameter
2713 checkSequencingOne (exprNode f, exprNodeList args,
2714 /*@notnull@*/ exprNode el, int argno)
2717 ** Do second loop, iff +undefunspec
2721 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2723 for (checkloop = 0; checkloop < numloops; checkloop++)
2729 thissets = el->sets;
2733 llassert (checkloop == 1);
2734 thissets = el->msets;
2737 sRefSet_realElements (thissets, thisset)
2741 /*@access exprNodeList@*/
2742 for (j = 0; j < args->nelements; j++)
2744 exprNode jl = args->elements[j];
2745 int thisargno = j + 1;
2747 if (thisargno != argno && exprNode_isDefined (jl))
2749 sRefSet otheruses = jl->uses;
2751 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
2752 sRefSet_hasUnconstrained (thissets))
2755 (FLG_EVALORDERUNCON,
2758 ("%q used in argument %d may set "
2759 "global variable %q used by argument %d: %s(%q)",
2760 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2763 sRef_unparse (sRef_getRootBase (jl->sref)),
2765 exprNode_unparse (f), exprNodeList_unparse (args)),
2769 if (sRefSet_member (otheruses, thisset))
2771 if (sRef_isUnconstrained (thisset))
2774 (FLG_EVALORDERUNCON,
2776 ("Unconstrained functions used in arguments %d (%q) "
2777 "and %d (%s) may modify "
2778 "or use global state in undefined way: %s(%q)",
2780 sRefSet_unparseUnconstrainedPlain (otheruses),
2782 sRef_unconstrainedName (thisset),
2783 exprNode_unparse (f),
2784 exprNodeList_unparse (args)),
2792 ("Argument %d modifies %q, used by argument %d "
2793 "(order of evaluation of actual parameters is "
2794 "undefined): %s(%q)",
2795 argno, sRef_unparse (thisset), thisargno,
2796 exprNode_unparse (f), exprNodeList_unparse (args)),
2802 sRefSet othersets = jl->sets;
2804 if (sRefSet_member (othersets, thisset))
2806 if (sRef_isUnconstrained (thisset))
2809 (FLG_EVALORDERUNCON,
2811 ("Unconstrained functions used in "
2812 "arguments %d (%q) and %d (%s) may modify "
2813 "or use global state in undefined way: %s(%q)",
2815 sRefSet_unparseUnconstrainedPlain (othersets),
2817 sRef_unconstrainedName (thisset),
2818 exprNode_unparse (f), exprNodeList_unparse (args)),
2826 ("Argument %d modifies %q, set by argument %d (order of"
2827 " evaluation of actual parameters is undefined): %s(%q)",
2828 argno, sRef_unparse (thisset), thisargno,
2829 exprNode_unparse (f), exprNodeList_unparse (args)),
2836 /*@noaccess exprNodeList@*/
2837 } end_sRefSet_realElements;
2842 checkSequencing (exprNode f, exprNodeList args)
2844 if (exprNodeList_size (args) > 1)
2849 /*@access exprNodeList*/
2851 for (i = 0; i < args->nelements; i++)
2853 el = args->elements[i];
2855 if (!exprNode_isError (el))
2857 checkSequencingOne (f, args, el, i + 1);
2860 /*@noaccess exprNodeList*/
2865 ** requires le = exprNode_getUentry (f)
2869 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2870 uentry le, exprNodeList args,
2871 /*@notnull@*/ exprNode ret, int specialArgs)
2873 bool isSpec = FALSE;
2874 bool hasMods = FALSE;
2876 globSet usesGlobs = globSet_undefined;
2877 sRefSet mods = sRefSet_undefined;
2878 bool freshMods = FALSE;
2879 uentryList params = uentryList_undefined;
2881 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2884 ** check globals and modifies
2889 if (!uentry_isValid (le))
2891 ctype fr = ctype_realType (f->typ);
2893 if (ctype_isFunction (fr))
2895 params = ctype_argsFunction (fr);
2899 params = uentryList_missingParams;
2902 if (!context_getFlag (FLG_MODNOMODS)
2903 && !context_getFlag (FLG_GLOBUNSPEC))
2905 checkUnspecCall (f, params, args);
2911 fname = uentry_rawName (le);
2915 if (uentry_isFunction (le))
2917 params = uentry_getParams (le);
2918 mods = uentry_getMods (le);
2919 hasMods = uentry_hasMods (le);
2920 usesGlobs = uentry_getGlobs (le);
2921 isSpec = uentry_isSpecified (le);
2923 else /* not a function */
2925 ctype ct = ctype_realType (uentry_getType (le));
2927 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2928 ("checkModGlobs: uentry not a function: %s",
2929 uentry_unparse (le)));
2931 params = ctype_argsFunction (ct);
2932 return; /* No checking for non-function */
2941 globSet_allElements (usesGlobs, el)
2943 if (sRef_isValid (el))
2945 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2947 context_usedGlobal (el);
2948 exprNode_checkUse (f, el, f->loc);
2950 if (context_checkInternalUse ())
2952 if (!context_globAccess (el))
2954 if (sRef_isSystemState (el)
2955 && !context_getFlag (FLG_MODFILESYSTEM))
2964 ("Called procedure %s may access %q, but "
2965 "globals list does not include globals %s",
2966 exprNode_unparse (f),
2968 cstring_makeLiteralTemp (sRef_isInternalState (el)
2976 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2982 uentry gle = sRef_getUentry (el);
2983 sRef sr = sRef_updateSref (el);
2985 if (sRef_isUndefGlob (el))
2987 sRef_setDefined (sr, f->loc);
2988 exprNode_checkSet (f, sr);
2996 if (sRef_isAllocated (el))
2998 exprNode_checkSet (f, sr);
3002 if (sRef_isStateUndefined (sr))
3007 ("%s %q used by function undefined before call: %s",
3008 sRef_getScopeName (sr),
3010 exprNode_unparse (f)),
3012 sRef_setDefined (sr, f->loc);
3014 exprNode_checkUse (f, sr, f->loc);
3017 checkGlobUse (gle, TRUE, f);
3020 if (sRef_isKilledGlob (el))
3022 sRef_kill (sr, f->loc);
3023 context_usedGlobal (sr);
3027 } end_globSet_allElements;
3033 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
3035 sRefSet smods = sRefSet_undefined;
3038 ** NEED to check for modifies anything
3042 ** check each sRef that called function modifies (ml), is
3048 sRefSet_allElements (mods, s) /* s is something which may be modified */
3050 DPRINTF (("Check modify: %s", sRef_unparse (s)));
3052 if (sRef_isKindSpecial (s))
3054 if (sRef_isSpecInternalState (s))
3056 if (context_getFlag (FLG_MODINTERNALSTRICT))
3058 exprNode_checkCallModifyVal (s, args, f, ret);
3062 sRefSet mmods = context_modList ();
3064 sRefSet_allElements (mmods, el)
3066 if (sRef_isInternalState (el))
3068 sRef_setModified (el);
3070 } end_sRefSet_allElements ;
3075 exprNode_checkCallModifyVal (s, args, f, ret);
3080 sRef rb = sRef_getRootBase (s);
3082 if (sRef_isFileOrGlobalScope (rb))
3084 context_usedGlobal (rb);
3087 if (sRef_isFileStatic (s)
3088 && !fileId_equal (fileloc_fileId (f->loc),
3089 fileloc_fileId (uentry_whereDefined (le))))
3091 smods = sRefSet_insert (smods, s);
3095 exprNode_checkCallModifyVal (s, args, f, ret);
3098 } end_sRefSet_allElements;
3103 ** Static elements in modifies set can have nasty consequences.
3104 ** (I think...have not been able to reproduce a possible bug.)
3107 if (!sRefSet_isDefined (smods))
3109 mods = sRefSet_newCopy (mods);
3112 sRefSet_allElements (smods, el)
3114 bool res = sRefSet_delete (mods, el);
3117 } end_sRefSet_allElements;
3119 sRefSet_free (smods);
3124 else if (sRefSet_isDefined (mods))
3125 { /* just check observers */
3128 sRefSet_allElements (mods, s) /* s is something which may be modified */
3130 sRef rb = sRef_getRootBase (s);
3134 if (sRef_isParam (rb))
3136 sRef b = sRef_fixBaseParam (s, args);
3138 if (sRef_isObserver (b))
3140 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
3144 message ("Function call may modify observer%q: %s",
3145 sRef_unparsePreOpt (b), exprNode_unparse (e)),
3148 sRef_showExpInfo (b);
3152 } end_sRefSet_allElements;
3156 if (!hasMods) /* no specified modifications */
3158 if (context_getFlag (FLG_MODOBSERVERUNCON))
3160 exprNodeList_elements (args, e)
3162 if (exprNode_isDefined (e))
3164 sRef s = exprNode_getSref (e);
3166 if (sRef_isObserver (s)
3167 && ctype_isMutable (sRef_getType (s)))
3170 (FLG_MODOBSERVERUNCON,
3172 ("Call to unconstrained function %s may modify observer%q: %s",
3173 exprNode_unparse (f),
3174 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3177 sRef_showExpInfo (s);
3181 } end_exprNodeList_elements;
3186 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3188 ret->uses = sRefSet_union (ret->uses, f->uses);
3189 ret->sets = sRefSet_union (ret->sets, f->sets);
3190 ret->msets = sRefSet_union (ret->msets, f->msets);
3195 ** Spurious errors reported, because splint can't tell
3196 ** mods must be fresh if freshMods is true.
3199 /*@i@*/ sRefSet_free (mods);
3205 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3207 if (uentry_isVar (glob))
3209 if (context_inFunctionLike ())
3211 sRef sr = uentry_getSref (glob);
3213 context_usedGlobal (sr);
3215 if (context_checkGlobUse (glob))
3217 if (!context_globAccess (sr))
3223 message ("Called procedure %s may access %s %q",
3224 exprNode_unparse (e),
3225 sRef_unparseScope (sr),
3226 uentry_getName (glob)),
3233 message ("Undocumented use of %s %s",
3234 sRef_unparseScope (sr),
3235 exprNode_unparse (e)),
3244 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3249 reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
3251 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3252 exprNode_unparse (f), exprNodeList_unparse (args),
3253 uentry_unparseFull (le),
3254 stateClauseList_unparse (uentry_getStateClauseList (le))));
3256 if (uentry_isValid (le) && uentry_isFunction (le))
3258 stateClauseList sclauses = uentry_getStateClauseList (le);
3260 if (stateClauseList_isDefined (sclauses))
3262 DPRINTF (("Reflect ensures: %s / %s / %s",
3263 uentry_unparse (le),
3264 exprNode_unparse (f), exprNodeList_unparse (args)));
3266 stateClauseList_elements (sclauses, cl)
3268 if (stateClause_hasEnsures (cl))
3270 /* Same in usymtab.c:1904 */
3271 if (stateClause_setsMetaState (cl))
3273 qual q = stateClause_getMetaQual (cl);
3274 annotationInfo ainfo = qual_getAnnotationInfo (q);
3275 metaStateInfo minfo = annotationInfo_getState (ainfo);
3276 cstring key = metaStateInfo_getName (minfo);
3277 int mvalue = annotationInfo_getValue (ainfo);
3279 sRefSet osrs = sRefSet_undefined;
3282 if (stateClause_isGlobal (cl))
3284 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3289 srs = stateClause_getRefs (cl);
3292 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3295 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3297 sRefSet_elements (srs, sel)
3301 if (sRef_isResult (sRef_getRootBase (sel)))
3303 s = exprNode_getSref (ret);
3307 s = sRef_fixBaseParam (sel, args);
3310 DPRINTF (("Reflecting state clause on: %s / %s",
3311 sRef_unparse (sel), sRef_unparse (s)));
3313 sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3314 } end_sRefSet_elements;
3316 sRefSet_free (osrs);
3320 sRefSet srs = stateClause_getRefs (cl);
3321 sRefModVal modf = stateClause_getEnsuresFunction (cl);
3322 int eparam = stateClause_getStateParameter (cl);
3324 llassert (modf != NULL);
3326 DPRINTF (("Reflect after clause: %s / %s",
3327 stateClause_unparse (cl),
3328 sRefSet_unparse (srs)));
3330 sRefSet_elements (srs, sel)
3334 DPRINTF (("elements: %s", sRef_unparse (sel)));
3335 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3337 if (sRef_isResult (sRef_getRootBase (sel)))
3339 DPRINTF (("Fix base: %s / %s",
3340 sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
3341 s = sRef_fixBase (sel, exprNode_getSref (ret));
3342 DPRINTF (("==> %s", sRef_unparseFull (s)));
3346 s = sRef_fixBaseParam (sel, args);
3349 DPRINTF (("elements: %s", sRef_unparse (s)));
3350 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3352 DPRINTF (("Reflecting state clause on: %s / %s",
3353 sRef_unparseFull (sel), sRef_unparseFull (s)));
3355 /* evans 2001-08-24 - added aliasSetCompleteParam */
3356 sRef_aliasSetCompleteParam (modf, s, eparam, exprNode_loc (f));
3358 DPRINTF (("After reflecting state clause on: %s / %s",
3359 sRef_unparseFull (sel), sRef_unparseFull (s)));
3360 } end_sRefSet_elements;
3363 } end_stateClauseList_elements ;
3366 DPRINTF (("Here: %s / %s",
3367 uentry_unparseFull (le),
3368 bool_unparse (uentry_hasMetaStateEnsures (le))));
3370 if (uentry_hasMetaStateEnsures (le))
3372 fileloc loc = exprNode_loc (f);
3374 metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3376 metaStateConstraintList_elements (mscl, msc)
3378 metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3379 metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3380 metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
3381 cstring key = metaStateInfo_getName (msinfo);
3382 sRef mlsr = metaStateSpecifier_getSref (msspec);
3384 sRef lastref = sRef_undefined;
3385 stateValue sval = stateValue_undefined;
3387 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3388 metaStateConstraint_unparse (msc)));
3389 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3391 if (sRef_isResult (sRef_getRootBase (mlsr)))
3393 s = exprNode_getSref (ret);
3397 s = sRef_fixBaseParam (mlsr, args);
3400 DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3402 while (metaStateExpression_isDefined (msexpr))
3404 metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
3405 metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
3408 DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3410 if (metaStateExpression_isMerge (msexpr))
3412 msexpr = metaStateExpression_getRest (msexpr);
3416 msexpr = metaStateExpression_undefined;
3419 if (metaStateInfo_isDefined (msi))
3421 /* Must match lhs state */
3422 llassert (metaStateInfo_equal (msinfo, msi));
3425 if (metaStateSpecifier_isElipsis (ms))
3428 ** For elipsis, we need to merge all the relevant elipsis parameters
3432 uentryList params = uentry_getParams (le);
3433 int paramno = uentryList_size (params) - 1;
3435 if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
3439 message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3440 uentry_getName (le)),
3441 uentry_whereLast (le));
3442 /*@innerbreak@*/ break;
3445 while (paramno < exprNodeList_size (args))
3447 exprNode arg = exprNodeList_getN (args, paramno);
3448 fs = exprNode_getSref (arg);
3449 DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3451 /* cut and pasted... gack*/
3452 if (stateValue_isDefined (sval))
3454 /* Use combination table to merge old state value with new one: */
3455 stateValue tval = sRef_getMetaStateValue (fs, key);
3457 if (stateValue_isDefined (tval))
3459 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3460 cstring msg = cstring_undefined;
3461 int nval = stateCombinationTable_lookup (sctable,
3462 stateValue_getValue (sval),
3463 stateValue_getValue (tval),
3465 DPRINTF (("Combining: %s + %s -> %d",
3466 stateValue_unparseValue (sval, msinfo),
3467 stateValue_unparseValue (tval, msinfo),
3470 if (nval == stateValue_error)
3475 ("Attributes merged in ensures clause in states that "
3476 "cannot be combined (%q is %q, %q is %q)%q",
3477 sRef_unparse (lastref),
3478 stateValue_unparseValue (sval, msinfo),
3480 stateValue_unparseValue (tval, msinfo),
3481 cstring_isDefined (msg) ?
3482 message (": %s", msg) : cstring_undefined),
3485 sRef_showMetaStateInfo (fs, key);
3489 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3490 loc = exprNode_loc (arg);
3494 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3499 sval = sRef_getMetaStateValue (fs, key);
3504 if (stateValue_isError (sval))
3506 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3515 msr = metaStateSpecifier_getSref (ms);
3518 llassert (sRef_isParam (sRef_getRootBase (msr)));
3519 fs = sRef_fixBaseParam (msr, args);
3521 if (stateValue_isDefined (sval))
3523 /* Use combination table to merge old state value with new one: */
3524 stateValue tval = sRef_getMetaStateValue (fs, key);
3526 if (stateValue_isDefined (tval))
3528 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3529 cstring msg = cstring_undefined;
3530 int nval = stateCombinationTable_lookup (sctable,
3531 stateValue_getValue (sval),
3532 stateValue_getValue (tval),
3534 DPRINTF (("Combining: %s + %s -> %d",
3535 stateValue_unparseValue (sval, msinfo),
3536 stateValue_unparseValue (tval, msinfo),
3539 if (nval == stateValue_error)
3544 ("Attributes merged in ensures clause in states that "
3545 "cannot be combined (%q is %q, %q is %q)%q",
3546 sRef_unparse (lastref),
3547 stateValue_unparseValue (sval, msinfo),
3549 stateValue_unparseValue (tval, msinfo),
3550 cstring_isDefined (msg)
3551 ? message (": %s", msg) : cstring_undefined),
3554 sRef_showMetaStateInfo (fs, key);
3558 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3562 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3567 sval = sRef_getMetaStateValue (fs, key);
3572 if (stateValue_isError (sval))
3574 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3579 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3581 if (stateValue_isDefined (sval))
3583 sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
3587 DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
3589 } end_metaStateConstraintList_elements ;
3591 metaStateConstraintList_free (mscl);
3597 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3599 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3600 exprNode_unparse (f), exprNodeList_unparse (args),
3601 uentry_unparseFull (le),
3602 stateClauseList_unparse (uentry_getStateClauseList (le))));
3604 if (uentry_isValid (le) && uentry_isFunction (le))
3606 stateClauseList sclauses = uentry_getStateClauseList (le);
3608 if (stateClauseList_isDefined (sclauses))
3610 DPRINTF (("Check requires: %s / %s / %s",
3611 uentry_unparse (le),
3612 exprNode_unparse (f), exprNodeList_unparse (args)));
3614 stateClauseList_elements (sclauses, cl)
3616 DPRINTF (("Check clause: %s / %s",
3617 stateClause_unparse (cl),
3618 bool_unparse (stateClause_hasRequires (cl))));
3620 if (stateClause_hasRequires (cl))
3622 sRefSet osrs = sRefSet_undefined;
3625 if (stateClause_isGlobal (cl))
3627 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3632 srs = stateClause_getRefs (cl);
3635 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3637 if (stateClause_setsMetaState (cl))
3639 qual q = stateClause_getMetaQual (cl);
3640 annotationInfo ainfo = qual_getAnnotationInfo (q);
3641 metaStateInfo minfo = annotationInfo_getState (ainfo);
3642 cstring key = metaStateInfo_getName (minfo);
3643 int mvalue = annotationInfo_getValue (ainfo);
3645 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3647 sRefSet_elements (srs, sel)
3649 sRef s = sRef_fixBaseParam (sel, args);
3651 if (sRef_isResult (sRef_getRootBase (sel)))
3657 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3658 sRef_unparseFull (sel), sRef_unparseFull (s),
3661 if (!sRef_checkMetaStateValue (s, key, mvalue))
3663 DPRINTF (("HERE: %s", sRef_unparse (s)));
3667 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3668 uentry_getName (le),
3669 sRef_isGlobalMarker (s)
3671 : message (" by %q", sRef_unparse (s)),
3672 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3674 stateClause_unparse (cl)),
3677 sRef_showAliasInfo (s);
3681 DPRINTF (("Error supressed!"));
3682 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3683 DPRINTF (("Context supress: %s",
3684 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3688 } end_sRefSet_elements;
3692 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3693 int eparam = stateClause_getStateParameter (cl);
3695 DPRINTF (("Reflect after clause: %s / %s",
3696 stateClause_unparse (cl),
3697 sRefSet_unparse (srs)));
3699 llassert (modf != NULL);
3701 sRefSet_elements (srs, sel)
3705 DPRINTF (("elements: %s", sRef_unparse (sel)));
3706 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3708 s = sRef_fixBaseParam (sel, args);
3710 DPRINTF (("elements: %s", sRef_unparse (s)));
3711 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3713 if (sRef_isResult (sRef_getRootBase (sel)))
3715 ; /* what do we do about results? */
3719 DPRINTF (("Reflecting state clause on: %s / %s",
3720 sRef_unparse (sel), sRef_unparse (s)));
3722 modf (s, eparam, exprNode_loc (f));
3724 } end_sRefSet_elements;
3727 sRefSet_free (osrs);
3729 } end_stateClauseList_elements ;
3734 static /*@only@*/ exprNode
3735 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3736 ctype t, /*@keep@*/ exprNodeList args)
3738 /* requires f is a non-error exprNode, with type function */
3739 cstring fname = exprNode_unparse (f);
3740 uentry le = exprNode_getUentry (f);
3741 exprNode ret = exprNode_createPartialCopy (f);
3746 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3748 ret->typ = ctype_getReturnType (t);
3749 ret->kind = XPR_CALL;
3751 ret->edata = exprData_makeCall (f, args);
3754 ** Order of these steps is very important!
3756 ** Must check for argument dependencies before messing up uses and sets.
3759 if (context_getFlag (FLG_EVALORDER))
3761 exprNodeList_elements (args, current)
3763 if (exprNode_isDefined (current))
3765 exprNode_addUse (current, current->sref);
3767 } end_exprNodeList_elements;
3769 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3771 checkSequencing (f, args);
3774 exprNodeList_elements (args, current)
3776 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3778 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3780 } end_exprNodeList_elements ;
3783 special = checkArgs (le, f, t, args, ret);
3784 checkGlobMods (f, le, args, ret, special);
3785 checkRequiresClause (le, f, args);
3788 if (uentry_isValid (le)
3789 && (uentry_isFunction (le)
3790 || (uentry_isVariable (le)
3791 && ctype_isFunction (uentry_getType (le)))))
3793 exitkind exk = uentry_getExitCode (le);
3795 /* f->typ is already set to the return type */
3797 DPRINTF (("Function: %s", uentry_unparseFull (le)));
3798 ret->sref = uentry_returnedRef (le, args, exprNode_loc (f));
3799 DPRINTF (("Returned: %s / %s",
3800 uentry_unparseFull (le),
3801 sRef_unparseFull (ret->sref)));
3803 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3805 qual nullPred = uentry_nullPred (le);
3807 if (qual_isTrueNull (nullPred))
3809 exprNode arg = exprNodeList_head (args);
3811 if (exprNode_isDefined (arg))
3813 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3816 else if (qual_isFalseNull (nullPred))
3818 exprNode arg = exprNodeList_head (args);
3820 if (exprNode_isDefined (arg))
3822 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3827 llassert (qual_isUnknown (nullPred));
3831 if (exitkind_isConditionalExit (exk))
3835 ** if (arg0) then { exit! } else { ; }
3837 ** if (arg0) then { ; } else { exit! }
3842 llassert (!exprNodeList_isEmpty (args));
3843 firstArg = exprNodeList_head (args);
3845 if (exprNode_isDefined (firstArg)
3846 && !guardSet_isEmpty (firstArg->guards))
3848 usymtab_trueBranch (guardSet_undefined);
3849 usymtab_altBranch (guardSet_undefined);
3851 if (exitkind_isTrueExit (exk))
3853 usymtab_popBranches (firstArg,
3854 exprNode_makeMustExit (),
3856 TRUE, TRUEEXITCLAUSE);
3860 usymtab_popBranches (firstArg,
3862 exprNode_makeMustExit (),
3863 TRUE, FALSEEXITCLAUSE);
3867 ret->exitCode = XK_MAYEXIT;
3869 else if (exitkind_mustExit (exk))
3871 ret->exitCode = XK_MUSTEXIT;
3873 else if (exitkind_couldExit (exk))
3875 ret->exitCode = XK_MAYEXIT;
3882 if (cstring_equalLit (fname, "exit"))
3884 if (exprNodeList_size (args) == 1)
3886 exprNode arg = exprNodeList_head (args);
3888 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3890 long int val = multiVal_forceInt (exprNode_getValue (arg));
3897 ("Argument to exit has implementation defined behavior: %s",
3898 exprNode_unparse (arg)),
3899 exprNode_loc (arg));
3907 ret->sref = sRef_undefined;
3908 exprNode_checkSetAny (ret, uentry_rawName (le));
3911 DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3912 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3913 reflectEnsuresClause (ret, le, f, args);
3916 DPRINTF (("Here: %s", sRef_unparseFull (ret->sref)));
3921 ** this is yucky! should keep the uentry as part of exprNode!
3924 uentry exprNode_getUentry (exprNode e)
3926 if (exprNode_isError (e))
3928 return uentry_undefined;
3932 cstring s = exprNode_rootVarName (e);
3933 uentry ue = usymtab_lookupSafe (s);
3940 ** Returns true iff e1 and e2 are both exactly the same storage
3944 static bool exprNode_sameStorage (exprNode e1, exprNode e2)
3946 sRef s1 = exprNode_getSref (e1);
3947 sRef s2 = exprNode_getSref (e2);
3949 return (sRef_realSame (s1, s2));
3953 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3955 exprNode ret = exprNode_createPlain (ctype_unknown);
3957 ret->kind = XPR_INITBLOCK;
3958 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3959 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3965 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3970 usymtab_checkAllValid ();
3973 if (exprNode_isUndefined (f))
3976 exprNodeList_free (args);
3977 return exprNode_undefined;
3980 t = exprNode_getType (f);
3982 if (sRef_isLocalVar (f->sref))
3984 exprNode_checkUse (f, f->sref, f->loc);
3986 if (sRef_possiblyNull (f->sref))
3988 if (!usymtab_isGuarded (f->sref))
3990 if (optgenerror (FLG_NULLDEREF,
3991 message ("Function call using %s pointer %q",
3992 sRef_nullMessage (f->sref),
3993 sRef_unparse (f->sref)),
3996 sRef_showNullInfo (f->sref);
3997 sRef_setNullError (f->sref);
4005 if (ctype_isRealFunction (t))
4007 exprNode ret = functionCallSafe (f, t, args);
4011 else if (ctype_isUnknown (t))
4013 exprNode ret = exprNode_createPartialCopy (f);
4019 exprNodeList_elements (args, current)
4021 if (exprNode_isDefined (current))
4023 exprNode_checkUse (ret, current->sref, ret->loc);
4026 ** also, anything derivable from current->sref may be used
4029 exprNode_addUse (ret, sRef_makeDerived (current->sref));
4030 exprNode_mergeUSs (ret, current);
4032 } end_exprNodeList_elements;
4034 ret->edata = exprData_makeCall (f, args);
4035 ret->kind = XPR_CALL;
4037 tstring = cstring_copy (exprNode_unparse (f));
4039 cstring_markOwned (tstring);
4040 exprNode_checkSetAny (ret, tstring);
4046 voptgenerror (FLG_TYPE,
4047 message ("Call to non-function (type %t): %s", t,
4048 exprNode_unparse (f)),
4051 exprNodeList_free (args);
4053 return (exprNode_makeError ());
4058 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4059 /*@only@*/ cstring f)
4061 exprNode ret = exprNode_createPartialCopy (s);
4063 ret->kind = XPR_FACCESS;
4065 if (exprNode_isError (s))
4067 ret->edata = exprData_makeField (s, f);
4072 ctype t = exprNode_getType (s);
4073 ctype tr = ctype_realType (t);
4075 checkMacroParen (s);
4077 ret->edata = exprData_makeField (s, f);
4079 if (ctype_isStructorUnion (tr))
4081 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
4083 if (uentry_isUndefined (tf))
4085 voptgenerror (FLG_TYPE,
4086 message ("Access non-existent field %s of %t: %s", f, t,
4087 exprNode_unparse (ret)),
4089 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
4094 uentry_setUsed (tf, exprNode_loc (ret));
4096 ret->typ = uentry_getType (tf);
4097 checkSafeUse (ret, s->sref);
4099 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
4100 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
4104 else /* isStructorUnion */
4106 if (ctype_isRealAbstract (tr))
4110 message ("Access field of abstract type (%t): %s.%s",
4111 t, exprNode_unparse (s), f),
4113 ret->typ = ctype_unknown;
4117 if (ctype_isKnown (tr))
4122 ("Access field of non-struct or union (%t): %s.%s",
4123 t, exprNode_unparse (s), f),
4126 ret->typ = ctype_unknown;
4130 cstring sn = cstring_copy (f);
4132 checkSafeUse (ret, s->sref);
4133 cstring_markOwned (sn);
4134 ret->sref = sRef_makeField (s->sref, sn);
4146 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
4147 /*@only@*/ cstring f)
4149 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
4155 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
4157 exprNode ret = exprNode_createPartialCopy (e);
4159 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
4160 ret->kind = XPR_PARENS;
4161 ret->edata = exprData_makeUop (e, lpar);
4163 if (!exprNode_isError (e))
4165 ret->exitCode = e->exitCode;
4166 ret->canBreak = e->canBreak;
4167 ret->mustBreak = e->mustBreak;
4168 ret->isJumpPoint = e->isJumpPoint;
4169 ret->sref = e->sref;
4176 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4177 /*@only@*/ cstring f)
4179 exprNode ret = exprNode_createPartialCopy (s);
4181 ret->edata = exprData_makeField (s, f);
4182 ret->kind = XPR_ARROW;
4184 if (exprNode_isError (s))
4190 ctype t = exprNode_getType (s);
4191 ctype tr = ctype_realType (t);
4193 checkMacroParen (s);
4195 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4197 if (ctype_isRealPointer (tr))
4199 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4201 if (ctype_isStructorUnion (b))
4203 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4205 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4207 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4211 message ("Arrow access from %s pointer%q: %s",
4212 sRef_nullMessage (s->sref),
4213 sRef_unparsePreOpt (s->sref),
4214 exprNode_unparse (ret)),
4217 sRef_showNullInfo (s->sref);
4218 sRef_setNullError (s->sref);
4223 if (uentry_isUndefined (fentry))
4227 message ("Access non-existent field %s of %t: %s",
4228 f, t, exprNode_unparse (ret)),
4230 ret->typ = ctype_unknown;
4236 ** was safeUse: shouldn't be safe!
4239 ** rec must be defined,
4240 ** *rec must be allocated
4241 ** rec->field need only be defined it if is an rvalue
4244 uentry_setUsed (fentry, exprNode_loc (ret));
4245 ret->typ = uentry_getType (fentry);
4247 exprNode_checkUse (ret, s->sref, s->loc);
4249 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4250 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4254 else /* Pointer to something that is not a struct or union*/
4256 if (ctype_isRealAbstract (tr))
4258 ctype xrt = ctype_forceRealType (tr);
4262 message ("Arrow access field of abstract type (%t): %s->%s",
4263 t, exprNode_unparse (s), f),
4267 ** Set the state correctly, as if the abstraction is broken.
4270 if (ctype_isRealPointer (xrt) &&
4271 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4272 ctype_isStructorUnion (b)))
4274 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4275 ret->typ = uentry_getType (fentry);
4276 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4280 ret->typ = ctype_unknown;
4281 ret->sref = sRef_undefined;
4284 else /* not a struct, union or abstract */
4286 if (ctype_isUnknown (tr)) {
4287 cstring sn = cstring_copy (f);
4289 DPRINTF (("Here: %s", exprNode_unparse (s)));
4291 exprNode_checkUse (ret, s->sref, s->loc);
4292 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4294 cstring_markOwned (sn);
4295 ret->sref = sRef_makeArrow (s->sref, sn);
4297 ret->kind = XPR_ARROW;
4302 message ("Arrow access field of non-struct or union "
4303 "pointer (%t): %s->%s",
4304 t, exprNode_unparse (s), f),
4307 ret->typ = ctype_unknown;
4308 ret->sref = sRef_undefined;
4313 else /* its not a pointer */
4315 if (!ctype_isUnknown (tr))
4319 message ("Arrow access of non-pointer (%t): %s->%s",
4320 t, exprNode_unparse (s), f),
4323 ret->typ = ctype_unknown;
4324 ret->sref = sRef_undefined;
4328 cstring sn = cstring_copy (f);
4330 DPRINTF (("Here: %s", exprNode_unparse (s)));
4332 exprNode_checkUse (ret, s->sref, s->loc);
4333 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4335 cstring_markOwned (sn);
4336 ret->sref = sRef_makeArrow (s->sref, sn);
4338 ret->kind = XPR_ARROW;
4349 exprNode_arrowAccess (/*@only@*/ exprNode s,
4350 /*@only@*/ lltok arrow,
4351 /*@only@*/ cstring f)
4353 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4359 ** only postOp's in C: i++ and i--
4363 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4365 /* check modification also */
4366 /* cstring opname = lltok_unparse (op);*/
4368 exprNode ret = exprNode_createPartialCopy (e);
4370 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4371 ret->kind = XPR_POSTOP;
4372 ret->edata = exprData_makeUop (e, op);
4374 if (!exprNode_isDefined (e))
4379 checkMacroParen (e);
4381 exprNode_checkUse (ret, e->sref, e->loc);
4382 exprNode_checkSet (ret, e->sref);
4384 t = exprNode_getType (e);
4386 if (sRef_isUnsafe (e->sref))
4388 voptgenerror (FLG_MACROPARAMS,
4389 message ("Operand of %s is macro parameter (non-functional): %s%s",
4390 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4392 sRef_makeSafe (e->sref);
4393 sRef_makeSafe (ret->sref);
4396 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4402 if (ctype_isRealAbstract (t))
4404 if (ctype_isRealNumAbstract (t)) {
4405 ; /* Allow operations on numabstract types */
4409 message ("Operand of %s is abstract type (%t): %s",
4410 lltok_unparse (op), t, exprNode_unparse (e)),
4418 message ("Operand of %s is non-numeric (%t): %s",
4419 lltok_unparse (op), t, exprNode_unparse (e)),
4422 ret->typ = ctype_unknown;
4425 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4427 exprNode_checkModify (e, ret);
4429 /* added 7/11/2000 D.L */
4431 /* updateEnvironmentForPostOp (e); */
4433 /* start modifications */
4434 /* added by Seejo on 4/16/2000 */
4436 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4438 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4440 ret->sref = sRef_copy (e->sref);
4443 if (lltok_getTok (op) == INC_OP) {
4444 if (sRef_getSize(e->sref) > 0) {
4446 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4448 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4449 /* Assumption: there is only 1 \0 in the buffer */
4450 /* This will not be correct if there are 2 \0's in the buffer */
4451 sRef_setNotNullTerminatedState(ret->sref);
4452 sRef_resetLen(ret->sref);
4454 sRef_setNullTerminatedState(ret->sref);
4455 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4457 if (sRef_isNullTerminated (ret->sref))
4458 printf ("ret->sref is Null Terminated\n");
4459 else if (sRef_isPossiblyNullTerminated (ret->sref))
4460 printf ("ret->sref is Possibly Null Terminated\n");
4461 else if (sRef_isNotNullTerminated (ret->sref))
4462 printf ("ret->sref is Not Null Terminated\n");
4469 if (lltok_getTok (op) == DEC_OP) {
4470 if (sRef_getSize(e->sref) >= 0) {
4471 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4472 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4476 /* end modifications */
4482 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4484 bool checkMod = FALSE;
4486 int opid = lltok_getTok (op);
4487 exprNode ret = exprNode_createSemiCopy (e);
4489 exprNode_copySets (ret, e);
4491 multiVal_free (ret->val);
4492 ret->val = multiVal_undefined;
4493 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4494 ret->kind = XPR_PREOP;
4495 ret->edata = exprData_makeUop (e, op);
4497 if (exprNode_isError (e))
4502 checkMacroParen (e);
4504 te = exprNode_getType (e);
4505 tr = ctype_realType (te);
4507 if (opid != TAMPERSAND)
4509 exprNode_checkUse (ret, e->sref, e->loc);
4511 if (ctype_isRealAbstract (tr)
4512 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4514 if (ctype_isRealNumAbstract (tr))
4516 ; /* no warning for numabstract types */
4520 if (optgenerror (FLG_ABSTRACT,
4521 message ("Operand of %s is abstract type (%t): %s",
4522 lltok_unparse (op), tr,
4523 exprNode_unparse (ret)),
4526 tr = te = ctype_unknown;
4527 ret->typ = ctype_unknown;
4528 sRef_setNullError (e->sref);
4537 case DEC_OP: /* should also check modification! */
4538 if (sRef_isMacroParamRef (e->sref))
4542 message ("Operand of %s is macro parameter (non-functional): %s",
4543 lltok_unparse (op), exprNode_unparse (ret)),
4548 exprNode_checkSet (ret, e->sref);
4551 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4556 if (context_msgStrictOps ())
4560 message ("Operand of %s is non-numeric (%t): %s",
4561 lltok_unparse (op), te, exprNode_unparse (ret)),
4564 ret->typ = ctype_int;
4567 /* start modifications */
4568 /* added by Seejo on 4/16/2000 */
4570 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4572 if ((sRef_isPossiblyNullTerminated (e->sref))
4573 || (sRef_isNullTerminated(e->sref))) {
4574 ret->sref = sRef_copy (e->sref);
4577 if (lltok_getTok (op) == INC_OP) {
4578 if (sRef_getSize(e->sref) > 0) {
4580 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4582 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4583 /* Assumption: there is only 1 \0 in the buffer */
4584 /* This will not be correct if there are 2 \0's in the buffer */
4585 sRef_setNotNullTerminatedState(ret->sref);
4586 sRef_resetLen (ret->sref);
4588 sRef_setNullTerminatedState(ret->sref);
4589 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4595 if (lltok_getTok (op) == DEC_OP) {
4596 if (sRef_getSize(e->sref) >= 0) {
4597 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4598 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4603 /* end modifications */
4610 if (ctype_isForceRealNumeric (&tr))
4614 ret->val = multiVal_invert (exprNode_getValue (e));
4618 ret->val = multiVal_copy (exprNode_getValue (e));
4623 if (context_msgStrictOps ())
4627 message ("Operand of %s is non-numeric (%t): %s",
4628 lltok_unparse (op), te, exprNode_unparse (ret)),
4632 ret->typ = ctype_int;
4636 case TEXCL: /* maybe this should be restricted */
4637 guardSet_flip (ret->guards);
4639 if (ctype_isRealBool (te) || ctype_isUnknown (te))
4645 if (ctype_isRealPointer (tr))
4647 if (sRef_isKnown (e->sref))
4649 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4653 (FLG_BOOLOPS, FLG_PTRNEGATE,
4654 message ("Operand of %s is non-boolean (%t): %s",
4655 lltok_unparse (op), te, exprNode_unparse (ret)),
4662 message ("Operand of %s is non-boolean (%t): %s",
4663 lltok_unparse (op), te, exprNode_unparse (ret)),
4667 ret->typ = ctype_bool;
4672 if (ctype_isForceRealInt (&tr))
4677 if (context_msgStrictOps ())
4681 message ("Operand of %s is non-integer (%t): %s",
4682 lltok_unparse (op), te, exprNode_unparse (ret)),
4686 if (ctype_isInt (e->typ))
4692 ret->typ = ctype_int;
4698 ret->typ = ctype_makePointer (e->typ);
4700 if (sRef_isKnown (e->sref))
4702 ret->sref = sRef_makeAddress (e->sref);
4709 if (ctype_isAP (tr))
4711 ret->typ = ctype_baseArrayPtr (e->typ);
4715 if (ctype_isKnown (te))
4717 if (ctype_isFunction (te))
4723 message ("Dereference of function type (%t): %s",
4724 te, exprNode_unparse (ret)),
4729 voptgenerror (FLG_TYPE,
4730 message ("Dereference of non-pointer (%t): %s",
4731 te, exprNode_unparse (ret)),
4733 ret->typ = ctype_unknown;
4738 ret->typ = ctype_unknown;
4743 if (sRef_isKnown (e->sref))
4745 DPRINTF (("Checking possibly null: %s", sRef_unparseFull (e->sref)));
4747 if (sRef_possiblyNull (e->sref))
4749 DPRINTF (("Checking possibly null: %s", sRef_unparse (e->sref)));
4750 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4754 message ("Dereference of %s pointer %q: %s",
4755 sRef_nullMessage (e->sref),
4756 sRef_unparse (e->sref),
4757 exprNode_unparse (ret)),
4760 sRef_showNullInfo (e->sref);
4761 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4766 ret->sref = sRef_makePointer (e->sref);
4771 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4776 exprNode_checkModify (e, ret);
4783 ** any reason to disallow sizeof (abstract type) ?
4787 ** used by both sizeof
4791 ctype sizeof_resultType (void)
4793 static ctype sizet = ctype_unknown;
4795 if (ctype_isUnknown (sizet))
4797 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4799 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4803 sizet = ctype_ulint;
4810 exprNode_sizeofType (/*@only@*/ qtype qt)
4812 exprNode ret = exprNode_create (sizeof_resultType ());
4813 ctype ct = qtype_getType (qt);
4815 ret->kind = XPR_SIZEOFT;
4816 ret->edata = exprData_makeSizeofType (qt);
4818 voptgenerror (FLG_SIZEOFTYPE,
4819 message ("Parameter to sizeof is type %s: %s",
4821 exprNode_unparse (ret)),
4828 exprNode_alignofType (/*@only@*/ qtype qt)
4830 exprNode ret = exprNode_create (sizeof_resultType ());
4831 ctype ct = qtype_getType (qt);
4833 ret->kind = XPR_ALIGNOFT;
4834 ret->edata = exprData_makeSizeofType (qt);
4836 voptgenerror (FLG_SIZEOFTYPE,
4837 message ("Parameter to alignof is type %s: %s",
4839 exprNode_unparse (ret)),
4845 exprNode exprNode_offsetof (qtype qt, cstringList s)
4847 exprNode ret = exprNode_create (sizeof_resultType ());
4848 ctype ct = qtype_getType (qt);
4850 ret->kind = XPR_OFFSETOF;
4851 ret->edata = exprData_makeOffsetof (qt, s);
4853 if (!ctype_isRealSU (ct))
4855 voptgenerror (FLG_TYPE,
4856 message ("First parameter to offsetof is not a "
4857 "struct or union type (type %s): %s",
4859 exprNode_unparse (ret)),
4866 cstringList_elements (s, el) {
4870 if (ctype_isUndefined (lt))
4874 else if (!ctype_isRealSU (lt))
4876 voptgenerror (FLG_TYPE,
4877 message ("Inner offsetof type is not a "
4878 "struct or union type (type %s before field %s): %s",
4879 ctype_unparse (lt), el,
4880 exprNode_unparse (ret)),
4886 fields = ctype_getFields (ctype_realType (lt));
4887 fld = uentryList_lookupField (fields, el);
4888 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4890 if (uentry_isUndefined (fld))
4892 if (ctype_equal (lt, ct)) {
4893 voptgenerror (FLG_TYPE,
4894 message ("Field %s in offsetof is not the "
4895 "name of a field of %s: %s",
4898 exprNode_unparse (ret)),
4901 voptgenerror (FLG_TYPE,
4902 message ("Deep field %s in offsetof is not the "
4903 "name of a field of %s: %s",
4906 exprNode_unparse (ret)),
4912 lt = uentry_getType (fld);
4915 } end_cstringList_elements;
4917 /* Should report error if its a bit field - behavior is undefined! */
4924 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4928 if (exprNode_isUndefined (e))
4930 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4931 ret->edata = exprData_makeSingle (e);
4932 ret->typ = sizeof_resultType ();
4933 ret->kind = XPR_SIZEOF;
4937 uentry u = exprNode_getUentry (e);
4939 ret = exprNode_createPartialCopy (e);
4940 ret->edata = exprData_makeSingle (e);
4942 ret->typ = sizeof_resultType ();
4943 ret->kind = XPR_SIZEOF;
4945 if (uentry_isValid (u)
4946 && uentry_isRefParam (u)
4947 && ctype_isRealArray (uentry_getType (u)))
4950 (FLG_SIZEOFFORMALARRAY,
4951 message ("Parameter to sizeof is an array-type function parameter: %s",
4952 exprNode_unparse (ret)),
4958 ** sizeof (x) doesn't "really" use x
4965 exprNode_alignofExpr (/*@only@*/ exprNode e)
4969 if (exprNode_isUndefined (e))
4971 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4975 ret = exprNode_createPartialCopy (e);
4978 ret->edata = exprData_makeSingle (e);
4979 ret->typ = sizeof_resultType ();
4980 ret->kind = XPR_ALIGNOF;
4983 ** sizeof (x) doesn't "really" use x
4990 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4996 if (exprNode_isError (e))
5000 return exprNode_undefined;
5003 checkMacroParen (e);
5005 c = qtype_getType (q);
5006 t = exprNode_getType (e);
5008 ret = exprNode_createPartialCopy (e);
5010 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
5012 ret->kind = XPR_CAST;
5013 ret->edata = exprData_makeCast (tok, e, q);
5015 ret->sref = sRef_copy (e->sref);
5017 DPRINTF (("Cast: -> %s", sRef_unparseFull (ret->sref)));
5019 if (!sRef_isConst (e->sref))
5021 usymtab_addForceMustAlias (ret->sref, e->sref);
5024 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
5025 sRef_setTypeFull (ret->sref, c);
5026 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
5032 ** void * <-> abstract * (if FLG_ABSTVOIDP)
5033 ** abstract * <-> void * (if FLG_ABSTVOIDP)
5036 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
5038 /* evans 2002-07-19: added this warning */
5039 DPRINTF (("Checking: %s / %s", exprNode_unparse (ret), sRef_unparseFull (ret->sref)));
5040 if (sRef_isFresh (ret->sref))
5044 message ("New fresh storage %q(type %s) cast to void (not released): %s",
5045 sRef_unparseOpt (ret->sref),
5046 ctype_unparse (exprNode_getType (ret)),
5047 exprNode_unparse (ret)),
5048 exprNode_loc (ret));
5051 else if (ctype_isRealAP (c)) /* casting to array or pointer */
5053 ctype bc = ctype_getBaseType (c);
5054 ctype bt = ctype_getBaseType (t);
5055 ctype rt = ctype_realType (t);
5057 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
5058 && (ctype_isArrayPtr (rt)
5059 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5063 message ("Cast from function pointer type (%t) to "
5064 "non-function pointer (%t): %s",
5065 c, t, exprNode_unparse (ret)),
5069 if (!ctype_isFunction (ctype_baseArrayPtr (c))
5070 && (ctype_isArrayPtr (rt)
5071 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5075 message ("Cast from non-function pointer type (%t) to "
5076 "function pointer (%t): %s",
5077 c, t, exprNode_unparse (ret)),
5081 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
5082 !(ctype_isRealAbstract (bc)
5083 && context_hasAccess (ctype_typeId (bc))))
5085 ; /* okay to cast zero */
5089 if (ctype_isRealAbstract (bc)
5090 && !context_hasAccess (ctype_typeId (bc)))
5092 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
5096 message ("Cast to underlying abstract type %t: %s",
5097 c, exprNode_unparse (ret)),
5104 message ("Cast to underlying abstract type %t: %s",
5105 c, exprNode_unparse (ret)),
5110 if (ctype_isRealAbstract (bt)
5111 && !context_hasAccess (ctype_typeId (bt)))
5113 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
5117 message ("Cast from underlying abstract type %t: %s",
5118 t, exprNode_unparse (ret)),
5125 message ("Cast from underlying abstract type %t: %s",
5126 t, exprNode_unparse (ret)),
5134 ctype bt = ctype_realType (ctype_getBaseType (t));
5135 ctype bc = ctype_realType (ctype_getBaseType (c));
5137 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
5139 if (ctype_match (c, t))
5141 if (ctype_equal (c, t))
5145 message ("Redundant cast involving abstract type %t: %s",
5146 bt, exprNode_unparse (ret)),
5154 message ("Cast from abstract type %t: %s",
5155 bt, exprNode_unparse (ret)),
5160 if (ctype_isAbstract (bc)
5161 && !context_hasAccess (ctype_typeId (bc)))
5163 if (ctype_match (c, t))
5169 if (ctype_isNumAbstract (bc))
5171 if (exprNode_isNumLiteral (e))
5174 (FLG_NUMABSTRACTCAST,
5175 message ("Cast from literal to numabstract type %t: %s", bc,
5176 exprNode_unparse (ret)),
5183 message ("Cast to numabstract type %t: %s", bc,
5184 exprNode_unparse (ret)),
5190 DPRINTF (("No access to: %s / %d",
5191 ctype_unparse (bc), ctype_typeId (bc)));
5192 DPRINTF (("Context %s %s",
5193 bool_unparse (context_inFunctionLike ()),
5194 context_unparse ()));
5197 message ("Cast to abstract type %t: %s", bc,
5198 exprNode_unparse (ret)),
5205 if (ctype_isAbstract (c))
5207 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
5209 /* okay, cast exposed to abstract */
5210 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
5214 if (ctype_isVisiblySharable (t)
5215 && sRef_isExternallyVisible (e->sref)
5216 && !(ctype_isAbstract (t)
5217 && context_hasAccess (ctype_typeId (t))))
5221 message ("Cast to abstract type from externally visible "
5222 "mutable storage exposes rep of %s: %s",
5224 exprNode_unparse (e)),
5234 evaluationOrderUndefined (lltok op)
5236 int opid = lltok_getTok (op);
5238 return (opid != AND_OP && opid != OR_OP);
5241 static bool checkIntegral (/*@notnull@*/ exprNode e1,
5242 /*@notnull@*/ exprNode e2,
5243 /*@notnull@*/ exprNode ret,
5248 ctype te1 = exprNode_getType (e1);
5249 ctype te2 = exprNode_getType (e2);
5251 ctype tr1 = ctype_realishType (te1);
5252 ctype tr2 = ctype_realishType (te2);
5254 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5260 if (context_msgStrictOps ())
5262 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5264 if (ctype_sameName (te1, te2))
5268 message ("Operands of %s are non-integer (%t): %s",
5269 lltok_unparse (op), te1,
5270 exprNode_unparse (ret)),
5277 message ("Operands of %s are non-integers (%t, %t): %s",
5278 lltok_unparse (op), te1, te2,
5279 exprNode_unparse (ret)),
5283 else if (!ctype_isInt (tr1))
5287 message ("Left operand of %s is non-integer (%t): %s",
5288 lltok_unparse (op), te1, exprNode_unparse (ret)),
5292 /* !ctype_isInt (te2) */
5296 message ("Right operand of %s is non-integer (%t): %s",
5297 lltok_unparse (op), te2, exprNode_unparse (ret)),
5307 ** returns exprNode representing e1 op e2
5309 ** uses msg if there are errors
5310 ** can be used for both assignment ops and regular ops
5315 static /*@only@*/ /*@notnull@*/ exprNode
5316 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
5317 /*@keep@*/ lltok op)
5319 ctype te1, te2, tr1, tr2, tret;
5320 int opid = lltok_getTok (op);
5321 bool hasError = FALSE;
5324 if (exprNode_isError (e1))
5326 ret = exprNode_createPartialNVCopy (e2);
5330 ret = exprNode_createPartialNVCopy (e1);
5333 ret->val = multiVal_undefined;
5336 ret->edata = exprData_makeOp (e1, e2, op);
5338 if (exprNode_isError (e1) || exprNode_isError (e2))
5340 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5341 || opid == EQ_OP || opid == NE_OP
5342 || opid == AND_OP || opid == OR_OP)
5344 ret->typ = ctype_bool;
5347 if (exprNode_isDefined (e1))
5349 exprNode_checkUse (ret, e1->sref, e1->loc);
5352 if (exprNode_isDefined (e2))
5354 exprNode_mergeUSs (ret, e2);
5355 exprNode_checkUse (ret, e2->sref, e2->loc);
5361 tret = ctype_unknown;
5362 te1 = exprNode_getType (e1);
5364 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5366 te2 = exprNode_getType (e2);
5368 tr1 = ctype_realishType (te1);
5369 tr2 = ctype_realishType (te2);
5373 exprNode_produceGuards (e2);
5374 ret->guards = guardSet_or (ret->guards, e2->guards);
5376 else if (opid == AND_OP)
5378 exprNode_produceGuards (e2); /* evans 2003-08-13: need to produce guards for expression */
5379 /* Shouldn't this have already happened? */
5380 DPRINTF (("Anding guards: %s / %s", guardSet_unparse (ret->guards), guardSet_unparse (e2->guards)));
5381 ret->guards = guardSet_and (ret->guards, e2->guards);
5388 if (opid == EQ_OP || opid == NE_OP)
5390 exprNode temp1 = e1, temp2 = e2;
5392 /* could do NULL == x */
5394 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5396 temp1 = e2; temp2 = e1;
5399 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5401 reflectNullTest (temp1, (opid == NE_OP));
5402 guardSet_free (ret->guards);
5403 ret->guards = guardSet_copy (temp1->guards);
5407 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5408 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5413 if (anyAbstract (tr1, tr2) &&
5414 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
5415 (opid == AND_OP || opid == OR_OP
5416 || opid == EQ_OP || opid == NE_OP))))
5418 if (abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc))
5420 tret = ctype_unknown;
5425 if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5427 /* unknown types, no comparisons possible */
5433 case TMULT: /* multiplication and division: */
5435 case MUL_ASSIGN: /* numeric, numeric -> numeric */
5436 case DIV_ASSIGN: /* */
5437 if (opid == TMULT || opid == MUL_ASSIGN)
5439 ret->val = multiVal_multiply (exprNode_getValue (e1),
5440 exprNode_getValue (e2));
5444 ret->val = multiVal_divide (exprNode_getValue (e1),
5445 exprNode_getValue (e2));
5448 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5451 case TPLUS: /* addition and subtraction: */
5452 case TMINUS: /* pointer, int -> pointer */
5453 case SUB_ASSIGN: /* int, pointer -> pointer */
5454 case ADD_ASSIGN: /* numeric, numeric -> numeric */
5455 if (opid == TPLUS || opid == ADD_ASSIGN)
5457 ret->val = multiVal_add (exprNode_getValue (e1),
5458 exprNode_getValue (e2));
5462 ret->val = multiVal_subtract (exprNode_getValue (e1),
5463 exprNode_getValue (e2));
5466 tr1 = ctype_fixArrayPtr (tr1);
5468 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5469 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5473 if (context_msgPointerArith ())
5477 message ("Pointer arithmetic (%t, %t): %s",
5478 te1, te2, exprNode_unparse (ret)),
5483 ** Swap terms so e1 is always the pointer
5486 if (ctype_isRealPointer (tr1))
5492 exprNode_swap (e1, e2);
5495 if (sRef_possiblyNull (e1->sref)
5496 && !usymtab_isGuarded (e1->sref))
5499 (FLG_NULLPOINTERARITH,
5500 message ("Pointer arithmetic involving possibly "
5501 "null pointer %s: %s",
5502 exprNode_unparse (e1),
5503 exprNode_unparse (ret)),
5507 ret->sref = sRef_copy (e1->sref);
5509 /* start modifications */
5510 /* added by Seejo on 4/16/2000 */
5512 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5514 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5517 added ugly fixed to stop
5518 program from crashing on point + int +int
5519 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5521 if (!multiVal_isInt (e2->val) )
5525 val = (int) multiVal_forceInt (e2->val);
5527 /* Operator : + or += */
5528 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5529 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5530 val should not result in a
5531 size < 0 (size = 0 is ok !) */
5533 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5535 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5536 sRef_setNotNullTerminatedState(ret->sref);
5537 sRef_resetLen (ret->sref);
5539 sRef_setNullTerminatedState(ret->sref);
5540 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5545 /* Operator : - or -= */
5546 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5547 if (sRef_getSize(e1->sref) >= 0) {
5548 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5549 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5554 /* end modifications */
5556 sRef_setNullError (ret->sref);
5559 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5560 ** since is points to storage that should not be deallocated
5561 ** through this pointer.
5564 if (sRef_isOnly (ret->sref)
5565 || sRef_isFresh (ret->sref))
5567 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5572 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5573 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5575 if (context_msgPointerArith ())
5579 message ("Pointer arithmetic (%t, %t): %s",
5580 te1, te2, exprNode_unparse (ret)),
5584 if (sRef_possiblyNull (e1->sref)
5585 && !usymtab_isGuarded (e1->sref))
5588 (FLG_NULLPOINTERARITH,
5589 message ("Pointer arithmetic involving possibly "
5590 "null pointer %s: %s",
5591 exprNode_unparse (e2),
5592 exprNode_unparse (ret)),
5596 ret->sref = sRef_copy (e2->sref);
5598 /* start modifications */
5599 /* added by Seejo on 4/16/2000 */
5601 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5604 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5605 if (multiVal_isDefined (e1->val))
5607 int val = (int) multiVal_forceInt (e1->val);
5609 /* Operator : + or += */
5610 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5611 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5612 val should not result in a
5613 size < 0 (size = 0 is ok !) */
5615 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5617 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5618 sRef_setNotNullTerminatedState(ret->sref);
5619 sRef_resetLen (ret->sref);
5621 sRef_setNullTerminatedState(ret->sref);
5622 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5627 /* Operator : - or -= */
5628 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5629 if (sRef_getSize(e2->sref) >= 0) {
5630 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5631 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5637 /* end modifications */
5639 sRef_setNullError (ret->sref);
5642 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5643 ** since is points to storage that should not be deallocated
5644 ** through this pointer.
5647 if (sRef_isOnly (ret->sref)
5648 || sRef_isFresh (ret->sref)) {
5649 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5653 ret->sref = e2->sref;
5657 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5666 case TAMPERSAND: /* bitwise & */
5668 case TCIRC: /* ^ (XOR) */
5673 bool reported = FALSE;
5679 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5680 || opid == RIGHT_OP || opid == RIGHT_ASSIGN)
5683 ** evans 2002-01-01: fixed this to follow ISO 6.5.7.
5686 if (!ctype_isUnsigned (tr2)
5687 && !exprNode_isNonNegative (e2))
5689 reported = optgenerror
5691 message ("Right operand of %s may be negative (%t): %s",
5692 lltok_unparse (op), te2,
5693 exprNode_unparse (ret)),
5697 if (!ctype_isUnsigned (tr1)
5698 && !exprNode_isNonNegative (e1))
5700 reported = optgenerror
5701 (FLG_SHIFTIMPLEMENTATION,
5702 message ("Left operand of %s may be negative (%t): %s",
5703 lltok_unparse (op), te1,
5704 exprNode_unparse (ret)),
5709 ** Should check size of right operand also...
5715 if (!ctype_isUnsigned (tr1))
5717 if (exprNode_isNonNegative (e1)) {
5720 reported = optgenerror
5722 message ("Left operand of %s is not unsigned value (%t): %s",
5723 lltok_unparse (op), te1,
5724 exprNode_unparse (ret)),
5734 if (!ctype_isUnsigned (tr2))
5736 if (!exprNode_isNonNegative (e2)) {
5737 reported = optgenerror
5739 message ("Right operand of %s is not unsigned value (%t): %s",
5740 lltok_unparse (op), te2,
5741 exprNode_unparse (ret)),
5750 if (!checkIntegral (e1, e2, ret, op)) {
5751 te1 = ctype_unknown;
5755 DPRINTF (("Set: %s", ctype_unparse (te1)));
5758 ** tret is the widest type of te1 and te2
5761 tret = ctype_widest (te1, te2);
5766 if (checkIntegral (e1, e2, ret, op)) {
5769 tret = ctype_unknown;
5774 case TLT: /* comparisons */
5775 case TGT: /* numeric, numeric -> bool */
5777 DPRINTF (("Here we go: %s / %s",
5778 ctype_unparse (tr1), ctype_unparse (tr2)));
5780 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5781 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5784 bool fepsilon = FALSE;
5786 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5791 if (opid == TLT || opid == TGT)
5793 uentry ue1 = exprNode_getUentry (e1);
5794 uentry ue2 = exprNode_getUentry (e2);
5797 ** FLT_EPSILON, etc. really is a variable, not
5801 if (uentry_isVariable (ue1))
5803 cstring uname = uentry_rawName (ue1);
5805 if (cstring_equalLit (uname, "FLT_EPSILON")
5806 || cstring_equalLit (uname, "DBL_EPSILON")
5807 || cstring_equalLit (uname, "LDBL_EPSILON"))
5813 if (uentry_isVariable (ue2))
5815 cstring uname = uentry_rawName (ue2);
5817 if (cstring_equalLit (uname, "FLT_EPSILON")
5818 || cstring_equalLit (uname, "DBL_EPSILON")
5819 || cstring_equalLit (uname, "LDBL_EPSILON"))
5828 ; /* Don't complain. */
5832 if (opid == EQ_OP || opid == NE_OP)
5836 message ("Dangerous equality comparison involving %s types: %s",
5837 ctype_unparse (rtype),
5838 exprNode_unparse (ret)),
5844 (FLG_REALRELATECOMPARE,
5845 message ("Possibly dangerous relational comparison involving %s types: %s",
5846 ctype_unparse (rtype),
5847 exprNode_unparse (ret)),
5857 ** Types should match.
5860 DPRINTF (("Match types: %s / %s", exprNode_unparse (e1),
5861 exprNode_unparse (e2)));
5863 if (!exprNode_matchTypes (e1, e2))
5865 hasError = gentypeerror
5867 message ("Operands of %s have incompatible types (%t, %t): %s",
5868 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5874 || (ctype_isForceRealNumeric (&tr1)
5875 && ctype_isForceRealNumeric (&tr2)) ||
5876 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5882 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5883 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5887 message ("Comparison of pointer and numeric (%t, %t): %s",
5888 te1, te2, exprNode_unparse (ret)),
5893 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5898 /* certain comparisons on unsigned's and zero look suspicious */
5900 if (opid == TLT || opid == LE_OP || opid == GE_OP)
5902 if ((ctype_isUnsigned (tr1) && exprNode_isZero (e2))
5903 || (ctype_isUnsigned (tr2) && exprNode_isZero (e1)))
5906 (FLG_UNSIGNEDCOMPARE,
5907 message ("Comparison of unsigned value involving zero: %s",
5908 exprNode_unparse (ret)),
5913 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5915 if ((opid == EQ_OP || opid == NE_OP) &&
5916 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5919 ** is one a variable?
5922 if (uentry_isVariable (exprNode_getUentry (e1))
5923 || uentry_isVariable (exprNode_getUentry (e2)))
5926 ** comparisons with FALSE are okay
5929 if (exprNode_isFalseConstant (e1)
5930 || exprNode_isFalseConstant (e2))
5939 ("Use of %q with %s variables (risks inconsistency because "
5940 "of multiple true values): %s",
5941 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5942 context_printBoolName (), exprNode_unparse (ret)),
5949 case AND_OP: /* bool, bool -> bool */
5951 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5957 if (context_maybeSet (FLG_BOOLOPS))
5959 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5961 if (ctype_sameName (te1, te2))
5965 message ("Operands of %s are non-boolean (%t): %s",
5966 lltok_unparse (op), te1,
5967 exprNode_unparse (ret)),
5975 ("Operands of %s are non-booleans (%t, %t): %s",
5976 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5980 else if (!ctype_isRealBool (te1))
5984 message ("Left operand of %s is non-boolean (%t): %s",
5985 lltok_unparse (op), te1, exprNode_unparse (ret)),
5988 else if (!ctype_isRealBool (te2))
5992 message ("Right operand of %s is non-boolean (%t): %s",
5993 lltok_unparse (op), te2, exprNode_unparse (ret)),
6006 (cstring_makeLiteral
6007 ("There has been a problem in the parser. This is believed to result "
6008 "from a problem with bison v. 1.25. Please try rebuidling Splint "
6009 "using the pre-compiled grammar files by commenting out the "
6010 "BISON= line in the top-level Makefile."));
6015 DPRINTF (("Return type %s: %s", exprNode_unparse (ret), ctype_unparse (tret)));
6017 exprNode_checkUse (ret, e1->sref, e1->loc);
6018 exprNode_mergeUSs (ret, e2);
6019 exprNode_checkUse (ret, e2->sref, e2->loc);
6025 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
6026 /*@only@*/ lltok op)
6030 checkMacroParen (e1);
6031 checkMacroParen (e2);
6033 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
6035 checkExpressionDefined (e1, e2, op);
6038 ret = exprNode_makeOp (e1, e2, op);
6043 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
6046 ** This is somewhat bogus!
6048 ** Assigning to a nested observer in a non-observer datatype
6049 ** should not produce an error.
6052 sRef ref = exprNode_getSref (e1);
6054 DPRINTF (("Check assign mod: %s",
6055 sRef_unparseFull (ref)));
6057 if (sRef_isObserver (ref)
6058 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
6059 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
6061 sRef base = sRef_getBase (ref);
6063 if (sRef_isValid (base) && sRef_isObserver (base))
6065 exprNode_checkModify (e1, ret);
6069 exprNode_checkModifyVal (e1, ret);
6074 exprNode_checkModify (e1, ret);
6079 exprNode_assign (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2, /*@only@*/ lltok op)
6081 bool isalloc = FALSE;
6082 bool isjustalloc = FALSE;
6083 bool noalias = FALSE;
6086 DPRINTF (("%s [%s] <- %s [%s]",
6087 exprNode_unparse (e1),
6088 ctype_unparse (e1->typ),
6089 exprNode_unparse (e2),
6090 ctype_unparse (e2->typ)));
6092 if (lltok_getTok (op) != TASSIGN)
6094 ret = exprNode_makeOp (e1, e2, op);
6096 DPRINTF (("Here goes: %s %s",
6097 ctype_unparse (e1->typ),
6098 ctype_unparse (e2->typ)));
6100 if (exprNode_isDefined (e1)
6101 && exprNode_isDefined (e2))
6103 if (ctype_isNumeric (e2->typ)
6104 || ctype_isNumeric (e1->typ))
6106 /* Its a pointer arithmetic expression like ptr += i */
6113 ret = exprNode_createPartialCopy (e1);
6114 ret->kind = XPR_ASSIGN;
6115 ret->edata = exprData_makeOp (e1, e2, op);
6117 if (!exprNode_isError (e2))
6119 ret->sets = sRefSet_union (ret->sets, e2->sets);
6120 ret->msets = sRefSet_union (ret->msets, e2->msets);
6121 ret->uses = sRefSet_union (ret->uses, e2->uses);
6125 checkExpressionDefined (e1, e2, op);
6127 if (exprNode_isError (e1))
6129 if (!exprNode_isError (e2))
6131 ret->loc = fileloc_update (ret->loc, e2->loc);
6135 ret->loc = fileloc_update (ret->loc, g_currentloc);
6139 if (!exprNode_isError (e2))
6141 checkMacroParen (e2);
6144 if (exprNode_isDefined (e1))
6146 if (sRef_isMacroParamRef (e1->sref))
6148 if (context_inIterDef ())
6150 uentry ue = sRef_getUentry (e1->sref);
6152 if (uentry_isYield (ue))
6158 if (fileloc_isDefined (e1->loc))
6162 message ("Assignment to non-yield iter parameter: %q",
6163 sRef_unparse (e1->sref)),
6170 message ("Assignment to non-yield iter parameter: %q",
6171 sRef_unparse (e1->sref)),
6178 if (fileloc_isDefined (e1->loc))
6182 message ("Assignment to macro parameter: %q",
6183 sRef_unparse (e1->sref)),
6190 message ("Assignment to macro parameter: %q",
6191 sRef_unparse (e1->sref)),
6195 exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
6200 exprNode_checkAssignMod (e1, ret);
6203 if (exprNode_isDefined (e2))
6205 if (lltok_getTok (op) == TASSIGN)
6207 ctype te1 = exprNode_getType (e1);
6208 ctype te2 = exprNode_getType (e2);
6210 if (ctype_isVoid (te2))
6214 message ("Assignment of void value to %t: %s %s %s",
6215 te1, exprNode_unparse (e1),
6217 exprNode_unparse (e2)),
6220 else if (!ctype_forceMatch (te1, te2))
6222 if (exprNode_matchLiteral (te1, e2))
6224 DPRINTF (("Literals match: %s / %s",
6225 ctype_unparse (te1), exprNode_unparse (e2)));
6226 if (ctype_isNumAbstract (te1)) {
6227 if (!context_flagOn (FLG_NUMABSTRACTLIT, e1->loc)) {
6228 (void) llgenhinterror
6231 ("Assignment of %t literal to numabstract type %t: %s %s %s",
6233 exprNode_unparse (e1),
6235 exprNode_unparse (e2)),
6237 ("Use +numabstractlit to allow numeric literals to be used as numabstract values"),
6246 message ("Assignment of %t to %t: %s %s %s",
6247 te2, te1, exprNode_unparse (e1),
6249 exprNode_unparse (e2)),
6255 /* Type checks okay */
6259 exprNode_mergeUSs (ret, e2);
6260 exprNode_checkUse (ret, e2->sref, e2->loc);
6262 DPRINTF (("Do assign! %s %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6269 doAssign (e1, e2, FALSE);
6272 ret->sref = e1->sref;
6276 if (exprNode_isDefined (e2))
6278 exprNode_mergeUSs (ret, e2);
6279 exprNode_checkUse (ret, e2->sref, e2->loc);
6283 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
6285 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
6288 isjustalloc = sRef_isJustAllocated (e1->sref);
6289 isalloc = sRef_isAllocated (e1->sref);
6291 if (sRef_isField (e1->sref))
6293 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
6295 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
6297 exprNode_checkUse (ret, root, e1->loc);
6303 ** be careful! this defines e1->sref.
6306 /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
6308 DPRINTF (("Setting: %s -> %s", exprNode_unparse (ret), sRef_unparse (e1->sref)));
6309 exprNode_checkSet (ret, e1->sref);
6313 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
6314 ? e2->loc : e1->loc);
6320 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
6329 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
6330 /*@keep@*/ exprNode elseclause)
6334 if (!exprNode_isError (pred))
6336 ret = exprNode_createPartialCopy (pred);
6337 checkMacroParen (pred);
6338 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
6340 if (!exprNode_isError (ifclause))
6342 checkMacroParen (ifclause); /* update macro counts! */
6344 if (!exprNode_isError (elseclause))
6346 checkMacroParen (elseclause);
6348 if (!exprNode_matchTypes (ifclause, elseclause))
6351 (exprNode_getType (ifclause),
6353 exprNode_getType (elseclause),
6355 message ("Conditional clauses are not of same type: "
6357 exprNode_unparse (ifclause),
6358 exprNode_getType (ifclause),
6359 exprNode_unparse (elseclause),
6360 exprNode_getType (elseclause)),
6363 ret->sref = sRef_undefined;
6364 ret->typ = ctype_unknown;
6369 /* for now...should merge the states */
6370 ret->sref = ifclause->sref;
6371 ret->typ = ifclause->typ;
6373 if (exprNode_isNullValue (ifclause))
6375 ret->typ = elseclause->typ;
6379 exprNode_checkUse (ret, pred->sref, pred->loc);
6380 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6381 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6383 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6388 ret->typ = ifclause->typ;
6390 exprNode_checkUse (pred, pred->sref, pred->loc);
6391 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6393 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6398 if (!exprNode_isError (elseclause))
6400 ret->typ = elseclause->typ;
6402 exprNode_checkUse (pred, pred->sref, pred->loc);
6403 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6405 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6409 else /* pred is error */
6411 if (!exprNode_isError (ifclause))
6413 ret = exprNode_createSemiCopy (ifclause);
6415 checkMacroParen (ifclause); /* update macro counts! */
6417 if (!exprNode_isError (elseclause))
6419 checkMacroParen (elseclause);
6421 ret->typ = ifclause->typ;
6423 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6426 (exprNode_getType (ifclause),
6428 exprNode_getType (elseclause),
6430 message ("Conditional clauses are not of same type: "
6432 exprNode_unparse (ifclause),
6433 exprNode_getType (ifclause),
6434 exprNode_unparse (elseclause),
6435 exprNode_getType (elseclause)),
6438 ret->typ = ctype_unknown;
6442 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6443 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6445 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6448 else if (!exprNode_isError (elseclause)) /* pred, if errors */
6450 ret = exprNode_createSemiCopy (ifclause);
6452 ret->typ = elseclause->typ;
6453 checkMacroParen (elseclause);
6455 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6456 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6458 else /* all errors! */
6460 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6464 ret->kind = XPR_COND;
6465 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
6467 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6469 exprNode_combineControl (ret, ifclause, elseclause);
6476 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6478 ctype totype = qtype_getType (qt);
6480 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6484 ** check use of va_arg : <valist>, type -> type
6487 if (exprNode_isError (arg))
6492 targ = exprNode_getType (arg);
6495 ** arg should have be a pointer
6498 if (!ctype_isUA (targ) ||
6499 (!typeId_equal (ctype_typeId (targ),
6500 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6504 message ("First argument to va_arg is not a va_list (type %t): %s",
6505 targ, exprNode_unparse (arg)),
6509 exprNode_checkSet (ret, arg->sref);
6513 ** return type is totype
6517 ret->kind = XPR_VAARG;
6518 ret->edata = exprData_makeCast (tok, arg, qt);
6523 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6525 exprNode ret = exprNode_createPlain (ctype_undefined);
6526 ret->kind = XPR_LABEL;
6527 ret->edata = exprData_makeLiteral (label);
6528 ret->isJumpPoint = TRUE;
6530 return (ret); /* for now, ignore label */
6533 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6535 if (exprNode_isDefined (stmt))
6537 stmt->isJumpPoint = TRUE;
6539 /* This prevent stray no return path errors, etc. */
6540 stmt->exitCode = XK_MUSTEXIT;
6546 bool exprNode_isDefaultMarker (exprNode e)
6548 if (exprNode_isDefined (e))
6550 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6556 bool exprNode_isCaseMarker (exprNode e)
6558 if (exprNode_isDefined (e))
6560 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6566 bool exprNode_isLabelMarker (exprNode e)
6568 if (exprNode_isDefined (e))
6570 return (e->kind == XPR_LABEL);
6576 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6578 exprNode ret = exprNode_createPartialCopy (test);
6580 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6582 if (exprNode_isError (test)) {
6586 exprNode_checkUse (ret, test->sref, test->loc);
6588 usymtab_setExitCode (ret->exitCode);
6592 usymtab_setMustBreak ();
6595 ret->edata = exprData_makeSingle (test);
6596 ret->isJumpPoint = TRUE;
6602 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6604 exprNode ret = exprNode_createPartialCopy (test);
6606 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6607 ret->edata = exprData_makePair (test, stmt);
6608 ret->isJumpPoint = TRUE;
6610 if (exprNode_isError (test))
6615 exprNode_checkUse (ret, test->sref, test->loc);
6617 if (exprNode_isError (stmt))
6622 exprNode_mergeUSs (ret, stmt);
6624 ret->exitCode = stmt->exitCode;
6625 ret->mustBreak = stmt->mustBreak;
6626 ret->canBreak = stmt->canBreak;
6628 usymtab_setExitCode (ret->exitCode);
6632 usymtab_setMustBreak ();
6639 /*@notnull@*/ /*@only@*/ exprNode
6640 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6642 exprNode ret = exprNode_createTok (def);
6644 ret->isJumpPoint = TRUE;
6645 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6650 exprNode_mayEscape (exprNode e)
6652 if (exprNode_isDefined (e))
6654 return exitkind_couldEscape (e->exitCode);
6660 exprNode_mustBreak (exprNode e)
6662 if (exprNode_isDefined (e))
6664 return e->mustBreak;
6671 exprNode_mustEscape (exprNode e)
6673 if (exprNode_isDefined (e))
6675 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6682 exprNode_errorEscape (exprNode e)
6684 if (exprNode_isDefined (e))
6686 return exitkind_isError (e->exitCode);
6692 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6694 exprNode ret = exprNode_createPartialCopy (e1);
6696 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6698 ret->edata = exprData_makePair (e1, e2);
6699 ret->kind = XPR_STMTLIST;
6701 if (exprNode_isDefined (e1))
6703 ret->isJumpPoint = e1->isJumpPoint;
6704 ret->canBreak = e1->canBreak;
6708 if (exprNode_isDefined (e2))
6710 ret->loc = fileloc_update (ret->loc, e2->loc);
6714 if (exprNode_isDefined (e2))
6716 ret->exitCode = e2->exitCode;
6717 ret->mustBreak = e2->mustBreak;
6718 if (e2->canBreak) ret->canBreak = TRUE;
6722 ** if e1 must return, then e2 is unreachable!
6725 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6727 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6728 && !(e2->isJumpPoint))
6730 if (context_getFlag (FLG_UNREACHABLE))
6734 if (e2->kind == XPR_STMT)
6736 nr = exprData_getUopNode (e2->edata);
6739 if ((nr->kind == XPR_TOK
6740 && lltok_isSemi (exprData_getTok (nr->edata))))
6742 /* okay to have unreachable ";" */
6743 ret->exitCode = XK_MUSTEXIT;
6744 ret->canBreak = TRUE;
6748 if (optgenerror (FLG_UNREACHABLE,
6749 message ("Unreachable code: %s",
6750 exprNode_unparseFirst (nr)),
6753 ret->isJumpPoint = TRUE;
6754 ret->mustBreak = FALSE;
6755 ret->exitCode = XK_ERROR;
6756 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6760 ret->exitCode = XK_MUSTEXIT;
6761 ret->canBreak = TRUE;
6769 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6772 ** We want a warning anytime we have:
6774 ** yyy; <<<- no break or return
6778 exprNode lastStmt = exprNode_lastStatement (e1);
6780 if (exprNode_isDefined (lastStmt)
6781 && !exprNode_mustEscape (lastStmt)
6782 && !exprNode_mustBreak (lastStmt)
6783 && !exprNode_isCaseMarker (lastStmt)
6784 && !exprNode_isDefaultMarker (lastStmt)
6785 && !exprNode_isLabelMarker (lastStmt))
6787 voptgenerror (FLG_CASEBREAK,
6789 ("Fall through case (no preceding break)"),
6796 exprNode_mergeUSs (ret, e2);
6798 usymtab_setExitCode (ret->exitCode);
6802 usymtab_setMustBreak ();
6805 DPRINTF (("==> %s", exprNode_unparse (ret)));
6809 exprNode exprNode_createTok (/*@only@*/ lltok t)
6811 exprNode ret = exprNode_create (ctype_unknown);
6812 ret->kind = XPR_TOK;
6813 ret->edata = exprData_makeTok (t);
6817 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6819 if (!exprNode_isError (e))
6821 exprChecks_checkStatementEffect(e);
6824 return (exprNode_statementError (e, t));
6827 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6829 exprNode ret = exprNode_createPartialCopy (e);
6831 if (!exprNode_isError (e))
6833 if (e->kind != XPR_ASSIGN)
6835 exprNode_checkUse (ret, e->sref, e->loc);
6838 ret->exitCode = e->exitCode;
6839 ret->canBreak = e->canBreak;
6840 ret->mustBreak = e->mustBreak;
6843 ret->edata = exprData_makeUop (e, t);
6844 ret->kind = XPR_STMT;
6849 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6851 if (!exprNode_isError (e))
6853 if (e->kind != XPR_ASSIGN)
6855 exprNode_checkUse (e, e->sref, e->loc);
6862 void exprNode_produceGuards (exprNode pred)
6864 if (!exprNode_isError (pred))
6866 if (ctype_isRealPointer (pred->typ))
6868 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6871 exprNode_checkUse (pred, pred->sref, pred->loc);
6872 exprNode_resetSref (pred);
6876 exprNode exprNode_compoundStatementExpression (/*@only@*/ lltok tlparen, /*@only@*/ exprNode e)
6880 DPRINTF (("Compound: %s", exprNode_unparse (e)));
6882 if (!context_flagOn (FLG_GNUEXTENSIONS, exprNode_loc (e)))
6884 (void) llgenhinterror
6886 message ("Compound statement expressions is not supported by ISO C99"),
6887 message ("Use +gnuextensions to allow compound statement expressions (and other GNU language extensions) "
6888 "without this warning"),
6893 ** The type of a compoundStatementExpression is the type of the last statement
6896 llassert (exprNode_isBlock (e));
6897 laststmt = exprNode_lastStatement (e);
6899 DPRINTF (("Last statement: %s / %s", exprNode_unparse (laststmt), ctype_unparse (exprNode_getType (laststmt))));
6900 DPRINTF (("e: %s", exprNode_unparse (e)));
6901 e->typ = exprNode_getType (laststmt);
6902 return exprNode_addParens (tlparen, e);
6906 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6908 exprNode ret = exprNode_createPartialCopy (e);
6910 if (!exprNode_isError (e))
6912 ret->exitCode = e->exitCode;
6913 ret->canBreak = e->canBreak;
6914 ret->mustBreak = e->mustBreak;
6917 DPRINTF (("Block e: %s", exprNode_unparse (e)));
6918 ret->edata = exprData_makeSingle (e);
6919 ret->kind = XPR_BLOCK;
6920 DPRINTF (("Block: %s", exprNode_unparse (ret)));
6924 bool exprNode_isBlock (exprNode e)
6926 return (exprNode_isDefined (e)
6927 && ((e)->kind == XPR_BLOCK));
6930 bool exprNode_isStatement (exprNode e)
6932 return (exprNode_isDefined (e)
6933 && ((e)->kind == XPR_STMT));
6936 bool exprNode_isAssign (exprNode e)
6938 if (exprNode_isDefined (e))
6940 return (e->kind == XPR_ASSIGN);
6946 bool exprNode_isEmptyStatement (exprNode e)
6948 return (exprNode_isDefined (e)
6949 && (e->kind == XPR_TOK)
6950 && (lltok_isSemi (exprData_getTok (e->edata))));
6953 bool exprNode_isMultiStatement (exprNode e)
6955 return (exprNode_isDefined (e)
6956 && ((e->kind == XPR_FOR)
6957 || (e->kind == XPR_FORPRED)
6958 || (e->kind == XPR_IF)
6959 || (e->kind == XPR_IFELSE)
6960 || (e->kind == XPR_WHILE)
6961 || (e->kind == XPR_WHILEPRED)
6962 || (e->kind == XPR_DOWHILE)
6963 || (e->kind == XPR_BLOCK)
6964 || (e->kind == XPR_STMT)
6965 || (e->kind == XPR_STMTLIST)
6966 || (e->kind == XPR_SWITCH)));
6969 void exprNode_checkIfPred (exprNode pred)
6971 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6974 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6977 bool emptyErr = FALSE;
6979 if (context_maybeSet (FLG_IFEMPTY))
6981 if (exprNode_isEmptyStatement (tclause))
6983 emptyErr = optgenerror (FLG_IFEMPTY,
6985 ("Body of if statement is empty"),
6986 exprNode_loc (tclause));
6990 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6992 if (exprNode_isDefined (tclause)
6993 && !exprNode_isBlock (tclause))
6995 voptgenerror (FLG_IFBLOCK,
6997 ("Body of if statement is not a block: %s",
6998 exprNode_unparse (tclause)),
6999 exprNode_loc (tclause));
7003 if (exprNode_isError (pred))
7005 if (exprNode_isError (tclause))
7007 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7011 ret = exprNode_createPartialCopy (tclause);
7016 if (exprNode_mustEscape (pred))
7020 message ("Predicate always exits: %s", exprNode_unparse (pred)),
7021 exprNode_loc (pred));
7024 exprNode_checkUse (pred, pred->sref, pred->loc);
7026 if (!exprNode_isError (tclause))
7028 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
7031 ret = exprNode_createPartialCopy (pred);
7035 ret->edata = exprData_makePair (pred, tclause);
7037 ret->exitCode = XK_UNKNOWN;
7039 if (exprNode_isDefined (tclause))
7041 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
7042 ret->canBreak = tclause->canBreak;
7043 ret->sets = sRefSet_union (ret->sets, tclause->sets);
7044 ret->msets = sRefSet_union (ret->msets, tclause->msets);
7045 ret->uses = sRefSet_union (ret->uses, tclause->uses);
7048 ret->mustBreak = FALSE;
7053 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
7054 /*@only@*/ exprNode tclause,
7055 /*@only@*/ exprNode eclause)
7058 bool tEmptyErr = FALSE;
7059 bool eEmptyErr = FALSE;
7061 if (context_maybeSet (FLG_IFEMPTY))
7063 if (exprNode_isEmptyStatement (tclause))
7065 tEmptyErr = optgenerror
7068 ("Body of if clause of if statement is empty"),
7069 exprNode_loc (tclause));
7072 if (exprNode_isEmptyStatement (eclause))
7074 eEmptyErr = optgenerror
7077 ("Body of else clause of if statement is empty"),
7078 exprNode_loc (eclause));
7082 if (context_maybeSet (FLG_IFBLOCK))
7085 && exprNode_isDefined (tclause)
7086 && !exprNode_isBlock (tclause))
7088 voptgenerror (FLG_IFBLOCK,
7090 ("Body of if clause of if statement is not a block: %s",
7091 exprNode_unparse (tclause)),
7092 exprNode_loc (tclause));
7096 && exprNode_isDefined (eclause)
7097 && !exprNode_isBlock (eclause)
7098 && !(eclause->kind == XPR_IF)
7099 && !(eclause->kind == XPR_IFELSE))
7104 ("Body of else clause of if statement is not a block: %s",
7105 exprNode_unparse (eclause)),
7106 exprNode_loc (eclause));
7110 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
7112 if (exprNode_isDefined (eclause)
7113 && (eclause->kind == XPR_IF))
7115 voptgenerror (FLG_ELSEIFCOMPLETE,
7116 message ("Incomplete else if logic (no final else): %s",
7117 exprNode_unparse (eclause)),
7118 exprNode_loc (eclause));
7122 if (exprNode_isError (pred))
7124 if (exprNode_isError (tclause))
7126 if (exprNode_isError (eclause))
7128 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7132 ret = exprNode_createPartialCopy (eclause);
7137 ret = exprNode_createPartialCopy (tclause);
7140 else /* pred is okay */
7142 ret = exprNode_createPartialCopy (pred);
7144 if (exprNode_mustEscape (pred))
7148 message ("Predicate always exits: %s", exprNode_unparse (pred)),
7149 exprNode_loc (pred));
7152 exprNode_checkUse (ret, pred->sref, pred->loc);
7153 exprNode_mergeCondUSs (ret, tclause, eclause);
7156 ret->kind = XPR_IFELSE;
7157 ret->edata = exprData_makeCond (pred, tclause, eclause);
7159 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
7161 exprNode_combineControl (ret, tclause, eclause);
7162 ret->loc = fileloc_update (ret->loc, eclause->loc);
7169 ** *allpaths <- TRUE iff all executions paths must go through the switch
7173 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
7175 exprNodeSList el = exprNode_flatten (e);
7176 bool mustReturn = TRUE; /* find a branch that doesn't */
7177 bool thisReturn = FALSE;
7178 bool hasDefault = FALSE;
7179 bool hasAllMembers = FALSE;
7180 bool inSwitch = FALSE;
7181 bool isEnumSwitch = FALSE;
7182 bool canBreak = FALSE;
7183 bool fallThrough = FALSE;
7184 ctype ct = ctype_unknown;
7185 enumNameSList usedEnums;
7188 if (exprNode_isDefined (test))
7193 ttype = ctype_realType (ct);
7195 if (ctype_isEnum (ttype))
7197 isEnumSwitch = TRUE;
7198 enums = ctype_elist (ttype);
7199 usedEnums = enumNameSList_new ();
7203 exprNodeSList_elements (el, current)
7206 DPRINTF ((message("checkSwitchExpr current = %s ", exprNode_unparse(current) ) ));
7208 if (exprNode_isDefined (current))
7210 switch (current->kind)
7217 (FLG_DUPLICATECASES,
7218 message ("Duplicate default cases in switch"),
7219 exprNode_loc (current));
7224 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
7232 exprNode st = exprData_getSingle (current->edata);
7233 uentry ue = exprNode_getUentry (st);
7235 if (uentry_isValid (ue))
7237 cstring cname = uentry_rawName (ue);
7239 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
7241 if (enumNameSList_member
7242 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
7245 (FLG_DUPLICATECASES,
7246 message ("Duplicate case in switch: %s",
7252 enumNameSList_addh (usedEnums, cname);
7259 message ("Case in switch not %s member: %s",
7260 ctype_unparse (ct), cname),
7267 if (inSwitch && !fallThrough)
7269 if (!thisReturn || canBreak)
7279 /*@switchbreak@*/ break;
7281 thisReturn = thisReturn || exprNode_mustEscape (current);
7282 canBreak = canBreak || current->canBreak;
7283 if (canBreak) fallThrough = FALSE;
7286 } end_exprNodeSList_elements;
7288 if (inSwitch) /* check the last one! */
7290 if (!thisReturn || canBreak)
7299 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
7300 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
7302 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
7304 voptgenerror (FLG_MISSCASE,
7305 message ("Missing case%s in switch: %q",
7306 cstring_makeLiteralTemp
7307 ((enumNameSList_size (unused) > 1) ? "s" : ""),
7308 enumNameSList_unparse (unused)),
7311 enumNameSList_free (unused);
7312 *allpaths = FALSE; /* evans 2002-01-01 */
7316 hasAllMembers = TRUE;
7320 enumNameSList_free (usedEnums);
7324 *allpaths = hasDefault;
7327 exprNodeSList_free (el);
7328 return ((hasDefault || hasAllMembers) && mustReturn);
7331 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
7333 exprNode ret = exprNode_createPartialCopy (e);
7336 DPRINTF (("Switch: %s", exprNode_unparse (s)));
7338 ret->kind = XPR_SWITCH;
7339 ret->edata = exprData_makePair (e, s);
7341 if (!exprNode_isError (s))
7343 exprNode fs = exprNode_firstStatement (s);
7344 ret->loc = fileloc_update (ret->loc, s->loc);
7346 if (exprNode_isUndefined (fs)
7347 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
7348 || exprNode_isDefaultMarker (fs)) {
7351 voptgenerror (FLG_FIRSTCASE,
7353 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
7358 if (!exprNode_isError (e))
7360 if (checkSwitchExpr (e, s, &allpaths))
7362 ret->exitCode = XK_MUSTRETURN;
7366 ret->exitCode = e->exitCode;
7369 ret->canBreak = e->canBreak;
7370 ret->mustBreak = e->mustBreak;
7374 ** exprNode.c:3883,32: Variable allpaths used before definition
7381 DPRINTF (("Context exit switch!"));
7382 context_exitSwitch (ret, allpaths);
7383 DPRINTF (("Context exit switch done!"));
7388 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
7389 /*@notnull@*/ exprNode body)
7391 sRefSet tuses = test->uses;
7393 if (!sRefSet_isEmpty (test->uses))
7395 sRefSet sets = sRefSet_newCopy (body->sets);
7396 bool hasError = TRUE;
7397 bool innerState = FALSE;
7398 sRefSet tuncon = sRefSet_undefined;
7400 sets = sRefSet_union (sets, test->sets);
7401 sets = sRefSet_union (sets, body->msets);
7402 sets = sRefSet_union (sets, test->msets);
7404 sRefSet_allElements (tuses, el)
7406 if (sRef_isUnconstrained (el))
7408 tuncon = sRefSet_insert (tuncon, el);
7412 if (sRefSet_member (sets, el))
7419 if (sRef_isInternalState (el)
7420 || sRef_isFileStatic (sRef_getRootBase (el)))
7424 } end_sRefSet_allElements ;
7428 sRefSet suncon = sRefSet_undefined;
7429 bool sinner = FALSE;
7431 sRefSet_allElements (sets, el)
7433 if (sRef_isUnconstrained (el))
7435 suncon = sRefSet_insert (suncon, el);
7437 else if (sRef_isInternalState (el))
7445 } end_sRefSet_allElements ;
7447 if (sinner && innerState)
7451 else if (sRefSet_isEmpty (tuncon)
7452 && sRefSet_isEmpty (suncon))
7457 ("Suspected infinite loop. No value used in loop test (%q) "
7458 "is modified by test or loop body.",
7459 sRefSet_unparsePlain (tuses)),
7464 if (sRefSet_isEmpty (tuncon))
7468 message ("Suspected infinite loop. No condition values "
7469 "modified. Modification possible through "
7470 "unconstrained calls: %q",
7471 sRefSet_unparsePlain (suncon)),
7478 message ("Suspected infinite loop. No condition values "
7479 "modified. Possible undetected dependency through "
7480 "unconstrained calls in loop test: %q",
7481 sRefSet_unparsePlain (tuncon)),
7487 sRefSet_free (sets);
7491 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7494 bool emptyErr = FALSE;
7496 if (context_maybeSet (FLG_WHILEEMPTY))
7498 if (exprNode_isEmptyStatement (b))
7500 emptyErr = optgenerror
7503 ("Body of while statement is empty"),
7508 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7510 if (exprNode_isDefined (b)
7511 && !exprNode_isBlock (b))
7513 if (context_inIterDef ()
7514 && (b->kind == XPR_STMTLIST
7515 || b->kind == XPR_TOK))
7521 voptgenerror (FLG_WHILEBLOCK,
7523 ("Body of while statement is not a block: %s",
7524 exprNode_unparse (b)),
7530 if (exprNode_isError (t))
7532 if (exprNode_isError (b))
7534 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7538 ret = exprNode_createPartialCopy (b);
7545 ret = exprNode_createPartialCopy (t);
7547 llassert (t->kind == XPR_WHILEPRED);
7549 test = exprData_getSingle (t->edata);
7551 if (!exprNode_isError (b) && exprNode_isDefined (test))
7553 if (context_maybeSet (FLG_INFLOOPS)
7554 || context_maybeSet (FLG_INFLOOPSUNCON))
7557 ** check that some variable in the predicate is set by the body
7558 ** if the predicate uses any variables
7561 checkInfiniteLoop (test, b);
7564 exprNode_mergeUSs (ret, b);
7566 if (exprNode_isDefined (b))
7568 ret->exitCode = exitkind_makeConditional (b->exitCode);
7573 ret->edata = exprData_makePair (t, b);
7574 ret->kind = XPR_WHILE;
7576 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7580 message ("Predicate always exits: %s", exprNode_unparse (t)),
7584 ret->exitCode = XK_NEVERESCAPE;
7587 ** If loop is infinite, and there is no break inside,
7588 ** exit code is never reach.
7591 if (exprNode_knownIntValue (t))
7593 if (!exprNode_isZero (t))
7595 if (exprNode_isDefined (b))
7599 /* Really, it means never reached. */
7600 ret->exitCode = XK_MUSTEXIT;
7610 ret->canBreak = FALSE;
7611 ret->mustBreak = FALSE;
7617 ** do { b } while (t);
7619 ** note: body passed as first argument
7622 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7626 DPRINTF (("Do while: %s / %s",
7627 exprNode_unparse (b), exprNode_unparse (t)));
7629 if (exprNode_isError (t))
7631 if (exprNode_isError (b))
7633 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7637 ret = exprNode_createPartialCopy (b);
7639 ret->exitCode = exitkind_makeConditional (b->exitCode);
7640 exprNode_checkUse (ret, b->sref, b->loc);
7641 ret->exitCode = b->exitCode;
7642 ret->canBreak = b->canBreak;
7643 ret->mustBreak = FALSE;
7648 DPRINTF (("Do while: %s / %s",
7649 exitkind_unparse (t->exitCode),
7650 exitkind_unparse (b->exitCode)));
7652 ret = exprNode_createPartialCopy (t);
7653 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7655 if (!exprNode_isError (b))
7658 ** forgot the copy's --- why wasn't this detected??
7661 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7662 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7663 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
7665 /* left this out --- causes and aliasing bug (infinite loop)
7666 should be detected?? */
7668 exprNode_checkUse (ret, b->sref, b->loc);
7669 exprNode_mergeUSs (ret, t);
7670 exprNode_checkUse (ret, t->sref, t->loc);
7672 /* evans 2001-10-05: while loop can break */
7673 ret->exitCode = exitkind_makeConditional (b->exitCode);
7675 DPRINTF (("Do while: %s",
7676 exitkind_unparse (ret->exitCode)));
7678 ret->canBreak = b->canBreak;
7680 /* Always FALSE for doWhile loops - break's when test is false */
7681 ret->mustBreak = FALSE; /* b->mustBreak; */
7685 context_exitDoWhileClause (t);
7687 ret->kind = XPR_DOWHILE;
7688 ret->edata = exprData_makePair (t, b);
7692 bool exprNode_loopMustExec (exprNode forPred)
7695 ** Returns true if it is obvious that the loop always executes at least once
7697 ** For now, we only identify the most obvious cases. Should be true anytime
7698 ** we can prove init => !test.
7701 if (exprNode_isDefined (forPred))
7703 exprNode init, test, inc;
7706 llassert (forPred->kind == XPR_FORPRED);
7708 edata = forPred->edata;
7709 init = exprData_getTripleInit (edata);
7710 test = exprData_getTripleTest (edata);
7711 inc = exprData_getTripleInc (edata);
7713 if (exprNode_isAssign (init))
7715 exprNode loopVar = exprData_getOpA (init->edata);
7716 exprNode loopInit = exprData_getOpB (init->edata);
7718 if (exprNode_isDefined (test) && test->kind == XPR_OP)
7720 exprNode testVar = exprData_getOpA (test->edata);
7721 exprNode testVal = exprData_getOpB (test->edata);
7722 lltok comp = exprData_getOpTok (test->edata);
7723 int opid = lltok_getTok (comp);
7725 DPRINTF (("Same storage: %s / %s", exprNode_unparse (loopVar),
7726 exprNode_unparse (testVar)));
7728 if (exprNode_sameStorage (loopVar, testVar))
7730 multiVal valinit = exprNode_getValue (loopInit);
7731 multiVal valtest = exprNode_getValue (testVal);
7733 DPRINTF (("Values: %s / %s", multiVal_unparse (valinit),
7734 multiVal_unparse (valtest)));
7736 if (multiVal_isInt (valinit) && multiVal_isInt (valtest))
7738 long v1 = multiVal_forceInt (valinit);
7739 long v2 = multiVal_forceInt (valtest);
7741 DPRINTF (("Here: %ld %ld", v1, v2));
7743 if ((opid == EQ_OP && v1 < v2)
7744 || (opid == NE_OP && v1 != v2)
7745 || (opid == TLT && v1 <= v2)
7746 || (opid == TGT && v1 >= v2)
7747 || (opid == LE_OP && v1 < v2)
7748 || (opid == GE_OP && v1 > v2))
7750 DPRINTF (("mustexec if inc"));
7759 DPRINTF (("loop must exec: FALSE"));
7763 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7766 bool emptyErr = FALSE;
7768 if (context_maybeSet (FLG_FOREMPTY))
7770 if (exprNode_isEmptyStatement (body))
7772 emptyErr = optgenerror
7775 ("Body of for statement is empty"),
7776 exprNode_loc (body));
7780 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7782 if (exprNode_isDefined (body)
7783 && !exprNode_isBlock (body))
7785 if (context_inIterDef ()
7786 && (body->kind == XPR_STMTLIST
7787 || body->kind == XPR_TOK))
7793 voptgenerror (FLG_FORBLOCK,
7795 ("Body of for statement is not a block: %s",
7796 exprNode_unparse (body)),
7797 exprNode_loc (body));
7803 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7806 if (exprNode_isError (body))
7808 ret = exprNode_createPartialCopy (inc);
7812 ret = exprNode_createPartialCopy (body);
7814 ret->exitCode = exitkind_makeConditional (body->exitCode);
7816 exprNode_mergeUSs (inc, body);
7818 if (exprNode_isDefined (inc))
7822 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7824 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7825 exprNode_freeShallow (tmp);
7827 context_clearMessageAnnote ();
7828 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7830 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7831 exprNode_freeShallow (tmp);
7833 context_clearMessageAnnote ();
7835 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7836 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7837 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7841 ret->kind = XPR_FOR;
7842 ret->edata = exprData_makePair (inc, body);
7844 if (exprNode_isDefined (inc)) {
7845 exprNode test = exprData_getTripleTest (inc->edata);
7847 if (exprNode_isUndefined (test)) {
7848 if (exprNode_isDefined (body)) {
7849 if (!body->canBreak) {
7850 /* Really, it means never reached. */
7851 ret->exitCode = XK_MUSTEXIT;
7861 ** for (init; test; inc)
7864 ** while (test) { body; inc; }
7866 ** Now: check use of init (may set vars for test)
7867 ** check use of test
7871 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7875 if (exprNode_isError (pred)) return guardSet_undefined;
7877 llassert (pred->kind == XPR_FORPRED);
7879 test = exprData_getTripleTest (pred->edata);
7881 if (!exprNode_isError (test))
7883 return (test->guards);
7886 return guardSet_undefined;
7889 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7891 exprNode ret = exprNode_createSemiCopy (test);
7893 if (exprNode_isDefined (test))
7895 exprNode_copySets (ret, test);
7896 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7897 exprNode_checkUse (ret, test->sref, test->loc);
7899 exprNode_produceGuards (test);
7901 ret->guards = guardSet_copy (test->guards);
7904 ret->edata = exprData_makeSingle (test);
7905 ret->kind = XPR_WHILEPRED;
7909 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7910 /*@only@*/ exprNode inc)
7915 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7918 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7920 if (!exprNode_isError (inc))
7922 ret = exprNode_createPartialCopy (inc);
7926 if (!exprNode_isError (init))
7928 ret = exprNode_createPartialCopy (init);
7930 else if (!exprNode_isError (test))
7932 ret = exprNode_createPartialCopy (test);
7936 ret = exprNode_createUnknown ();
7940 exprNode_mergeUSs (ret, init);
7942 if (exprNode_isDefined (init))
7944 exprNode_checkUse (ret, init->sref, init->loc);
7947 exprNode_mergeUSs (ret, test);
7949 if (exprNode_isDefined (test))
7951 exprNode_checkUse (ret, test->sref, test->loc);
7954 ret->kind = XPR_FORPRED;
7955 ret->edata = exprData_makeFor (init, test, inc);
7959 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7961 exprNode ret = exprNode_createUnknown ();
7963 if (context_inMacro ())
7965 voptgenerror (FLG_MACROSTMT,
7966 message ("Macro %s uses goto (not functional)",
7967 context_inFunctionName ()),
7971 ret->kind = XPR_GOTO;
7972 ret->edata = exprData_makeLiteral (label);
7973 ret->mustBreak = TRUE;
7974 ret->exitCode = XK_GOTO;
7975 ret->canBreak = TRUE;
7979 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7981 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7983 ret->kind = XPR_CONTINUE;
7984 ret->edata = exprData_makeTok (l);
7985 ret->canBreak = TRUE;
7986 ret->mustBreak = TRUE;
7988 if (qcontinue == QSAFEBREAK)
7992 else if (qcontinue == QINNERCONTINUE)
7994 if (!context_inDeepLoop ())
7997 (FLG_LOOPLOOPCONTINUE,
7998 cstring_makeLiteral ("Continue statement marked with innercontinue "
7999 "is not inside a nested loop"),
8000 exprNode_loc (ret));
8003 else if (qcontinue == BADTOK)
8005 if (context_inDeepLoop ())
8008 (FLG_LOOPLOOPCONTINUE,
8009 cstring_makeLiteral ("Continue statement in nested loop"),
8010 exprNode_loc (ret));
8015 llbuglit ("exprNode_continue: bad qcontinue");
8021 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
8023 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
8024 clause breakClause = context_breakClause ();
8026 ret->kind = XPR_BREAK;
8027 ret->edata = exprData_makeTok (l);
8028 ret->canBreak = TRUE;
8029 ret->mustBreak = TRUE;
8031 if (breakClause == NOCLAUSE)
8035 cstring_makeLiteral ("Break not inside while, for or switch statement"),
8036 exprNode_loc (ret));
8040 if (bqual != BADTOK)
8047 if (breakClause == SWITCHCLAUSE)
8049 if (!context_inDeepSwitch ())
8051 voptgenerror (FLG_SYNTAX,
8053 ("Break preceded by innerbreak is not in a deep switch"),
8054 exprNode_loc (ret));
8059 if (!context_inDeepLoop ())
8061 voptgenerror (FLG_SYNTAX,
8063 ("Break preceded by innerbreak is not in a deep loop"),
8064 exprNode_loc (ret));
8069 if (breakClause == SWITCHCLAUSE)
8071 voptgenerror (FLG_SYNTAX,
8073 ("Break preceded by loopbreak is breaking a switch"),
8074 exprNode_loc (ret));
8078 if (breakClause != SWITCHCLAUSE)
8082 message ("Break preceded by switchbreak is breaking %s",
8083 cstring_makeLiteralTemp
8084 ((breakClause == WHILECLAUSE
8085 || breakClause == DOWHILECLAUSE) ? "a while loop"
8086 : (breakClause == FORCLAUSE) ? "a for loop"
8087 : (breakClause == ITERCLAUSE) ? "an iterator"
8089 exprNode_loc (ret));
8097 if (breakClause == SWITCHCLAUSE)
8099 clause nextBreakClause = context_nextBreakClause ();
8101 switch (nextBreakClause)
8103 case NOCLAUSE: break;
8109 (FLG_LOOPSWITCHBREAK,
8110 cstring_makeLiteral ("Break statement in switch inside loop"),
8111 exprNode_loc (ret));
8115 (FLG_SWITCHSWITCHBREAK,
8116 cstring_makeLiteral ("Break statement in switch inside switch"),
8117 exprNode_loc (ret));
8124 if (context_inDeepLoop ())
8128 cstring_makeLiteral ("Break statement in nested loop"),
8129 exprNode_loc (ret));
8133 if (context_inDeepLoopSwitch ())
8136 (FLG_SWITCHLOOPBREAK,
8137 cstring_makeLiteral ("Break statement in loop inside switch"),
8138 exprNode_loc (ret));
8148 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
8150 fileloc loc = lltok_getLoc (t);
8151 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
8153 context_returnFunction ();
8154 exprChecks_checkNullReturn (loc);
8156 ret->kind = XPR_NULLRETURN;
8157 ret->edata = exprData_makeTok (t);
8158 ret->exitCode = XK_MUSTRETURN;
8162 exprNode exprNode_return (/*@only@*/ exprNode e)
8166 if (exprNode_isError (e))
8168 ret = exprNode_createUnknown ();
8172 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
8174 exprNode_checkUse (ret, e->sref, e->loc);
8175 exprNode_checkReturn (e);
8178 context_returnFunction ();
8179 ret->kind = XPR_RETURN;
8180 ret->edata = exprData_makeSingle (e);
8181 ret->exitCode = XK_MUSTRETURN;
8186 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
8190 if (exprNode_isError (e1))
8192 if (exprNode_isError (e2))
8194 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
8198 ret = exprNode_createPartialCopy (e2);
8199 exprNode_checkUse (ret, e2->sref, e2->loc);
8200 ret->sref = e2->sref;
8205 ret = exprNode_createPartialCopy (e1);
8207 exprNode_checkUse (ret, e1->sref, e1->loc);
8209 if (!exprNode_isError (e2))
8211 exprNode_mergeUSs (ret, e2);
8212 exprNode_checkUse (ret, e2->sref, e2->loc);
8213 ret->sref = e2->sref;
8217 ret->kind = XPR_COMMA;
8218 ret->edata = exprData_makePair (e1, e2);
8220 if (exprNode_isDefined (e1))
8222 if (exprNode_isDefined (e2))
8226 if (exprNode_mustEscape (e1) || e1->mustBreak)
8230 message ("Second clause of comma expression is unreachable: %s",
8231 exprNode_unparse (e2)),
8235 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
8236 ret->mustBreak = e1->mustBreak || e2->mustBreak;
8237 ret->canBreak = e1->canBreak || e2->canBreak;
8241 if (exprNode_mustEscape (e1) || e1->mustBreak)
8245 message ("Second clause of comma expression is unreachable: %s",
8246 exprNode_unparse (e2)),
8250 ret->exitCode = e1->exitCode;
8251 ret->canBreak = e1->canBreak;
8256 if (exprNode_isDefined (e2))
8258 ret->exitCode = e2->exitCode;
8259 ret->mustBreak = e2->mustBreak;
8260 ret->canBreak = e2->canBreak;
8267 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
8269 ctype t1 = exprNode_getType (el);
8270 ctype t2 = exprNode_getType (val);
8271 bool hasError = FALSE;
8273 DPRINTF (("Check one init: %s / %s",
8274 exprNode_unparse (el),
8275 exprNode_unparse (val)));
8277 if (ctype_isUnknown (t1))
8279 voptgenerror (FLG_IMPTYPE,
8280 message ("Variable has unknown (implicitly int) type: %s",
8281 exprNode_unparse (el)),
8285 el->typ = ctype_int;
8288 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
8290 exprNodeList vals = exprData_getArgs (val->edata);
8292 DPRINTF (("Check one init: %s", exprNodeList_unparse (vals)));
8293 DPRINTF (("Type: %s", ctype_unparse (t1)));
8295 if (ctype_isRealAP (t1))
8300 if (ctype_isFixedArray (t1))
8302 size_t nelements = ctype_getArraySize (t1);
8304 DPRINTF (("Checked array: %s / %d",
8305 ctype_unparse (t1), nelements));
8307 if (exprNode_isStringLiteral (val))
8309 exprNode_checkStringLiteralLength (t1, val);
8313 if (exprNodeList_size (vals) != size_toInt (nelements))
8315 hasError = optgenerror
8316 (exprNodeList_size (vals) > size_toInt (nelements)
8317 ? FLG_INITSIZE : FLG_INITALLELEMENTS,
8318 message ("Initializer block for "
8319 "%s has %d element%&, but declared as %s: %q",
8320 exprNode_unparse (el),
8321 exprNodeList_size (vals),
8323 exprNodeList_unparse (vals)),
8329 exprNodeList_elements (vals, oneval)
8331 cstring istring = message ("%d", i);
8334 (exprNode_fakeCopy (el),
8335 exprNode_numLiteral (ctype_int, istring,
8336 fileloc_copy (el->loc), i));
8338 if (exprNode_isDefined (newel))
8340 if (exprNodeList_size (vals) == 1
8341 && ctype_isString (exprNode_getType (oneval))
8342 && ctype_isChar (exprNode_getType (newel)))
8344 exprNode_freeIniter (newel);
8348 if (exprNode_checkOneInit (newel, oneval))
8353 if (nerrors > 3 && exprNodeList_size (vals) > 6)
8356 (message ("Additional initialization errors "
8357 "for %s not reported",
8358 exprNode_unparse (el)),
8360 exprNode_freeIniter (newel);
8365 exprNode_freeIniter (newel);
8370 exprNode_freeIniter (newel);
8375 cstring_free (istring);
8378 } end_exprNodeList_elements;
8381 else if (ctype_isStruct (ctype_realType (t1)))
8383 uentryList fields = ctype_getFields (t1);
8386 if (uentryList_size (fields) != exprNodeList_size (vals))
8388 if (uentryList_size (fields) > exprNodeList_size (vals))
8390 hasError = optgenerror
8392 message ("Initializer block for "
8393 "%s has %d field%&, but %s has %d field%&: %q",
8394 exprNode_unparse (el),
8395 exprNodeList_size (vals),
8397 uentryList_size (fields),
8398 exprNodeList_unparse (vals)),
8403 hasError = optgenerror
8405 message ("Initializer block for "
8406 "%s has %d field%&, but %s has %d field%&: %q",
8407 exprNode_unparse (el),
8408 exprNodeList_size (vals),
8410 uentryList_size (fields),
8411 exprNodeList_unparse (vals)),
8417 exprNodeList_elements (vals, oneval)
8419 uentry thisfield = uentryList_getN (fields, i);
8421 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8423 uentry_getName (thisfield));
8425 if (exprNode_isDefined (newel))
8427 if (exprNode_checkOneInit (newel, oneval))
8432 exprNode_freeIniter (newel);
8436 } end_exprNodeList_elements;
8439 /* evans 2001-12-30: added to fix bug reported by Jim Zelenka */
8440 else if (ctype_isUnion (ctype_realType (t1)))
8442 uentryList fields = ctype_getFields (t1);
8446 ** Union initializers set the first member always.
8449 DPRINTF (("Union initializer: %s / %s",
8450 exprNode_unparse (el), ctype_unparse (ctype_realType (t1))));
8452 if (exprNodeList_size (vals) != 1)
8454 hasError = optgenerror
8456 message ("Initializer block for union "
8457 "%s has %d elements, union initializers should have one element: %q",
8458 exprNode_unparse (el),
8459 exprNodeList_size (vals),
8460 exprNodeList_unparse (vals)),
8465 exprNode oneval = exprNodeList_head (vals);
8466 uentry thisfield = uentryList_getN (fields, i);
8468 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8470 uentry_getName (thisfield));
8472 if (exprNode_isDefined (newel))
8474 if (exprNode_checkOneInit (newel, oneval))
8479 exprNode_freeIniter (newel);
8485 hasError = optgenerror
8487 message ("Initializer block used for "
8488 "%s where %t is expected: %s",
8489 exprNode_unparse (el), t1, exprNode_unparse (val)),
8495 if (exprNode_isDefined (val))
8497 doAssign (el, val, TRUE);
8499 if (!exprNode_matchType (t1, val))
8501 hasError = gentypeerror
8503 message ("Initial value of %s is type %t, "
8505 exprNode_unparse (el),
8506 t2, t1, exprNode_unparse (val)),
8515 static /*@notnull@*/ exprNode
8516 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
8520 DPRINTF (("Initialization: %s", idDecl_unparse (t)));
8522 if (usymtab_exists (idDecl_observeId (t)))
8524 uentry ue = usymtab_lookup (idDecl_observeId (t));
8525 ret = exprNode_createId (ue);
8531 DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
8533 ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
8534 ret = exprNode_fromIdentifierAux (ue);
8537 ** No error - this happens in old style declarations:
8541 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8548 exprData_free (ret->edata, ret->kind);
8549 ret->edata = exprData_undefined;
8550 ret->exitCode = XK_NEVERESCAPE;
8551 ret->mustBreak = FALSE;
8552 ret->kind = XPR_INIT;
8556 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8558 exprNode ret = exprNode_makeInitializationAux (t);
8559 llassert (ret->edata == exprData_undefined);
8560 ret->edata = exprData_makeInit (t, exprNode_undefined);
8564 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8565 /*@only@*/ exprNode e)
8567 uentry ue = usymtab_lookup (idDecl_observeId (t));
8568 exprNode ret = exprNode_makeInitializationAux (t);
8569 fileloc loc = exprNode_loc (e);
8571 DPRINTF (("initialization: %s = %s", idDecl_unparse (t), exprNode_unparse (e)));
8573 if (exprNode_isError (e))
8575 e = exprNode_createUnknown ();
8576 /* error: assume initializer is defined */
8577 sRef_setDefined (ret->sref, g_currentloc);
8578 ret->edata = exprData_makeInit (t, e);
8582 ctype ct = ctype_realishType (ret->typ);
8587 ** was addSafeUse --- what's the problem?
8589 ** int x = 3, y = x ?
8592 exprData_free (ret->edata, ret->kind);
8593 ret->edata = exprData_makeInit (t, e);
8594 DPRINTF (("ret: %s", exprNode_unparse (ret)));
8596 exprNode_checkUse (ret, e->sref, e->loc);
8598 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8600 exprNode lhs = exprNode_createId (ue);
8603 ** static storage should be undefined before initializing
8606 if (uentry_isStatic (ue))
8608 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8611 (void) exprNode_checkOneInit (lhs, e);
8613 if (uentry_isStatic (ue))
8615 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8618 exprNode_free (lhs);
8622 if (!exprNode_matchType (ct, e))
8624 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
8631 (exprNode_getType (e), e, exprNode_getType (ret), ret,
8633 ("Variable %q initialized to type %t, expects %t: %s",
8634 uentry_getName (ue), exprNode_getType (e),
8635 exprNode_getType (ret),
8636 exprNode_unparse (e)),
8642 if (uentry_isStatic (ue))
8644 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8647 if (exprNode_isStringLiteral (e)
8648 && (ctype_isArray (ct))
8649 && (ctype_isChar (ctype_realType (ctype_baseArrayPtr (ct)))))
8652 ** If t is a char [], the literal is copied.
8655 exprNode_checkStringLiteralLength (ct, e);
8656 sRef_setDefState (ret->sref, SS_DEFINED, e->loc);
8657 ret->val = multiVal_copy (e->val);
8659 sRef_setNullTerminatedState (ret->sref);
8661 if (multiVal_isDefined (e->val))
8663 cstring slit = multiVal_forceString (e->val);
8664 sRef_setLen (ret->sref, size_toInt (cstring_length (slit) + 1));
8667 if (ctype_isFixedArray (ct))
8669 sRef_setSize (ret->sref, size_toInt (ctype_getArraySize (ct)));
8674 doAssign (ret, e, TRUE);
8677 if (uentry_isStatic (ue))
8679 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8683 if (context_inIterDef ())
8685 /* should check if it is yield */
8686 uentry_setUsed (ue, loc);
8693 exprNode_mergeUSs (ret, e);
8694 DPRINTF (("Ret: %s %p %p",
8695 exprNode_unparse (ret),
8696 ret->requiresConstraints,
8697 ret->ensuresConstraints));
8699 DPRINTF (("Ret: %s %s %s",
8700 exprNode_unparse (ret),
8701 constraintList_unparse (ret->requiresConstraints),
8702 constraintList_unparse (ret->ensuresConstraints)));
8706 exprNode exprNode_iter (/*@observer@*/ uentry name,
8707 /*@only@*/ exprNodeList alist,
8708 /*@only@*/ exprNode body,
8709 /*@observer@*/ uentry end)
8714 llassert (uentry_isValid (name));
8716 uentry_setUsed (name, exprNode_loc (body));
8718 ret = exprNode_createPartialCopy (body);
8719 iname = uentry_getName (name);
8721 if (uentry_isInvalid (end))
8723 llerror (FLG_ITERBALANCE,
8724 message ("Iter %s not balanced with end_%s", iname, iname));
8728 cstring ename = uentry_getName (end);
8730 if (!cstring_equalPrefixLit (ename, "end_"))
8732 llerror (FLG_ITERBALANCE, message ("Iter %s not balanced with end_%s: %s",
8733 iname, iname, ename));
8737 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8739 llerror (FLG_ITERBALANCE,
8740 message ("Iter %s not balanced with end_%s: %s",
8741 iname, iname, ename));
8745 cstring_free (ename);
8748 context_exitIterClause (body);
8750 ret->kind = XPR_ITER;
8751 ret->edata = exprData_makeIter (name, alist, body, end);
8753 if (uentry_isIter (name))
8755 (void) checkArgsReal (name, body,
8756 uentry_getParams (name), alist, TRUE, ret);
8759 cstring_free (iname);
8765 exprNode_iterNewId (/*@only@*/ cstring s)
8767 exprNode e = exprNode_new ();
8768 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8770 llassert (processingIterVars ());
8772 e->loc = context_getSaveLocation ();
8774 if (fileloc_isUndefined (e->loc))
8776 fileloc_free (e->loc);
8777 e->loc = fileloc_copy (g_currentloc);
8780 e->uses = sRefSet_new ();
8781 e->sets = sRefSet_new ();
8782 e->msets = sRefSet_new ();
8784 e->val = multiVal_unknown ();
8785 e->guards = guardSet_new ();
8786 e->sref = sRef_undefined;
8787 e->isJumpPoint = FALSE;
8788 e->exitCode = XK_NEVERESCAPE;
8790 /*> missing fields, detected by splint <*/
8791 e->canBreak = FALSE;
8792 e->mustBreak = FALSE;
8793 e->etext = cstring_undefined;
8795 if (uentry_isYield (ue))
8797 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8798 fileloc_copy (e->loc),
8802 uue = usymtab_supEntrySrefReturn (uue);
8804 sr = uentry_getSref (uue);
8805 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8806 sr = uentry_getSref (uue);
8807 sRef_setDefined (sr, e->loc);
8809 e->typ = uentry_getType (uue);
8811 e->edata = exprData_makeId (uue);
8812 uentry_setUsed (uue, g_currentloc);
8818 sRef_setGlobalScope ();
8819 uue = uentry_makeVariableLoc (s, ctype_unknown);
8821 e->typ = ctype_unknown;
8822 e->edata = exprData_makeId (uue);
8824 uentry_setUsed (uue, e->loc);
8825 uentry_setHasNameError (uue);
8827 if (context_getFlag (FLG_REPEATUNRECOG))
8829 uentry_markOwned (uue);
8833 usymtab_supGlobalEntry (uue);
8836 sRef_clearGlobalScope ();
8838 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8845 exprNode_defineConstraints(e);
8850 exprNode_iterExpr (/*@returned@*/ exprNode e)
8852 if (!processingIterVars ())
8854 llcontbuglit ("checkIterParam: not in iter");
8858 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8861 if (exprNode_isDefined (e))
8863 if (fileloc_isDefined (e->loc))
8867 message ("Yield parameter is not simple identifier: %s",
8868 exprNode_unparse (e)),
8875 message ("Yield parameter is not simple identifier: %s",
8876 exprNode_unparse (e)),
8886 exprNode_iterId (/*@observer@*/ uentry c)
8890 llassert (processingIterVars ());
8892 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8895 if (uentry_isYield (ue))
8897 ctype ct = uentry_getType (ue);
8898 exprNode e = exprNode_createPlain (ct);
8899 cstring name = uentry_getName (c);
8900 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8902 uentry_setUsed (ue, g_currentloc);
8903 uentry_setHasNameError (ue);
8905 cstring_free (name);
8908 e->edata = exprData_makeId (le);
8909 e->loc = context_getSaveLocation ();
8910 e->sref = uentry_getSref (le);
8912 usymtab_supEntrySref (le);
8914 if (!context_inHeader ())
8918 message ("Yield parameter shadows local declaration: %q",
8919 uentry_getName (c)),
8920 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8922 uentry_showWhereDeclared (c);
8929 return (exprNode_fromIdentifierAux (c));
8932 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8934 exprNode ret = exprNode_create (ctype_unknown);
8936 ret->kind = XPR_ITERCALL;
8937 ret->edata = exprData_makeIterCall (name, alist);
8939 if (uentry_isIter (name))
8941 uentryList params = uentry_getParams (name);
8943 if (context_inIterDef ()
8944 && uentryList_size (params) == exprNodeList_size (alist))
8948 exprNodeList_elements (alist, arg)
8950 uentry parg = uentryList_getN (params, i);
8952 if (uentry_isYield (parg))
8954 uentry ue = exprNode_getUentry (arg);
8956 if (uentry_isValid (ue))
8963 } end_exprNodeList_elements;
8966 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8967 checkUnspecCall (ret, params, alist);
8973 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8975 if (exprNode_isDefined (e))
8977 if (sRef_isInvalid (e->sref))
8980 e->sref = sRef_makeUnknown ();
8981 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8992 return sRef_undefined;
8996 /*@observer@*/ cstring
8997 exprNode_unparseFirst (exprNode e)
8999 if (exprNode_isDefined (e))
9003 if (e->kind == XPR_STMTLIST
9004 || e->kind == XPR_COMMA || e->kind == XPR_COND)
9006 exprNode first = exprData_getPairA (e->edata);
9008 if (exprNode_isDefined (first))
9010 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
9014 return (cstring_makeLiteralTemp ("..."));
9018 ret = cstring_elide (exprNode_unparse (e), 20);
9019 cstring_markOwned (ret);
9025 return cstring_makeLiteralTemp ("<error>");
9029 /*@observer@*/ cstring
9030 exprNode_unparse (/*@temp@*/ exprNode e)
9032 if (exprNode_isError (e))
9034 return cstring_makeLiteralTemp ("<error>");
9037 if (cstring_isDefined (e->etext))
9043 cstring ret = exprNode_doUnparse (e);
9045 /*@-modifies@*/ /* benevolent */
9052 /*@observer@*/ fileloc
9053 exprNode_loc (exprNode e)
9055 if (exprNode_isError (e))
9057 return (g_currentloc);
9066 ** executes exprNode e
9067 ** recursively rexecutes as though in original parse using
9068 ** information in e->edata
9071 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
9073 exprNodeList ret = exprNodeList_new ();
9075 exprNodeList_elements (e, current)
9077 exprNodeList_addh (ret, exprNode_effect (current));
9078 } end_exprNodeList_elements;
9083 static /*@only@*/ exprNode exprNode_effect (exprNode e)
9084 /*@globals internalState@*/
9086 bool innerEffect = inEffect;
9092 context_clearJustPopped ();
9094 if (exprNode_isError (e))
9096 ret = exprNode_undefined;
9101 ** Turn off expose and dependent transfer checking.
9102 ** Need to pass exposed internal nodes,
9103 ** [ copying would be a waste! ]
9104 ** [ Actually, I think I wasted a lot more time than its worth ]
9105 ** [ trying to do this. ]
9109 /*@-observertrans@*/
9110 /*@-dependenttrans@*/
9117 ret = exprNode_addParens (exprData_getUopTok (data),
9118 exprNode_effect (exprData_getUopNode (data)));
9121 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
9122 exprNode_effect (exprData_getOpB (data)),
9123 exprData_getOpTok (data));
9126 ret = exprNode_undefined;
9129 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
9130 exprNodeList_effect (exprData_getArgs (data)));
9143 cstring id = exprData_getId (data);
9144 uentry ue = usymtab_lookupSafe (id);
9146 ret = exprNode_fromIdentifierAux (ue);
9147 ret->loc = fileloc_update (ret->loc, e->loc);
9154 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
9155 exprNode_effect (exprData_getPairB (data)));
9159 ** evans 2002-03-15: for && and ||, need to do the guards also
9160 ** this is what cgrammar.y does - should be
9161 ** able to avoid duplication, but need to
9162 ** time with grammar productions.
9165 DPRINTF (("Effect: %s", exprNode_unparse (e)));
9167 if (lltok_getTok (exprData_getOpTok (data)) == AND_OP)
9169 exprNode e1 = exprNode_effect (exprData_getOpA (data));
9171 exprNode_produceGuards (e1);
9172 context_enterAndClause (e1);
9173 e2 = exprNode_effect (exprData_getOpB (data));
9175 ret = exprNode_op (e1, e2,
9176 exprData_getOpTok (data));
9178 context_exitAndClause (ret, e2);
9180 else if (lltok_getTok (exprData_getOpTok (data)) == OR_OP)
9182 exprNode e1 = exprNode_effect (exprData_getOpA (data));
9184 exprNode_produceGuards (e1);
9185 context_enterOrClause (e1);
9186 e2 = exprNode_effect (exprData_getOpB (data));
9188 ret = exprNode_op (e1, e2,
9189 exprData_getOpTok (data));
9191 context_exitOrClause (ret, e2);
9195 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
9196 exprNode_effect (exprData_getOpB (data)),
9197 exprData_getOpTok (data));
9202 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
9203 exprData_getUopTok (data));
9206 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
9207 exprData_getUopTok (data));
9219 ret = exprNode_vaArg (exprData_getCastTok (data),
9220 exprNode_effect (exprData_getCastNode (data)),
9221 exprData_getCastType (data));
9225 ret = exprNode_cast (exprData_getCastTok (data),
9226 exprNode_effect (exprData_getCastNode (data)),
9227 exprData_getCastType (data));
9230 ret = exprNode_iterStart (exprData_getIterCallIter (data),
9232 (exprData_getIterCallArgs (data)));
9236 ret = exprNode_iter (exprData_getIterSname (data),
9237 exprNodeList_effect (exprData_getIterAlist (data)),
9238 exprNode_effect (exprData_getIterBody (data)),
9239 exprData_getIterEname (data));
9243 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
9244 exprNode_effect (exprData_getPairB (data)));
9248 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
9249 exprNode_effect (exprData_getTripleTest (data)),
9250 exprNode_effect (exprData_getTripleInc (data)));
9254 ret = exprNode_createTok (exprData_getTok (data));
9258 ret = exprNode_goto (exprData_getLiteral (data));
9259 ret->loc = fileloc_update (ret->loc, e->loc);
9263 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
9267 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
9271 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
9274 case XPR_NULLRETURN:
9275 ret = exprNode_nullReturn (exprData_getTok (data));
9279 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
9280 exprNode_effect (exprData_getPairB (data)));
9284 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
9285 exprNode_effect (exprData_getTripleTrue (data)),
9286 exprNode_effect (exprData_getTripleFalse (data)));
9289 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
9290 exprNode_effect (exprData_getPairB (data)));
9294 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
9295 exprNode_effect (exprData_getTripleTrue (data)),
9296 exprNode_effect (exprData_getTripleFalse (data)));
9299 ret = exprNode_whilePred (exprData_getSingle (data));
9303 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
9304 exprNode_effect (exprData_getPairB (data)));
9308 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
9309 exprNode_effect (exprData_getPairB (data)));
9313 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
9317 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
9318 exprData_getUopTok (data));
9322 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
9323 exprNode_effect (exprData_getPairB (data)));
9328 ret = exprNode_caseMarker
9329 (exprNode_effect (exprData_getSingle (data)),
9335 ret = exprNode_createTok (exprData_getTok (data));
9339 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
9340 exprNode_effect (exprData_getPairB (data)));
9344 ret = exprNode_makeInitialization
9345 (exprData_getInitId (data),
9346 exprNode_effect (exprData_getInitNode (data)));
9350 ret = exprNode_fieldAccessAux
9351 (exprNode_effect (exprData_getFieldNode (data)),
9352 exprNode_loc (exprData_getFieldNode (data)),
9353 cstring_copy (exprData_getFieldName (data)));
9357 ret = exprNode_arrowAccessAux
9358 (exprNode_effect (exprData_getFieldNode (data)),
9359 exprNode_loc (exprData_getFieldNode (data)),
9360 cstring_copy (exprData_getFieldName (data)));
9363 case XPR_STRINGLITERAL:
9377 /*@=observertrans@*/
9379 /*@=dependenttrans@*/
9390 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
9395 if (exprNode_isError (e))
9397 return cstring_undefined;
9405 ret = exprNode_rootVarName (exprData_getUopNode (data));
9408 ret = exprNode_rootVarName (exprData_getOpA (data));
9412 ret = exprData_getId (data);
9415 ret = idDecl_getName (exprData_getInitId (data));
9440 case XPR_NULLRETURN:
9462 case XPR_STRINGLITERAL:
9463 ret = cstring_undefined;
9470 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
9475 if (exprNode_isError (e))
9477 static /*@only@*/ cstring error = cstring_undefined;
9479 if (!cstring_isDefined (error))
9481 error = cstring_makeLiteral ("<error>");
9492 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
9495 ret = message ("%s %s %s",
9496 exprNode_unparse (exprData_getOpA (data)),
9497 lltok_unparse (exprData_getOpTok (data)),
9498 exprNode_unparse (exprData_getOpB (data)));
9501 ret = message ("%s(%q)",
9502 exprNode_unparse (exprData_getFcn (data)),
9503 exprNodeList_unparse (exprData_getArgs (data)));
9506 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
9509 ret = cstring_undefined;
9512 ret = message ("%s:", exprData_getId (data));
9516 ret = cstring_copy (exprData_getId (data));
9519 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
9520 exprNode_unparse (exprData_getPairB (data)));
9523 ret = message ("<body>");
9526 ret = message ("%s %s %s",
9527 exprNode_unparse (exprData_getOpA (data)),
9528 lltok_unparse (exprData_getOpTok (data)),
9529 exprNode_unparse (exprData_getOpB (data)));
9533 ret = message ("%s%s",
9534 lltok_unparse (exprData_getUopTok (data)),
9535 exprNode_unparse (exprData_getUopNode (data)));
9539 ret = message ("%s%s",
9540 exprNode_unparse (exprData_getUopNode (data)),
9541 lltok_unparse (exprData_getUopTok (data)));
9545 ret = message ("offsetof(%s,%q)",
9546 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
9547 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
9551 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9555 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
9559 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9563 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
9567 ret = message ("va_arg(%s, %q)",
9568 exprNode_unparse (exprData_getCastNode (data)),
9569 qtype_unparse (exprData_getCastType (data)));
9573 ret = message ("%q(%q)",
9574 uentry_getName (exprData_getIterCallIter (data)),
9575 exprNodeList_unparse (exprData_getIterCallArgs (data)));
9578 ret = message ("%q(%q) %s %q",
9579 uentry_getName (exprData_getIterSname (data)),
9580 exprNodeList_unparse (exprData_getIterAlist (data)),
9581 exprNode_unparse (exprData_getIterBody (data)),
9582 uentry_getName (exprData_getIterEname (data)));
9585 ret = message ("(%q)%s",
9586 qtype_unparse (exprData_getCastType (data)),
9587 exprNode_unparse (exprData_getCastNode (data)));
9591 ret = message ("%s %s",
9592 exprNode_unparse (exprData_getPairA (data)),
9593 exprNode_unparse (exprData_getPairB (data)));
9597 ret = message ("for (%s; %s; %s)",
9598 exprNode_unparse (exprData_getTripleInit (data)),
9599 exprNode_unparse (exprData_getTripleTest (data)),
9600 exprNode_unparse (exprData_getTripleInc (data)));
9604 ret = message ("goto %s", exprData_getLiteral (data));
9608 ret = cstring_makeLiteral ("continue");
9612 ret = cstring_makeLiteral ("break");
9616 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
9619 case XPR_NULLRETURN:
9620 ret = cstring_makeLiteral ("return");
9624 ret = message ("%s, %s",
9625 exprNode_unparse (exprData_getPairA (data)),
9626 exprNode_unparse (exprData_getPairB (data)));
9630 ret = message ("%s ? %s : %s",
9631 exprNode_unparse (exprData_getTriplePred (data)),
9632 exprNode_unparse (exprData_getTripleTrue (data)),
9633 exprNode_unparse (exprData_getTripleFalse (data)));
9636 ret = message ("if (%s) %s",
9637 exprNode_unparse (exprData_getPairA (data)),
9638 exprNode_unparse (exprData_getPairB (data)));
9642 ret = message ("if (%s) %s else %s",
9643 exprNode_unparse (exprData_getTriplePred (data)),
9644 exprNode_unparse (exprData_getTripleTrue (data)),
9645 exprNode_unparse (exprData_getTripleFalse (data)));
9648 ret = message ("while (%s) %s",
9649 exprNode_unparse (exprData_getPairA (data)),
9650 exprNode_unparse (exprData_getPairB (data)));
9654 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9658 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9662 ret = message ("do { %s } while (%s)",
9663 exprNode_unparse (exprData_getPairB (data)),
9664 exprNode_unparse (exprData_getPairA (data)));
9668 ret = message ("{ %s }", exprNode_unparse (exprData_getSingle (data)));
9669 /* evans 2002-02-20 was unparseFirst! */
9673 ret = message ("%s;", exprNode_unparse (exprData_getUopNode (data)));
9677 if (exprNode_isStatement (exprData_getPairA (data)))
9680 ** statement expressions already print the ;
9683 ret = message ("%s %s",
9684 exprNode_unparse (exprData_getPairA (data)),
9685 exprNode_unparse (exprData_getPairB (data)));
9689 ret = message ("%s; %s",
9690 exprNode_unparse (exprData_getPairA (data)),
9691 exprNode_unparse (exprData_getPairB (data)));
9697 ret = cstring_makeLiteral ("default:");
9701 ret = message ("switch (%s) %s",
9702 exprNode_unparse (exprData_getPairA (data)),
9703 exprNode_unparse (exprData_getPairB (data)));
9708 ret = message ("case %s:",
9709 exprNode_unparse (exprData_getSingle (data)));
9713 if (exprNode_isError (exprData_getInitNode (data)))
9715 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9719 ret = message ("%q = %s",
9720 idDecl_unparseC (exprData_getInitId (data)),
9721 exprNode_unparse (exprData_getInitNode (data)));
9726 ret = message ("%s.%s",
9727 exprNode_unparse (exprData_getFieldNode (data)),
9728 exprData_getFieldName (data));
9732 ret = message ("%s->%s",
9733 exprNode_unparse (exprData_getFieldNode (data)),
9734 exprData_getFieldName (data));
9737 case XPR_STRINGLITERAL:
9738 if (ctype_isWideString (e->typ))
9740 ret = message ("L\"%s\"", exprData_getLiteral (data));
9744 ret = message ("\"%s\"", exprData_getLiteral (data));
9749 ret = cstring_copy (exprData_getLiteral (data));
9753 ret = cstring_makeLiteral ("<node>");
9761 exprNode_isInitializer (exprNode e)
9763 return (exprNode_isDefined (e)
9764 && e->kind == XPR_INIT);
9768 exprNode_isCharLiteral (exprNode e)
9770 if (exprNode_isDefined (e))
9772 return (multiVal_isChar (exprNode_getValue (e)));
9781 exprNode_isNumLiteral (exprNode e)
9783 if (exprNode_isDefined (e))
9785 return (multiVal_isInt (exprNode_getValue (e)));
9794 exprNode_isFalseConstant (exprNode e)
9796 if (exprNode_isDefined (e))
9798 cstring s = exprNode_rootVarName (e);
9800 if (cstring_equal (s, context_getFalseName ()))
9810 exprNode_matchLiteral (ctype expected, exprNode e)
9812 if (exprNode_isDefined (e))
9814 multiVal m = exprNode_getValue (e);
9816 if (multiVal_isDefined (m))
9818 if (multiVal_isInt (m))
9820 long int val = multiVal_forceInt (m);
9822 if (ctype_isNumAbstract (expected)
9823 && context_flagOn (FLG_NUMABSTRACTLIT, exprNode_loc (e)))
9828 if (ctype_isDirectBool (ctype_realishType (expected)))
9832 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9840 if (ctype_isRealInt (expected))
9843 ** unsigned <- [ constant >= 0 is okay ]
9846 if (ctype_isUnsigned (expected))
9855 ** No checks on sizes of integers...maybe add
9859 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9860 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9861 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9863 if (context_getFlag (FLG_NUMLITERAL)
9864 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9870 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9874 else if (ctype_isChar (expected))
9878 else if (ctype_isArrayPtr (expected))
9881 ** evans 2001-10-14: We allow 0 to match any pointer, but only if the type matches or is void *.
9886 if (ctype_match (exprNode_getType (e), expected)
9887 || ctype_isVoidPointer (exprNode_getType (e)))
9897 else if (ctype_isAnyFloat (expected))
9899 return (context_getFlag (FLG_NUMLITERAL));
9906 else if (multiVal_isDouble (m))
9908 if (ctype_isAnyFloat (expected))
9913 else if (multiVal_isChar (m))
9915 /*signed? */ char val = multiVal_forceChar (m);
9917 if (ctype_isChar (expected))
9919 if (ctype_isUnsigned (expected) && ((int) val) < 0)
9940 exprNode_matchType (ctype expected, exprNode e)
9944 if (!exprNode_isDefined (e)) return TRUE;
9946 actual = ctype_realishType (exprNode_getType (e));
9948 if (ctype_match (ctype_realishType (expected), actual))
9953 llassert (!exprNode_isError (e));
9954 return (exprNode_matchLiteral (expected, e));
9958 exprNode_matchTypes (exprNode e1, exprNode e2)
9963 if (!exprNode_isDefined (e1)) return TRUE;
9964 if (!exprNode_isDefined (e2)) return TRUE;
9967 ** realish type --- keep bools, bools
9970 t1 = ctype_realishType (exprNode_getType (e1));
9971 t2 = ctype_realishType (exprNode_getType (e2));
9973 if (ctype_match (t1, t2))
9978 DPRINTF (("Matching literal! %s %s %s %s",
9979 ctype_unparse (t1), exprNode_unparse (e2),
9980 ctype_unparse (t2), exprNode_unparse (e1)));
9982 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9990 exprNode_matchArgType (ctype ct, exprNode e)
9994 if (!exprNode_isDefined (e))
9999 et = ctype_realType (exprNode_getType (e));
10001 if (ctype_matchArg (ct, et)) return TRUE;
10003 llassert (!exprNode_isError (e));
10004 return (exprNode_matchLiteral (ct, e));
10007 static /*@only@*/ exprNodeSList
10008 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
10010 if (exprNode_isDefined (e))
10012 if (e->kind == XPR_STMTLIST)
10014 return (exprNodeSList_append
10015 (exprNode_flatten (exprData_getPairA (e->edata)),
10016 exprNode_flatten (exprData_getPairB (e->edata))));
10018 else if (e->kind == XPR_BLOCK)
10020 return (exprNode_flatten (exprData_getSingle (e->edata)));
10024 return (exprNodeSList_singleton (e));
10028 return exprNodeSList_new ();
10031 static /*@exposed@*/ exprNode
10032 exprNode_lastStatement (/*@returned@*/ exprNode e)
10034 if (exprNode_isDefined (e))
10036 if (e->kind == XPR_STMTLIST)
10038 exprNode b = exprData_getPairB (e->edata);
10040 if (exprNode_isDefined (b))
10042 return exprNode_lastStatement (b);
10046 return exprNode_lastStatement (exprData_getPairA (e->edata));
10049 else if (e->kind == XPR_BLOCK)
10051 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
10059 return exprNode_undefined;
10062 static /*@exposed@*/ exprNode
10063 exprNode_firstStatement (/*@returned@*/ exprNode e)
10065 if (exprNode_isDefined (e))
10067 if (e->kind == XPR_STMTLIST)
10069 exprNode b = exprData_getPairA (e->edata);
10071 if (exprNode_isDefined (b))
10073 return exprNode_firstStatement (b);
10077 return exprNode_firstStatement (exprData_getPairB (e->edata));
10080 else if (e->kind == XPR_BLOCK)
10082 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
10090 return exprNode_undefined;
10094 exprNode_mergeUSs (exprNode res, exprNode other)
10096 if (exprNode_isDefined (res) && exprNode_isDefined (other))
10098 res->msets = sRefSet_union (res->msets, other->msets);
10099 res->sets = sRefSet_union (res->sets, other->sets);
10100 res->uses = sRefSet_union (res->uses, other->uses);
10105 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
10107 if (exprNode_isDefined (res))
10109 if (exprNode_isDefined (other1))
10111 res->sets = sRefSet_union (res->sets, other1->sets);
10112 res->msets = sRefSet_union (res->msets, other1->msets);
10113 res->uses = sRefSet_union (res->uses, other1->uses);
10115 if (exprNode_isDefined (other2))
10117 res->sets = sRefSet_union (res->sets, other2->sets);
10118 res->msets = sRefSet_union (res->msets, other2->msets);
10119 res->uses = sRefSet_union (res->uses, other2->uses);
10125 ** modifies e->uses
10127 ** Reports errors is s is not defined.
10131 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
10133 if (exprNode_isDefined (e))
10135 e->uses = sRefSet_insert (e->uses, s);
10140 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
10142 if (sRef_isKnown (s) && !sRef_isConst (s))
10145 ** need to check all outer types are useable
10148 DPRINTF (("Check use: %s / %s",
10149 exprNode_unparse (e), sRef_unparse (s)));
10151 exprNode_addUse (e, s);
10153 if (!context_inProtectVars ())
10156 ** only report the deepest error
10159 sRef errorRef = sRef_undefined;
10160 sRef lastRef = sRef_undefined;
10161 bool deadRef = FALSE;
10162 bool unuseable = FALSE;
10163 bool errorMaybe = FALSE;
10165 while (sRef_isValid (s) && sRef_isKnown (s))
10167 ynm readable = sRef_isValidLvalue (s);
10169 DPRINTF (("Readable: %s / %s",
10170 sRef_unparseFull (s), ynm_unparse (readable)));
10172 if (!(ynm_toBoolStrict (readable)))
10174 if (ynm_isMaybe (readable))
10176 lastRef = errorRef;
10178 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
10179 deadRef = sRef_isPossiblyDead (errorRef);
10180 unuseable = sRef_isUnuseable (errorRef);
10185 lastRef = errorRef;
10187 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
10188 deadRef = sRef_isDead (errorRef);
10189 unuseable = sRef_isUnuseable (errorRef);
10190 errorMaybe = FALSE;
10194 if (!sRef_isPartial (s))
10196 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
10197 sRef_setDefined (s, loc);
10198 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
10203 s = sRef_getBaseSafe (s);
10206 if (sRef_isValid (errorRef))
10208 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
10209 && sRef_isPointer (errorRef))
10211 errorRef = lastRef;
10212 DPRINTF (("errorRef: %s", sRef_unparseFull (errorRef)));
10217 if (sRef_isThroughArrayFetch (errorRef))
10220 (FLG_STRICTUSERELEASED,
10221 message ("%q %q may be used after being released",
10222 sRef_unparseKindNamePlain (errorRef),
10223 sRef_unparse (errorRef)),
10226 sRef_showRefKilled (errorRef);
10228 if (sRef_isKept (errorRef))
10230 sRef_clearAliasState (errorRef, loc);
10236 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
10240 message ("%q %q %qused after being released",
10241 sRef_unparseKindNamePlain (errorRef),
10242 sRef_unparse (errorRef),
10243 cstring_makeLiteral (errorMaybe
10244 ? "may be " : "")),
10247 sRef_showRefKilled (errorRef);
10249 if (sRef_isKept (errorRef))
10251 sRef_clearAliasState (errorRef, loc);
10256 else if (unuseable)
10260 message ("%q %q%qused in inconsistent state",
10261 sRef_unparseKindName (errorRef),
10262 sRef_unparseOpt (errorRef),
10263 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10266 sRef_showStateInconsistent (errorRef);
10271 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
10275 message ("%q %q%qused before definition",
10276 sRef_unparseKindName (errorRef),
10277 sRef_unparseOpt (errorRef),
10278 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10284 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
10287 sRef_setDefined (errorRef, loc);
10289 if (sRef_isAddress (errorRef))
10291 sRef_setDefined (sRef_getRootBase (errorRef), loc);
10293 } /* end is error */
10301 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
10303 if (exprNode_isDefined (e) && sRef_isKnown (s))
10305 e->uses = sRefSet_insert (e->uses, s);
10310 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
10312 if (exprNode_isDefined (e))
10314 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
10319 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
10321 sRef defines = sRef_undefined;
10323 if (sRef_isValid (s) && !sRef_isNothing (s))
10325 uentry ue = sRef_getBaseUentry (s);
10327 if (uentry_isValid (ue))
10329 uentry_setLset (ue);
10332 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10334 voptgenerror (FLG_USEDEF,
10335 message ("Attempt to set unuseable storage: %q",
10340 if (sRef_isMeaningful (s))
10342 if (sRef_isDead (s))
10344 sRef base = sRef_getBaseSafe (s);
10346 if (sRef_isValid (base)
10347 && sRef_isDead (base))
10349 sRef_setPartial (s, exprNode_loc (e));
10352 defines = s; /* okay - modifies for only param */
10354 else if (sRef_isPartial (s))
10356 sRef eref = exprNode_getSref (e);
10358 if (!sRef_isPartial (eref))
10361 ** should do something different here???
10364 sRef_setDefinedComplete (eref, exprNode_loc (e));
10368 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
10371 if (sRef_isMeaningful (eref))
10380 else if (sRef_isAllocated (s))
10382 sRef eref = exprNode_getSref (e);
10385 if (!sRef_isAllocated (eref))
10387 sRef_setDefinedComplete (eref, exprNode_loc (e));
10391 sRef base = sRef_getBaseSafe (eref);
10393 if (sRef_isValid (base))
10395 sRef_setPdefined (base, exprNode_loc (e));
10403 sRef_setDefinedNCComplete (s, exprNode_loc (e));
10408 else /* not meaningful...but still need to insert it */
10414 if (exprNode_isDefined (e) && sRef_isValid (defines))
10416 e->sets = sRefSet_insert (e->sets, defines);
10421 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
10423 if (sRef_isValid (s) && !sRef_isNothing (s))
10425 uentry ue = sRef_getBaseUentry (s);
10427 if (uentry_isValid (ue))
10429 uentry_setLset (ue);
10432 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10434 voptgenerror (FLG_USEDEF,
10435 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
10439 if (sRef_isMeaningful (s))
10441 sRef_setDefinedComplete (s, exprNode_loc (e));
10444 if (exprNode_isDefined (e))
10446 e->msets = sRefSet_insert (e->msets, s);
10452 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
10454 checkAnyCall (fcn, cstring_undefined, params, args,
10455 FALSE, sRefSet_undefined, FALSE, 0);
10459 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
10460 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
10464 if (uentry_isYield (ucurrent))
10466 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
10467 exprNode_checkSet (current, current->sref);
10471 if (uentry_isSefParam (ucurrent))
10473 sRefSet sets = current->sets;
10474 sRef ref = exprNode_getSref (current);
10476 if (sRef_isMacroParamRef (ref))
10478 uentry ue = sRef_getUentry (ref);
10480 if (!uentry_isSefParam (ue))
10485 ("Parameter %d to %s is declared sef, but "
10486 "the argument is a macro parameter declared "
10488 argno, exprNode_unparse (fcn),
10489 exprNode_unparse (current)),
10490 exprNode_loc (current));
10494 if (!sRefSet_isEmpty (sets))
10496 sRefSet reported = sRefSet_undefined;
10498 sRefSet_realElements (current->sets, el)
10500 if (sRefSet_isSameNameMember (reported, el))
10502 ; /* don't report again */
10506 if (sRef_isUnconstrained (el))
10511 ("Parameter %d to %s is declared sef, but "
10512 "the argument calls unconstrained function %s "
10513 "(no guarantee it will not modify something): %s",
10514 argno, exprNode_unparse (fcn),
10515 sRef_unconstrainedName (el),
10516 exprNode_unparse (current)),
10517 exprNode_loc (current));
10524 ("Parameter %d to %s is declared sef, but "
10525 "the argument may modify %q: %s",
10526 argno, exprNode_unparse (fcn),
10528 exprNode_unparse (current)),
10529 exprNode_loc (current));
10532 } end_sRefSet_realElements;
10536 transferChecks_passParam (current, ucurrent, isSpec, fcn, argno, totargs);
10537 exprNode_mergeUSs (fcn, current);
10542 checkAnyCall (/*@dependent@*/ exprNode fcn,
10543 /*@dependent@*/ cstring fname,
10546 bool hasMods, sRefSet mods,
10551 int nargs = exprNodeList_size (args);
10556 ** concat all args ud's to f, add each arg sref as a use unless
10557 ** it was specified as "out", in which case it is a def.
10560 uentryList_reset (pn);
10563 ** aliasing checks:
10565 ** if paramn is only or unique, no other arg may alias argn
10568 exprNodeList_elements (args, current)
10572 if (exprNode_isDefined (current))
10574 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
10576 uentry ucurrent = uentryList_current (pn);
10578 if (specialArgs == 0
10579 || (paramno < specialArgs))
10581 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
10583 if (context_maybeSet (FLG_ALIASUNIQUE))
10585 if (uentry_isOnly (ucurrent)
10586 || uentry_isUnique (ucurrent))
10588 checkUniqueParams (fcn, current, args,
10589 paramno, ucurrent);
10594 else /* uentry is undefined */
10596 if (specialArgs == 0)
10598 exprNode_checkUseParam (current);
10601 exprNode_mergeUSs (fcn, current);
10604 uentryList_advanceSafe (pn);
10605 } end_exprNodeList_elements;
10611 sRefSet_allElements (mods, s)
10614 sRef rb = sRef_getRootBase (s);
10616 if (sRef_isFileOrGlobalScope (rb))
10618 context_usedGlobal (rb);
10621 fb = sRef_fixBaseParam (s, args);
10623 if (!sRef_isMacroParamRef (fb))
10625 if (sRef_isNothing (fb))
10631 if (sRef_isValid (fb))
10633 uentry ue = sRef_getBaseUentry (s);
10635 if (uentry_isValid (ue))
10637 uentry_setLset (ue);
10641 fcn->sets = sRefSet_insert (fcn->sets, fb);
10644 sRef_clearDerivedComplete (s);
10645 } end_sRefSet_allElements;
10651 if (context_hasMods ())
10653 if (context_maybeSet (FLG_MODUNCON))
10657 message ("Undetected modification possible "
10658 "from call to unconstrained function %s: %s",
10660 exprNode_unparse (fcn)),
10661 exprNode_loc (fcn));
10666 if (context_maybeSet (FLG_MODUNCONNOMODS)
10667 && !(context_inIterDef () || context_inIterEnd ()))
10670 (FLG_MODUNCONNOMODS,
10671 message ("Undetected modification possible "
10672 "from call to unconstrained function %s: %s",
10674 exprNode_unparse (fcn)),
10675 exprNode_loc (fcn));
10679 exprNode_checkSetAny (fcn, fname);
10683 void exprNode_checkUseParam (exprNode current)
10685 if (exprNode_isDefined (current))
10687 exprNode_checkUse (current, current->sref, current->loc);
10692 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10693 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10698 if (!ctype_match (tr1, tr2))
10700 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10701 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10703 DPRINTF (("No error: [%s] %s / [%s] %s",
10704 exprNode_unparse (e1), ctype_unparse (tr1),
10705 exprNode_unparse (e2), ctype_unparse (tr2)));
10708 ** evans 2003-06-15: changed this so if either type is a literal,
10709 ** the other type is used.
10710 ** (Need to look at the ISO C99 rules on this...)
10713 if (exprNode_isNumLiteral (e1)) {
10715 } else if (exprNode_isNumLiteral (e2)) {
10718 ret = ctype_biggerType (tr1, tr2);
10723 if (ctype_isNumAbstract (tr1)
10724 && exprNode_isNumLiteral (e2)
10725 && context_flagOn (FLG_NUMABSTRACTLIT, e1->loc))
10727 ret = tr1; /* No error */
10729 else if (ctype_isNumAbstract (tr2)
10730 && exprNode_isNumLiteral (e1)
10731 && context_flagOn (FLG_NUMABSTRACTLIT, e1->loc))
10739 message ("Incompatible types for %s (%s, %s): %s %s %s",
10740 lltok_unparse (op),
10741 ctype_unparse (te1),
10742 ctype_unparse (te2),
10743 exprNode_unparse (e1), lltok_unparse (op),
10744 exprNode_unparse (e2)),
10747 ret = ctype_unknown;
10751 ret = ctype_biggerType (tr1, tr2);
10758 if (ctype_isNumAbstract (tr1))
10762 else if (ctype_isForceRealNumeric (&tr1)
10763 && ctype_isForceRealNumeric (&tr2))
10765 ret = ctype_resolveNumerics (tr1, tr2);
10767 else if (!context_msgStrictOps ())
10769 if (ctype_isPointer (tr1))
10771 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10775 else if (ctype_isInt (tr2))
10781 ret = ctype_unknown;
10784 else if (ctype_isPointer (tr2))
10786 if (ctype_isPointer (tr1))
10790 else if (ctype_isInt (tr1))
10796 ret = ctype_unknown;
10801 ret = ctype_resolveNumerics (tr1, tr2);
10806 int opid = lltok_getTok (op);
10807 bool comparop = (opid == EQ_OP || opid == NE_OP
10808 || opid == TLT || opid == TGT
10809 || opid == LE_OP || opid == GE_OP);
10811 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10814 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10815 || (ctype_isBool (tr1) && ctype_isBool (tr2))
10816 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10822 if (ctype_sameName (te1, te2))
10826 message ("Operands of %s are non-numeric (%t): %s %s %s",
10827 lltok_unparse (op), te1,
10828 exprNode_unparse (e1), lltok_unparse (op),
10829 exprNode_unparse (e2)),
10836 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10837 lltok_unparse (op), te1, te2,
10838 exprNode_unparse (e1), lltok_unparse (op),
10839 exprNode_unparse (e2)),
10844 else if (!ctype_isNumeric (tr1))
10848 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10849 lltok_unparse (op), te1,
10850 exprNode_unparse (e1), lltok_unparse (op),
10851 exprNode_unparse (e2)),
10856 if (!ctype_isNumeric (tr2))
10860 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10861 lltok_unparse (op), te2,
10862 exprNode_unparse (e1), lltok_unparse (op),
10863 exprNode_unparse (e2)),
10868 ret = ctype_unknown;
10876 abstractOpError (ctype tr1, ctype tr2, lltok op,
10877 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10878 fileloc loc1, fileloc loc2)
10880 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10882 if (ctype_match (tr1, tr2))
10884 if (ctype_isRealNumAbstract (tr1))
10886 ; /* No warning for numabstract types */
10890 if (lltok_isEqOp (op) || lltok_isNotEqOp (op))
10893 (FLG_ABSTRACTCOMPARE,
10894 message ("Object equality comparison (%s) on objects of abstract type (%t): %s %s %s",
10895 lltok_unparse (op), tr1,
10896 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10903 message ("Operands of %s are abstract type (%t): %s %s %s",
10904 lltok_unparse (op), tr1,
10905 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10912 if (ctype_isRealNumAbstract (tr1) && ctype_isRealNumAbstract (tr2))
10917 ("Operands of %s are different numabstract types (%t, %t): %s %s %s",
10918 lltok_unparse (op), tr1, tr2,
10919 exprNode_unparse (e1),
10920 lltok_unparse (op), exprNode_unparse (e2)),
10927 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10928 lltok_unparse (op), tr1, tr2,
10929 exprNode_unparse (e1), lltok_unparse (op),
10930 exprNode_unparse (e2)),
10935 else if (ctype_isRealAbstract (tr1) && !ctype_isRealNumAbstract (tr1))
10939 message ("Left operand of %s is abstract type (%t): %s %s %s",
10940 lltok_unparse (op), tr1,
10941 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10946 if (ctype_isRealAbstract (tr2) && !ctype_isRealNumAbstract (tr2))
10950 message ("Right operand of %s is abstract type (%t): %s %s %s",
10951 lltok_unparse (op), tr2,
10952 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10963 ** requies e1 and e2 and not error exprNode's.
10967 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10968 ** the rep of the abstract type is exposed.
10970 ** The order is very important:
10972 ** check rep expose (move into check transfer)
10978 ** This isn't really a sensible procedure, but the indententation
10979 ** was getting too deep.
10983 checkOneRepExpose (sRef ysr, sRef base,
10984 /*@notnull@*/ exprNode e1,
10985 /*@notnull@*/ exprNode e2, ctype ct,
10988 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
10989 || sRef_isOwned (ysr)
10990 || sRef_isExposed (ysr)))
10992 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10993 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10996 if (sRef_isIReference (ysr))
10998 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
11003 ("Assignment of mutable component of parameter %q "
11004 "to component of abstract "
11005 "type %s exposes rep: %s = %s",
11006 sRef_unparse (base),
11007 ctype_unparse (ct),
11008 exprNode_unparse (e1), exprNode_unparse (e2)),
11016 ("Assignment of mutable component of parameter %q "
11017 "(through alias %q) to component of abstract "
11018 "type %s exposes rep: %s = %s",
11019 sRef_unparse (base),
11020 sRef_unparse (e2->sref),
11021 ctype_unparse (ct),
11022 exprNode_unparse (e1), exprNode_unparse (e2)),
11028 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
11032 message ("Assignment of mutable parameter %q "
11033 "to component of abstract type %s "
11034 "exposes rep: %s = %s",
11035 sRef_unparse (base),
11036 ctype_unparse (ct),
11037 exprNode_unparse (e1),
11038 exprNode_unparse (e2)),
11045 message ("Assignment of mutable parameter %q "
11046 "(through alias %q) to "
11047 "component of abstract type %s exposes "
11049 sRef_unparse (base),
11050 sRef_unparse (e2->sref),
11051 ctype_unparse (ct),
11052 exprNode_unparse (e1),
11053 exprNode_unparse (e2)),
11059 if (sRef_isFileOrGlobalScope (s2b))
11061 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
11065 message ("Assignment of global %q "
11067 "abstract type %s exposes rep: %s = %s",
11068 sRef_unparse (base),
11069 ctype_unparse (ct),
11070 exprNode_unparse (e1), exprNode_unparse (e2)),
11077 message ("Assignment of global %q (through alias %q) "
11079 "abstract type %s exposes rep: %s = %s",
11080 sRef_unparse (base),
11081 sRef_unparse (e2->sref),
11082 ctype_unparse (ct),
11083 exprNode_unparse (e1), exprNode_unparse (e2)),
11091 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
11093 DPRINTF (("Do assign: %s <- %s",
11094 exprNode_unparse (e1), exprNode_unparse (e2)));
11095 DPRINTF (("Ctype: %s", ctype_unparse (exprNode_getType (e1))));
11097 if (ctype_isRealFunction (exprNode_getType (e1))
11098 && !ctype_isRealPointer (exprNode_getType (e1)))
11102 message ("Invalid left-hand side of assignment (function type %s): %s",
11103 ctype_unparse (exprNode_getType (e1)),
11104 exprNode_unparse (e1)),
11108 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
11110 ctype t2 = exprNode_getType (e2);
11111 sRef sr = sRef_getRootBase (e1->sref);
11112 ctype ct = sRef_getType (sr);
11114 if (ctype_isAbstract (t2)
11115 && !ctype_isNumAbstract (t2)
11116 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
11118 /* it is immutable, okay to reference */
11119 goto donerepexpose;
11122 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
11124 sRef s2b = sRef_getRootBase (e2->sref);
11125 sRef s1 = e1->sref;
11126 sRef s1b = sRef_getRootBase (s1);
11129 aliases = usymtab_canAlias (e2->sref);
11131 if (!sRef_similar (s2b, s1b)
11132 && !sRef_isExposed (s1)
11133 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
11135 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
11136 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
11137 && !sRef_isExposed (s2b))
11139 if (sRef_isIReference (e2->sref))
11144 ("Assignment of mutable component of parameter %q "
11145 "to component of abstract type %s exposes rep: %s = %s",
11146 sRef_unparse (s2b),
11147 ctype_unparse (ct),
11148 exprNode_unparse (e1), exprNode_unparse (e2)),
11155 message ("Assignment of mutable parameter %q to "
11156 "component of abstract type %s exposes rep: %s = %s",
11157 sRef_unparse (s2b),
11158 ctype_unparse (ct),
11159 exprNode_unparse (e1), exprNode_unparse (e2)),
11164 if (sRef_isFileOrGlobalScope (s2b))
11168 message ("Assignment of global %q to component of "
11169 "abstract type %s exposes rep: %s = %s",
11170 sRef_unparse (s2b),
11171 ctype_unparse (ct),
11172 exprNode_unparse (e1), exprNode_unparse (e2)),
11176 sRefSet_realElements (aliases, ysr)
11178 sRef base = sRef_getRootBase (ysr);
11180 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
11181 || sRef_sameName (base, s1b))
11183 ; /* error already reported or same sref */
11187 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
11189 } end_sRefSet_realElements;
11191 sRefSet_free (aliases);
11198 ** function variables don't really work...
11201 if (!ctype_isFunction (ctype_realType (e2->typ)))
11205 DPRINTF (("Check init: %s / %s",
11206 exprNode_unparse (e1), exprNode_unparse (e2)));
11207 transferChecks_initialization (e1, e2);
11211 transferChecks_assign (e1, e2);
11216 sRef fref = e2->sref;
11218 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
11219 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
11221 /* Need to typecheck the annotation on the parameters */
11223 if (ctype_isRealFunction (e1->typ)) {
11224 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
11225 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
11227 if (!uentryList_isMissingParams (e1p)
11228 && !uentryList_isMissingParams (e2p)
11229 && uentryList_size (e1p) > 0) {
11230 if (uentryList_size (e1p) == uentryList_size (e2p)) {
11233 uentryList_elements (e1p, el1) {
11236 el2 = uentryList_getN (e2p, n);
11238 uentry_checkMatchParam (el1, el2, n, e2);
11239 } end_uentryList_elements;
11245 if (exprNode_isStringLiteral (e2))
11247 exprNode_checkStringLiteralLength (exprNode_getType (e1), e2);
11250 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
11256 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
11257 updateAliases (e1, e2);
11262 checkMacroParen (exprNode e)
11264 if (exprNode_isError (e) || e->kind == XPR_CAST)
11270 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
11274 message ("Macro parameter used without parentheses: %s",
11275 exprNode_unparse (e)),
11282 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
11286 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
11290 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
11297 ** if e2 is a parameter or global derived location which
11298 ** can be modified (that is, e2 is a mutable abstract type,
11299 ** or a derived pointer), then e1 can alias e2.
11301 ** e1 can alias everything which e2 can alias.
11303 ** Also, if e1 is guarded, remove from guard sets!
11306 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
11308 if (!context_inProtectVars ())
11311 ** depends on types of e1 and e2
11314 sRef s1 = e1->sref;
11315 sRef s2 = e2->sref;
11316 ctype t1 = exprNode_getType (e1);
11318 /* handle pointer sRefs, record fields, arrays, etc... */
11320 if (!ctype_isRealSU (t1))
11322 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
11323 sRef_copyRealDerivedComplete (s1, s2);
11328 ** Fields should alias
11331 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
11334 if (ctype_isMutable (t1) && sRef_isKnown (s1))
11336 usymtab_clearAlias (s1);
11337 usymtab_addMustAlias (s1, s2);
11338 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
11342 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
11345 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
11347 usymtab_unguard (s1);
11352 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
11354 if (exprNode_isDefined (e))
11356 e->loc = fileloc_update (e->loc, loc);
11360 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
11366 static void checkUniqueParams (exprNode fcn,
11367 /*@notnull@*/ exprNode current,
11369 int paramno, uentry ucurrent)
11372 sRef thisref = exprNode_getSref (current);
11375 ** Check if any argument could match this argument.
11378 exprNodeList_elements (args, icurrent)
11382 if (iparamno != paramno)
11384 sRef sr = exprNode_getSref (icurrent);
11386 if (sRef_similarRelaxed (thisref, sr))
11388 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
11393 ("Parameter %d (%s) to function %s is declared %s but "
11394 "is aliased by parameter %d (%s)",
11396 exprNode_unparse (current),
11397 exprNode_unparse (fcn),
11398 alkind_unparse (uentry_getAliasKind (ucurrent)),
11399 iparamno, exprNode_unparse (icurrent)),
11405 sRefSet aliases = usymtab_canAlias (sr);
11407 sRefSet_allElements (aliases, asr)
11409 if (ctype_isUnknown (sRef_getType (thisref)))
11411 sRef_setType (thisref, uentry_getType (ucurrent));
11414 if (sRef_similarRelaxed (thisref, asr))
11416 if (sRef_isExternal (asr))
11418 if (sRef_isLocalState (thisref))
11424 sRef base = sRef_getRootBase (asr);
11426 if (!sRef_similar (sRef_getBase (asr), thisref))
11428 if (sRef_isUnique (base) || sRef_isOnly (base)
11429 || sRef_isKept (base)
11430 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
11431 || (sRef_isAddress (thisref)
11432 && sRef_isLocalVar (sRef_getRootBase (thisref))))
11434 ; /* okay, no error */
11439 (FLG_MAYALIASUNIQUE,
11441 ("Parameter %d (%s) to function %s is declared %s but "
11442 "may be aliased externally by parameter %d (%s)",
11444 exprNode_unparse (current),
11445 exprNode_unparse (fcn),
11446 alkind_unparse (uentry_getAliasKind (ucurrent)),
11447 iparamno, exprNode_unparse (icurrent)),
11458 ("Parameter %d (%s) to function %s is declared %s but "
11459 "is aliased externally by parameter %d (%s) through "
11462 exprNode_unparse (current),
11463 exprNode_unparse (fcn),
11464 alkind_unparse (uentry_getAliasKind (ucurrent)),
11465 iparamno, exprNode_unparse (icurrent),
11466 sRef_unparse (asr)),
11470 } end_sRefSet_allElements;
11471 sRefSet_free (aliases);
11474 } end_exprNodeList_elements;
11477 long exprNode_getLongValue (exprNode e)
11481 if (exprNode_hasValue (e) && multiVal_isInt (exprNode_getValue (e)))
11483 value = multiVal_forceInt (exprNode_getValue (e));
11487 value = 0; /* Unknown value */
11493 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
11496 ** Returns the location of the sequence point following e.
11498 ** Only works for statements (for now).
11501 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
11502 lltok t = exprData_getUopTok (e->edata);
11503 return fileloc_copy(lltok_getLoc (t));
11505 /* drl possible problem : warning fix
11506 llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
11508 return fileloc_undefined;
11512 exprNode exprNode_createNew(ctype c)
11516 ret = exprNode_createPlain (c);
11521 bool exprNode_isInitBlock (exprNode e)
11523 return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);
11526 /*drl 3/2/2003 moved this function out of constraint.c */
11527 exprNode exprNode_copyConstraints (/*@returned@*/ exprNode dst, exprNode src)
11530 llassert (exprNode_isDefined (dst) );
11531 llassert (exprNode_isDefined (src) );
11533 constraintList_free (dst->ensuresConstraints);
11534 constraintList_free (dst->requiresConstraints);
11535 constraintList_free (dst->trueEnsuresConstraints);
11536 constraintList_free (dst->falseEnsuresConstraints);
11538 dst->ensuresConstraints = constraintList_copy (src->ensuresConstraints);
11539 dst->requiresConstraints = constraintList_copy (src->requiresConstraints);
11540 dst->trueEnsuresConstraints = constraintList_copy (src->trueEnsuresConstraints);
11541 dst->falseEnsuresConstraints = constraintList_copy (src->falseEnsuresConstraints);
11545 void exprNode_revealState (exprNode e)
11547 if (exprNode_isDefined (e)) {
11548 llmsg (message ("%s: State of %s: %s", fileloc_unparse (exprNode_loc (e)),
11549 exprNode_unparse (e), sRef_unparseFull (e->sref)));
11551 llmsg (message ("%s: Reveal state undefined", fileloc_unparse (g_currentloc)));