2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
28 # include <ctype.h> /* for isdigit */
29 # include "splintMacros.nf"
31 # include "cgrammar.h"
32 # include "cscanner.h"
33 # include "cscannerHelp.h"
34 # include "cgrammar_tokens.h"
36 # include "exprChecks.h"
37 # include "transferChecks.h"
38 # include "exprNodeSList.h"
40 static bool exprNode_sameStorage (exprNode p_e1, exprNode p_e2) /*@*/ ;
41 static bool exprNode_isEmptyStatement (exprNode p_e);
42 static /*@exposed@*/ exprNode exprNode_firstStatement (/*@returned@*/ exprNode p_e);
43 static bool exprNode_isFalseConstant (exprNode p_e) /*@*/ ;
44 static bool exprNode_isStatement (exprNode p_e);
45 static void checkGlobUse (uentry p_glob, bool p_isCall, /*@notnull@*/ exprNode p_e);
46 static void exprNode_addUse (exprNode p_e, /*@exposed@*/ sRef p_s);
47 static bool exprNode_matchArgType (ctype p_ct, exprNode p_e);
48 static exprNode exprNode_fakeCopy (exprNode p_e) /*@*/ ;
49 static exprNode exprNode_statementError (/*@only@*/ exprNode p_e, /*@only@*/ lltok p_t);
50 static bool exprNode_matchTypes (exprNode p_e1, exprNode p_e2);
51 static void checkUniqueParams (exprNode p_fcn,
52 /*@notnull@*/ exprNode p_current, exprNodeList p_args,
53 int p_paramno, uentry p_ucurrent);
54 static void updateAliases (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2);
55 static bool abstractOpError (ctype p_tr1, ctype p_tr2, lltok p_op,
56 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2,
57 fileloc p_loc1, fileloc p_loc2)
58 /*@modifies g_warningstream@*/ ;
59 static ctype checkNumerics (ctype p_tr1, ctype p_tr2, ctype p_te1, ctype p_te2,
60 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, lltok p_op);
61 static void doAssign (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, bool p_isInit);
62 static void checkSafeUse (exprNode p_e, /*@exposed@*/ sRef p_s);
63 static void reflectNullTest (/*@notnull@*/ exprNode p_e, bool p_isnull);
64 static void checkMacroParen (exprNode p_e);
65 static exprNodeSList exprNode_flatten (/*@dependent@*/ exprNode p_e);
66 static void exprNode_checkSetAny (exprNode p_e, /*@dependent@*/ cstring p_name);
67 static void exprNode_checkUse (exprNode p_e, /*@exposed@*/ sRef p_s, fileloc p_loc);
68 static void exprNode_mergeUSs (exprNode p_res, exprNode p_other);
69 static void exprNode_mergeCondUSs (exprNode p_res, exprNode p_other1, exprNode p_other2);
70 static /*@only@*/ /*@notnull@*/ exprNode exprNode_fromIdentifierAux (/*@observer@*/ uentry p_c);
71 static void checkAnyCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn,
72 /*@dependent@*/ cstring p_fname,
73 uentryList p_pn, exprNodeList p_args,
74 bool p_hasMods, sRefSet p_mods, bool p_isSpec,
76 static void checkOneArg (uentry p_ucurrent, /*@notnull@*/ exprNode p_current,
77 /*@dependent@*/ exprNode p_fcn, bool p_isSpec, int p_argno, int p_totargs);
79 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn, uentryList p_params, exprNodeList p_args);
81 static /*@only@*/ exprNode exprNode_effect (exprNode p_e)
82 /*@globals internalState@*/ ;
83 static /*@only@*/ cstring exprNode_doUnparse (exprNode p_e);
84 static /*@observer@*/ cstring exprNode_rootVarName (exprNode p_e);
85 static /*@exposed@*/ exprNode
86 exprNode_lastStatement (/*@returned@*/ exprNode p_e);
88 static /*@only@*/ exprNode s_mustExitNode = exprNode_undefined;
90 static int checkArgsReal (uentry p_fcn, /*@dependent@*/ exprNode p_f,
92 exprNodeList p_args, bool p_isIter, exprNode p_ret);
94 static bool inEffect = FALSE;
95 static int nowalloc = 0;
96 static int totalloc = 0;
97 static int maxalloc = 0;
99 static /*@only@*/ uentry regArg;
100 static /*@only@*/ uentry outArg;
101 static /*@only@*/ uentry outStringArg;
102 static /*@exposed@*/ sRef stdinRef;
103 static /*@exposed@*/ sRef stdoutRef;
104 static /*@only@*/ uentry csArg;
105 static /*@only@*/ uentry csOnlyArg;
106 static ctype cstringType;
107 static ctype ctypeType;
108 static ctype filelocType;
109 static bool initMod = FALSE;
111 /*@function void exprNode_swap (sef exprNode, sef exprNode)@*/
113 # define exprNode_swap(e1,e2) do { exprNode m_tmp = (e1); (e1) = (e2); (e2) = m_tmp; } while (FALSE)
116 static void exprNode_defineConstraints(/*@sef@*/ /*@special@*/ /*@notnull@*/ exprNode e)
117 /*@defines e->requiresConstraints, e->ensuresConstraints,
118 e->trueEnsuresConstraints, e->falseEnsuresConstraints @*/
120 e->requiresConstraints = constraintList_makeNew ();
121 e->ensuresConstraints = constraintList_makeNew ();
122 e->trueEnsuresConstraints = constraintList_makeNew ();
123 e->falseEnsuresConstraints = constraintList_makeNew ();
127 ** must occur after library has been read
130 void exprNode_initMod (void)
131 /*@globals undef regArg, undef outArg, undef outStringArg,
132 undef csOnlyArg, undef csArg;
139 cstringType = ctype_unknown;
140 ctypeType = ctype_unknown;
141 filelocType = ctype_unknown;
143 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
145 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
148 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
150 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
153 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
155 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
158 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdin")))
160 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdin"));
162 else /* define stdin */
164 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdin"),
166 fileloc_getBuiltin (),
168 uentry_setHasNameError (ue);
169 ue = usymtab_supGlobalEntryReturn (ue);
172 stdinRef = sRef_makePointer (uentry_getSref (ue));
174 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdout")))
176 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdout"));
180 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdout"),
182 fileloc_getBuiltin (),
184 uentry_setHasNameError (ue);
185 ue = usymtab_supGlobalEntryReturn (ue);
188 stdoutRef = sRef_makePointer (uentry_getSref (ue));
190 tmp = idDecl_create (cstring_undefined, qtype_create (ctype_unknown));
192 regArg = uentry_makeParam (tmp, PARAMUNKNOWN);
195 qtype_addQual (qtype_create (ctype_makePointer (ctype_unknown)),
198 outArg = uentry_makeParam (tmp, PARAMUNKNOWN);
200 idDecl_setTyp (tmp, qtype_addQual (qtype_create (ctype_string),
203 outStringArg = uentry_makeParam (tmp, PARAMUNKNOWN);
205 idDecl_setTyp (tmp, qtype_addQual (qtype_addQual (qtype_create (cstringType),
207 qual_createNull ()));
209 csOnlyArg = uentry_makeParam (tmp, PARAMUNKNOWN);
211 idDecl_setTyp (tmp, qtype_addQual (qtype_create (cstringType), qual_createNull ()));
212 csArg = uentry_makeParam (tmp, PARAMUNKNOWN);
218 exprNode_destroyMod (void)
219 /*@globals killed regArg, killed outArg, killed outStringArg,
220 killed s_mustExitNode, initMod @*/
224 /* evans 2002-07-12: changed uentry_free to uentry_freeComplete */
225 uentry_freeComplete (regArg);
226 uentry_freeComplete (outArg);
227 uentry_freeComplete (outStringArg);
229 exprNode_free (s_mustExitNode);
236 static void exprNode_resetSref (/*@notnull@*/ exprNode e)
238 e->sref = sRef_undefined;
241 exprNode exprNode_fakeCopy (exprNode e)
243 /*@-temptrans@*/ /*@-retalias@*/
245 /*@=temptrans@*/ /*@=retalias@*/
248 static bool isFlagKey (char key)
250 return (key == '-' || key == '+' || key == ' ' || key == '#');
253 static void exprNode_combineControl (/*@notnull@*/ exprNode ret,
254 /*@notnull@*/ exprNode ifclause,
255 /*@notnull@*/ exprNode elseclause)
257 ret->canBreak = ifclause->canBreak || elseclause->canBreak;
260 (ifclause->mustBreak || exprNode_mustEscape (ifclause))
261 && (elseclause->mustBreak || exprNode_mustEscape (elseclause));
263 ret->exitCode = exitkind_combine (ifclause->exitCode,
264 elseclause->exitCode);
269 ** For exprNode's returned by exprNode_effect.
272 static bool shallowKind (exprKind kind)
274 return (kind == XPR_STRINGLITERAL
275 || kind == XPR_NUMLIT
278 || kind == XPR_NODE);
282 exprNode_freeIniter (/*@only@*/ exprNode e)
284 if (!exprNode_isError (e))
290 ** Its a fake copy, don't free the field->rec and field->field
295 sfree (e->edata->field);
301 exprNode_free (e->edata->op->b);
302 /*@-compdestroy@*/ sfree (e->edata->op); /*@=compdestroy@*/
306 llbug (message ("other: %s", exprNode_unparse (e)));
309 multiVal_free (e->val);
310 cstring_free (e->etext);
311 fileloc_free (e->loc);
312 sRefSet_free (e->uses);
313 sRefSet_free (e->sets);
314 sRefSet_free (e->msets);
315 guardSet_free (e->guards);
317 constraintList_free(e->requiresConstraints);
318 constraintList_free(e->ensuresConstraints);
319 constraintList_free(e->trueEnsuresConstraints);
320 constraintList_free(e->falseEnsuresConstraints);
322 e->requiresConstraints = NULL;
323 e->ensuresConstraints = NULL;
324 e->trueEnsuresConstraints = NULL;
325 e->falseEnsuresConstraints = NULL;
332 exprNode_freeShallow (/*@only@*/ exprNode e)
334 if (!exprNode_isError (e))
336 if (shallowKind (e->kind))
343 if (e->kind == XPR_EMPTY
344 || e->kind == XPR_BODY
345 || e->kind == XPR_STRINGLITERAL
346 || e->kind == XPR_NUMLIT
347 || e->kind == XPR_NODE
348 || e->kind == XPR_OFFSETOF
349 || e->kind == XPR_ALIGNOFT
350 || e->kind == XPR_ALIGNOF
351 || e->kind == XPR_SIZEOFT
352 || e->kind == XPR_SIZEOF)
354 /* don't free anything */
358 /* multiVal_free (e->val); */
359 cstring_free (e->etext);
360 fileloc_free (e->loc);
361 sRefSet_free (e->uses);
362 sRefSet_free (e->sets);
363 sRefSet_free (e->msets);
364 guardSet_free (e->guards);
365 exprData_freeShallow (e->edata, e->kind);
367 /*@-compdestroy@*/ sfree (e); /*@=compdestroy@*/
376 exprNode_free (exprNode e)
378 if (!exprNode_isError (e))
382 multiVal_free (e->val);
383 cstring_free (e->etext);
384 fileloc_free (e->loc);
385 sRefSet_free (e->uses);
386 sRefSet_free (e->sets);
387 sRefSet_free (e->msets);
388 guardSet_free (e->guards);
389 exprData_free (e->edata, e->kind);
391 constraintList_free(e->requiresConstraints);
392 constraintList_free(e->ensuresConstraints);
393 constraintList_free(e->trueEnsuresConstraints);
394 constraintList_free(e->falseEnsuresConstraints);
396 e->requiresConstraints = NULL;
397 e->ensuresConstraints = NULL;
398 e->trueEnsuresConstraints = NULL;
399 e->falseEnsuresConstraints = NULL;
409 exprNode_makeError ()
411 return exprNode_undefined;
414 static /*@out@*/ /*@only@*/ /*@notnull@*/ exprNode
417 exprNode ret = (exprNode) dmalloc (sizeof (*ret));
418 /* static int lastexpnodes = 0; */
423 if (nowalloc > maxalloc)
431 static /*@notnull@*/ /*@special@*/ exprNode
432 exprNode_createPlain (ctype c)
434 /*@ensures isnull result->edata, result->loc, result->val, result->guards,
435 result->uses, result->sets, result->msets, result->etext @*/
438 exprNode e = exprNode_new ();
442 e->val = multiVal_undefined;
443 e->sref = sRef_undefined;
444 e->etext = cstring_undefined;
445 e->loc = fileloc_undefined;
446 e->guards = guardSet_undefined;
447 e->uses = sRefSet_undefined;
448 e->sets = sRefSet_undefined;
449 e->msets = sRefSet_undefined;
450 e->edata = exprData_undefined;
451 e->exitCode = XK_NEVERESCAPE;
453 e->mustBreak = FALSE;
454 e->isJumpPoint = FALSE;
456 exprNode_defineConstraints(e);
461 /*@observer@*/ exprNode exprNode_makeMustExit (void)
463 if (exprNode_isUndefined (s_mustExitNode))
465 s_mustExitNode = exprNode_createPlain (ctype_unknown);
466 s_mustExitNode->exitCode = XK_MUSTEXIT;
469 return s_mustExitNode;
473 static /*@notnull@*/ /*@special@*/ exprNode exprNode_create (ctype c)
475 /*@post:isnull result->edata, result->guards, result->val,
476 result->uses, result->sets, result->msets@*/
479 exprNode e = exprNode_createPlain (c);
480 e->loc = fileloc_copy (g_currentloc);
484 static /*@notnull@*/ /*@special@*/ exprNode exprNode_createUnknown (void)
486 /*@post:isnull result->edata, result->guards,
487 result->uses, result->sets, result->msets@*/
490 return (exprNode_create (ctype_unknown));
493 static /*@notnull@*/ /*@special@*/ exprNode
494 exprNode_createLoc (ctype c, /*@keep@*/ fileloc loc)
496 /*@post:isnull result->edata, result->guards, result->val,
497 result->uses, result->sets, result->msets@*/
500 exprNode e = exprNode_createPlain (c);
506 exprNode_copySets (/*@special@*/ /*@notnull@*/ exprNode ret, exprNode e)
507 /*@defines ret->guards, ret->uses, ret->sets, ret->msets@*/
509 if (exprNode_isDefined (e))
511 ret->guards = guardSet_copy (e->guards);
512 ret->uses = sRefSet_newCopy (e->uses);
513 ret->sets = sRefSet_newCopy (e->sets);
514 ret->msets = sRefSet_newCopy (e->msets);
518 ret->guards = guardSet_undefined;
519 ret->uses = sRefSet_undefined;
520 ret->sets = sRefSet_undefined;
521 ret->msets = sRefSet_undefined;
525 static /*@notnull@*/ /*@special@*/ exprNode
526 exprNode_createPartialLocCopy (exprNode e, /*@only@*/ fileloc loc)
528 /*@post:isnull result->edata, result->etext@*/
531 exprNode ret = exprNode_new ();
533 if (exprNode_isError (e))
535 ret->typ = ctype_unknown;
536 ret->val = multiVal_undefined;
538 ret->guards = guardSet_undefined;
539 ret->uses = sRefSet_undefined;
540 ret->sets = sRefSet_undefined;
541 ret->msets = sRefSet_undefined;
546 ret->val = multiVal_copy (e->val);
548 ret->guards = guardSet_copy (e->guards);
549 ret->uses = sRefSet_newCopy (e->uses);
550 ret->sets = sRefSet_newCopy (e->sets);
551 ret->msets = sRefSet_newCopy (e->msets);
554 ret->kind = XPR_EMPTY;
555 ret->sref = sRef_undefined;
556 ret->etext = cstring_undefined;
557 ret->exitCode = XK_NEVERESCAPE;
558 ret->canBreak = FALSE;
559 ret->mustBreak = FALSE;
560 ret->isJumpPoint = FALSE;
561 ret->edata = exprData_undefined;
563 exprNode_defineConstraints(ret);
569 static /*@notnull@*/ /*@special@*/ exprNode
570 exprNode_createPartialCopy (exprNode e)
572 /*@post:isnull result->edata, result->etext@*/
575 return (exprNode_createPartialLocCopy (e, fileloc_copy (exprNode_loc (e))));
578 static /*@notnull@*/ /*@special@*/ exprNode
579 exprNode_createPartialNVCopy (exprNode e)
581 /*@post:isnull result->edata, result->etext, result->val @*/
584 exprNode ret = exprNode_new ();
586 if (exprNode_isError (e))
588 ret->typ = ctype_unknown;
589 ret->loc = fileloc_undefined;
590 ret->guards = guardSet_undefined;
591 ret->uses = sRefSet_undefined;
592 ret->sets = sRefSet_undefined;
593 ret->msets = sRefSet_undefined;
598 ret->loc = fileloc_copy (e->loc);
599 ret->guards = guardSet_copy (e->guards);
600 ret->uses = sRefSet_newCopy (e->uses);
601 ret->sets = sRefSet_newCopy (e->sets);
602 ret->msets = sRefSet_newCopy (e->msets);
605 ret->val = multiVal_undefined;
606 ret->kind = XPR_EMPTY;
607 ret->sref = sRef_undefined;
608 ret->etext = cstring_undefined;
609 ret->exitCode = XK_NEVERESCAPE;
610 ret->canBreak = FALSE;
611 ret->mustBreak = FALSE;
612 ret->isJumpPoint = FALSE;
613 ret->edata = exprData_undefined;
615 exprNode_defineConstraints(ret);
620 static /*@notnull@*/ /*@special@*/ exprNode
621 exprNode_createSemiCopy (exprNode e)
623 /*@post:isnull result->edata, result->etext, result->sets,
624 result->msets, result->uses, result->guards@*/
627 if (exprNode_isError (e))
629 return exprNode_createPlain (ctype_unknown);
633 exprNode ret = exprNode_new ();
636 ret->val = multiVal_copy (e->val);
637 ret->loc = fileloc_copy (e->loc);
638 ret->guards = guardSet_undefined;
639 ret->uses = sRefSet_undefined;
640 ret->sets = sRefSet_undefined;
641 ret->msets = sRefSet_undefined;
643 ret->kind = XPR_EMPTY;
644 ret->sref = sRef_undefined;
645 ret->etext = cstring_undefined;
646 ret->exitCode = XK_NEVERESCAPE;
647 ret->canBreak = FALSE;
648 ret->mustBreak = FALSE;
649 ret->isJumpPoint = FALSE;
650 ret->edata = exprData_undefined;
652 exprNode_defineConstraints(ret);
659 exprNode_isNullValue (exprNode e)
661 if (exprNode_isDefined (e))
663 multiVal m = exprNode_getValue (e);
665 if (multiVal_isInt (m))
667 return (multiVal_forceInt (m) == 0);
675 exprNode_isUnknownConstant (/*@notnull@*/ exprNode e)
677 while (e->kind == XPR_PARENS)
679 e = exprData_getUopNode (e->edata);
681 if (!exprNode_isDefined (e))
686 /* evans 2002-02-05: was llassert (exprNode_isDefined (e)); but this can fail */
689 if (e->kind == XPR_CONST)
691 multiVal m = exprNode_getValue (e);
693 if (multiVal_isUnknown (m))
703 exprNode_numLiteral (ctype c, /*@temp@*/ cstring t,
704 /*@only@*/ fileloc loc, long val)
706 exprNode e = exprNode_createLoc (c, loc);
708 e->kind = XPR_NUMLIT;
710 llassert (multiVal_isUndefined (e->val));
711 e->val = multiVal_makeInt (val);
712 e->edata = exprData_makeLiteral (cstring_copy (t));
716 e->sref = sRef_makeUnknown ();
717 sRef_setDefNull (e->sref, e->loc);
720 DPRINTF (("Num lit: %s / %s", exprNode_unparse (e), ctype_unparse (exprNode_getType (e))));
725 exprNode_charLiteral (char c, cstring text, /*@only@*/ fileloc loc)
727 exprNode e = exprNode_createLoc (ctype_char, loc);
729 if (context_getFlag (FLG_CHARINTLITERAL))
731 e->typ = ctype_makeConj (ctype_char, ctype_int);
734 e->kind = XPR_NUMLIT;
735 e->val = multiVal_makeChar (c);
737 e->edata = exprData_makeLiteral (cstring_copy (text));
742 exprNode_floatLiteral (double d, ctype ct, cstring text, /*@only@*/ fileloc loc)
744 exprNode e = exprNode_createLoc (ct, loc);
746 e->kind = XPR_NUMLIT;
747 e->val = multiVal_makeDouble (d);
748 e->edata = exprData_makeLiteral (cstring_copy (text));
752 multiVal exprNode_getValue (exprNode e)
754 while (exprNode_isInParens (e)) {
755 if (e->edata != NULL) {
756 e = exprData_getUopNode (e->edata);
762 if (exprNode_isDefined (e)) {
765 return multiVal_undefined;
770 exprNode_combineLiterals (exprNode e, exprNode rest)
774 /* Both must be string literals. */
776 if (exprNode_isUndefined (rest) || exprNode_isUndefined (e))
778 exprNode_free (rest);
782 if (!exprNode_isStringLiteral (e))
786 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e),
787 exprNode_unparse (rest)),
789 exprNode_free (rest);
793 if (!exprNode_isStringLiteral (rest))
797 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e), exprNode_unparse (rest)),
800 exprNode_free (rest);
804 ns = cstring_concat (multiVal_forceString (exprNode_getValue (e)),
805 multiVal_forceString (exprNode_getValue (rest)));
807 multiVal_free (e->val);
808 exprData_free (e->edata, e->kind);
809 e->edata = exprData_makeLiteral (cstring_copy (ns));
810 e->val = multiVal_makeString (ns);
811 exprNode_free (rest);
816 exprNode_rawStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
818 exprNode e = exprNode_createLoc (ctype_string, loc);
819 size_t len = cstring_length (t);
821 if (context_getFlag (FLG_STRINGLITERALLEN))
823 if (len > size_fromInt (context_getValue (FLG_STRINGLITERALLEN)))
825 voptgenerror (FLG_STRINGLITERALLEN,
827 ("String literal length (%d) exceeds maximum "
828 "length (%d): \"%s\"",
830 context_getValue (FLG_STRINGLITERALLEN),
836 e->kind = XPR_STRINGLITERAL;
837 e->val = multiVal_makeString (cstring_copy (t));
838 e->edata = exprData_makeLiteral (t);
839 e->sref = sRef_makeConst (ctype_string);
841 if (context_getFlag (FLG_READONLYSTRINGS))
843 sRef_setAliasKind (e->sref, AK_STATIC, fileloc_undefined);
844 sRef_setExKind (e->sref, XO_OBSERVER, loc);
848 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
851 return (e); /* s released */
855 exprNode_wideStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
857 exprNode res = exprNode_stringLiteral (t, loc);
858 res->typ = ctype_makeWideString ();
863 exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
865 size_t len = size_fromInt (size_toInt (cstring_length (t)) - 2);
866 char *ts = cstring_toCharsSafe (t);
867 char *s = cstring_toCharsSafe (cstring_create (len + 1));
869 llassert (*ts == '\"' && *(ts + len + 1) == '\"');
870 strncpy (s, ts+1, len);
873 return exprNode_rawStringLiteral (cstring_fromCharsO (s), loc);
876 exprNode exprNode_fromUIO (cstring c)
878 fileloc loc = context_getSaveLocation ();
879 exprNode e = exprNode_createPlain (ctype_unknown);
883 if (fileloc_isUndefined (loc))
885 loc = fileloc_copy (g_currentloc);
888 e->loc = loc; /* save loc was mangled */
889 e->sref = sRef_undefined;
891 if (usymtab_exists (c))
893 uentry ue = usymtab_lookupEither (c);
895 if (uentry_isDatatype (ue)
896 && uentry_isSpecified (ue))
899 (message ("%q: Specified datatype %s used in code, but not defined. "
900 "(Cannot continue reasonably from this error.)",
901 fileloc_unparse (e->loc), c));
909 llassertprint (!usymtab_exists (c), ("Entry exists: %s", c));
912 ** was supercedeGlobalEntry...is this better?
915 if (!context_inIterEnd ())
917 if (context_inMacro ())
919 if (context_getFlag (FLG_UNRECOG))
923 message ("Unrecognized identifier in macro definition: %s", c), e->loc);
927 flagcode_recordSuppressed (FLG_UNRECOG);
933 (FLG_UNRECOG, message ("Unrecognized identifier: %s", c), e->loc);
937 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
939 /* No alias errors for unrecognized identifiers */
940 sRef_setAliasKind (e->sref, AK_ERROR, loc);
945 exprNode exprNode_makeConstantString (cstring c, /*@only@*/ fileloc loc)
947 exprNode e = exprNode_createPlain (ctype_unknown);
950 e->sref = sRef_makeConst (ctype_string);
951 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
952 e->typ = ctype_string;
954 /* No alias errors for unrecognized identifiers */
955 sRef_setAliasKind (e->sref, AK_STATIC, loc);
956 sRef_setExKind (e->sref, XO_OBSERVER, loc);
961 exprNode exprNode_createId (/*@observer@*/ uentry c)
963 if (uentry_isValid (c))
965 exprNode e = exprNode_new ();
967 DPRINTF (("create id: %s", uentry_unparse (c)));
969 e->typ = uentry_getType (c);
971 if (uentry_isFunction (c)
972 && !sRef_isLocalVar (uentry_getSref (c)))
974 e->sref = sRef_undefined;
978 e->sref = uentry_getSref (c);
981 if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
983 sRef_setDefined (e->sref, fileloc_undefined);
987 ** yoikes! leaving this out was a heinous bug...that would have been
988 ** caught if i had splint working first. gag!
991 e->etext = cstring_undefined;
993 if (uentry_isEitherConstant (c))
996 e->val = multiVal_copy (uentry_getConstantValue (c));
1001 e->val = multiVal_unknown ();
1004 e->edata = exprData_makeId (c);
1005 e->loc = context_getSaveLocation ();
1007 if (fileloc_isUndefined (e->loc))
1009 fileloc_free (e->loc);
1010 e->loc = fileloc_copy (g_currentloc);
1013 e->guards = guardSet_new ();
1014 e->sets = sRefSet_new ();
1015 e->msets = sRefSet_new ();
1016 e->uses = sRefSet_new ();
1018 /*> missing fields, detected by splint <*/
1019 e->exitCode = XK_NEVERESCAPE;
1020 e->isJumpPoint = FALSE;
1021 e->canBreak = FALSE;
1022 e->mustBreak = FALSE;
1024 exprNode_defineConstraints (e);
1029 return exprNode_createUnknown ();
1033 /*@notnull@*/ exprNode
1034 exprNode_fromIdentifier (/*@observer@*/ uentry c)
1038 if (context_justPopped ()) /* watch out! c could be dead */
1040 uentry ce = usymtab_lookupSafe (cscannerHelp_observeLastIdentifier ());
1042 if (uentry_isValid (ce))
1048 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
1052 ret = exprNode_fromIdentifierAux (c);
1056 static void exprNode_checkStringLiteralLength (ctype t1, exprNode e2)
1058 multiVal mval = exprNode_getValue (e2);
1062 if (ctype_isFixedArray (t1))
1064 size_t nelements = ctype_getArraySize (t1);
1066 llassert (multiVal_isString (mval));
1067 slit = multiVal_forceString (mval);
1069 len = cstring_lengthExpandEscapes (slit);
1071 llassert (exprNode_isDefined (e2));
1073 if (len == nelements)
1077 temp = cstring_expandEscapes (slit);
1079 if (temp[len-1] == '\0')
1082 (FLG_STRINGLITNOROOMFINALNULL,
1083 message ("String literal with %d character%& "
1084 "is assigned to %s (no room for final null terminator): %s",
1085 size_toInt (len + 1),
1087 exprNode_unparse (e2)),
1093 (FLG_STRINGLITNOROOM,
1094 message ("String literal with %d character%& "
1095 "is assigned to %s (no room for null terminator): %s",
1096 size_toInt (len + 1),
1098 exprNode_unparse (e2)),
1102 else if (len > nelements)
1105 (FLG_STRINGLITTOOLONG,
1106 message ("String literal with %d character%& (counting null terminator) "
1107 "is assigned to %s (insufficient storage available): %s",
1108 size_toInt (len + 1),
1110 exprNode_unparse (e2)),
1113 else if (len < nelements - 1)
1116 (FLG_STRINGLITSMALLER,
1117 message ("String literal with %d character%& is assigned to %s (possible waste of storage): %s",
1118 size_toInt (len + 1),
1120 exprNode_unparse (e2)),
1130 static /*@only@*/ /*@notnull@*/ exprNode
1131 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
1133 exprNode e = exprNode_createId (c);
1136 uentry_setUsed (c, e->loc);
1138 if (uentry_isVar (c) && sRef_isFileOrGlobalScope (sr))
1140 checkGlobUse (c, FALSE, e);
1147 exprNode_isZero (exprNode e)
1149 if (exprNode_isDefined (e))
1151 multiVal m = exprNode_getValue (e);
1153 if (multiVal_isInt (m))
1155 return (multiVal_forceInt (m) == 0);
1163 exprNode_isNonNegative (exprNode e)
1165 if (exprNode_isDefined (e))
1167 multiVal m = exprNode_getValue (e);
1169 if (multiVal_isInt (m))
1171 return (multiVal_forceInt (m) >= 0);
1175 ** This is not always true if programmer defines enum
1176 ** values, but then the constant should be known.
1179 if (ctype_isEnum (ctype_realType (e->typ)))
1189 ** a[x] - uses a but NOT a[]
1190 ** result sref = a[] (set/use in assignment)
1192 ** The syntax x[a] is also legal in C, and has the same
1193 ** semantics. If ind is an array, and arr is an int, flip
1198 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
1201 ** error in arr, error propagates (no new messages)
1202 ** error in ind, assume valid and continue
1205 DPRINTF (("Array fetch: %s / %s",
1206 exprNode_unparse (e1), exprNode_unparse (e2)));
1208 if (exprNode_isError (e1))
1211 return (exprNode_makeError ());
1217 ctype carr = exprNode_getType (e1);
1218 ctype crarr = ctype_realType (carr);
1221 ** this sets up funny aliasing, that leads to spurious
1222 ** splint errors. Hence, the i2 comments.
1225 /* evans 2001-09-09 added ctype_isKnown so there is no swap when e1 type is unknown */
1226 if (ctype_isKnown (crarr)
1227 && !ctype_isRealArray (crarr)
1228 && ctype_isRealNumeric (crarr)
1229 && !exprNode_isError (e2)
1230 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1235 carr = exprNode_getType (arr);
1236 crarr = ctype_realType (carr);
1244 DPRINTF (("arr: %s", exprNode_unparse (arr)));
1246 if (sRef_possiblyNull (arr->sref))
1248 if (!usymtab_isGuarded (arr->sref))
1250 if (!context_inSizeof() )
1252 if (optgenerror (FLG_NULLDEREF,
1253 message ("Index of %s pointer %q: %s",
1254 sRef_nullMessage (arr->sref),
1255 sRef_unparse (arr->sref),
1256 exprNode_unparse (arr)),
1259 DPRINTF (("ref: %s", sRef_unparseFull (arr->sref)));
1260 sRef_showNullInfo (arr->sref);
1262 /* suppress future messages */
1263 sRef_setNullError (arr->sref);
1269 if (exprNode_isError (ind))
1271 if ((ctype_isArrayPtr (crarr)
1272 && !ctype_isFunction (crarr))
1273 || ctype_isUnknown (carr))
1275 exprNode ret = exprNode_createPartialCopy (arr);
1277 if (ctype_isKnown (carr))
1279 ret->typ = ctype_baseArrayPtr (crarr);
1283 ret->typ = ctype_unknown;
1286 ret->sref = sRef_makeArrayFetch (arr->sref);
1288 ret->kind = XPR_FETCH;
1291 ** Because of funny aliasing (when arr and ind are
1292 ** flipped) spurious errors would be reported here.
1295 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1296 checkSafeUse (ret, arr->sref);
1301 voptgenerror (FLG_TYPE,
1302 message ("Array fetch from non-array (%t): %s[%s]", carr,
1303 exprNode_unparse (e1), exprNode_unparse (e2)),
1305 exprNode_free (arr);
1306 return (exprNode_makeError ());
1311 if (!ctype_isForceRealInt (&(ind->typ)))
1313 ctype rt = ctype_realType (ind->typ);
1315 if (ctype_isChar (rt))
1319 message ("Array fetch using non-integer, %t: %s[%s]",
1321 exprNode_unparse (e1), exprNode_unparse (e2)),
1324 else if (ctype_isEnum (rt))
1328 message ("Array fetch using non-integer, %t: %s[%s]",
1330 exprNode_unparse (e1), exprNode_unparse (e2)),
1333 else if (ctype_isNumAbstract (rt))
1336 (FLG_NUMABSTRACTINDEX,
1337 message ("Array fetch using numabstract type, %t: %s[%s]",
1339 exprNode_unparse (e1), exprNode_unparse (e2)),
1346 message ("Array fetch using non-integer, %t: %s[%s]",
1348 exprNode_unparse (e1), exprNode_unparse (e2)),
1352 multiVal_free (ind->val);
1353 ind->val = multiVal_unknown ();
1356 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1358 exprNode ret = exprNode_createSemiCopy (arr);
1359 multiVal m = exprNode_getValue (ind);
1361 ret->typ = ctype_baseArrayPtr (crarr);
1362 ret->kind = XPR_FETCH;
1364 if (multiVal_isInt (m))
1366 int i = (int) multiVal_forceInt (m);
1368 if (sRef_isValid (arr->sref)) {
1369 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1371 ret->sref = sRef_undefined;
1376 ret->sref = sRef_makeArrayFetch (arr->sref);
1379 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1380 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1381 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1383 /* (see comment on spurious errors above) */
1384 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1386 exprNode_checkUse (ret, ind->sref, ind->loc);
1387 exprNode_checkUse (ret, arr->sref, arr->loc);
1393 if (ctype_isUnknown (carr))
1395 exprNode ret = exprNode_createPartialCopy (arr);
1397 ret->kind = XPR_FETCH;
1398 ret->typ = ctype_unknown;
1399 ret->sets = sRefSet_union (ret->sets, ind->sets);
1400 ret->msets = sRefSet_union (ret->msets, ind->msets);
1401 ret->uses = sRefSet_union (ret->uses, ind->uses);
1403 /* (see comment on spurious errors above) */
1404 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1406 exprNode_checkUse (ret, ind->sref, ind->loc);
1407 exprNode_checkUse (ret, arr->sref, arr->loc);
1414 message ("Array fetch from non-array (%t): %s[%s]", carr,
1415 exprNode_unparse (e1), exprNode_unparse (e2)),
1418 exprNode_free (arr);
1419 exprNode_free (ind);
1421 return (exprNode_makeError ());
1431 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1432 exprNodeList args, exprNode ret)
1434 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1438 ** checkPrintfArgs --- checks arguments for printf-like functions
1439 ** Arguments before ... have already been checked.
1440 ** The argument before the ... is a char *.
1441 ** argno is the format string argument.
1445 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1446 exprNodeList args, exprNode ret, int argno)
1449 ** the last argument before the elips is the format string
1454 int nargs = exprNodeList_size (args);
1455 uentryList params = uentry_getParams (fcn);
1459 ** These should be ensured by checkSpecialFunction
1462 llassert (uentryList_size (params) == argno + 1);
1463 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1465 a = exprNodeList_getN (args, argno - 1);
1466 formatloc = fileloc_copy (exprNode_loc (a));
1468 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1469 && exprNode_knownStringValue (a))
1471 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1472 char *code = format;
1475 nargs = exprNodeList_size (args);
1477 while ((code = strchr (code, '%')) != NULL)
1479 char *origcode = code;
1480 cstring codetext = cstring_newEmpty ();
1481 char key = *(++code);
1482 ctype modtype = ctype_int;
1483 bool modified = FALSE;
1485 fileloc_addColumn (formatloc, code - ocode);
1487 codetext = cstring_appendChar (codetext, key);
1490 while (isFlagKey (key))
1493 codetext = cstring_appendChar (codetext, key);
1494 fileloc_incColumn (formatloc);
1497 if (key == 'm') /* skipped in syslog */
1502 /* ignore field width */
1503 while (isdigit ((int) key) != 0)
1506 codetext = cstring_appendChar (codetext, key);
1507 fileloc_incColumn (formatloc);
1510 /* ignore precision */
1514 codetext = cstring_appendChar (codetext, key);
1515 fileloc_incColumn (formatloc);
1518 ** In printf, '*' means: read the next arg as an int for the
1519 ** field width. This seems to be missing from my copy of the
1520 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1521 ** later) but never does.
1526 ; /* don't do anything --- handle later */
1530 while (isdigit ((int) key) != 0)
1533 codetext = cstring_appendChar (codetext, key);
1534 fileloc_incColumn (formatloc);
1541 modtype = ctype_sint; /* short */
1543 codetext = cstring_appendChar (codetext, key);
1544 fileloc_incColumn (formatloc);
1546 else if (key == 'l' || key == 'L')
1548 modtype = ctype_lint; /* long */
1550 codetext = cstring_appendChar (codetext, key);
1551 fileloc_incColumn (formatloc);
1553 if (key == 'l' || key == 'L') {
1554 modtype = ctype_llint; /* long long */
1556 codetext = cstring_appendChar (codetext, key);
1557 fileloc_incColumn (formatloc);
1565 /* now, key = type of conversion to apply */
1567 fileloc_incColumn (formatloc);
1575 message ("No argument corresponding to %q format "
1576 "code %d (%%%s): \"%s\"",
1577 uentry_getName (fcn),
1579 cstring_fromChars (format)),
1582 if (fileloc_isDefined (formatloc)
1583 && context_getFlag (FLG_SHOWCOL))
1585 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1593 a = exprNodeList_getN (args, i);
1596 if (!exprNode_isError (a))
1602 case '*': /* int argument for fieldwidth */
1603 expecttype = ctype_int;
1604 *(--code) = '%'; /* convert it for next code */
1605 fileloc_subColumn (formatloc, 1);
1606 /*@switchbreak@*/ break;
1609 expecttype = ctype_combine (ctype_uint, modtype);
1610 /*@switchbreak@*/ break;
1612 case 'i': /* int argument */
1614 expecttype = ctype_combine (ctype_int, modtype);
1615 /*@switchbreak@*/ break;
1617 case 'x': /* unsigned int */
1619 expecttype = ctype_combine (ctype_uint, modtype);
1621 /*@switchbreak@*/ break;
1627 case 'f': /* double */
1628 expecttype = ctype_combine (ctype_double, modtype);
1629 /*@switchbreak@*/ break;
1631 case 'c': /* int converted to char (check its a char?) */
1632 expecttype = ctype_makeConj (ctype_int,
1633 ctype_makeConj (ctype_char,
1635 /* evans 2001-10-05 - changed to reflect correct ISO spec:
1636 int converted to char */
1638 /*@switchbreak@*/ break;
1640 case 's': /* string */
1641 expecttype = ctype_string;
1642 /*@switchbreak@*/ break;
1645 while (((key = *(++code)) != ']')
1648 codetext = cstring_appendChar (codetext, key);
1649 fileloc_incColumn (formatloc);
1655 (message ("Bad character set format: %s",
1656 cstring_fromChars (origcode)));
1659 expecttype = ctype_string;
1660 /*@switchbreak@*/ break;
1662 case 'p': /* pointer */
1663 expecttype = ctype_makePointer (ctype_void);
1664 /* need not be defined */
1665 uentry_setDefState (regArg, SS_RELDEF);
1666 sRef_setPosNull (uentry_getSref (regArg),
1669 /*@switchbreak@*/ break;
1671 case 'n': /* pointer to int, modified by call! */
1672 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1674 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1675 /*@switchbreak@*/ break;
1677 case 'm': /* in a syslog, it doesn't consume an argument */
1678 /* should check we're really doing syslog */
1680 /*@switchbreak@*/ break;
1684 expecttype = ctype_unknown;
1688 message ("Unrecognized format code: %s",
1689 cstring_fromChars (origcode)),
1690 fileloc_isDefined (formatloc)
1691 ? formatloc : g_currentloc);
1693 /*@switchbreak@*/ break;
1696 if (!(exprNode_matchArgType (expecttype, a)))
1698 if (ctype_isVoidPointer (expecttype)
1699 && ctype_isRealAbstract (a->typ)
1700 && (context_getFlag (FLG_ABSTVOIDP)))
1706 if (llgenformattypeerror
1707 (expecttype, exprNode_undefined,
1709 message ("Format argument %d to %q (%%%s) expects "
1712 uentry_getName (fcn),
1715 a->typ, exprNode_unparse (a)),
1718 if (fileloc_isDefined (formatloc)
1719 && context_getFlag (FLG_SHOWCOL))
1722 (cstring_makeLiteral
1723 ("Corresponding format code"),
1730 uentry_setType (regArg, expecttype);
1731 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1733 if (ctype_equal (expecttype, ctype_string))
1735 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1738 uentry_setType (regArg, ctype_unknown);
1739 uentry_fixupSref (regArg);
1743 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1754 cstring_free (codetext);
1759 voptgenerror (FLG_TYPE,
1760 message ("Format string for %q has %d arg%&, given %d",
1761 uentry_getName (fcn), i - argno, nargs - argno),
1767 /* no checking possible for compile-time unknown format strings */
1768 if (exprNode_isDefined (a))
1772 message ("Format string parameter to %s is not a compile-time constant: %s",
1773 exprNode_unparse (f),
1774 exprNode_unparse (a)),
1779 fileloc_free (formatloc);
1783 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1784 exprNodeList args, exprNode ret, int argno)
1788 int nargs = exprNodeList_size (args);
1789 uentryList params = uentry_getParams (fcn);
1793 ** These should be ensured by checkSpecialFunction
1796 llassert (uentryList_size (params) == argno + 1);
1797 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1799 a = exprNodeList_getN (args, argno - 1);
1800 formatloc = fileloc_copy (exprNode_loc (a));
1802 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1803 && exprNode_knownStringValue (a))
1805 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1806 char *code = format;
1809 nargs = exprNodeList_size (args);
1811 while ((code = strchr (code, '%')) != NULL)
1813 char *origcode = code;
1814 char key = *(++code);
1815 cstring codetext = cstring_newEmpty ();
1816 ctype modtype = ctype_int;
1817 char modifier = '\0';
1818 bool modified = TRUE;
1819 bool ignore = FALSE;
1821 codetext = cstring_appendChar (codetext, key);
1822 fileloc_addColumn (formatloc, code - ocode);
1825 ** this is based on ANSI standard library description of fscanf
1826 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1829 /* '*' suppresses assignment (does not need match argument) */
1834 codetext = cstring_appendChar (codetext, key);
1837 fileloc_incColumn (formatloc);
1840 /* ignore field width */
1841 while (isdigit ((int) key) != 0)
1844 codetext = cstring_appendChar (codetext, key);
1845 fileloc_incColumn (formatloc);
1850 modtype = ctype_sint; /* short */
1852 codetext = cstring_appendChar (codetext, key);
1853 fileloc_incColumn (formatloc);
1855 else if (key == 'l' || key == 'L')
1857 modtype = ctype_lint; /* long */
1861 codetext = cstring_appendChar (codetext, key);
1863 fileloc_incColumn (formatloc);
1865 if (key == 'l' || key == 'L') {
1866 modtype = ctype_llint; /* long long */
1868 codetext = cstring_appendChar (codetext, key);
1869 fileloc_incColumn (formatloc);
1877 /* now, key = type of conversion to apply */
1879 fileloc_incColumn (formatloc);
1893 message ("No argument corresponding to %q format "
1894 "code %d (%%%s): \"%s\"",
1895 uentry_getName (fcn),
1897 cstring_fromChars (format)),
1900 if (fileloc_isDefined (formatloc)
1901 && context_getFlag (FLG_SHOWCOL))
1904 (cstring_makeLiteral ("Corresponding format code"),
1912 a = exprNodeList_getN (args, i);
1915 if (!exprNode_isError (a))
1921 case '*': /* int argument for fieldwidth */
1922 expecttype = ctype_makePointer (ctype_int);
1923 *(--code) = '%'; /* convert it for next code */
1924 fileloc_subColumn (formatloc, 1);
1925 /*@switchbreak@*/ break;
1928 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1929 /*@switchbreak@*/ break;
1933 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1934 /*@switchbreak@*/ break;
1937 case 'X': /* unsigned int */
1938 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1939 /*@switchbreak@*/ break;
1946 /* printf is double, scanf is float! */
1948 if (modifier == 'l')
1950 expecttype = ctype_makePointer (ctype_double);
1952 else if (modifier == 'L')
1954 expecttype = ctype_makePointer (ctype_ldouble);
1958 llassert (modifier == '\0');
1959 expecttype = ctype_makePointer (ctype_float);
1961 /*@switchbreak@*/ break;
1963 case 'c': /* int converted to char (check its a char?) */
1964 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1965 /*@switchbreak@*/ break;
1967 case 's': /* string */
1968 expecttype = ctype_string;
1969 /*@switchbreak@*/ break;
1973 while (((key = *(++code)) != ']')
1976 codetext = cstring_appendChar (codetext, key);
1977 fileloc_incColumn (formatloc);
1983 (message ("Bad character set format: %s",
1984 cstring_fromChars (origcode)));
1987 expecttype = ctype_string;
1988 /*@switchbreak@*/ break;
1991 case 'p': /* pointer */
1994 message ("Format code should not be used in scanf: %s",
1995 cstring_fromChars (origcode)),
1996 fileloc_isDefined (formatloc)
1997 ? formatloc : g_currentloc);
1999 expecttype = ctype_unknown;
2000 /*@switchbreak@*/ break;
2002 case 'n': /* pointer to int, modified by call! */
2003 expecttype = ctype_makePointer (ctype_int);
2004 /*@switchbreak@*/ break;
2007 expecttype = ctype_unknown;
2011 message ("Unrecognized format code: %s",
2012 cstring_fromChars (origcode)),
2013 fileloc_isDefined (formatloc)
2014 ? formatloc : g_currentloc);
2016 /*@switchbreak@*/ break;
2019 if (!(exprNode_matchArgType (expecttype, a)))
2021 if (ctype_isVoidPointer (expecttype)
2022 && ctype_isRealAbstract (a->typ)
2023 && (context_getFlag (FLG_ABSTVOIDP)))
2029 if (llgenformattypeerror
2030 (expecttype, exprNode_undefined,
2032 message ("Format argument %d to %q (%%%s) expects "
2035 uentry_getName (fcn),
2036 codetext, expecttype,
2037 a->typ, exprNode_unparse (a)),
2040 if (fileloc_isDefined (formatloc)
2041 && context_getFlag (FLG_SHOWCOL))
2044 (cstring_makeLiteral
2045 ("Corresponding format code"),
2052 uentry_setType (outArg, expecttype);
2053 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
2054 uentry_setType (outArg, ctype_unknown);
2055 uentry_fixupSref (outArg);
2059 exprNode_checkCallModifyVal (a->sref, args, f, ret);
2064 /* a->sref = sRef_undefined; */
2071 cstring_free (codetext);
2076 voptgenerror (FLG_TYPE,
2077 message ("Format string for %q has %d arg%&, given %d",
2078 uentry_getName (fcn), i - argno, nargs - argno),
2084 /* no checking possible for compile-time unknown format strings */
2087 fileloc_free (formatloc);
2091 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
2094 /*@unused@*/ int argno)
2097 ** the last argument before the elips is the format string
2100 int nargs = exprNodeList_size (args);
2105 a = exprNodeList_getN (args, argno - 1);
2106 formatloc = fileloc_copy (exprNode_loc (a));
2108 if (ctype_isUnknown (cstringType)) {
2109 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
2111 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
2115 if (ctype_isUnknown (ctypeType)) {
2116 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
2118 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
2122 if (ctype_isUnknown (filelocType)) {
2123 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
2125 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
2129 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
2130 && exprNode_knownStringValue (a))
2132 cstring format = multiVal_forceString (exprNode_getValue (a));
2133 char *code = cstring_toCharsSafe (format);
2136 nargs = exprNodeList_size (args);
2138 while ((code = strchr (code, '%')) != NULL)
2140 char *origcode = code;
2141 char key = *(++code);
2142 cstring codetext = cstring_newEmpty ();
2143 bool isOnly = FALSE;
2145 codetext = cstring_appendChar (codetext, key);
2147 fileloc_addColumn (formatloc, code - ocode);
2149 while (key >= '0' && key <= '9')
2152 codetext = cstring_appendChar (codetext, key);
2153 fileloc_incColumn (formatloc);
2157 fileloc_incColumn (formatloc);
2161 if (key == '&') /* plural marker */
2170 message ("Message missing format arg %d (%%%s): \"%s\"",
2171 i + 1, codetext, format),
2177 a = exprNodeList_getN (args, i);
2181 if (!exprNode_isError (a))
2185 /*@-loopswitchbreak@*/
2191 expecttype = ctype_char; break;
2193 expecttype = cstringType; break;
2195 expecttype = cstringType; isOnly = TRUE; break;
2197 expecttype = cstringType; isOnly = TRUE; break;
2198 case 'd': expecttype = ctype_int; break;
2199 case 'u': expecttype = ctype_uint; break;
2200 case 'w': expecttype = ctype_ulint; break;
2201 case 'f': expecttype = ctype_float; break;
2202 case 'b': expecttype = ctype_bool; break;
2203 case 't': expecttype = ctypeType; break;
2205 expecttype = ctype_makePointer (ctype_void);
2206 /* need not be defined */
2207 uentry_setDefState (regArg, SS_RELDEF);
2208 sRef_setPosNull (uentry_getSref (regArg),
2211 /*@switchbreak@*/ break;
2212 case 'l': expecttype = filelocType; break;
2213 case '&': /* a wee bit of a hack methinks */
2214 expecttype = ctype_int;
2216 case 'r': expecttype = ctype_bool; break;
2218 expecttype = ctype_unknown;
2221 message ("Unrecognized format code: %s",
2222 cstring_fromChars (origcode)),
2223 fileloc_isDefined (formatloc)
2224 ? formatloc : g_currentloc);
2227 /*@=loopswitchbreak@*/
2229 if (!(exprNode_matchArgType (expecttype, a)))
2231 if (ctype_isVoidPointer (expecttype)
2232 && ctype_isRealAbstract (a->typ)
2233 && (context_getFlag (FLG_ABSTVOIDP)))
2239 if (llgenformattypeerror
2240 (expecttype, exprNode_undefined,
2242 message ("Format argument %d to %q (%%%s) expects "
2245 uentry_getName (fcn),
2246 codetext, expecttype,
2247 a->typ, exprNode_unparse (a)),
2250 if (fileloc_isDefined (formatloc)
2251 && context_getFlag (FLG_SHOWCOL))
2254 (cstring_makeLiteral
2255 ("Corresponding format code"),
2262 if (ctype_equal (expecttype, cstringType))
2266 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2267 uentry_fixupSref (csOnlyArg);
2271 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2272 uentry_fixupSref (csArg);
2277 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2278 uentry_fixupSref (regArg);
2284 cstring_free (codetext);
2289 voptgenerror (FLG_TYPE,
2290 message ("Format string for %q has %d arg%&, given %d",
2291 uentry_getName (fcn), i - argno, nargs -argno),
2297 /* no checking possible for compile-time unknown format strings */
2300 fileloc_free (formatloc);
2304 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2305 /*@notnull@*/ exprNode e2,
2311 bool hadUncon = FALSE;
2313 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
2314 sRefSet_hasUnconstrained (sets2))
2317 (FLG_EVALORDERUNCON,
2319 ("Expression may have undefined behavior (%q used in right operand "
2320 "may set global variable %q used in left operand): %s %s %s",
2321 sRefSet_unparseUnconstrained (sets2),
2322 sRef_unparse (sRef_getRootBase (e1->sref)),
2323 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2327 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
2328 sRefSet_hasUnconstrained (sets1))
2331 (FLG_EVALORDERUNCON,
2333 ("Expression has undefined behavior (%q used in left operand "
2334 "may set global variable %q used in right operand): %s %s %s",
2335 sRefSet_unparseUnconstrained (sets1),
2336 sRef_unparse (e2->sref),
2337 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2341 sRefSet_realElements (e1->uses, sr)
2343 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2348 ("Expression has undefined behavior (left operand uses %q, "
2349 "modified by right operand): %s %s %s",
2351 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2354 } end_sRefSet_realElements;
2356 sRefSet_realElements (sets1, sr)
2358 if (sRef_isMeaningful (sr))
2360 if (sRef_same (sr, e2->sref))
2365 ("Expression has undefined behavior (value of right operand "
2366 "modified by left operand): %s %s %s",
2367 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2370 else if (sRefSet_member (e2->uses, sr))
2375 ("Expression has undefined behavior (left operand modifies %q, "
2376 "used by right operand): %s %s %s",
2378 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2383 if (sRefSet_member (sets2, sr))
2385 if (sRef_isUnconstrained (sr))
2393 hadUncon = optgenerror
2394 (FLG_EVALORDERUNCON,
2396 ("Expression may have undefined behavior. Left operand "
2397 "calls %q; right operand calls %q. The unconstrained "
2398 "functions may modify global state used by "
2399 "the other operand): %s %s %s",
2400 sRefSet_unparseUnconstrained (sets1),
2401 sRefSet_unparseUnconstrained (sets2),
2402 exprNode_unparse (e1), lltok_unparse (op),
2403 exprNode_unparse (e2)),
2412 ("Expression has undefined behavior (both "
2413 "operands modify %q): %s %s %s",
2415 exprNode_unparse (e1),
2416 lltok_unparse (op), exprNode_unparse (e2)),
2422 } end_sRefSet_realElements;
2425 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2427 bool hasError = FALSE;
2429 if (exprNode_isError (e1) || exprNode_isError (e2))
2434 if (sRefSet_member (e2->sets, e1->sref))
2436 if (e2->kind == XPR_CALL)
2442 hasError = optgenerror
2444 message ("Expression has undefined behavior "
2445 "(value of left operand %s is modified "
2446 "by right operand %s): %s %s %s",
2447 exprNode_unparse (e1),
2448 exprNode_unparse (e2),
2449 exprNode_unparse (e1), lltok_unparse (op),
2450 exprNode_unparse (e2)),
2455 if (context_getFlag (FLG_EVALORDERUNCON))
2457 if (sRefSet_member (e2->msets, e1->sref))
2459 if (e2->kind == XPR_CALL)
2465 hasError = optgenerror
2468 ("Expression has undefined behavior (value of left "
2469 "operand may be modified by right operand): %s %s %s",
2470 exprNode_unparse (e1), lltok_unparse (op),
2471 exprNode_unparse (e2)),
2479 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2481 if (context_maybeSet (FLG_EVALORDERUNCON))
2483 checkExpressionDefinedAux (e1, e2, e1->msets,
2484 e2->msets, op, FLG_EVALORDERUNCON);
2489 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2492 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2493 exprNodeList args, bool isIter, exprNode ret)
2497 if (!exprNode_isError (f))
2499 if (!uentryList_isMissingParams (cl))
2501 int nargs = exprNodeList_size (args);
2502 int expectargs = uentryList_size (cl);
2506 if (expectargs == 0)
2514 message ("Iter %q invoked with %d args, "
2516 uentry_getName (fcn),
2524 message ("Function %s called with %d args, "
2526 exprNode_unparse (f), nargs),
2533 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2535 exprNodeList_reset (args);
2537 uentryList_elements (cl, current)
2539 ctype ct = uentry_getType (current);
2542 if (ctype_isElips (ct))
2545 ** do special checking for printf/scanf library functions
2547 ** this is kludgey code, just for handling the special case
2551 if (uentry_isPrintfLike (fcn))
2553 checkPrintfArgs (f, fcn, args, ret, i);
2556 else if (uentry_isScanfLike (fcn))
2558 checkScanfArgs (f, fcn, args, ret, i);
2561 else if (uentry_isMessageLike (fcn))
2563 checkMessageArgs (f, fcn, args, i);
2568 llassert (!uentry_isSpecialFunction (fcn));
2571 nargs = expectargs; /* avoid errors */
2576 if (i >= nargs) break;
2578 a = exprNodeList_current (args);
2579 exprNodeList_advance (args);
2583 if (exprNode_isError (a))
2590 probably necessary? I'm not sure about this one
2591 checkMacroParen (a);
2594 f->guards = guardSet_union (f->guards, a->guards);
2596 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2598 if (!(exprNode_matchArgType (ct, a)))
2600 DPRINTF (("Args mismatch!"));
2602 if (ctype_isVoidPointer (ct)
2603 && (ctype_isPointer (a->typ)
2604 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2609 ("Pointer to abstract type (%t) used "
2611 "(arg %d to %q): %s",
2613 uentry_getName (fcn),
2614 exprNode_unparse (a)),
2622 (ct, exprNode_undefined,
2625 ("Iter %q expects arg %d to "
2626 "be %t gets %t: %s",
2627 uentry_getName (fcn),
2628 i, ct, a->typ, exprNode_unparse (a)),
2639 ("Function %q expects arg %d to be %t gets %t: %s",
2640 uentry_getName (fcn),
2641 i, ct, a->typ, exprNode_unparse (a)),
2644 DPRINTF (("Types: %s / %s",
2646 ctype_unparse (a->typ)));
2650 ** Clear null marker for abstract types.
2651 ** (It is not revealed, so suppress future messages.)
2654 if (ctype_isAbstract (a->typ))
2656 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2663 } end_uentryList_elements ;
2666 if (expectargs != nargs) /* note: not != since we may have ... */
2668 if (ctype_isElips (last))
2672 message ("Function %s called with %d args, expects at least %d",
2673 exprNode_unparse (f),
2674 nargs, expectargs - 1),
2683 message ("Iter %q invoked with %d args, expects %d",
2684 uentry_getName (fcn), nargs, expectargs),
2691 message ("Function %s called with %d args, expects %d",
2692 exprNode_unparse (f),
2705 ** Check for undefined code sequences in function arguments:
2707 ** one parameter sets something used by another parameter
2708 ** one parameter sets something set by another parameter
2712 checkSequencingOne (exprNode f, exprNodeList args,
2713 /*@notnull@*/ exprNode el, int argno)
2716 ** Do second loop, iff +undefunspec
2720 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2722 for (checkloop = 0; checkloop < numloops; checkloop++)
2728 thissets = el->sets;
2732 llassert (checkloop == 1);
2733 thissets = el->msets;
2736 sRefSet_realElements (thissets, thisset)
2740 /*@access exprNodeList@*/
2741 for (j = 0; j < args->nelements; j++)
2743 exprNode jl = args->elements[j];
2744 int thisargno = j + 1;
2746 if (thisargno != argno && exprNode_isDefined (jl))
2748 sRefSet otheruses = jl->uses;
2750 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
2751 sRefSet_hasUnconstrained (thissets))
2754 (FLG_EVALORDERUNCON,
2757 ("%q used in argument %d may set "
2758 "global variable %q used by argument %d: %s(%q)",
2759 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2762 sRef_unparse (sRef_getRootBase (jl->sref)),
2764 exprNode_unparse (f), exprNodeList_unparse (args)),
2768 if (sRefSet_member (otheruses, thisset))
2770 if (sRef_isUnconstrained (thisset))
2773 (FLG_EVALORDERUNCON,
2775 ("Unconstrained functions used in arguments %d (%q) "
2776 "and %d (%s) may modify "
2777 "or use global state in undefined way: %s(%q)",
2779 sRefSet_unparseUnconstrainedPlain (otheruses),
2781 sRef_unconstrainedName (thisset),
2782 exprNode_unparse (f),
2783 exprNodeList_unparse (args)),
2791 ("Argument %d modifies %q, used by argument %d "
2792 "(order of evaluation of actual parameters is "
2793 "undefined): %s(%q)",
2794 argno, sRef_unparse (thisset), thisargno,
2795 exprNode_unparse (f), exprNodeList_unparse (args)),
2801 sRefSet othersets = jl->sets;
2803 if (sRefSet_member (othersets, thisset))
2805 if (sRef_isUnconstrained (thisset))
2808 (FLG_EVALORDERUNCON,
2810 ("Unconstrained functions used in "
2811 "arguments %d (%q) and %d (%s) may modify "
2812 "or use global state in undefined way: %s(%q)",
2814 sRefSet_unparseUnconstrainedPlain (othersets),
2816 sRef_unconstrainedName (thisset),
2817 exprNode_unparse (f), exprNodeList_unparse (args)),
2825 ("Argument %d modifies %q, set by argument %d (order of"
2826 " evaluation of actual parameters is undefined): %s(%q)",
2827 argno, sRef_unparse (thisset), thisargno,
2828 exprNode_unparse (f), exprNodeList_unparse (args)),
2835 /*@noaccess exprNodeList@*/
2836 } end_sRefSet_realElements;
2841 checkSequencing (exprNode f, exprNodeList args)
2843 if (exprNodeList_size (args) > 1)
2848 /*@access exprNodeList*/
2850 for (i = 0; i < args->nelements; i++)
2852 el = args->elements[i];
2854 if (!exprNode_isError (el))
2856 checkSequencingOne (f, args, el, i + 1);
2859 /*@noaccess exprNodeList*/
2864 ** requires le = exprNode_getUentry (f)
2868 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2869 uentry le, exprNodeList args,
2870 /*@notnull@*/ exprNode ret, int specialArgs)
2872 bool isSpec = FALSE;
2873 bool hasMods = FALSE;
2875 globSet usesGlobs = globSet_undefined;
2876 sRefSet mods = sRefSet_undefined;
2877 bool freshMods = FALSE;
2878 uentryList params = uentryList_undefined;
2880 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2883 ** check globals and modifies
2888 if (!uentry_isValid (le))
2890 ctype fr = ctype_realType (f->typ);
2892 if (ctype_isFunction (fr))
2894 params = ctype_argsFunction (fr);
2898 params = uentryList_missingParams;
2901 if (!context_getFlag (FLG_MODNOMODS)
2902 && !context_getFlag (FLG_GLOBUNSPEC))
2904 checkUnspecCall (f, params, args);
2910 fname = uentry_rawName (le);
2914 if (uentry_isFunction (le))
2916 params = uentry_getParams (le);
2917 mods = uentry_getMods (le);
2918 hasMods = uentry_hasMods (le);
2919 usesGlobs = uentry_getGlobs (le);
2920 isSpec = uentry_isSpecified (le);
2922 else /* not a function */
2924 ctype ct = ctype_realType (uentry_getType (le));
2926 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2927 ("checkModGlobs: uentry not a function: %s",
2928 uentry_unparse (le)));
2930 params = ctype_argsFunction (ct);
2931 return; /* No checking for non-function */
2940 globSet_allElements (usesGlobs, el)
2942 if (sRef_isValid (el))
2944 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2946 context_usedGlobal (el);
2947 exprNode_checkUse (f, el, f->loc);
2949 if (context_checkInternalUse ())
2951 if (!context_globAccess (el))
2953 if (sRef_isSystemState (el)
2954 && !context_getFlag (FLG_MODFILESYSTEM))
2963 ("Called procedure %s may access %q, but "
2964 "globals list does not include globals %s",
2965 exprNode_unparse (f),
2967 cstring_makeLiteralTemp (sRef_isInternalState (el)
2975 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2981 uentry gle = sRef_getUentry (el);
2982 sRef sr = sRef_updateSref (el);
2984 if (sRef_isUndefGlob (el))
2986 sRef_setDefined (sr, f->loc);
2987 exprNode_checkSet (f, sr);
2995 if (sRef_isAllocated (el))
2997 exprNode_checkSet (f, sr);
3001 if (sRef_isStateUndefined (sr))
3006 ("%s %q used by function undefined before call: %s",
3007 sRef_getScopeName (sr),
3009 exprNode_unparse (f)),
3011 sRef_setDefined (sr, f->loc);
3013 exprNode_checkUse (f, sr, f->loc);
3016 checkGlobUse (gle, TRUE, f);
3019 if (sRef_isKilledGlob (el))
3021 sRef_kill (sr, f->loc);
3022 context_usedGlobal (sr);
3026 } end_globSet_allElements;
3032 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
3034 sRefSet smods = sRefSet_undefined;
3037 ** NEED to check for modifies anything
3041 ** check each sRef that called function modifies (ml), is
3047 sRefSet_allElements (mods, s) /* s is something which may be modified */
3049 DPRINTF (("Check modify: %s", sRef_unparse (s)));
3051 if (sRef_isKindSpecial (s))
3053 if (sRef_isSpecInternalState (s))
3055 if (context_getFlag (FLG_MODINTERNALSTRICT))
3057 exprNode_checkCallModifyVal (s, args, f, ret);
3061 sRefSet mmods = context_modList ();
3063 sRefSet_allElements (mmods, el)
3065 if (sRef_isInternalState (el))
3067 sRef_setModified (el);
3069 } end_sRefSet_allElements ;
3074 exprNode_checkCallModifyVal (s, args, f, ret);
3079 sRef rb = sRef_getRootBase (s);
3081 if (sRef_isFileOrGlobalScope (rb))
3083 context_usedGlobal (rb);
3086 if (sRef_isFileStatic (s)
3087 && !fileId_equal (fileloc_fileId (f->loc),
3088 fileloc_fileId (uentry_whereDefined (le))))
3090 smods = sRefSet_insert (smods, s);
3094 exprNode_checkCallModifyVal (s, args, f, ret);
3097 } end_sRefSet_allElements;
3102 ** Static elements in modifies set can have nasty consequences.
3103 ** (I think...have not been able to reproduce a possible bug.)
3106 if (!sRefSet_isDefined (smods))
3108 mods = sRefSet_newCopy (mods);
3111 sRefSet_allElements (smods, el)
3113 bool res = sRefSet_delete (mods, el);
3116 } end_sRefSet_allElements;
3118 sRefSet_free (smods);
3123 else if (sRefSet_isDefined (mods))
3124 { /* just check observers */
3127 sRefSet_allElements (mods, s) /* s is something which may be modified */
3129 sRef rb = sRef_getRootBase (s);
3133 if (sRef_isParam (rb))
3135 sRef b = sRef_fixBaseParam (s, args);
3137 if (sRef_isObserver (b))
3139 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
3143 message ("Function call may modify observer%q: %s",
3144 sRef_unparsePreOpt (b), exprNode_unparse (e)),
3147 sRef_showExpInfo (b);
3151 } end_sRefSet_allElements;
3155 if (!hasMods) /* no specified modifications */
3157 if (context_getFlag (FLG_MODOBSERVERUNCON))
3159 exprNodeList_elements (args, e)
3161 if (exprNode_isDefined (e))
3163 sRef s = exprNode_getSref (e);
3165 if (sRef_isObserver (s)
3166 && ctype_isMutable (sRef_getType (s)))
3169 (FLG_MODOBSERVERUNCON,
3171 ("Call to unconstrained function %s may modify observer%q: %s",
3172 exprNode_unparse (f),
3173 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3176 sRef_showExpInfo (s);
3180 } end_exprNodeList_elements;
3185 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3187 ret->uses = sRefSet_union (ret->uses, f->uses);
3188 ret->sets = sRefSet_union (ret->sets, f->sets);
3189 ret->msets = sRefSet_union (ret->msets, f->msets);
3194 ** Spurious errors reported, because splint can't tell
3195 ** mods must be fresh if freshMods is true.
3198 /*@i@*/ sRefSet_free (mods);
3204 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3206 if (uentry_isVar (glob))
3208 if (context_inFunctionLike ())
3210 sRef sr = uentry_getSref (glob);
3212 context_usedGlobal (sr);
3214 if (context_checkGlobUse (glob))
3216 if (!context_globAccess (sr))
3222 message ("Called procedure %s may access %s %q",
3223 exprNode_unparse (e),
3224 sRef_unparseScope (sr),
3225 uentry_getName (glob)),
3232 message ("Undocumented use of %s %s",
3233 sRef_unparseScope (sr),
3234 exprNode_unparse (e)),
3243 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3248 reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
3250 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3251 exprNode_unparse (f), exprNodeList_unparse (args),
3252 uentry_unparseFull (le),
3253 stateClauseList_unparse (uentry_getStateClauseList (le))));
3255 if (uentry_isValid (le) && uentry_isFunction (le))
3257 stateClauseList sclauses = uentry_getStateClauseList (le);
3259 if (stateClauseList_isDefined (sclauses))
3261 DPRINTF (("Reflect ensures: %s / %s / %s",
3262 uentry_unparse (le),
3263 exprNode_unparse (f), exprNodeList_unparse (args)));
3265 stateClauseList_elements (sclauses, cl)
3267 if (stateClause_hasEnsures (cl))
3269 /* Same in usymtab.c:1904 */
3270 if (stateClause_setsMetaState (cl))
3272 qual q = stateClause_getMetaQual (cl);
3273 annotationInfo ainfo = qual_getAnnotationInfo (q);
3274 metaStateInfo minfo = annotationInfo_getState (ainfo);
3275 cstring key = metaStateInfo_getName (minfo);
3276 int mvalue = annotationInfo_getValue (ainfo);
3278 sRefSet osrs = sRefSet_undefined;
3281 if (stateClause_isGlobal (cl))
3283 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3288 srs = stateClause_getRefs (cl);
3291 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3294 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3296 sRefSet_elements (srs, sel)
3300 if (sRef_isResult (sRef_getRootBase (sel)))
3302 s = exprNode_getSref (ret);
3306 s = sRef_fixBaseParam (sel, args);
3309 DPRINTF (("Reflecting state clause on: %s / %s",
3310 sRef_unparse (sel), sRef_unparse (s)));
3312 sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3313 } end_sRefSet_elements;
3315 sRefSet_free (osrs);
3319 sRefSet srs = stateClause_getRefs (cl);
3320 sRefModVal modf = stateClause_getEnsuresFunction (cl);
3321 int eparam = stateClause_getStateParameter (cl);
3323 llassert (modf != NULL);
3325 DPRINTF (("Reflect after clause: %s / %s",
3326 stateClause_unparse (cl),
3327 sRefSet_unparse (srs)));
3329 sRefSet_elements (srs, sel)
3333 DPRINTF (("elements: %s", sRef_unparse (sel)));
3334 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3336 if (sRef_isResult (sRef_getRootBase (sel)))
3338 DPRINTF (("Fix base: %s / %s",
3339 sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
3340 s = sRef_fixBase (sel, exprNode_getSref (ret));
3341 DPRINTF (("==> %s", sRef_unparseFull (s)));
3345 s = sRef_fixBaseParam (sel, args);
3348 DPRINTF (("elements: %s", sRef_unparse (s)));
3349 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3351 DPRINTF (("Reflecting state clause on: %s / %s",
3352 sRef_unparseFull (sel), sRef_unparseFull (s)));
3354 /* evans 2001-08-24 - added aliasSetCompleteParam */
3355 sRef_aliasSetCompleteParam (modf, s, eparam, exprNode_loc (f));
3357 DPRINTF (("After reflecting state clause on: %s / %s",
3358 sRef_unparseFull (sel), sRef_unparseFull (s)));
3359 } end_sRefSet_elements;
3362 } end_stateClauseList_elements ;
3365 DPRINTF (("Here: %s / %s",
3366 uentry_unparseFull (le),
3367 bool_unparse (uentry_hasMetaStateEnsures (le))));
3369 if (uentry_hasMetaStateEnsures (le))
3371 fileloc loc = exprNode_loc (f);
3373 metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3375 metaStateConstraintList_elements (mscl, msc)
3377 metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3378 metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3379 metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
3380 cstring key = metaStateInfo_getName (msinfo);
3381 sRef mlsr = metaStateSpecifier_getSref (msspec);
3383 sRef lastref = sRef_undefined;
3384 stateValue sval = stateValue_undefined;
3386 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3387 metaStateConstraint_unparse (msc)));
3388 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3390 if (sRef_isResult (sRef_getRootBase (mlsr)))
3392 s = exprNode_getSref (ret);
3396 s = sRef_fixBaseParam (mlsr, args);
3399 DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3401 while (metaStateExpression_isDefined (msexpr))
3403 metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
3404 metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
3407 DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3409 if (metaStateExpression_isMerge (msexpr))
3411 msexpr = metaStateExpression_getRest (msexpr);
3415 msexpr = metaStateExpression_undefined;
3418 if (metaStateInfo_isDefined (msi))
3420 /* Must match lhs state */
3421 llassert (metaStateInfo_equal (msinfo, msi));
3424 if (metaStateSpecifier_isElipsis (ms))
3427 ** For elipsis, we need to merge all the relevant elipsis parameters
3431 uentryList params = uentry_getParams (le);
3432 int paramno = uentryList_size (params) - 1;
3434 if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
3438 message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3439 uentry_getName (le)),
3440 uentry_whereLast (le));
3441 /*@innerbreak@*/ break;
3444 while (paramno < exprNodeList_size (args))
3446 exprNode arg = exprNodeList_getN (args, paramno);
3447 fs = exprNode_getSref (arg);
3448 DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3450 /* cut and pasted... gack*/
3451 if (stateValue_isDefined (sval))
3453 /* Use combination table to merge old state value with new one: */
3454 stateValue tval = sRef_getMetaStateValue (fs, key);
3456 if (stateValue_isDefined (tval))
3458 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3459 cstring msg = cstring_undefined;
3460 int nval = stateCombinationTable_lookup (sctable,
3461 stateValue_getValue (sval),
3462 stateValue_getValue (tval),
3464 DPRINTF (("Combining: %s + %s -> %d",
3465 stateValue_unparseValue (sval, msinfo),
3466 stateValue_unparseValue (tval, msinfo),
3469 if (nval == stateValue_error)
3474 ("Attributes merged in ensures clause in states that "
3475 "cannot be combined (%q is %q, %q is %q)%q",
3476 sRef_unparse (lastref),
3477 stateValue_unparseValue (sval, msinfo),
3479 stateValue_unparseValue (tval, msinfo),
3480 cstring_isDefined (msg) ?
3481 message (": %s", msg) : cstring_undefined),
3484 sRef_showMetaStateInfo (fs, key);
3488 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3489 loc = exprNode_loc (arg);
3493 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3498 sval = sRef_getMetaStateValue (fs, key);
3503 if (stateValue_isError (sval))
3505 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3514 msr = metaStateSpecifier_getSref (ms);
3517 llassert (sRef_isParam (sRef_getRootBase (msr)));
3518 fs = sRef_fixBaseParam (msr, args);
3520 if (stateValue_isDefined (sval))
3522 /* Use combination table to merge old state value with new one: */
3523 stateValue tval = sRef_getMetaStateValue (fs, key);
3525 if (stateValue_isDefined (tval))
3527 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3528 cstring msg = cstring_undefined;
3529 int nval = stateCombinationTable_lookup (sctable,
3530 stateValue_getValue (sval),
3531 stateValue_getValue (tval),
3533 DPRINTF (("Combining: %s + %s -> %d",
3534 stateValue_unparseValue (sval, msinfo),
3535 stateValue_unparseValue (tval, msinfo),
3538 if (nval == stateValue_error)
3543 ("Attributes merged in ensures clause in states that "
3544 "cannot be combined (%q is %q, %q is %q)%q",
3545 sRef_unparse (lastref),
3546 stateValue_unparseValue (sval, msinfo),
3548 stateValue_unparseValue (tval, msinfo),
3549 cstring_isDefined (msg)
3550 ? message (": %s", msg) : cstring_undefined),
3553 sRef_showMetaStateInfo (fs, key);
3557 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3561 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3566 sval = sRef_getMetaStateValue (fs, key);
3571 if (stateValue_isError (sval))
3573 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3578 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3580 if (stateValue_isDefined (sval))
3582 sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
3586 DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
3588 } end_metaStateConstraintList_elements ;
3590 metaStateConstraintList_free (mscl);
3596 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3598 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3599 exprNode_unparse (f), exprNodeList_unparse (args),
3600 uentry_unparseFull (le),
3601 stateClauseList_unparse (uentry_getStateClauseList (le))));
3603 if (uentry_isValid (le) && uentry_isFunction (le))
3605 stateClauseList sclauses = uentry_getStateClauseList (le);
3607 if (stateClauseList_isDefined (sclauses))
3609 DPRINTF (("Check requires: %s / %s / %s",
3610 uentry_unparse (le),
3611 exprNode_unparse (f), exprNodeList_unparse (args)));
3613 stateClauseList_elements (sclauses, cl)
3615 DPRINTF (("Check clause: %s / %s",
3616 stateClause_unparse (cl),
3617 bool_unparse (stateClause_hasRequires (cl))));
3619 if (stateClause_hasRequires (cl))
3621 sRefSet osrs = sRefSet_undefined;
3624 if (stateClause_isGlobal (cl))
3626 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3631 srs = stateClause_getRefs (cl);
3634 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3636 if (stateClause_setsMetaState (cl))
3638 qual q = stateClause_getMetaQual (cl);
3639 annotationInfo ainfo = qual_getAnnotationInfo (q);
3640 metaStateInfo minfo = annotationInfo_getState (ainfo);
3641 cstring key = metaStateInfo_getName (minfo);
3642 int mvalue = annotationInfo_getValue (ainfo);
3644 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3646 sRefSet_elements (srs, sel)
3648 sRef s = sRef_fixBaseParam (sel, args);
3650 if (sRef_isResult (sRef_getRootBase (sel)))
3656 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3657 sRef_unparseFull (sel), sRef_unparseFull (s),
3660 if (!sRef_checkMetaStateValue (s, key, mvalue))
3662 DPRINTF (("HERE: %s", sRef_unparse (s)));
3666 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3667 uentry_getName (le),
3668 sRef_isGlobalMarker (s)
3670 : message (" by %q", sRef_unparse (s)),
3671 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3673 stateClause_unparse (cl)),
3676 sRef_showAliasInfo (s);
3680 DPRINTF (("Error supressed!"));
3681 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3682 DPRINTF (("Context supress: %s",
3683 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3687 } end_sRefSet_elements;
3691 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3692 int eparam = stateClause_getStateParameter (cl);
3694 DPRINTF (("Reflect after clause: %s / %s",
3695 stateClause_unparse (cl),
3696 sRefSet_unparse (srs)));
3698 llassert (modf != NULL);
3700 sRefSet_elements (srs, sel)
3704 DPRINTF (("elements: %s", sRef_unparse (sel)));
3705 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3707 s = sRef_fixBaseParam (sel, args);
3709 DPRINTF (("elements: %s", sRef_unparse (s)));
3710 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3712 if (sRef_isResult (sRef_getRootBase (sel)))
3714 ; /* what do we do about results? */
3718 DPRINTF (("Reflecting state clause on: %s / %s",
3719 sRef_unparse (sel), sRef_unparse (s)));
3721 modf (s, eparam, exprNode_loc (f));
3723 } end_sRefSet_elements;
3726 sRefSet_free (osrs);
3728 } end_stateClauseList_elements ;
3733 static /*@only@*/ exprNode
3734 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3735 ctype t, /*@keep@*/ exprNodeList args)
3737 /* requires f is a non-error exprNode, with type function */
3738 cstring fname = exprNode_unparse (f);
3739 uentry le = exprNode_getUentry (f);
3740 exprNode ret = exprNode_createPartialCopy (f);
3745 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3747 ret->typ = ctype_getReturnType (t);
3748 ret->kind = XPR_CALL;
3750 ret->edata = exprData_makeCall (f, args);
3753 ** Order of these steps is very important!
3755 ** Must check for argument dependencies before messing up uses and sets.
3758 if (context_getFlag (FLG_EVALORDER))
3760 exprNodeList_elements (args, current)
3762 if (exprNode_isDefined (current))
3764 exprNode_addUse (current, current->sref);
3766 } end_exprNodeList_elements;
3768 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3770 checkSequencing (f, args);
3773 exprNodeList_elements (args, current)
3775 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3777 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3779 } end_exprNodeList_elements ;
3782 special = checkArgs (le, f, t, args, ret);
3783 checkGlobMods (f, le, args, ret, special);
3784 checkRequiresClause (le, f, args);
3787 if (uentry_isValid (le)
3788 && (uentry_isFunction (le)
3789 || (uentry_isVariable (le)
3790 && ctype_isFunction (uentry_getType (le)))))
3792 exitkind exk = uentry_getExitCode (le);
3794 /* f->typ is already set to the return type */
3796 DPRINTF (("Function: %s", uentry_unparseFull (le)));
3797 ret->sref = uentry_returnedRef (le, args, exprNode_loc (f));
3798 DPRINTF (("Returned: %s / %s",
3799 uentry_unparseFull (le),
3800 sRef_unparseFull (ret->sref)));
3802 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3804 qual nullPred = uentry_nullPred (le);
3806 if (qual_isTrueNull (nullPred))
3808 exprNode arg = exprNodeList_head (args);
3810 if (exprNode_isDefined (arg))
3812 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3815 else if (qual_isFalseNull (nullPred))
3817 exprNode arg = exprNodeList_head (args);
3819 if (exprNode_isDefined (arg))
3821 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3826 llassert (qual_isUnknown (nullPred));
3830 if (exitkind_isConditionalExit (exk))
3834 ** if (arg0) then { exit! } else { ; }
3836 ** if (arg0) then { ; } else { exit! }
3841 llassert (!exprNodeList_isEmpty (args));
3842 firstArg = exprNodeList_head (args);
3844 if (exprNode_isDefined (firstArg)
3845 && !guardSet_isEmpty (firstArg->guards))
3847 usymtab_trueBranch (guardSet_undefined);
3848 usymtab_altBranch (guardSet_undefined);
3850 if (exitkind_isTrueExit (exk))
3852 usymtab_popBranches (firstArg,
3853 exprNode_makeMustExit (),
3855 TRUE, TRUEEXITCLAUSE);
3859 usymtab_popBranches (firstArg,
3861 exprNode_makeMustExit (),
3862 TRUE, FALSEEXITCLAUSE);
3866 ret->exitCode = XK_MAYEXIT;
3868 else if (exitkind_mustExit (exk))
3870 ret->exitCode = XK_MUSTEXIT;
3872 else if (exitkind_couldExit (exk))
3874 ret->exitCode = XK_MAYEXIT;
3881 if (cstring_equalLit (fname, "exit"))
3883 if (exprNodeList_size (args) == 1)
3885 exprNode arg = exprNodeList_head (args);
3887 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3889 long int val = multiVal_forceInt (exprNode_getValue (arg));
3896 ("Argument to exit has implementation defined behavior: %s",
3897 exprNode_unparse (arg)),
3898 exprNode_loc (arg));
3906 ret->sref = sRef_undefined;
3907 exprNode_checkSetAny (ret, uentry_rawName (le));
3910 DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3911 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3912 reflectEnsuresClause (ret, le, f, args);
3915 DPRINTF (("Here: %s", sRef_unparseFull (ret->sref)));
3920 ** this is yucky! should keep the uentry as part of exprNode!
3923 uentry exprNode_getUentry (exprNode e)
3925 if (exprNode_isError (e))
3927 return uentry_undefined;
3931 cstring s = exprNode_rootVarName (e);
3932 uentry ue = usymtab_lookupSafe (s);
3939 ** Returns true iff e1 and e2 are both exactly the same storage
3943 static bool exprNode_sameStorage (exprNode e1, exprNode e2)
3945 sRef s1 = exprNode_getSref (e1);
3946 sRef s2 = exprNode_getSref (e2);
3948 return (sRef_realSame (s1, s2));
3952 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3954 exprNode ret = exprNode_createPlain (ctype_unknown);
3956 ret->kind = XPR_INITBLOCK;
3957 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3958 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3964 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3969 usymtab_checkAllValid ();
3972 if (exprNode_isUndefined (f))
3975 exprNodeList_free (args);
3976 return exprNode_undefined;
3979 t = exprNode_getType (f);
3981 if (sRef_isLocalVar (f->sref))
3983 exprNode_checkUse (f, f->sref, f->loc);
3985 if (sRef_possiblyNull (f->sref))
3987 if (!usymtab_isGuarded (f->sref))
3989 if (optgenerror (FLG_NULLDEREF,
3990 message ("Function call using %s pointer %q",
3991 sRef_nullMessage (f->sref),
3992 sRef_unparse (f->sref)),
3995 sRef_showNullInfo (f->sref);
3996 sRef_setNullError (f->sref);
4004 if (ctype_isRealFunction (t))
4006 exprNode ret = functionCallSafe (f, t, args);
4010 else if (ctype_isUnknown (t))
4012 exprNode ret = exprNode_createPartialCopy (f);
4018 exprNodeList_elements (args, current)
4020 if (exprNode_isDefined (current))
4022 exprNode_checkUse (ret, current->sref, ret->loc);
4025 ** also, anything derivable from current->sref may be used
4028 exprNode_addUse (ret, sRef_makeDerived (current->sref));
4029 exprNode_mergeUSs (ret, current);
4031 } end_exprNodeList_elements;
4033 ret->edata = exprData_makeCall (f, args);
4034 ret->kind = XPR_CALL;
4036 tstring = cstring_copy (exprNode_unparse (f));
4038 cstring_markOwned (tstring);
4039 exprNode_checkSetAny (ret, tstring);
4045 voptgenerror (FLG_TYPE,
4046 message ("Call to non-function (type %t): %s", t,
4047 exprNode_unparse (f)),
4050 exprNodeList_free (args);
4052 return (exprNode_makeError ());
4057 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4058 /*@only@*/ cstring f)
4060 exprNode ret = exprNode_createPartialCopy (s);
4062 ret->kind = XPR_FACCESS;
4064 if (exprNode_isError (s))
4066 ret->edata = exprData_makeField (s, f);
4071 ctype t = exprNode_getType (s);
4072 ctype tr = ctype_realType (t);
4074 checkMacroParen (s);
4076 ret->edata = exprData_makeField (s, f);
4078 if (ctype_isStructorUnion (tr))
4080 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
4082 if (uentry_isUndefined (tf))
4084 voptgenerror (FLG_TYPE,
4085 message ("Access non-existent field %s of %t: %s", f, t,
4086 exprNode_unparse (ret)),
4088 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
4093 uentry_setUsed (tf, exprNode_loc (ret));
4095 ret->typ = uentry_getType (tf);
4096 checkSafeUse (ret, s->sref);
4098 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
4099 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
4103 else /* isStructorUnion */
4105 if (ctype_isRealAbstract (tr))
4109 message ("Access field of abstract type (%t): %s.%s",
4110 t, exprNode_unparse (s), f),
4112 ret->typ = ctype_unknown;
4116 if (ctype_isKnown (tr))
4121 ("Access field of non-struct or union (%t): %s.%s",
4122 t, exprNode_unparse (s), f),
4125 ret->typ = ctype_unknown;
4129 cstring sn = cstring_copy (f);
4131 checkSafeUse (ret, s->sref);
4132 cstring_markOwned (sn);
4133 ret->sref = sRef_makeField (s->sref, sn);
4145 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
4146 /*@only@*/ cstring f)
4148 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
4154 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
4156 exprNode ret = exprNode_createPartialCopy (e);
4158 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
4159 ret->kind = XPR_PARENS;
4160 ret->edata = exprData_makeUop (e, lpar);
4162 if (!exprNode_isError (e))
4164 ret->exitCode = e->exitCode;
4165 ret->canBreak = e->canBreak;
4166 ret->mustBreak = e->mustBreak;
4167 ret->isJumpPoint = e->isJumpPoint;
4168 ret->sref = e->sref;
4175 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4176 /*@only@*/ cstring f)
4178 exprNode ret = exprNode_createPartialCopy (s);
4180 ret->edata = exprData_makeField (s, f);
4181 ret->kind = XPR_ARROW;
4183 if (exprNode_isError (s))
4189 ctype t = exprNode_getType (s);
4190 ctype tr = ctype_realType (t);
4192 checkMacroParen (s);
4194 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4196 if (ctype_isRealPointer (tr))
4198 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4200 if (ctype_isStructorUnion (b))
4202 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4204 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4206 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4210 message ("Arrow access from %s pointer%q: %s",
4211 sRef_nullMessage (s->sref),
4212 sRef_unparsePreOpt (s->sref),
4213 exprNode_unparse (ret)),
4216 sRef_showNullInfo (s->sref);
4217 sRef_setNullError (s->sref);
4222 if (uentry_isUndefined (fentry))
4226 message ("Access non-existent field %s of %t: %s",
4227 f, t, exprNode_unparse (ret)),
4229 ret->typ = ctype_unknown;
4235 ** was safeUse: shouldn't be safe!
4238 ** rec must be defined,
4239 ** *rec must be allocated
4240 ** rec->field need only be defined it if is an rvalue
4243 uentry_setUsed (fentry, exprNode_loc (ret));
4244 ret->typ = uentry_getType (fentry);
4246 exprNode_checkUse (ret, s->sref, s->loc);
4248 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4249 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4253 else /* Pointer to something that is not a struct or union*/
4255 if (ctype_isRealAbstract (tr))
4257 ctype xrt = ctype_forceRealType (tr);
4261 message ("Arrow access field of abstract type (%t): %s->%s",
4262 t, exprNode_unparse (s), f),
4266 ** Set the state correctly, as if the abstraction is broken.
4269 if (ctype_isRealPointer (xrt) &&
4270 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4271 ctype_isStructorUnion (b)))
4273 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4274 ret->typ = uentry_getType (fentry);
4275 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4279 ret->typ = ctype_unknown;
4280 ret->sref = sRef_undefined;
4283 else /* not a struct, union or abstract */
4285 if (ctype_isUnknown (tr)) {
4286 cstring sn = cstring_copy (f);
4288 DPRINTF (("Here: %s", exprNode_unparse (s)));
4290 exprNode_checkUse (ret, s->sref, s->loc);
4291 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4293 cstring_markOwned (sn);
4294 ret->sref = sRef_makeArrow (s->sref, sn);
4296 ret->kind = XPR_ARROW;
4301 message ("Arrow access field of non-struct or union "
4302 "pointer (%t): %s->%s",
4303 t, exprNode_unparse (s), f),
4306 ret->typ = ctype_unknown;
4307 ret->sref = sRef_undefined;
4312 else /* its not a pointer */
4314 if (!ctype_isUnknown (tr))
4318 message ("Arrow access of non-pointer (%t): %s->%s",
4319 t, exprNode_unparse (s), f),
4322 ret->typ = ctype_unknown;
4323 ret->sref = sRef_undefined;
4327 cstring sn = cstring_copy (f);
4329 DPRINTF (("Here: %s", exprNode_unparse (s)));
4331 exprNode_checkUse (ret, s->sref, s->loc);
4332 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4334 cstring_markOwned (sn);
4335 ret->sref = sRef_makeArrow (s->sref, sn);
4337 ret->kind = XPR_ARROW;
4348 exprNode_arrowAccess (/*@only@*/ exprNode s,
4349 /*@only@*/ lltok arrow,
4350 /*@only@*/ cstring f)
4352 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4358 ** only postOp's in C: i++ and i--
4362 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4364 /* check modification also */
4365 /* cstring opname = lltok_unparse (op);*/
4367 exprNode ret = exprNode_createPartialCopy (e);
4369 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4370 ret->kind = XPR_POSTOP;
4371 ret->edata = exprData_makeUop (e, op);
4373 if (!exprNode_isDefined (e))
4378 checkMacroParen (e);
4380 exprNode_checkUse (ret, e->sref, e->loc);
4381 exprNode_checkSet (ret, e->sref);
4383 t = exprNode_getType (e);
4385 if (sRef_isUnsafe (e->sref))
4387 voptgenerror (FLG_MACROPARAMS,
4388 message ("Operand of %s is macro parameter (non-functional): %s%s",
4389 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4391 sRef_makeSafe (e->sref);
4392 sRef_makeSafe (ret->sref);
4395 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4401 if (ctype_isRealAbstract (t))
4403 if (ctype_isRealNumAbstract (t)) {
4404 ; /* Allow operations on numabstract types */
4408 message ("Operand of %s is abstract type (%t): %s",
4409 lltok_unparse (op), t, exprNode_unparse (e)),
4417 message ("Operand of %s is non-numeric (%t): %s",
4418 lltok_unparse (op), t, exprNode_unparse (e)),
4421 ret->typ = ctype_unknown;
4424 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4426 exprNode_checkModify (e, ret);
4428 /* added 7/11/2000 D.L */
4430 /* updateEnvironmentForPostOp (e); */
4432 /* start modifications */
4433 /* added by Seejo on 4/16/2000 */
4435 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4437 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4439 ret->sref = sRef_copy (e->sref);
4442 if (lltok_getTok (op) == INC_OP) {
4443 if (sRef_getSize(e->sref) > 0) {
4445 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4447 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4448 /* Assumption: there is only 1 \0 in the buffer */
4449 /* This will not be correct if there are 2 \0's in the buffer */
4450 sRef_setNotNullTerminatedState(ret->sref);
4451 sRef_resetLen(ret->sref);
4453 sRef_setNullTerminatedState(ret->sref);
4454 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4456 if (sRef_isNullTerminated (ret->sref))
4457 printf ("ret->sref is Null Terminated\n");
4458 else if (sRef_isPossiblyNullTerminated (ret->sref))
4459 printf ("ret->sref is Possibly Null Terminated\n");
4460 else if (sRef_isNotNullTerminated (ret->sref))
4461 printf ("ret->sref is Not Null Terminated\n");
4468 if (lltok_getTok (op) == DEC_OP) {
4469 if (sRef_getSize(e->sref) >= 0) {
4470 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4471 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4475 /* end modifications */
4481 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4483 bool checkMod = FALSE;
4485 int opid = lltok_getTok (op);
4486 exprNode ret = exprNode_createSemiCopy (e);
4488 exprNode_copySets (ret, e);
4490 multiVal_free (ret->val);
4491 ret->val = multiVal_undefined;
4492 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4493 ret->kind = XPR_PREOP;
4494 ret->edata = exprData_makeUop (e, op);
4496 if (exprNode_isError (e))
4501 checkMacroParen (e);
4503 te = exprNode_getType (e);
4504 tr = ctype_realType (te);
4506 if (opid != TAMPERSAND)
4508 exprNode_checkUse (ret, e->sref, e->loc);
4510 if (ctype_isRealAbstract (tr)
4511 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4513 if (ctype_isRealNumAbstract (tr))
4515 ; /* no warning for numabstract types */
4519 if (optgenerror (FLG_ABSTRACT,
4520 message ("Operand of %s is abstract type (%t): %s",
4521 lltok_unparse (op), tr,
4522 exprNode_unparse (ret)),
4525 tr = te = ctype_unknown;
4526 ret->typ = ctype_unknown;
4527 sRef_setNullError (e->sref);
4536 case DEC_OP: /* should also check modification! */
4537 if (sRef_isMacroParamRef (e->sref))
4541 message ("Operand of %s is macro parameter (non-functional): %s",
4542 lltok_unparse (op), exprNode_unparse (ret)),
4547 exprNode_checkSet (ret, e->sref);
4550 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4555 if (context_msgStrictOps ())
4559 message ("Operand of %s is non-numeric (%t): %s",
4560 lltok_unparse (op), te, exprNode_unparse (ret)),
4563 ret->typ = ctype_int;
4566 /* start modifications */
4567 /* added by Seejo on 4/16/2000 */
4569 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4571 if ((sRef_isPossiblyNullTerminated (e->sref))
4572 || (sRef_isNullTerminated(e->sref))) {
4573 ret->sref = sRef_copy (e->sref);
4576 if (lltok_getTok (op) == INC_OP) {
4577 if (sRef_getSize(e->sref) > 0) {
4579 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4581 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4582 /* Assumption: there is only 1 \0 in the buffer */
4583 /* This will not be correct if there are 2 \0's in the buffer */
4584 sRef_setNotNullTerminatedState(ret->sref);
4585 sRef_resetLen (ret->sref);
4587 sRef_setNullTerminatedState(ret->sref);
4588 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4594 if (lltok_getTok (op) == DEC_OP) {
4595 if (sRef_getSize(e->sref) >= 0) {
4596 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4597 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4602 /* end modifications */
4609 if (ctype_isForceRealNumeric (&tr))
4613 ret->val = multiVal_invert (exprNode_getValue (e));
4617 ret->val = multiVal_copy (exprNode_getValue (e));
4622 if (context_msgStrictOps ())
4626 message ("Operand of %s is non-numeric (%t): %s",
4627 lltok_unparse (op), te, exprNode_unparse (ret)),
4631 ret->typ = ctype_int;
4635 case TEXCL: /* maybe this should be restricted */
4636 guardSet_flip (ret->guards);
4638 if (ctype_isRealBool (te) || ctype_isUnknown (te))
4644 if (ctype_isRealPointer (tr))
4646 if (sRef_isKnown (e->sref))
4648 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4652 (FLG_BOOLOPS, FLG_PTRNEGATE,
4653 message ("Operand of %s is non-boolean (%t): %s",
4654 lltok_unparse (op), te, exprNode_unparse (ret)),
4661 message ("Operand of %s is non-boolean (%t): %s",
4662 lltok_unparse (op), te, exprNode_unparse (ret)),
4666 ret->typ = ctype_bool;
4671 if (ctype_isForceRealInt (&tr))
4676 if (context_msgStrictOps ())
4680 message ("Operand of %s is non-integer (%t): %s",
4681 lltok_unparse (op), te, exprNode_unparse (ret)),
4685 if (ctype_isInt (e->typ))
4691 ret->typ = ctype_int;
4697 ret->typ = ctype_makePointer (e->typ);
4699 if (sRef_isKnown (e->sref))
4701 ret->sref = sRef_makeAddress (e->sref);
4708 if (ctype_isAP (tr))
4710 ret->typ = ctype_baseArrayPtr (e->typ);
4714 if (ctype_isKnown (te))
4716 if (ctype_isFunction (te))
4722 message ("Dereference of function type (%t): %s",
4723 te, exprNode_unparse (ret)),
4728 voptgenerror (FLG_TYPE,
4729 message ("Dereference of non-pointer (%t): %s",
4730 te, exprNode_unparse (ret)),
4732 ret->typ = ctype_unknown;
4737 ret->typ = ctype_unknown;
4742 if (sRef_isKnown (e->sref))
4744 DPRINTF (("Checking possibly null: %s", sRef_unparseFull (e->sref)));
4746 if (sRef_possiblyNull (e->sref))
4748 DPRINTF (("Checking possibly null: %s", sRef_unparse (e->sref)));
4749 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4753 message ("Dereference of %s pointer %q: %s",
4754 sRef_nullMessage (e->sref),
4755 sRef_unparse (e->sref),
4756 exprNode_unparse (ret)),
4759 sRef_showNullInfo (e->sref);
4760 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4765 ret->sref = sRef_makePointer (e->sref);
4770 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4775 exprNode_checkModify (e, ret);
4782 ** any reason to disallow sizeof (abstract type) ?
4786 ** used by both sizeof
4790 ctype sizeof_resultType (void)
4792 static ctype sizet = ctype_unknown;
4794 if (ctype_isUnknown (sizet))
4796 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4798 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4802 sizet = ctype_ulint;
4809 exprNode_sizeofType (/*@only@*/ qtype qt)
4811 exprNode ret = exprNode_create (sizeof_resultType ());
4812 ctype ct = qtype_getType (qt);
4814 ret->kind = XPR_SIZEOFT;
4815 ret->edata = exprData_makeSizeofType (qt);
4817 voptgenerror (FLG_SIZEOFTYPE,
4818 message ("Parameter to sizeof is type %s: %s",
4820 exprNode_unparse (ret)),
4827 exprNode_alignofType (/*@only@*/ qtype qt)
4829 exprNode ret = exprNode_create (sizeof_resultType ());
4830 ctype ct = qtype_getType (qt);
4832 ret->kind = XPR_ALIGNOFT;
4833 ret->edata = exprData_makeSizeofType (qt);
4835 voptgenerror (FLG_SIZEOFTYPE,
4836 message ("Parameter to alignof is type %s: %s",
4838 exprNode_unparse (ret)),
4844 exprNode exprNode_offsetof (qtype qt, cstringList s)
4846 exprNode ret = exprNode_create (sizeof_resultType ());
4847 ctype ct = qtype_getType (qt);
4849 ret->kind = XPR_OFFSETOF;
4850 ret->edata = exprData_makeOffsetof (qt, s);
4852 if (!ctype_isRealSU (ct))
4854 voptgenerror (FLG_TYPE,
4855 message ("First parameter to offsetof is not a "
4856 "struct or union type (type %s): %s",
4858 exprNode_unparse (ret)),
4865 cstringList_elements (s, el) {
4869 if (ctype_isUndefined (lt))
4873 else if (!ctype_isRealSU (lt))
4875 voptgenerror (FLG_TYPE,
4876 message ("Inner offsetof type is not a "
4877 "struct or union type (type %s before field %s): %s",
4878 ctype_unparse (lt), el,
4879 exprNode_unparse (ret)),
4885 fields = ctype_getFields (ctype_realType (lt));
4886 fld = uentryList_lookupField (fields, el);
4887 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4889 if (uentry_isUndefined (fld))
4891 if (ctype_equal (lt, ct)) {
4892 voptgenerror (FLG_TYPE,
4893 message ("Field %s in offsetof is not the "
4894 "name of a field of %s: %s",
4897 exprNode_unparse (ret)),
4900 voptgenerror (FLG_TYPE,
4901 message ("Deep field %s in offsetof is not the "
4902 "name of a field of %s: %s",
4905 exprNode_unparse (ret)),
4911 lt = uentry_getType (fld);
4914 } end_cstringList_elements;
4916 /* Should report error if its a bit field - behavior is undefined! */
4923 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4927 if (exprNode_isUndefined (e))
4929 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4930 ret->edata = exprData_makeSingle (e);
4931 ret->typ = sizeof_resultType ();
4932 ret->kind = XPR_SIZEOF;
4936 uentry u = exprNode_getUentry (e);
4938 ret = exprNode_createPartialCopy (e);
4939 ret->edata = exprData_makeSingle (e);
4941 ret->typ = sizeof_resultType ();
4942 ret->kind = XPR_SIZEOF;
4944 if (uentry_isValid (u)
4945 && uentry_isRefParam (u)
4946 && ctype_isRealArray (uentry_getType (u)))
4949 (FLG_SIZEOFFORMALARRAY,
4950 message ("Parameter to sizeof is an array-type function parameter: %s",
4951 exprNode_unparse (ret)),
4957 ** sizeof (x) doesn't "really" use x
4964 exprNode_alignofExpr (/*@only@*/ exprNode e)
4968 if (exprNode_isUndefined (e))
4970 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4974 ret = exprNode_createPartialCopy (e);
4977 ret->edata = exprData_makeSingle (e);
4978 ret->typ = sizeof_resultType ();
4979 ret->kind = XPR_ALIGNOF;
4982 ** sizeof (x) doesn't "really" use x
4989 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4995 if (exprNode_isError (e))
4999 return exprNode_undefined;
5002 checkMacroParen (e);
5004 c = qtype_getType (q);
5005 t = exprNode_getType (e);
5007 ret = exprNode_createPartialCopy (e);
5009 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
5011 ret->kind = XPR_CAST;
5012 ret->edata = exprData_makeCast (tok, e, q);
5014 ret->sref = sRef_copy (e->sref);
5016 DPRINTF (("Cast: -> %s", sRef_unparseFull (ret->sref)));
5018 if (!sRef_isConst (e->sref))
5020 usymtab_addForceMustAlias (ret->sref, e->sref);
5023 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
5024 sRef_setTypeFull (ret->sref, c);
5025 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
5031 ** void * <-> abstract * (if FLG_ABSTVOIDP)
5032 ** abstract * <-> void * (if FLG_ABSTVOIDP)
5035 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
5037 /* evans 2002-07-19: added this warning */
5038 DPRINTF (("Checking: %s / %s", exprNode_unparse (ret), sRef_unparseFull (ret->sref)));
5039 if (sRef_isFresh (ret->sref))
5043 message ("New fresh storage %q(type %s) cast to void (not released): %s",
5044 sRef_unparseOpt (ret->sref),
5045 ctype_unparse (exprNode_getType (ret)),
5046 exprNode_unparse (ret)),
5047 exprNode_loc (ret));
5050 else if (ctype_isRealAP (c)) /* casting to array or pointer */
5052 ctype bc = ctype_getBaseType (c);
5053 ctype bt = ctype_getBaseType (t);
5054 ctype rt = ctype_realType (t);
5056 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
5057 && (ctype_isArrayPtr (rt)
5058 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5062 message ("Cast from function pointer type (%t) to "
5063 "non-function pointer (%t): %s",
5064 c, t, exprNode_unparse (ret)),
5068 if (!ctype_isFunction (ctype_baseArrayPtr (c))
5069 && (ctype_isArrayPtr (rt)
5070 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5074 message ("Cast from non-function pointer type (%t) to "
5075 "function pointer (%t): %s",
5076 c, t, exprNode_unparse (ret)),
5080 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
5081 !(ctype_isRealAbstract (bc)
5082 && context_hasAccess (ctype_typeId (bc))))
5084 ; /* okay to cast zero */
5088 if (ctype_isRealAbstract (bc)
5089 && !context_hasAccess (ctype_typeId (bc)))
5091 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
5095 message ("Cast to underlying abstract type %t: %s",
5096 c, exprNode_unparse (ret)),
5103 message ("Cast to underlying abstract type %t: %s",
5104 c, exprNode_unparse (ret)),
5109 if (ctype_isRealAbstract (bt)
5110 && !context_hasAccess (ctype_typeId (bt)))
5112 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
5116 message ("Cast from underlying abstract type %t: %s",
5117 t, exprNode_unparse (ret)),
5124 message ("Cast from underlying abstract type %t: %s",
5125 t, exprNode_unparse (ret)),
5133 ctype bt = ctype_realType (ctype_getBaseType (t));
5134 ctype bc = ctype_realType (ctype_getBaseType (c));
5136 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
5138 if (ctype_match (c, t))
5140 if (ctype_equal (c, t))
5144 message ("Redundant cast involving abstract type %t: %s",
5145 bt, exprNode_unparse (ret)),
5153 message ("Cast from abstract type %t: %s",
5154 bt, exprNode_unparse (ret)),
5159 if (ctype_isAbstract (bc)
5160 && !context_hasAccess (ctype_typeId (bc)))
5162 if (ctype_match (c, t))
5168 if (ctype_isNumAbstract (bc))
5170 if (exprNode_isNumLiteral (e))
5173 (FLG_NUMABSTRACTCAST,
5174 message ("Cast from literal to numabstract type %t: %s", bc,
5175 exprNode_unparse (ret)),
5182 message ("Cast to numabstract type %t: %s", bc,
5183 exprNode_unparse (ret)),
5189 DPRINTF (("No access to: %s / %d",
5190 ctype_unparse (bc), ctype_typeId (bc)));
5191 DPRINTF (("Context %s %s",
5192 bool_unparse (context_inFunctionLike ()),
5193 context_unparse ()));
5196 message ("Cast to abstract type %t: %s", bc,
5197 exprNode_unparse (ret)),
5204 if (ctype_isAbstract (c))
5206 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
5208 /* okay, cast exposed to abstract */
5209 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
5213 if (ctype_isVisiblySharable (t)
5214 && sRef_isExternallyVisible (e->sref)
5215 && !(ctype_isAbstract (t)
5216 && context_hasAccess (ctype_typeId (t))))
5220 message ("Cast to abstract type from externally visible "
5221 "mutable storage exposes rep of %s: %s",
5223 exprNode_unparse (e)),
5233 evaluationOrderUndefined (lltok op)
5235 int opid = lltok_getTok (op);
5237 return (opid != AND_OP && opid != OR_OP);
5240 static bool checkIntegral (/*@notnull@*/ exprNode e1,
5241 /*@notnull@*/ exprNode e2,
5242 /*@notnull@*/ exprNode ret,
5247 ctype te1 = exprNode_getType (e1);
5248 ctype te2 = exprNode_getType (e2);
5250 ctype tr1 = ctype_realishType (te1);
5251 ctype tr2 = ctype_realishType (te2);
5253 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5259 if (context_msgStrictOps ())
5261 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5263 if (ctype_sameName (te1, te2))
5267 message ("Operands of %s are non-integer (%t): %s",
5268 lltok_unparse (op), te1,
5269 exprNode_unparse (ret)),
5276 message ("Operands of %s are non-integers (%t, %t): %s",
5277 lltok_unparse (op), te1, te2,
5278 exprNode_unparse (ret)),
5282 else if (!ctype_isInt (tr1))
5286 message ("Left operand of %s is non-integer (%t): %s",
5287 lltok_unparse (op), te1, exprNode_unparse (ret)),
5291 /* !ctype_isInt (te2) */
5295 message ("Right operand of %s is non-integer (%t): %s",
5296 lltok_unparse (op), te2, exprNode_unparse (ret)),
5306 ** returns exprNode representing e1 op e2
5308 ** uses msg if there are errors
5309 ** can be used for both assignment ops and regular ops
5314 static /*@only@*/ /*@notnull@*/ exprNode
5315 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
5316 /*@keep@*/ lltok op)
5318 ctype te1, te2, tr1, tr2, tret;
5319 int opid = lltok_getTok (op);
5320 bool hasError = FALSE;
5323 if (exprNode_isError (e1))
5325 ret = exprNode_createPartialNVCopy (e2);
5329 ret = exprNode_createPartialNVCopy (e1);
5332 ret->val = multiVal_undefined;
5335 ret->edata = exprData_makeOp (e1, e2, op);
5337 if (exprNode_isError (e1) || exprNode_isError (e2))
5339 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5340 || opid == EQ_OP || opid == NE_OP
5341 || opid == AND_OP || opid == OR_OP)
5343 ret->typ = ctype_bool;
5346 if (exprNode_isDefined (e1))
5348 exprNode_checkUse (ret, e1->sref, e1->loc);
5351 if (exprNode_isDefined (e2))
5353 exprNode_mergeUSs (ret, e2);
5354 exprNode_checkUse (ret, e2->sref, e2->loc);
5360 tret = ctype_unknown;
5361 te1 = exprNode_getType (e1);
5363 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5365 te2 = exprNode_getType (e2);
5367 tr1 = ctype_realishType (te1);
5368 tr2 = ctype_realishType (te2);
5372 ret->guards = guardSet_or (ret->guards, e2->guards);
5374 else if (opid == AND_OP)
5376 ret->guards = guardSet_and (ret->guards, e2->guards);
5383 if (opid == EQ_OP || opid == NE_OP)
5385 exprNode temp1 = e1, temp2 = e2;
5387 /* could do NULL == x */
5389 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5391 temp1 = e2; temp2 = e1;
5394 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5396 reflectNullTest (temp1, (opid == NE_OP));
5397 guardSet_free (ret->guards);
5398 ret->guards = guardSet_copy (temp1->guards);
5402 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5403 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5408 if (anyAbstract (tr1, tr2) &&
5409 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
5410 (opid == AND_OP || opid == OR_OP
5411 || opid == EQ_OP || opid == NE_OP))))
5413 if (abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc))
5415 tret = ctype_unknown;
5420 if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5422 /* unknown types, no comparisons possible */
5428 case TMULT: /* multiplication and division: */
5430 case MUL_ASSIGN: /* numeric, numeric -> numeric */
5431 case DIV_ASSIGN: /* */
5432 if (opid == TMULT || opid == MUL_ASSIGN)
5434 ret->val = multiVal_multiply (exprNode_getValue (e1),
5435 exprNode_getValue (e2));
5439 ret->val = multiVal_divide (exprNode_getValue (e1),
5440 exprNode_getValue (e2));
5443 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5446 case TPLUS: /* addition and subtraction: */
5447 case TMINUS: /* pointer, int -> pointer */
5448 case SUB_ASSIGN: /* int, pointer -> pointer */
5449 case ADD_ASSIGN: /* numeric, numeric -> numeric */
5450 if (opid == TPLUS || opid == ADD_ASSIGN)
5452 ret->val = multiVal_add (exprNode_getValue (e1),
5453 exprNode_getValue (e2));
5457 ret->val = multiVal_subtract (exprNode_getValue (e1),
5458 exprNode_getValue (e2));
5461 tr1 = ctype_fixArrayPtr (tr1);
5463 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5464 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5468 if (context_msgPointerArith ())
5472 message ("Pointer arithmetic (%t, %t): %s",
5473 te1, te2, exprNode_unparse (ret)),
5478 ** Swap terms so e1 is always the pointer
5481 if (ctype_isRealPointer (tr1))
5487 exprNode_swap (e1, e2);
5490 if (sRef_possiblyNull (e1->sref)
5491 && !usymtab_isGuarded (e1->sref))
5494 (FLG_NULLPOINTERARITH,
5495 message ("Pointer arithmetic involving possibly "
5496 "null pointer %s: %s",
5497 exprNode_unparse (e1),
5498 exprNode_unparse (ret)),
5502 ret->sref = sRef_copy (e1->sref);
5504 /* start modifications */
5505 /* added by Seejo on 4/16/2000 */
5507 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5509 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5512 added ugly fixed to stop
5513 program from crashing on point + int +int
5514 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5516 if (!multiVal_isInt (e2->val) )
5520 val = (int) multiVal_forceInt (e2->val);
5522 /* Operator : + or += */
5523 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5524 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5525 val should not result in a
5526 size < 0 (size = 0 is ok !) */
5528 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5530 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5531 sRef_setNotNullTerminatedState(ret->sref);
5532 sRef_resetLen (ret->sref);
5534 sRef_setNullTerminatedState(ret->sref);
5535 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5540 /* Operator : - or -= */
5541 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5542 if (sRef_getSize(e1->sref) >= 0) {
5543 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5544 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5549 /* end modifications */
5551 sRef_setNullError (ret->sref);
5554 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5555 ** since is points to storage that should not be deallocated
5556 ** through this pointer.
5559 if (sRef_isOnly (ret->sref)
5560 || sRef_isFresh (ret->sref))
5562 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5567 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5568 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5570 if (context_msgPointerArith ())
5574 message ("Pointer arithmetic (%t, %t): %s",
5575 te1, te2, exprNode_unparse (ret)),
5579 if (sRef_possiblyNull (e1->sref)
5580 && !usymtab_isGuarded (e1->sref))
5583 (FLG_NULLPOINTERARITH,
5584 message ("Pointer arithmetic involving possibly "
5585 "null pointer %s: %s",
5586 exprNode_unparse (e2),
5587 exprNode_unparse (ret)),
5591 ret->sref = sRef_copy (e2->sref);
5593 /* start modifications */
5594 /* added by Seejo on 4/16/2000 */
5596 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5599 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5600 if (multiVal_isDefined (e1->val))
5602 int val = (int) multiVal_forceInt (e1->val);
5604 /* Operator : + or += */
5605 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5606 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5607 val should not result in a
5608 size < 0 (size = 0 is ok !) */
5610 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5612 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5613 sRef_setNotNullTerminatedState(ret->sref);
5614 sRef_resetLen (ret->sref);
5616 sRef_setNullTerminatedState(ret->sref);
5617 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5622 /* Operator : - or -= */
5623 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5624 if (sRef_getSize(e2->sref) >= 0) {
5625 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5626 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5632 /* end modifications */
5634 sRef_setNullError (ret->sref);
5637 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5638 ** since is points to storage that should not be deallocated
5639 ** through this pointer.
5642 if (sRef_isOnly (ret->sref)
5643 || sRef_isFresh (ret->sref)) {
5644 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5648 ret->sref = e2->sref;
5652 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5661 case TAMPERSAND: /* bitwise & */
5663 case TCIRC: /* ^ (XOR) */
5668 bool reported = FALSE;
5674 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5675 || opid == RIGHT_OP || opid == RIGHT_ASSIGN)
5678 ** evans 2002-01-01: fixed this to follow ISO 6.5.7.
5681 if (!ctype_isUnsigned (tr2)
5682 && !exprNode_isNonNegative (e2))
5684 reported = optgenerror
5686 message ("Right operand of %s may be negative (%t): %s",
5687 lltok_unparse (op), te2,
5688 exprNode_unparse (ret)),
5692 if (!ctype_isUnsigned (tr1)
5693 && !exprNode_isNonNegative (e1))
5695 reported = optgenerror
5696 (FLG_SHIFTIMPLEMENTATION,
5697 message ("Left operand of %s may be negative (%t): %s",
5698 lltok_unparse (op), te1,
5699 exprNode_unparse (ret)),
5704 ** Should check size of right operand also...
5710 if (!ctype_isUnsigned (tr1))
5712 if (exprNode_isNonNegative (e1)) {
5715 reported = optgenerror
5717 message ("Left operand of %s is not unsigned value (%t): %s",
5718 lltok_unparse (op), te1,
5719 exprNode_unparse (ret)),
5729 if (!ctype_isUnsigned (tr2))
5731 if (!exprNode_isNonNegative (e2)) {
5732 reported = optgenerror
5734 message ("Right operand of %s is not unsigned value (%t): %s",
5735 lltok_unparse (op), te2,
5736 exprNode_unparse (ret)),
5745 if (!checkIntegral (e1, e2, ret, op)) {
5746 te1 = ctype_unknown;
5750 DPRINTF (("Set: %s", ctype_unparse (te1)));
5753 ** tret is the widest type of te1 and te2
5756 tret = ctype_widest (te1, te2);
5761 if (checkIntegral (e1, e2, ret, op)) {
5764 tret = ctype_unknown;
5769 case TLT: /* comparisons */
5770 case TGT: /* numeric, numeric -> bool */
5772 DPRINTF (("Here we go: %s / %s",
5773 ctype_unparse (tr1), ctype_unparse (tr2)));
5775 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5776 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5779 bool fepsilon = FALSE;
5781 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5786 if (opid == TLT || opid == TGT)
5788 uentry ue1 = exprNode_getUentry (e1);
5789 uentry ue2 = exprNode_getUentry (e2);
5792 ** FLT_EPSILON, etc. really is a variable, not
5796 if (uentry_isVariable (ue1))
5798 cstring uname = uentry_rawName (ue1);
5800 if (cstring_equalLit (uname, "FLT_EPSILON")
5801 || cstring_equalLit (uname, "DBL_EPSILON")
5802 || cstring_equalLit (uname, "LDBL_EPSILON"))
5808 if (uentry_isVariable (ue2))
5810 cstring uname = uentry_rawName (ue2);
5812 if (cstring_equalLit (uname, "FLT_EPSILON")
5813 || cstring_equalLit (uname, "DBL_EPSILON")
5814 || cstring_equalLit (uname, "LDBL_EPSILON"))
5823 ; /* Don't complain. */
5829 message ("Dangerous comparison involving %s types: %s",
5830 ctype_unparse (rtype),
5831 exprNode_unparse (ret)),
5840 ** Types should match.
5843 DPRINTF (("Match types: %s / %s", exprNode_unparse (e1),
5844 exprNode_unparse (e2)));
5846 if (!exprNode_matchTypes (e1, e2))
5848 hasError = gentypeerror
5850 message ("Operands of %s have incompatible types (%t, %t): %s",
5851 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5857 || (ctype_isForceRealNumeric (&tr1)
5858 && ctype_isForceRealNumeric (&tr2)) ||
5859 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5865 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5866 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5870 message ("Comparison of pointer and numeric (%t, %t): %s",
5871 te1, te2, exprNode_unparse (ret)),
5876 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5881 /* certain comparisons on unsigned's and zero look suspicious */
5883 if (opid == TLT || opid == LE_OP || opid == GE_OP)
5885 if ((ctype_isUnsigned (tr1) && exprNode_isZero (e2))
5886 || (ctype_isUnsigned (tr2) && exprNode_isZero (e1)))
5889 (FLG_UNSIGNEDCOMPARE,
5890 message ("Comparison of unsigned value involving zero: %s",
5891 exprNode_unparse (ret)),
5896 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5898 if ((opid == EQ_OP || opid == NE_OP) &&
5899 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5902 ** is one a variable?
5905 if (uentry_isVariable (exprNode_getUentry (e1))
5906 || uentry_isVariable (exprNode_getUentry (e2)))
5909 ** comparisons with FALSE are okay
5912 if (exprNode_isFalseConstant (e1)
5913 || exprNode_isFalseConstant (e2))
5922 ("Use of %q with %s variables (risks inconsistency because "
5923 "of multiple true values): %s",
5924 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5925 context_printBoolName (), exprNode_unparse (ret)),
5932 case AND_OP: /* bool, bool -> bool */
5934 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5940 if (context_maybeSet (FLG_BOOLOPS))
5942 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5944 if (ctype_sameName (te1, te2))
5948 message ("Operands of %s are non-boolean (%t): %s",
5949 lltok_unparse (op), te1,
5950 exprNode_unparse (ret)),
5958 ("Operands of %s are non-booleans (%t, %t): %s",
5959 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5963 else if (!ctype_isRealBool (te1))
5967 message ("Left operand of %s is non-boolean (%t): %s",
5968 lltok_unparse (op), te1, exprNode_unparse (ret)),
5971 else if (!ctype_isRealBool (te2))
5975 message ("Right operand of %s is non-boolean (%t): %s",
5976 lltok_unparse (op), te2, exprNode_unparse (ret)),
5989 (cstring_makeLiteral
5990 ("There has been a problem in the parser. This is believed to result "
5991 "from a problem with bison v. 1.25. Please try rebuidling Splint "
5992 "using the pre-compiled grammar files by commenting out the "
5993 "BISON= line in the top-level Makefile."));
5998 DPRINTF (("Return type %s: %s", exprNode_unparse (ret), ctype_unparse (tret)));
6000 exprNode_checkUse (ret, e1->sref, e1->loc);
6001 exprNode_mergeUSs (ret, e2);
6002 exprNode_checkUse (ret, e2->sref, e2->loc);
6008 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
6009 /*@only@*/ lltok op)
6013 checkMacroParen (e1);
6014 checkMacroParen (e2);
6016 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
6018 checkExpressionDefined (e1, e2, op);
6021 ret = exprNode_makeOp (e1, e2, op);
6026 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
6029 ** This is somewhat bogus!
6031 ** Assigning to a nested observer in a non-observer datatype
6032 ** should not produce an error.
6035 sRef ref = exprNode_getSref (e1);
6037 DPRINTF (("Check assign mod: %s",
6038 sRef_unparseFull (ref)));
6040 if (sRef_isObserver (ref)
6041 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
6042 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
6044 sRef base = sRef_getBase (ref);
6046 if (sRef_isValid (base) && sRef_isObserver (base))
6048 exprNode_checkModify (e1, ret);
6052 exprNode_checkModifyVal (e1, ret);
6057 exprNode_checkModify (e1, ret);
6062 exprNode_assign (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2, /*@only@*/ lltok op)
6064 bool isalloc = FALSE;
6065 bool isjustalloc = FALSE;
6066 bool noalias = FALSE;
6069 DPRINTF (("%s [%s] <- %s [%s]",
6070 exprNode_unparse (e1),
6071 ctype_unparse (e1->typ),
6072 exprNode_unparse (e2),
6073 ctype_unparse (e2->typ)));
6075 if (lltok_getTok (op) != TASSIGN)
6077 ret = exprNode_makeOp (e1, e2, op);
6079 DPRINTF (("Here goes: %s %s",
6080 ctype_unparse (e1->typ),
6081 ctype_unparse (e2->typ)));
6083 if (exprNode_isDefined (e1)
6084 && exprNode_isDefined (e2))
6086 if (ctype_isNumeric (e2->typ)
6087 || ctype_isNumeric (e1->typ))
6089 /* Its a pointer arithmetic expression like ptr += i */
6096 ret = exprNode_createPartialCopy (e1);
6097 ret->kind = XPR_ASSIGN;
6098 ret->edata = exprData_makeOp (e1, e2, op);
6100 if (!exprNode_isError (e2))
6102 ret->sets = sRefSet_union (ret->sets, e2->sets);
6103 ret->msets = sRefSet_union (ret->msets, e2->msets);
6104 ret->uses = sRefSet_union (ret->uses, e2->uses);
6108 checkExpressionDefined (e1, e2, op);
6110 if (exprNode_isError (e1))
6112 if (!exprNode_isError (e2))
6114 ret->loc = fileloc_update (ret->loc, e2->loc);
6118 ret->loc = fileloc_update (ret->loc, g_currentloc);
6122 if (!exprNode_isError (e2))
6124 checkMacroParen (e2);
6127 if (exprNode_isDefined (e1))
6129 if (sRef_isMacroParamRef (e1->sref))
6131 if (context_inIterDef ())
6133 uentry ue = sRef_getUentry (e1->sref);
6135 if (uentry_isYield (ue))
6141 if (fileloc_isDefined (e1->loc))
6145 message ("Assignment to non-yield iter parameter: %q",
6146 sRef_unparse (e1->sref)),
6153 message ("Assignment to non-yield iter parameter: %q",
6154 sRef_unparse (e1->sref)),
6161 if (fileloc_isDefined (e1->loc))
6165 message ("Assignment to macro parameter: %q",
6166 sRef_unparse (e1->sref)),
6173 message ("Assignment to macro parameter: %q",
6174 sRef_unparse (e1->sref)),
6178 exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
6183 exprNode_checkAssignMod (e1, ret);
6186 if (exprNode_isDefined (e2))
6188 if (lltok_getTok (op) == TASSIGN)
6190 ctype te1 = exprNode_getType (e1);
6191 ctype te2 = exprNode_getType (e2);
6193 if (ctype_isVoid (te2))
6197 message ("Assignment of void value to %t: %s %s %s",
6198 te1, exprNode_unparse (e1),
6200 exprNode_unparse (e2)),
6203 else if (!ctype_forceMatch (te1, te2))
6205 if (exprNode_matchLiteral (te1, e2))
6207 DPRINTF (("Literals match: %s / %s",
6208 ctype_unparse (te1), exprNode_unparse (e2)));
6209 if (ctype_isNumAbstract (te1)) {
6210 if (!context_flagOn (FLG_NUMABSTRACTLIT, e1->loc)) {
6211 (void) llgenhinterror
6214 ("Assignment of %t literal to numabstract type %t: %s %s %s",
6216 exprNode_unparse (e1),
6218 exprNode_unparse (e2)),
6220 ("Use +numabstractlit to allow numeric literals to be used as numabstract values"),
6229 message ("Assignment of %t to %t: %s %s %s",
6230 te2, te1, exprNode_unparse (e1),
6232 exprNode_unparse (e2)),
6238 /* Type checks okay */
6242 exprNode_mergeUSs (ret, e2);
6243 exprNode_checkUse (ret, e2->sref, e2->loc);
6245 DPRINTF (("Do assign! %s %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6252 doAssign (e1, e2, FALSE);
6255 ret->sref = e1->sref;
6259 if (exprNode_isDefined (e2))
6261 exprNode_mergeUSs (ret, e2);
6262 exprNode_checkUse (ret, e2->sref, e2->loc);
6266 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
6268 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
6271 isjustalloc = sRef_isJustAllocated (e1->sref);
6272 isalloc = sRef_isAllocated (e1->sref);
6274 if (sRef_isField (e1->sref))
6276 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
6278 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
6280 exprNode_checkUse (ret, root, e1->loc);
6286 ** be careful! this defines e1->sref.
6289 /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
6291 DPRINTF (("Setting: %s -> %s", exprNode_unparse (ret), sRef_unparse (e1->sref)));
6292 exprNode_checkSet (ret, e1->sref);
6296 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
6297 ? e2->loc : e1->loc);
6303 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
6312 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
6313 /*@keep@*/ exprNode elseclause)
6317 if (!exprNode_isError (pred))
6319 ret = exprNode_createPartialCopy (pred);
6320 checkMacroParen (pred);
6321 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
6323 if (!exprNode_isError (ifclause))
6325 checkMacroParen (ifclause); /* update macro counts! */
6327 if (!exprNode_isError (elseclause))
6329 checkMacroParen (elseclause);
6331 if (!exprNode_matchTypes (ifclause, elseclause))
6334 (exprNode_getType (ifclause),
6336 exprNode_getType (elseclause),
6338 message ("Conditional clauses are not of same type: "
6340 exprNode_unparse (ifclause),
6341 exprNode_getType (ifclause),
6342 exprNode_unparse (elseclause),
6343 exprNode_getType (elseclause)),
6346 ret->sref = sRef_undefined;
6347 ret->typ = ctype_unknown;
6352 /* for now...should merge the states */
6353 ret->sref = ifclause->sref;
6354 ret->typ = ifclause->typ;
6356 if (exprNode_isNullValue (ifclause))
6358 ret->typ = elseclause->typ;
6362 exprNode_checkUse (ret, pred->sref, pred->loc);
6363 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6364 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6366 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6371 ret->typ = ifclause->typ;
6373 exprNode_checkUse (pred, pred->sref, pred->loc);
6374 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6376 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6381 if (!exprNode_isError (elseclause))
6383 ret->typ = elseclause->typ;
6385 exprNode_checkUse (pred, pred->sref, pred->loc);
6386 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6388 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6392 else /* pred is error */
6394 if (!exprNode_isError (ifclause))
6396 ret = exprNode_createSemiCopy (ifclause);
6398 checkMacroParen (ifclause); /* update macro counts! */
6400 if (!exprNode_isError (elseclause))
6402 checkMacroParen (elseclause);
6404 ret->typ = ifclause->typ;
6406 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6409 (exprNode_getType (ifclause),
6411 exprNode_getType (elseclause),
6413 message ("Conditional clauses are not of same type: "
6415 exprNode_unparse (ifclause),
6416 exprNode_getType (ifclause),
6417 exprNode_unparse (elseclause),
6418 exprNode_getType (elseclause)),
6421 ret->typ = ctype_unknown;
6425 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6426 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6428 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6431 else if (!exprNode_isError (elseclause)) /* pred, if errors */
6433 ret = exprNode_createSemiCopy (ifclause);
6435 ret->typ = elseclause->typ;
6436 checkMacroParen (elseclause);
6438 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6439 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6441 else /* all errors! */
6443 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6447 ret->kind = XPR_COND;
6448 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
6450 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6452 exprNode_combineControl (ret, ifclause, elseclause);
6459 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6461 ctype totype = qtype_getType (qt);
6463 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6467 ** check use of va_arg : <valist>, type -> type
6470 if (exprNode_isError (arg))
6475 targ = exprNode_getType (arg);
6478 ** arg should have be a pointer
6481 if (!ctype_isUA (targ) ||
6482 (!typeId_equal (ctype_typeId (targ),
6483 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6487 message ("First argument to va_arg is not a va_list (type %t): %s",
6488 targ, exprNode_unparse (arg)),
6492 exprNode_checkSet (ret, arg->sref);
6496 ** return type is totype
6500 ret->kind = XPR_VAARG;
6501 ret->edata = exprData_makeCast (tok, arg, qt);
6506 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6508 exprNode ret = exprNode_createPlain (ctype_undefined);
6509 ret->kind = XPR_LABEL;
6510 ret->edata = exprData_makeLiteral (label);
6511 ret->isJumpPoint = TRUE;
6513 return (ret); /* for now, ignore label */
6516 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6518 if (exprNode_isDefined (stmt))
6520 stmt->isJumpPoint = TRUE;
6522 /* This prevent stray no return path errors, etc. */
6523 stmt->exitCode = XK_MUSTEXIT;
6529 bool exprNode_isDefaultMarker (exprNode e)
6531 if (exprNode_isDefined (e))
6533 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6539 bool exprNode_isCaseMarker (exprNode e)
6541 if (exprNode_isDefined (e))
6543 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6549 bool exprNode_isLabelMarker (exprNode e)
6551 if (exprNode_isDefined (e))
6553 return (e->kind == XPR_LABEL);
6559 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6561 exprNode ret = exprNode_createPartialCopy (test);
6563 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6565 if (exprNode_isError (test)) {
6569 exprNode_checkUse (ret, test->sref, test->loc);
6571 usymtab_setExitCode (ret->exitCode);
6575 usymtab_setMustBreak ();
6578 ret->edata = exprData_makeSingle (test);
6579 ret->isJumpPoint = TRUE;
6585 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6587 exprNode ret = exprNode_createPartialCopy (test);
6589 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6590 ret->edata = exprData_makePair (test, stmt);
6591 ret->isJumpPoint = TRUE;
6593 if (exprNode_isError (test))
6598 exprNode_checkUse (ret, test->sref, test->loc);
6600 if (exprNode_isError (stmt))
6605 exprNode_mergeUSs (ret, stmt);
6607 ret->exitCode = stmt->exitCode;
6608 ret->mustBreak = stmt->mustBreak;
6609 ret->canBreak = stmt->canBreak;
6611 usymtab_setExitCode (ret->exitCode);
6615 usymtab_setMustBreak ();
6622 /*@notnull@*/ /*@only@*/ exprNode
6623 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6625 exprNode ret = exprNode_createTok (def);
6627 ret->isJumpPoint = TRUE;
6628 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6633 exprNode_mayEscape (exprNode e)
6635 if (exprNode_isDefined (e))
6637 return exitkind_couldEscape (e->exitCode);
6643 exprNode_mustBreak (exprNode e)
6645 if (exprNode_isDefined (e))
6647 return e->mustBreak;
6654 exprNode_mustEscape (exprNode e)
6656 if (exprNode_isDefined (e))
6658 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6665 exprNode_errorEscape (exprNode e)
6667 if (exprNode_isDefined (e))
6669 return exitkind_isError (e->exitCode);
6675 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6677 exprNode ret = exprNode_createPartialCopy (e1);
6679 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6681 ret->edata = exprData_makePair (e1, e2);
6682 ret->kind = XPR_STMTLIST;
6684 if (exprNode_isDefined (e1))
6686 ret->isJumpPoint = e1->isJumpPoint;
6687 ret->canBreak = e1->canBreak;
6691 if (exprNode_isDefined (e2))
6693 ret->loc = fileloc_update (ret->loc, e2->loc);
6697 if (exprNode_isDefined (e2))
6699 ret->exitCode = e2->exitCode;
6700 ret->mustBreak = e2->mustBreak;
6701 if (e2->canBreak) ret->canBreak = TRUE;
6705 ** if e1 must return, then e2 is unreachable!
6708 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6710 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6711 && !(e2->isJumpPoint))
6713 if (context_getFlag (FLG_UNREACHABLE))
6717 if (e2->kind == XPR_STMT)
6719 nr = exprData_getUopNode (e2->edata);
6722 if ((nr->kind == XPR_TOK
6723 && lltok_isSemi (exprData_getTok (nr->edata))))
6725 /* okay to have unreachable ";" */
6726 ret->exitCode = XK_MUSTEXIT;
6727 ret->canBreak = TRUE;
6731 if (optgenerror (FLG_UNREACHABLE,
6732 message ("Unreachable code: %s",
6733 exprNode_unparseFirst (nr)),
6736 ret->isJumpPoint = TRUE;
6737 ret->mustBreak = FALSE;
6738 ret->exitCode = XK_ERROR;
6739 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6743 ret->exitCode = XK_MUSTEXIT;
6744 ret->canBreak = TRUE;
6752 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6755 ** We want a warning anytime we have:
6757 ** yyy; <<<- no break or return
6761 exprNode lastStmt = exprNode_lastStatement (e1);
6763 if (exprNode_isDefined (lastStmt)
6764 && !exprNode_mustEscape (lastStmt)
6765 && !exprNode_mustBreak (lastStmt)
6766 && !exprNode_isCaseMarker (lastStmt)
6767 && !exprNode_isDefaultMarker (lastStmt)
6768 && !exprNode_isLabelMarker (lastStmt))
6770 voptgenerror (FLG_CASEBREAK,
6772 ("Fall through case (no preceding break)"),
6779 exprNode_mergeUSs (ret, e2);
6781 usymtab_setExitCode (ret->exitCode);
6785 usymtab_setMustBreak ();
6788 DPRINTF (("==> %s", exprNode_unparse (ret)));
6792 exprNode exprNode_createTok (/*@only@*/ lltok t)
6794 exprNode ret = exprNode_create (ctype_unknown);
6795 ret->kind = XPR_TOK;
6796 ret->edata = exprData_makeTok (t);
6800 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6802 if (!exprNode_isError (e))
6804 exprChecks_checkStatementEffect(e);
6807 return (exprNode_statementError (e, t));
6810 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6812 exprNode ret = exprNode_createPartialCopy (e);
6814 if (!exprNode_isError (e))
6816 if (e->kind != XPR_ASSIGN)
6818 exprNode_checkUse (ret, e->sref, e->loc);
6821 ret->exitCode = e->exitCode;
6822 ret->canBreak = e->canBreak;
6823 ret->mustBreak = e->mustBreak;
6826 ret->edata = exprData_makeUop (e, t);
6827 ret->kind = XPR_STMT;
6832 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6834 if (!exprNode_isError (e))
6836 if (e->kind != XPR_ASSIGN)
6838 exprNode_checkUse (e, e->sref, e->loc);
6845 void exprNode_produceGuards (exprNode pred)
6847 if (!exprNode_isError (pred))
6849 if (ctype_isRealPointer (pred->typ))
6851 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6854 exprNode_checkUse (pred, pred->sref, pred->loc);
6855 exprNode_resetSref (pred);
6859 exprNode exprNode_compoundStatementExpression (/*@only@*/ lltok tlparen, /*@only@*/ exprNode e)
6863 DPRINTF (("Compound: %s", exprNode_unparse (e)));
6865 if (!context_flagOn (FLG_GNUEXTENSIONS, exprNode_loc (e)))
6867 (void) llgenhinterror
6869 message ("Compound statement expressions is not supported by ISO C99"),
6870 message ("Use +gnuextensions to allow compound statement expressions (and other GNU language extensions) "
6871 "without this warning"),
6876 ** The type of a compoundStatementExpression is the type of the last statement
6879 llassert (exprNode_isBlock (e));
6880 laststmt = exprNode_lastStatement (e);
6882 DPRINTF (("Last statement: %s / %s", exprNode_unparse (laststmt), ctype_unparse (exprNode_getType (laststmt))));
6883 DPRINTF (("e: %s", exprNode_unparse (e)));
6884 e->typ = exprNode_getType (laststmt);
6885 return exprNode_addParens (tlparen, e);
6889 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6891 exprNode ret = exprNode_createPartialCopy (e);
6893 if (!exprNode_isError (e))
6895 ret->exitCode = e->exitCode;
6896 ret->canBreak = e->canBreak;
6897 ret->mustBreak = e->mustBreak;
6900 DPRINTF (("Block e: %s", exprNode_unparse (e)));
6901 ret->edata = exprData_makeSingle (e);
6902 ret->kind = XPR_BLOCK;
6903 DPRINTF (("Block: %s", exprNode_unparse (ret)));
6907 bool exprNode_isBlock (exprNode e)
6909 return (exprNode_isDefined (e)
6910 && ((e)->kind == XPR_BLOCK));
6913 bool exprNode_isStatement (exprNode e)
6915 return (exprNode_isDefined (e)
6916 && ((e)->kind == XPR_STMT));
6919 bool exprNode_isAssign (exprNode e)
6921 if (exprNode_isDefined (e))
6923 return (e->kind == XPR_ASSIGN);
6929 bool exprNode_isEmptyStatement (exprNode e)
6931 return (exprNode_isDefined (e)
6932 && (e->kind == XPR_TOK)
6933 && (lltok_isSemi (exprData_getTok (e->edata))));
6936 bool exprNode_isMultiStatement (exprNode e)
6938 return (exprNode_isDefined (e)
6939 && ((e->kind == XPR_FOR)
6940 || (e->kind == XPR_FORPRED)
6941 || (e->kind == XPR_IF)
6942 || (e->kind == XPR_IFELSE)
6943 || (e->kind == XPR_WHILE)
6944 || (e->kind == XPR_WHILEPRED)
6945 || (e->kind == XPR_DOWHILE)
6946 || (e->kind == XPR_BLOCK)
6947 || (e->kind == XPR_STMT)
6948 || (e->kind == XPR_STMTLIST)
6949 || (e->kind == XPR_SWITCH)));
6952 void exprNode_checkIfPred (exprNode pred)
6954 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6957 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6960 bool emptyErr = FALSE;
6962 if (context_maybeSet (FLG_IFEMPTY))
6964 if (exprNode_isEmptyStatement (tclause))
6966 emptyErr = optgenerror (FLG_IFEMPTY,
6968 ("Body of if statement is empty"),
6969 exprNode_loc (tclause));
6973 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6975 if (exprNode_isDefined (tclause)
6976 && !exprNode_isBlock (tclause))
6978 voptgenerror (FLG_IFBLOCK,
6980 ("Body of if statement is not a block: %s",
6981 exprNode_unparse (tclause)),
6982 exprNode_loc (tclause));
6986 if (exprNode_isError (pred))
6988 if (exprNode_isError (tclause))
6990 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6994 ret = exprNode_createPartialCopy (tclause);
6999 if (exprNode_mustEscape (pred))
7003 message ("Predicate always exits: %s", exprNode_unparse (pred)),
7004 exprNode_loc (pred));
7007 exprNode_checkUse (pred, pred->sref, pred->loc);
7009 if (!exprNode_isError (tclause))
7011 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
7014 ret = exprNode_createPartialCopy (pred);
7018 ret->edata = exprData_makePair (pred, tclause);
7020 ret->exitCode = XK_UNKNOWN;
7022 if (exprNode_isDefined (tclause))
7024 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
7025 ret->canBreak = tclause->canBreak;
7026 ret->sets = sRefSet_union (ret->sets, tclause->sets);
7027 ret->msets = sRefSet_union (ret->msets, tclause->msets);
7028 ret->uses = sRefSet_union (ret->uses, tclause->uses);
7031 ret->mustBreak = FALSE;
7036 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
7037 /*@only@*/ exprNode tclause,
7038 /*@only@*/ exprNode eclause)
7041 bool tEmptyErr = FALSE;
7042 bool eEmptyErr = FALSE;
7044 if (context_maybeSet (FLG_IFEMPTY))
7046 if (exprNode_isEmptyStatement (tclause))
7048 tEmptyErr = optgenerror
7051 ("Body of if clause of if statement is empty"),
7052 exprNode_loc (tclause));
7055 if (exprNode_isEmptyStatement (eclause))
7057 eEmptyErr = optgenerror
7060 ("Body of else clause of if statement is empty"),
7061 exprNode_loc (eclause));
7065 if (context_maybeSet (FLG_IFBLOCK))
7068 && exprNode_isDefined (tclause)
7069 && !exprNode_isBlock (tclause))
7071 voptgenerror (FLG_IFBLOCK,
7073 ("Body of if clause of if statement is not a block: %s",
7074 exprNode_unparse (tclause)),
7075 exprNode_loc (tclause));
7079 && exprNode_isDefined (eclause)
7080 && !exprNode_isBlock (eclause)
7081 && !(eclause->kind == XPR_IF)
7082 && !(eclause->kind == XPR_IFELSE))
7087 ("Body of else clause of if statement is not a block: %s",
7088 exprNode_unparse (eclause)),
7089 exprNode_loc (eclause));
7093 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
7095 if (exprNode_isDefined (eclause)
7096 && (eclause->kind == XPR_IF))
7098 voptgenerror (FLG_ELSEIFCOMPLETE,
7099 message ("Incomplete else if logic (no final else): %s",
7100 exprNode_unparse (eclause)),
7101 exprNode_loc (eclause));
7105 if (exprNode_isError (pred))
7107 if (exprNode_isError (tclause))
7109 if (exprNode_isError (eclause))
7111 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7115 ret = exprNode_createPartialCopy (eclause);
7120 ret = exprNode_createPartialCopy (tclause);
7123 else /* pred is okay */
7125 ret = exprNode_createPartialCopy (pred);
7127 if (exprNode_mustEscape (pred))
7131 message ("Predicate always exits: %s", exprNode_unparse (pred)),
7132 exprNode_loc (pred));
7135 exprNode_checkUse (ret, pred->sref, pred->loc);
7136 exprNode_mergeCondUSs (ret, tclause, eclause);
7139 ret->kind = XPR_IFELSE;
7140 ret->edata = exprData_makeCond (pred, tclause, eclause);
7142 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
7144 exprNode_combineControl (ret, tclause, eclause);
7145 ret->loc = fileloc_update (ret->loc, eclause->loc);
7152 ** *allpaths <- TRUE iff all executions paths must go through the switch
7156 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
7158 exprNodeSList el = exprNode_flatten (e);
7159 bool mustReturn = TRUE; /* find a branch that doesn't */
7160 bool thisReturn = FALSE;
7161 bool hasDefault = FALSE;
7162 bool hasAllMembers = FALSE;
7163 bool inSwitch = FALSE;
7164 bool isEnumSwitch = FALSE;
7165 bool canBreak = FALSE;
7166 bool fallThrough = FALSE;
7167 ctype ct = ctype_unknown;
7168 enumNameSList usedEnums;
7171 if (exprNode_isDefined (test))
7176 ttype = ctype_realType (ct);
7178 if (ctype_isEnum (ttype))
7180 isEnumSwitch = TRUE;
7181 enums = ctype_elist (ttype);
7182 usedEnums = enumNameSList_new ();
7186 exprNodeSList_elements (el, current)
7189 DPRINTF ((message("checkSwitchExpr current = %s ", exprNode_unparse(current) ) ));
7191 if (exprNode_isDefined (current))
7193 switch (current->kind)
7200 (FLG_DUPLICATECASES,
7201 message ("Duplicate default cases in switch"),
7202 exprNode_loc (current));
7207 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
7215 exprNode st = exprData_getSingle (current->edata);
7216 uentry ue = exprNode_getUentry (st);
7218 if (uentry_isValid (ue))
7220 cstring cname = uentry_rawName (ue);
7222 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
7224 if (enumNameSList_member
7225 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
7228 (FLG_DUPLICATECASES,
7229 message ("Duplicate case in switch: %s",
7235 enumNameSList_addh (usedEnums, cname);
7242 message ("Case in switch not %s member: %s",
7243 ctype_unparse (ct), cname),
7250 if (inSwitch && !fallThrough)
7252 if (!thisReturn || canBreak)
7262 /*@switchbreak@*/ break;
7264 thisReturn = thisReturn || exprNode_mustEscape (current);
7265 canBreak = canBreak || current->canBreak;
7266 if (canBreak) fallThrough = FALSE;
7269 } end_exprNodeSList_elements;
7271 if (inSwitch) /* check the last one! */
7273 if (!thisReturn || canBreak)
7282 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
7283 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
7285 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
7287 voptgenerror (FLG_MISSCASE,
7288 message ("Missing case%s in switch: %q",
7289 cstring_makeLiteralTemp
7290 ((enumNameSList_size (unused) > 1) ? "s" : ""),
7291 enumNameSList_unparse (unused)),
7294 enumNameSList_free (unused);
7295 *allpaths = FALSE; /* evans 2002-01-01 */
7299 hasAllMembers = TRUE;
7303 enumNameSList_free (usedEnums);
7307 *allpaths = hasDefault;
7310 exprNodeSList_free (el);
7311 return ((hasDefault || hasAllMembers) && mustReturn);
7314 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
7316 exprNode ret = exprNode_createPartialCopy (e);
7319 DPRINTF (("Switch: %s", exprNode_unparse (s)));
7321 ret->kind = XPR_SWITCH;
7322 ret->edata = exprData_makePair (e, s);
7324 if (!exprNode_isError (s))
7326 exprNode fs = exprNode_firstStatement (s);
7327 ret->loc = fileloc_update (ret->loc, s->loc);
7329 if (exprNode_isUndefined (fs)
7330 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
7331 || exprNode_isDefaultMarker (fs)) {
7334 voptgenerror (FLG_FIRSTCASE,
7336 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
7341 if (!exprNode_isError (e))
7343 if (checkSwitchExpr (e, s, &allpaths))
7345 ret->exitCode = XK_MUSTRETURN;
7349 ret->exitCode = e->exitCode;
7352 ret->canBreak = e->canBreak;
7353 ret->mustBreak = e->mustBreak;
7357 ** exprNode.c:3883,32: Variable allpaths used before definition
7364 DPRINTF (("Context exit switch!"));
7365 context_exitSwitch (ret, allpaths);
7366 DPRINTF (("Context exit switch done!"));
7371 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
7372 /*@notnull@*/ exprNode body)
7374 sRefSet tuses = test->uses;
7376 if (!sRefSet_isEmpty (test->uses))
7378 sRefSet sets = sRefSet_newCopy (body->sets);
7379 bool hasError = TRUE;
7380 bool innerState = FALSE;
7381 sRefSet tuncon = sRefSet_undefined;
7383 sets = sRefSet_union (sets, test->sets);
7384 sets = sRefSet_union (sets, body->msets);
7385 sets = sRefSet_union (sets, test->msets);
7387 sRefSet_allElements (tuses, el)
7389 if (sRef_isUnconstrained (el))
7391 tuncon = sRefSet_insert (tuncon, el);
7395 if (sRefSet_member (sets, el))
7402 if (sRef_isInternalState (el)
7403 || sRef_isFileStatic (sRef_getRootBase (el)))
7407 } end_sRefSet_allElements ;
7411 sRefSet suncon = sRefSet_undefined;
7412 bool sinner = FALSE;
7414 sRefSet_allElements (sets, el)
7416 if (sRef_isUnconstrained (el))
7418 suncon = sRefSet_insert (suncon, el);
7420 else if (sRef_isInternalState (el))
7428 } end_sRefSet_allElements ;
7430 if (sinner && innerState)
7434 else if (sRefSet_isEmpty (tuncon)
7435 && sRefSet_isEmpty (suncon))
7440 ("Suspected infinite loop. No value used in loop test (%q) "
7441 "is modified by test or loop body.",
7442 sRefSet_unparsePlain (tuses)),
7447 if (sRefSet_isEmpty (tuncon))
7451 message ("Suspected infinite loop. No condition values "
7452 "modified. Modification possible through "
7453 "unconstrained calls: %q",
7454 sRefSet_unparsePlain (suncon)),
7461 message ("Suspected infinite loop. No condition values "
7462 "modified. Possible undetected dependency through "
7463 "unconstrained calls in loop test: %q",
7464 sRefSet_unparsePlain (tuncon)),
7470 sRefSet_free (sets);
7474 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7477 bool emptyErr = FALSE;
7479 if (context_maybeSet (FLG_WHILEEMPTY))
7481 if (exprNode_isEmptyStatement (b))
7483 emptyErr = optgenerror
7486 ("Body of while statement is empty"),
7491 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7493 if (exprNode_isDefined (b)
7494 && !exprNode_isBlock (b))
7496 if (context_inIterDef ()
7497 && (b->kind == XPR_STMTLIST
7498 || b->kind == XPR_TOK))
7504 voptgenerror (FLG_WHILEBLOCK,
7506 ("Body of while statement is not a block: %s",
7507 exprNode_unparse (b)),
7513 if (exprNode_isError (t))
7515 if (exprNode_isError (b))
7517 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7521 ret = exprNode_createPartialCopy (b);
7528 ret = exprNode_createPartialCopy (t);
7530 llassert (t->kind == XPR_WHILEPRED);
7532 test = exprData_getSingle (t->edata);
7534 if (!exprNode_isError (b) && exprNode_isDefined (test))
7536 if (context_maybeSet (FLG_INFLOOPS)
7537 || context_maybeSet (FLG_INFLOOPSUNCON))
7540 ** check that some variable in the predicate is set by the body
7541 ** if the predicate uses any variables
7544 checkInfiniteLoop (test, b);
7547 exprNode_mergeUSs (ret, b);
7549 if (exprNode_isDefined (b))
7551 ret->exitCode = exitkind_makeConditional (b->exitCode);
7556 ret->edata = exprData_makePair (t, b);
7557 ret->kind = XPR_WHILE;
7559 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7563 message ("Predicate always exits: %s", exprNode_unparse (t)),
7567 ret->exitCode = XK_NEVERESCAPE;
7570 ** If loop is infinite, and there is no break inside,
7571 ** exit code is never reach.
7574 if (exprNode_knownIntValue (t))
7576 if (!exprNode_isZero (t))
7578 if (exprNode_isDefined (b))
7582 /* Really, it means never reached. */
7583 ret->exitCode = XK_MUSTEXIT;
7593 ret->canBreak = FALSE;
7594 ret->mustBreak = FALSE;
7600 ** do { b } while (t);
7602 ** note: body passed as first argument
7605 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7609 DPRINTF (("Do while: %s / %s",
7610 exprNode_unparse (b), exprNode_unparse (t)));
7612 if (exprNode_isError (t))
7614 if (exprNode_isError (b))
7616 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7620 ret = exprNode_createPartialCopy (b);
7622 ret->exitCode = exitkind_makeConditional (b->exitCode);
7623 exprNode_checkUse (ret, b->sref, b->loc);
7624 ret->exitCode = b->exitCode;
7625 ret->canBreak = b->canBreak;
7626 ret->mustBreak = FALSE;
7631 DPRINTF (("Do while: %s / %s",
7632 exitkind_unparse (t->exitCode),
7633 exitkind_unparse (b->exitCode)));
7635 ret = exprNode_createPartialCopy (t);
7636 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7638 if (!exprNode_isError (b))
7641 ** forgot the copy's --- why wasn't this detected??
7644 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7645 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7646 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
7648 /* left this out --- causes and aliasing bug (infinite loop)
7649 should be detected?? */
7651 exprNode_checkUse (ret, b->sref, b->loc);
7652 exprNode_mergeUSs (ret, t);
7653 exprNode_checkUse (ret, t->sref, t->loc);
7655 /* evans 2001-10-05: while loop can break */
7656 ret->exitCode = exitkind_makeConditional (b->exitCode);
7658 DPRINTF (("Do while: %s",
7659 exitkind_unparse (ret->exitCode)));
7661 ret->canBreak = b->canBreak;
7663 /* Always FALSE for doWhile loops - break's when test is false */
7664 ret->mustBreak = FALSE; /* b->mustBreak; */
7668 context_exitDoWhileClause (t);
7670 ret->kind = XPR_DOWHILE;
7671 ret->edata = exprData_makePair (t, b);
7675 bool exprNode_loopMustExec (exprNode forPred)
7678 ** Returns true if it is obvious that the loop always executes at least once
7680 ** For now, we only identify the most obvious cases. Should be true anytime
7681 ** we can prove init => !test.
7684 if (exprNode_isDefined (forPred))
7686 exprNode init, test, inc;
7689 llassert (forPred->kind == XPR_FORPRED);
7691 edata = forPred->edata;
7692 init = exprData_getTripleInit (edata);
7693 test = exprData_getTripleTest (edata);
7694 inc = exprData_getTripleInc (edata);
7696 if (exprNode_isAssign (init))
7698 exprNode loopVar = exprData_getOpA (init->edata);
7699 exprNode loopInit = exprData_getOpB (init->edata);
7701 if (exprNode_isDefined (test) && test->kind == XPR_OP)
7703 exprNode testVar = exprData_getOpA (test->edata);
7704 exprNode testVal = exprData_getOpB (test->edata);
7705 lltok comp = exprData_getOpTok (test->edata);
7706 int opid = lltok_getTok (comp);
7708 DPRINTF (("Same storage: %s / %s", exprNode_unparse (loopVar),
7709 exprNode_unparse (testVar)));
7711 if (exprNode_sameStorage (loopVar, testVar))
7713 multiVal valinit = exprNode_getValue (loopInit);
7714 multiVal valtest = exprNode_getValue (testVal);
7716 DPRINTF (("Values: %s / %s", multiVal_unparse (valinit),
7717 multiVal_unparse (valtest)));
7719 if (multiVal_isInt (valinit) && multiVal_isInt (valtest))
7721 long v1 = multiVal_forceInt (valinit);
7722 long v2 = multiVal_forceInt (valtest);
7724 DPRINTF (("Here: %ld %ld", v1, v2));
7726 if ((opid == EQ_OP && v1 < v2)
7727 || (opid == NE_OP && v1 != v2)
7728 || (opid == TLT && v1 <= v2)
7729 || (opid == TGT && v1 >= v2)
7730 || (opid == LE_OP && v1 < v2)
7731 || (opid == GE_OP && v1 > v2))
7733 DPRINTF (("mustexec if inc"));
7742 DPRINTF (("loop must exec: FALSE"));
7746 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7749 bool emptyErr = FALSE;
7751 if (context_maybeSet (FLG_FOREMPTY))
7753 if (exprNode_isEmptyStatement (body))
7755 emptyErr = optgenerror
7758 ("Body of for statement is empty"),
7759 exprNode_loc (body));
7763 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7765 if (exprNode_isDefined (body)
7766 && !exprNode_isBlock (body))
7768 if (context_inIterDef ()
7769 && (body->kind == XPR_STMTLIST
7770 || body->kind == XPR_TOK))
7776 voptgenerror (FLG_FORBLOCK,
7778 ("Body of for statement is not a block: %s",
7779 exprNode_unparse (body)),
7780 exprNode_loc (body));
7786 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7789 if (exprNode_isError (body))
7791 ret = exprNode_createPartialCopy (inc);
7795 ret = exprNode_createPartialCopy (body);
7797 ret->exitCode = exitkind_makeConditional (body->exitCode);
7799 exprNode_mergeUSs (inc, body);
7801 if (exprNode_isDefined (inc))
7805 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7807 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7808 exprNode_freeShallow (tmp);
7810 context_clearMessageAnnote ();
7811 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7813 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7814 exprNode_freeShallow (tmp);
7816 context_clearMessageAnnote ();
7818 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7819 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7820 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7824 ret->kind = XPR_FOR;
7825 ret->edata = exprData_makePair (inc, body);
7827 if (exprNode_isDefined (inc)) {
7828 exprNode test = exprData_getTripleTest (inc->edata);
7830 if (exprNode_isUndefined (test)) {
7831 if (exprNode_isDefined (body)) {
7832 if (!body->canBreak) {
7833 /* Really, it means never reached. */
7834 ret->exitCode = XK_MUSTEXIT;
7844 ** for (init; test; inc)
7847 ** while (test) { body; inc; }
7849 ** Now: check use of init (may set vars for test)
7850 ** check use of test
7854 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7858 if (exprNode_isError (pred)) return guardSet_undefined;
7860 llassert (pred->kind == XPR_FORPRED);
7862 test = exprData_getTripleTest (pred->edata);
7864 if (!exprNode_isError (test))
7866 return (test->guards);
7869 return guardSet_undefined;
7872 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7874 exprNode ret = exprNode_createSemiCopy (test);
7876 if (exprNode_isDefined (test))
7878 exprNode_copySets (ret, test);
7879 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7880 exprNode_checkUse (ret, test->sref, test->loc);
7882 exprNode_produceGuards (test);
7884 ret->guards = guardSet_copy (test->guards);
7887 ret->edata = exprData_makeSingle (test);
7888 ret->kind = XPR_WHILEPRED;
7892 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7893 /*@only@*/ exprNode inc)
7898 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7901 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7903 if (!exprNode_isError (inc))
7905 ret = exprNode_createPartialCopy (inc);
7909 if (!exprNode_isError (init))
7911 ret = exprNode_createPartialCopy (init);
7913 else if (!exprNode_isError (test))
7915 ret = exprNode_createPartialCopy (test);
7919 ret = exprNode_createUnknown ();
7923 exprNode_mergeUSs (ret, init);
7925 if (exprNode_isDefined (init))
7927 exprNode_checkUse (ret, init->sref, init->loc);
7930 exprNode_mergeUSs (ret, test);
7932 if (exprNode_isDefined (test))
7934 exprNode_checkUse (ret, test->sref, test->loc);
7937 ret->kind = XPR_FORPRED;
7938 ret->edata = exprData_makeFor (init, test, inc);
7942 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7944 exprNode ret = exprNode_createUnknown ();
7946 if (context_inMacro ())
7948 voptgenerror (FLG_MACROSTMT,
7949 message ("Macro %s uses goto (not functional)",
7950 context_inFunctionName ()),
7954 ret->kind = XPR_GOTO;
7955 ret->edata = exprData_makeLiteral (label);
7956 ret->mustBreak = TRUE;
7957 ret->exitCode = XK_GOTO;
7958 ret->canBreak = TRUE;
7962 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7964 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7966 ret->kind = XPR_CONTINUE;
7967 ret->edata = exprData_makeTok (l);
7968 ret->canBreak = TRUE;
7969 ret->mustBreak = TRUE;
7971 if (qcontinue == QSAFEBREAK)
7975 else if (qcontinue == QINNERCONTINUE)
7977 if (!context_inDeepLoop ())
7980 (FLG_LOOPLOOPCONTINUE,
7981 cstring_makeLiteral ("Continue statement marked with innercontinue "
7982 "is not inside a nested loop"),
7983 exprNode_loc (ret));
7986 else if (qcontinue == BADTOK)
7988 if (context_inDeepLoop ())
7991 (FLG_LOOPLOOPCONTINUE,
7992 cstring_makeLiteral ("Continue statement in nested loop"),
7993 exprNode_loc (ret));
7998 llbuglit ("exprNode_continue: bad qcontinue");
8004 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
8006 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
8007 clause breakClause = context_breakClause ();
8009 ret->kind = XPR_BREAK;
8010 ret->edata = exprData_makeTok (l);
8011 ret->canBreak = TRUE;
8012 ret->mustBreak = TRUE;
8014 if (breakClause == NOCLAUSE)
8018 cstring_makeLiteral ("Break not inside while, for or switch statement"),
8019 exprNode_loc (ret));
8023 if (bqual != BADTOK)
8030 if (breakClause == SWITCHCLAUSE)
8032 if (!context_inDeepSwitch ())
8034 voptgenerror (FLG_SYNTAX,
8036 ("Break preceded by innerbreak is not in a deep switch"),
8037 exprNode_loc (ret));
8042 if (!context_inDeepLoop ())
8044 voptgenerror (FLG_SYNTAX,
8046 ("Break preceded by innerbreak is not in a deep loop"),
8047 exprNode_loc (ret));
8052 if (breakClause == SWITCHCLAUSE)
8054 voptgenerror (FLG_SYNTAX,
8056 ("Break preceded by loopbreak is breaking a switch"),
8057 exprNode_loc (ret));
8061 if (breakClause != SWITCHCLAUSE)
8065 message ("Break preceded by switchbreak is breaking %s",
8066 cstring_makeLiteralTemp
8067 ((breakClause == WHILECLAUSE
8068 || breakClause == DOWHILECLAUSE) ? "a while loop"
8069 : (breakClause == FORCLAUSE) ? "a for loop"
8070 : (breakClause == ITERCLAUSE) ? "an iterator"
8072 exprNode_loc (ret));
8080 if (breakClause == SWITCHCLAUSE)
8082 clause nextBreakClause = context_nextBreakClause ();
8084 switch (nextBreakClause)
8086 case NOCLAUSE: break;
8092 (FLG_LOOPSWITCHBREAK,
8093 cstring_makeLiteral ("Break statement in switch inside loop"),
8094 exprNode_loc (ret));
8098 (FLG_SWITCHSWITCHBREAK,
8099 cstring_makeLiteral ("Break statement in switch inside switch"),
8100 exprNode_loc (ret));
8107 if (context_inDeepLoop ())
8111 cstring_makeLiteral ("Break statement in nested loop"),
8112 exprNode_loc (ret));
8116 if (context_inDeepLoopSwitch ())
8119 (FLG_SWITCHLOOPBREAK,
8120 cstring_makeLiteral ("Break statement in loop inside switch"),
8121 exprNode_loc (ret));
8131 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
8133 fileloc loc = lltok_getLoc (t);
8134 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
8136 context_returnFunction ();
8137 exprChecks_checkNullReturn (loc);
8139 ret->kind = XPR_NULLRETURN;
8140 ret->edata = exprData_makeTok (t);
8141 ret->exitCode = XK_MUSTRETURN;
8145 exprNode exprNode_return (/*@only@*/ exprNode e)
8149 if (exprNode_isError (e))
8151 ret = exprNode_createUnknown ();
8155 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
8157 exprNode_checkUse (ret, e->sref, e->loc);
8158 exprNode_checkReturn (e);
8161 context_returnFunction ();
8162 ret->kind = XPR_RETURN;
8163 ret->edata = exprData_makeSingle (e);
8164 ret->exitCode = XK_MUSTRETURN;
8169 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
8173 if (exprNode_isError (e1))
8175 if (exprNode_isError (e2))
8177 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
8181 ret = exprNode_createPartialCopy (e2);
8182 exprNode_checkUse (ret, e2->sref, e2->loc);
8183 ret->sref = e2->sref;
8188 ret = exprNode_createPartialCopy (e1);
8190 exprNode_checkUse (ret, e1->sref, e1->loc);
8192 if (!exprNode_isError (e2))
8194 exprNode_mergeUSs (ret, e2);
8195 exprNode_checkUse (ret, e2->sref, e2->loc);
8196 ret->sref = e2->sref;
8200 ret->kind = XPR_COMMA;
8201 ret->edata = exprData_makePair (e1, e2);
8203 if (exprNode_isDefined (e1))
8205 if (exprNode_isDefined (e2))
8209 if (exprNode_mustEscape (e1) || e1->mustBreak)
8213 message ("Second clause of comma expression is unreachable: %s",
8214 exprNode_unparse (e2)),
8218 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
8219 ret->mustBreak = e1->mustBreak || e2->mustBreak;
8220 ret->canBreak = e1->canBreak || e2->canBreak;
8224 if (exprNode_mustEscape (e1) || e1->mustBreak)
8228 message ("Second clause of comma expression is unreachable: %s",
8229 exprNode_unparse (e2)),
8233 ret->exitCode = e1->exitCode;
8234 ret->canBreak = e1->canBreak;
8239 if (exprNode_isDefined (e2))
8241 ret->exitCode = e2->exitCode;
8242 ret->mustBreak = e2->mustBreak;
8243 ret->canBreak = e2->canBreak;
8250 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
8252 ctype t1 = exprNode_getType (el);
8253 ctype t2 = exprNode_getType (val);
8254 bool hasError = FALSE;
8256 DPRINTF (("Check one init: %s / %s",
8257 exprNode_unparse (el),
8258 exprNode_unparse (val)));
8260 if (ctype_isUnknown (t1))
8262 voptgenerror (FLG_IMPTYPE,
8263 message ("Variable has unknown (implicitly int) type: %s",
8264 exprNode_unparse (el)),
8268 el->typ = ctype_int;
8271 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
8273 exprNodeList vals = exprData_getArgs (val->edata);
8275 DPRINTF (("Check one init: %s", exprNodeList_unparse (vals)));
8276 DPRINTF (("Type: %s", ctype_unparse (t1)));
8278 if (ctype_isRealAP (t1))
8283 if (ctype_isFixedArray (t1))
8285 size_t nelements = ctype_getArraySize (t1);
8287 DPRINTF (("Checked array: %s / %d",
8288 ctype_unparse (t1), nelements));
8290 if (exprNode_isStringLiteral (val))
8292 exprNode_checkStringLiteralLength (t1, val);
8296 if (exprNodeList_size (vals) != size_toInt (nelements))
8298 hasError = optgenerror
8299 (exprNodeList_size (vals) > size_toInt (nelements)
8300 ? FLG_INITSIZE : FLG_INITALLELEMENTS,
8301 message ("Initializer block for "
8302 "%s has %d element%&, but declared as %s: %q",
8303 exprNode_unparse (el),
8304 exprNodeList_size (vals),
8306 exprNodeList_unparse (vals)),
8312 exprNodeList_elements (vals, oneval)
8314 cstring istring = message ("%d", i);
8317 (exprNode_fakeCopy (el),
8318 exprNode_numLiteral (ctype_int, istring,
8319 fileloc_copy (el->loc), i));
8321 if (exprNode_isDefined (newel))
8323 if (exprNodeList_size (vals) == 1
8324 && ctype_isString (exprNode_getType (oneval))
8325 && ctype_isChar (exprNode_getType (newel)))
8327 exprNode_freeIniter (newel);
8331 if (exprNode_checkOneInit (newel, oneval))
8336 if (nerrors > 3 && exprNodeList_size (vals) > 6)
8339 (message ("Additional initialization errors "
8340 "for %s not reported",
8341 exprNode_unparse (el)),
8343 exprNode_freeIniter (newel);
8348 exprNode_freeIniter (newel);
8353 exprNode_freeIniter (newel);
8358 cstring_free (istring);
8361 } end_exprNodeList_elements;
8364 else if (ctype_isStruct (ctype_realType (t1)))
8366 uentryList fields = ctype_getFields (t1);
8369 if (uentryList_size (fields) != exprNodeList_size (vals))
8371 if (uentryList_size (fields) > exprNodeList_size (vals))
8373 hasError = optgenerror
8375 message ("Initializer block for "
8376 "%s has %d field%&, but %s has %d field%&: %q",
8377 exprNode_unparse (el),
8378 exprNodeList_size (vals),
8380 uentryList_size (fields),
8381 exprNodeList_unparse (vals)),
8386 hasError = optgenerror
8388 message ("Initializer block for "
8389 "%s has %d field%&, but %s has %d field%&: %q",
8390 exprNode_unparse (el),
8391 exprNodeList_size (vals),
8393 uentryList_size (fields),
8394 exprNodeList_unparse (vals)),
8400 exprNodeList_elements (vals, oneval)
8402 uentry thisfield = uentryList_getN (fields, i);
8404 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8406 uentry_getName (thisfield));
8408 if (exprNode_isDefined (newel))
8410 if (exprNode_checkOneInit (newel, oneval))
8415 exprNode_freeIniter (newel);
8419 } end_exprNodeList_elements;
8422 /* evans 2001-12-30: added to fix bug reported by Jim Zelenka */
8423 else if (ctype_isUnion (ctype_realType (t1)))
8425 uentryList fields = ctype_getFields (t1);
8429 ** Union initializers set the first member always.
8432 DPRINTF (("Union initializer: %s / %s",
8433 exprNode_unparse (el), ctype_unparse (ctype_realType (t1))));
8435 if (exprNodeList_size (vals) != 1)
8437 hasError = optgenerror
8439 message ("Initializer block for union "
8440 "%s has %d elements, union initializers should have one element: %q",
8441 exprNode_unparse (el),
8442 exprNodeList_size (vals),
8443 exprNodeList_unparse (vals)),
8448 exprNode oneval = exprNodeList_head (vals);
8449 uentry thisfield = uentryList_getN (fields, i);
8451 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8453 uentry_getName (thisfield));
8455 if (exprNode_isDefined (newel))
8457 if (exprNode_checkOneInit (newel, oneval))
8462 exprNode_freeIniter (newel);
8468 hasError = optgenerror
8470 message ("Initializer block used for "
8471 "%s where %t is expected: %s",
8472 exprNode_unparse (el), t1, exprNode_unparse (val)),
8478 if (exprNode_isDefined (val))
8480 doAssign (el, val, TRUE);
8482 if (!exprNode_matchType (t1, val))
8484 hasError = gentypeerror
8486 message ("Initial value of %s is type %t, "
8488 exprNode_unparse (el),
8489 t2, t1, exprNode_unparse (val)),
8498 static /*@notnull@*/ exprNode
8499 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
8503 DPRINTF (("Initialization: %s", idDecl_unparse (t)));
8505 if (usymtab_exists (idDecl_observeId (t)))
8507 uentry ue = usymtab_lookup (idDecl_observeId (t));
8508 ret = exprNode_createId (ue);
8514 DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
8516 ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
8517 ret = exprNode_fromIdentifierAux (ue);
8520 ** No error - this happens in old style declarations:
8524 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8531 exprData_free (ret->edata, ret->kind);
8532 ret->edata = exprData_undefined;
8533 ret->exitCode = XK_NEVERESCAPE;
8534 ret->mustBreak = FALSE;
8535 ret->kind = XPR_INIT;
8539 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8541 exprNode ret = exprNode_makeInitializationAux (t);
8542 llassert (ret->edata == exprData_undefined);
8543 ret->edata = exprData_makeInit (t, exprNode_undefined);
8547 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8548 /*@only@*/ exprNode e)
8550 uentry ue = usymtab_lookup (idDecl_observeId (t));
8551 exprNode ret = exprNode_makeInitializationAux (t);
8552 fileloc loc = exprNode_loc (e);
8554 DPRINTF (("initialization: %s = %s", idDecl_unparse (t), exprNode_unparse (e)));
8556 if (exprNode_isError (e))
8558 e = exprNode_createUnknown ();
8559 /* error: assume initializer is defined */
8560 sRef_setDefined (ret->sref, g_currentloc);
8561 ret->edata = exprData_makeInit (t, e);
8565 ctype ct = ctype_realishType (ret->typ);
8570 ** was addSafeUse --- what's the problem?
8572 ** int x = 3, y = x ?
8575 exprData_free (ret->edata, ret->kind);
8576 ret->edata = exprData_makeInit (t, e);
8577 DPRINTF (("ret: %s", exprNode_unparse (ret)));
8579 exprNode_checkUse (ret, e->sref, e->loc);
8581 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8583 exprNode lhs = exprNode_createId (ue);
8586 ** static storage should be undefined before initializing
8589 if (uentry_isStatic (ue))
8591 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8594 (void) exprNode_checkOneInit (lhs, e);
8596 if (uentry_isStatic (ue))
8598 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8601 exprNode_free (lhs);
8605 if (!exprNode_matchType (ct, e))
8607 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
8614 (exprNode_getType (e), e, exprNode_getType (ret), ret,
8616 ("Variable %q initialized to type %t, expects %t: %s",
8617 uentry_getName (ue), exprNode_getType (e),
8618 exprNode_getType (ret),
8619 exprNode_unparse (e)),
8625 if (uentry_isStatic (ue))
8627 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8630 if (exprNode_isStringLiteral (e)
8631 && (ctype_isArray (ct))
8632 && (ctype_isChar (ctype_realType (ctype_baseArrayPtr (ct)))))
8635 ** If t is a char [], the literal is copied.
8638 exprNode_checkStringLiteralLength (ct, e);
8639 sRef_setDefState (ret->sref, SS_DEFINED, e->loc);
8640 ret->val = multiVal_copy (e->val);
8642 sRef_setNullTerminatedState (ret->sref);
8644 if (multiVal_isDefined (e->val))
8646 cstring slit = multiVal_forceString (e->val);
8647 sRef_setLen (ret->sref, size_toInt (cstring_length (slit) + 1));
8650 if (ctype_isFixedArray (ct))
8652 sRef_setSize (ret->sref, size_toInt (ctype_getArraySize (ct)));
8657 doAssign (ret, e, TRUE);
8660 if (uentry_isStatic (ue))
8662 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8666 if (context_inIterDef ())
8668 /* should check if it is yield */
8669 uentry_setUsed (ue, loc);
8676 exprNode_mergeUSs (ret, e);
8677 DPRINTF (("Ret: %s %p %p",
8678 exprNode_unparse (ret),
8679 ret->requiresConstraints,
8680 ret->ensuresConstraints));
8682 DPRINTF (("Ret: %s %s %s",
8683 exprNode_unparse (ret),
8684 constraintList_unparse (ret->requiresConstraints),
8685 constraintList_unparse (ret->ensuresConstraints)));
8689 exprNode exprNode_iter (/*@observer@*/ uentry name,
8690 /*@only@*/ exprNodeList alist,
8691 /*@only@*/ exprNode body,
8692 /*@observer@*/ uentry end)
8697 llassert (uentry_isValid (name));
8699 uentry_setUsed (name, exprNode_loc (body));
8701 ret = exprNode_createPartialCopy (body);
8702 iname = uentry_getName (name);
8704 if (uentry_isInvalid (end))
8706 llerror (FLG_ITERBALANCE,
8707 message ("Iter %s not balanced with end_%s", iname, iname));
8711 cstring ename = uentry_getName (end);
8713 if (!cstring_equalPrefixLit (ename, "end_"))
8715 llerror (FLG_ITERBALANCE, message ("Iter %s not balanced with end_%s: %s",
8716 iname, iname, ename));
8720 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8722 llerror (FLG_ITERBALANCE,
8723 message ("Iter %s not balanced with end_%s: %s",
8724 iname, iname, ename));
8728 cstring_free (ename);
8731 context_exitIterClause (body);
8733 ret->kind = XPR_ITER;
8734 ret->edata = exprData_makeIter (name, alist, body, end);
8736 if (uentry_isIter (name))
8738 (void) checkArgsReal (name, body,
8739 uentry_getParams (name), alist, TRUE, ret);
8742 cstring_free (iname);
8748 exprNode_iterNewId (/*@only@*/ cstring s)
8750 exprNode e = exprNode_new ();
8751 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8753 llassert (processingIterVars ());
8755 e->loc = context_getSaveLocation ();
8757 if (fileloc_isUndefined (e->loc))
8759 fileloc_free (e->loc);
8760 e->loc = fileloc_copy (g_currentloc);
8763 e->uses = sRefSet_new ();
8764 e->sets = sRefSet_new ();
8765 e->msets = sRefSet_new ();
8767 e->val = multiVal_unknown ();
8768 e->guards = guardSet_new ();
8769 e->sref = sRef_undefined;
8770 e->isJumpPoint = FALSE;
8771 e->exitCode = XK_NEVERESCAPE;
8773 /*> missing fields, detected by splint <*/
8774 e->canBreak = FALSE;
8775 e->mustBreak = FALSE;
8776 e->etext = cstring_undefined;
8778 if (uentry_isYield (ue))
8780 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8781 fileloc_copy (e->loc),
8785 uue = usymtab_supEntrySrefReturn (uue);
8787 sr = uentry_getSref (uue);
8788 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8789 sr = uentry_getSref (uue);
8790 sRef_setDefined (sr, e->loc);
8792 e->typ = uentry_getType (uue);
8794 e->edata = exprData_makeId (uue);
8795 uentry_setUsed (uue, g_currentloc);
8801 sRef_setGlobalScope ();
8802 uue = uentry_makeVariableLoc (s, ctype_unknown);
8804 e->typ = ctype_unknown;
8805 e->edata = exprData_makeId (uue);
8807 uentry_setUsed (uue, e->loc);
8808 uentry_setHasNameError (uue);
8810 if (context_getFlag (FLG_REPEATUNRECOG))
8812 uentry_markOwned (uue);
8816 usymtab_supGlobalEntry (uue);
8819 sRef_clearGlobalScope ();
8821 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8828 exprNode_defineConstraints(e);
8833 exprNode_iterExpr (/*@returned@*/ exprNode e)
8835 if (!processingIterVars ())
8837 llcontbuglit ("checkIterParam: not in iter");
8841 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8844 if (exprNode_isDefined (e))
8846 if (fileloc_isDefined (e->loc))
8850 message ("Yield parameter is not simple identifier: %s",
8851 exprNode_unparse (e)),
8858 message ("Yield parameter is not simple identifier: %s",
8859 exprNode_unparse (e)),
8869 exprNode_iterId (/*@observer@*/ uentry c)
8873 llassert (processingIterVars ());
8875 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8878 if (uentry_isYield (ue))
8880 ctype ct = uentry_getType (ue);
8881 exprNode e = exprNode_createPlain (ct);
8882 cstring name = uentry_getName (c);
8883 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8885 uentry_setUsed (ue, g_currentloc);
8886 uentry_setHasNameError (ue);
8888 cstring_free (name);
8891 e->edata = exprData_makeId (le);
8892 e->loc = context_getSaveLocation ();
8893 e->sref = uentry_getSref (le);
8895 usymtab_supEntrySref (le);
8897 if (!context_inHeader ())
8901 message ("Yield parameter shadows local declaration: %q",
8902 uentry_getName (c)),
8903 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8905 uentry_showWhereDeclared (c);
8912 return (exprNode_fromIdentifierAux (c));
8915 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8917 exprNode ret = exprNode_create (ctype_unknown);
8919 ret->kind = XPR_ITERCALL;
8920 ret->edata = exprData_makeIterCall (name, alist);
8922 if (uentry_isIter (name))
8924 uentryList params = uentry_getParams (name);
8926 if (context_inIterDef ()
8927 && uentryList_size (params) == exprNodeList_size (alist))
8931 exprNodeList_elements (alist, arg)
8933 uentry parg = uentryList_getN (params, i);
8935 if (uentry_isYield (parg))
8937 uentry ue = exprNode_getUentry (arg);
8939 if (uentry_isValid (ue))
8946 } end_exprNodeList_elements;
8949 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8950 checkUnspecCall (ret, params, alist);
8956 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8958 if (exprNode_isDefined (e))
8960 if (sRef_isInvalid (e->sref))
8963 e->sref = sRef_makeUnknown ();
8964 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8975 return sRef_undefined;
8979 /*@observer@*/ cstring
8980 exprNode_unparseFirst (exprNode e)
8982 if (exprNode_isDefined (e))
8986 if (e->kind == XPR_STMTLIST
8987 || e->kind == XPR_COMMA || e->kind == XPR_COND)
8989 exprNode first = exprData_getPairA (e->edata);
8991 if (exprNode_isDefined (first))
8993 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8997 return (cstring_makeLiteralTemp ("..."));
9001 ret = cstring_elide (exprNode_unparse (e), 20);
9002 cstring_markOwned (ret);
9008 return cstring_makeLiteralTemp ("<error>");
9012 /*@observer@*/ cstring
9013 exprNode_unparse (/*@temp@*/ exprNode e)
9015 if (exprNode_isError (e))
9017 return cstring_makeLiteralTemp ("<error>");
9020 if (cstring_isDefined (e->etext))
9026 cstring ret = exprNode_doUnparse (e);
9028 /*@-modifies@*/ /* benevolent */
9035 /*@observer@*/ fileloc
9036 exprNode_loc (exprNode e)
9038 if (exprNode_isError (e))
9040 return (g_currentloc);
9049 ** executes exprNode e
9050 ** recursively rexecutes as though in original parse using
9051 ** information in e->edata
9054 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
9056 exprNodeList ret = exprNodeList_new ();
9058 exprNodeList_elements (e, current)
9060 exprNodeList_addh (ret, exprNode_effect (current));
9061 } end_exprNodeList_elements;
9066 static /*@only@*/ exprNode exprNode_effect (exprNode e)
9067 /*@globals internalState@*/
9069 bool innerEffect = inEffect;
9075 context_clearJustPopped ();
9077 if (exprNode_isError (e))
9079 ret = exprNode_undefined;
9084 ** Turn off expose and dependent transfer checking.
9085 ** Need to pass exposed internal nodes,
9086 ** [ copying would be a waste! ]
9087 ** [ Actually, I think I wasted a lot more time than its worth ]
9088 ** [ trying to do this. ]
9092 /*@-observertrans@*/
9093 /*@-dependenttrans@*/
9100 ret = exprNode_addParens (exprData_getUopTok (data),
9101 exprNode_effect (exprData_getUopNode (data)));
9104 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
9105 exprNode_effect (exprData_getOpB (data)),
9106 exprData_getOpTok (data));
9109 ret = exprNode_undefined;
9112 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
9113 exprNodeList_effect (exprData_getArgs (data)));
9126 cstring id = exprData_getId (data);
9127 uentry ue = usymtab_lookupSafe (id);
9129 ret = exprNode_fromIdentifierAux (ue);
9130 ret->loc = fileloc_update (ret->loc, e->loc);
9137 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
9138 exprNode_effect (exprData_getPairB (data)));
9142 ** evans 2002-03-15: for && and ||, need to do the guards also
9143 ** this is what cgrammar.y does - should be
9144 ** able to avoid duplication, but need to
9145 ** time with grammar productions.
9148 DPRINTF (("Effect: %s", exprNode_unparse (e)));
9150 if (lltok_getTok (exprData_getOpTok (data)) == AND_OP)
9152 exprNode e1 = exprNode_effect (exprData_getOpA (data));
9154 exprNode_produceGuards (e1);
9155 context_enterAndClause (e1);
9156 e2 = exprNode_effect (exprData_getOpB (data));
9158 ret = exprNode_op (e1, e2,
9159 exprData_getOpTok (data));
9161 context_exitAndClause (ret, e2);
9163 else if (lltok_getTok (exprData_getOpTok (data)) == OR_OP)
9165 exprNode e1 = exprNode_effect (exprData_getOpA (data));
9167 exprNode_produceGuards (e1);
9168 context_enterOrClause (e1);
9169 e2 = exprNode_effect (exprData_getOpB (data));
9171 ret = exprNode_op (e1, e2,
9172 exprData_getOpTok (data));
9174 context_exitOrClause (ret, e2);
9178 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
9179 exprNode_effect (exprData_getOpB (data)),
9180 exprData_getOpTok (data));
9185 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
9186 exprData_getUopTok (data));
9189 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
9190 exprData_getUopTok (data));
9202 ret = exprNode_vaArg (exprData_getCastTok (data),
9203 exprNode_effect (exprData_getCastNode (data)),
9204 exprData_getCastType (data));
9208 ret = exprNode_cast (exprData_getCastTok (data),
9209 exprNode_effect (exprData_getCastNode (data)),
9210 exprData_getCastType (data));
9213 ret = exprNode_iterStart (exprData_getIterCallIter (data),
9215 (exprData_getIterCallArgs (data)));
9219 ret = exprNode_iter (exprData_getIterSname (data),
9220 exprNodeList_effect (exprData_getIterAlist (data)),
9221 exprNode_effect (exprData_getIterBody (data)),
9222 exprData_getIterEname (data));
9226 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
9227 exprNode_effect (exprData_getPairB (data)));
9231 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
9232 exprNode_effect (exprData_getTripleTest (data)),
9233 exprNode_effect (exprData_getTripleInc (data)));
9237 ret = exprNode_createTok (exprData_getTok (data));
9241 ret = exprNode_goto (exprData_getLiteral (data));
9242 ret->loc = fileloc_update (ret->loc, e->loc);
9246 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
9250 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
9254 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
9257 case XPR_NULLRETURN:
9258 ret = exprNode_nullReturn (exprData_getTok (data));
9262 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
9263 exprNode_effect (exprData_getPairB (data)));
9267 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
9268 exprNode_effect (exprData_getTripleTrue (data)),
9269 exprNode_effect (exprData_getTripleFalse (data)));
9272 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
9273 exprNode_effect (exprData_getPairB (data)));
9277 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
9278 exprNode_effect (exprData_getTripleTrue (data)),
9279 exprNode_effect (exprData_getTripleFalse (data)));
9282 ret = exprNode_whilePred (exprData_getSingle (data));
9286 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
9287 exprNode_effect (exprData_getPairB (data)));
9291 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
9292 exprNode_effect (exprData_getPairB (data)));
9296 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
9300 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
9301 exprData_getUopTok (data));
9305 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
9306 exprNode_effect (exprData_getPairB (data)));
9311 ret = exprNode_caseMarker
9312 (exprNode_effect (exprData_getSingle (data)),
9318 ret = exprNode_createTok (exprData_getTok (data));
9322 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
9323 exprNode_effect (exprData_getPairB (data)));
9327 ret = exprNode_makeInitialization
9328 (exprData_getInitId (data),
9329 exprNode_effect (exprData_getInitNode (data)));
9333 ret = exprNode_fieldAccessAux
9334 (exprNode_effect (exprData_getFieldNode (data)),
9335 exprNode_loc (exprData_getFieldNode (data)),
9336 cstring_copy (exprData_getFieldName (data)));
9340 ret = exprNode_arrowAccessAux
9341 (exprNode_effect (exprData_getFieldNode (data)),
9342 exprNode_loc (exprData_getFieldNode (data)),
9343 cstring_copy (exprData_getFieldName (data)));
9346 case XPR_STRINGLITERAL:
9360 /*@=observertrans@*/
9362 /*@=dependenttrans@*/
9373 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
9378 if (exprNode_isError (e))
9380 return cstring_undefined;
9388 ret = exprNode_rootVarName (exprData_getUopNode (data));
9391 ret = exprNode_rootVarName (exprData_getOpA (data));
9395 ret = exprData_getId (data);
9398 ret = idDecl_getName (exprData_getInitId (data));
9423 case XPR_NULLRETURN:
9445 case XPR_STRINGLITERAL:
9446 ret = cstring_undefined;
9453 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
9458 if (exprNode_isError (e))
9460 static /*@only@*/ cstring error = cstring_undefined;
9462 if (!cstring_isDefined (error))
9464 error = cstring_makeLiteral ("<error>");
9475 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
9478 ret = message ("%s %s %s",
9479 exprNode_unparse (exprData_getOpA (data)),
9480 lltok_unparse (exprData_getOpTok (data)),
9481 exprNode_unparse (exprData_getOpB (data)));
9484 ret = message ("%s(%q)",
9485 exprNode_unparse (exprData_getFcn (data)),
9486 exprNodeList_unparse (exprData_getArgs (data)));
9489 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
9492 ret = cstring_undefined;
9495 ret = message ("%s:", exprData_getId (data));
9499 ret = cstring_copy (exprData_getId (data));
9502 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
9503 exprNode_unparse (exprData_getPairB (data)));
9506 ret = message ("<body>");
9509 ret = message ("%s %s %s",
9510 exprNode_unparse (exprData_getOpA (data)),
9511 lltok_unparse (exprData_getOpTok (data)),
9512 exprNode_unparse (exprData_getOpB (data)));
9516 ret = message ("%s%s",
9517 lltok_unparse (exprData_getUopTok (data)),
9518 exprNode_unparse (exprData_getUopNode (data)));
9522 ret = message ("%s%s",
9523 exprNode_unparse (exprData_getUopNode (data)),
9524 lltok_unparse (exprData_getUopTok (data)));
9528 ret = message ("offsetof(%s,%q)",
9529 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
9530 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
9534 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9538 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
9542 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9546 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
9550 ret = message ("va_arg(%s, %q)",
9551 exprNode_unparse (exprData_getCastNode (data)),
9552 qtype_unparse (exprData_getCastType (data)));
9556 ret = message ("%q(%q)",
9557 uentry_getName (exprData_getIterCallIter (data)),
9558 exprNodeList_unparse (exprData_getIterCallArgs (data)));
9561 ret = message ("%q(%q) %s %q",
9562 uentry_getName (exprData_getIterSname (data)),
9563 exprNodeList_unparse (exprData_getIterAlist (data)),
9564 exprNode_unparse (exprData_getIterBody (data)),
9565 uentry_getName (exprData_getIterEname (data)));
9568 ret = message ("(%q)%s",
9569 qtype_unparse (exprData_getCastType (data)),
9570 exprNode_unparse (exprData_getCastNode (data)));
9574 ret = message ("%s %s",
9575 exprNode_unparse (exprData_getPairA (data)),
9576 exprNode_unparse (exprData_getPairB (data)));
9580 ret = message ("for (%s; %s; %s)",
9581 exprNode_unparse (exprData_getTripleInit (data)),
9582 exprNode_unparse (exprData_getTripleTest (data)),
9583 exprNode_unparse (exprData_getTripleInc (data)));
9587 ret = message ("goto %s", exprData_getLiteral (data));
9591 ret = cstring_makeLiteral ("continue");
9595 ret = cstring_makeLiteral ("break");
9599 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
9602 case XPR_NULLRETURN:
9603 ret = cstring_makeLiteral ("return");
9607 ret = message ("%s, %s",
9608 exprNode_unparse (exprData_getPairA (data)),
9609 exprNode_unparse (exprData_getPairB (data)));
9613 ret = message ("%s ? %s : %s",
9614 exprNode_unparse (exprData_getTriplePred (data)),
9615 exprNode_unparse (exprData_getTripleTrue (data)),
9616 exprNode_unparse (exprData_getTripleFalse (data)));
9619 ret = message ("if (%s) %s",
9620 exprNode_unparse (exprData_getPairA (data)),
9621 exprNode_unparse (exprData_getPairB (data)));
9625 ret = message ("if (%s) %s else %s",
9626 exprNode_unparse (exprData_getTriplePred (data)),
9627 exprNode_unparse (exprData_getTripleTrue (data)),
9628 exprNode_unparse (exprData_getTripleFalse (data)));
9631 ret = message ("while (%s) %s",
9632 exprNode_unparse (exprData_getPairA (data)),
9633 exprNode_unparse (exprData_getPairB (data)));
9637 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9641 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9645 ret = message ("do { %s } while (%s)",
9646 exprNode_unparse (exprData_getPairB (data)),
9647 exprNode_unparse (exprData_getPairA (data)));
9651 ret = message ("{ %s }", exprNode_unparse (exprData_getSingle (data)));
9652 /* evans 2002-02-20 was unparseFirst! */
9656 ret = message ("%s;", exprNode_unparse (exprData_getUopNode (data)));
9660 if (exprNode_isStatement (exprData_getPairA (data)))
9663 ** statement expressions already print the ;
9666 ret = message ("%s %s",
9667 exprNode_unparse (exprData_getPairA (data)),
9668 exprNode_unparse (exprData_getPairB (data)));
9672 ret = message ("%s; %s",
9673 exprNode_unparse (exprData_getPairA (data)),
9674 exprNode_unparse (exprData_getPairB (data)));
9680 ret = cstring_makeLiteral ("default:");
9684 ret = message ("switch (%s) %s",
9685 exprNode_unparse (exprData_getPairA (data)),
9686 exprNode_unparse (exprData_getPairB (data)));
9691 ret = message ("case %s:",
9692 exprNode_unparse (exprData_getSingle (data)));
9696 if (exprNode_isError (exprData_getInitNode (data)))
9698 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9702 ret = message ("%q = %s",
9703 idDecl_unparseC (exprData_getInitId (data)),
9704 exprNode_unparse (exprData_getInitNode (data)));
9709 ret = message ("%s.%s",
9710 exprNode_unparse (exprData_getFieldNode (data)),
9711 exprData_getFieldName (data));
9715 ret = message ("%s->%s",
9716 exprNode_unparse (exprData_getFieldNode (data)),
9717 exprData_getFieldName (data));
9720 case XPR_STRINGLITERAL:
9721 if (ctype_isWideString (e->typ))
9723 ret = message ("L\"%s\"", exprData_getLiteral (data));
9727 ret = message ("\"%s\"", exprData_getLiteral (data));
9732 ret = cstring_copy (exprData_getLiteral (data));
9736 ret = cstring_makeLiteral ("<node>");
9744 exprNode_isInitializer (exprNode e)
9746 return (exprNode_isDefined (e)
9747 && e->kind == XPR_INIT);
9751 exprNode_isCharLiteral (exprNode e)
9753 if (exprNode_isDefined (e))
9755 return (multiVal_isChar (exprNode_getValue (e)));
9764 exprNode_isNumLiteral (exprNode e)
9766 if (exprNode_isDefined (e))
9768 return (multiVal_isInt (exprNode_getValue (e)));
9777 exprNode_isFalseConstant (exprNode e)
9779 if (exprNode_isDefined (e))
9781 cstring s = exprNode_rootVarName (e);
9783 if (cstring_equal (s, context_getFalseName ()))
9793 exprNode_matchLiteral (ctype expected, exprNode e)
9795 if (exprNode_isDefined (e))
9797 multiVal m = exprNode_getValue (e);
9799 if (multiVal_isDefined (m))
9801 if (multiVal_isInt (m))
9803 long int val = multiVal_forceInt (m);
9805 if (ctype_isNumAbstract (expected)
9806 && context_flagOn (FLG_NUMABSTRACTLIT, exprNode_loc (e)))
9811 if (ctype_isDirectBool (ctype_realishType (expected)))
9815 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9823 if (ctype_isRealInt (expected))
9826 ** unsigned <- [ constant >= 0 is okay ]
9829 if (ctype_isUnsigned (expected))
9838 ** No checks on sizes of integers...maybe add
9842 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9843 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9844 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9846 if (context_getFlag (FLG_NUMLITERAL)
9847 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9853 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9857 else if (ctype_isChar (expected))
9861 else if (ctype_isArrayPtr (expected))
9864 ** evans 2001-10-14: We allow 0 to match any pointer, but only if the type matches or is void *.
9869 if (ctype_match (exprNode_getType (e), expected)
9870 || ctype_isVoidPointer (exprNode_getType (e)))
9880 else if (ctype_isAnyFloat (expected))
9882 return (context_getFlag (FLG_NUMLITERAL));
9889 else if (multiVal_isDouble (m))
9891 if (ctype_isAnyFloat (expected))
9896 else if (multiVal_isChar (m))
9898 /*signed? */ char val = multiVal_forceChar (m);
9900 if (ctype_isChar (expected))
9902 if (ctype_isUnsigned (expected) && ((int) val) < 0)
9923 exprNode_matchType (ctype expected, exprNode e)
9927 if (!exprNode_isDefined (e)) return TRUE;
9929 actual = ctype_realishType (exprNode_getType (e));
9931 if (ctype_match (ctype_realishType (expected), actual))
9936 llassert (!exprNode_isError (e));
9937 return (exprNode_matchLiteral (expected, e));
9941 exprNode_matchTypes (exprNode e1, exprNode e2)
9946 if (!exprNode_isDefined (e1)) return TRUE;
9947 if (!exprNode_isDefined (e2)) return TRUE;
9950 ** realish type --- keep bools, bools
9953 t1 = ctype_realishType (exprNode_getType (e1));
9954 t2 = ctype_realishType (exprNode_getType (e2));
9956 if (ctype_match (t1, t2))
9961 DPRINTF (("Matching literal! %s %s %s %s",
9962 ctype_unparse (t1), exprNode_unparse (e2),
9963 ctype_unparse (t2), exprNode_unparse (e1)));
9965 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9973 exprNode_matchArgType (ctype ct, exprNode e)
9977 if (!exprNode_isDefined (e))
9982 et = ctype_realType (exprNode_getType (e));
9984 if (ctype_matchArg (ct, et)) return TRUE;
9986 llassert (!exprNode_isError (e));
9987 return (exprNode_matchLiteral (ct, e));
9990 static /*@only@*/ exprNodeSList
9991 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9993 if (exprNode_isDefined (e))
9995 if (e->kind == XPR_STMTLIST)
9997 return (exprNodeSList_append
9998 (exprNode_flatten (exprData_getPairA (e->edata)),
9999 exprNode_flatten (exprData_getPairB (e->edata))));
10001 else if (e->kind == XPR_BLOCK)
10003 return (exprNode_flatten (exprData_getSingle (e->edata)));
10007 return (exprNodeSList_singleton (e));
10011 return exprNodeSList_new ();
10014 static /*@exposed@*/ exprNode
10015 exprNode_lastStatement (/*@returned@*/ exprNode e)
10017 if (exprNode_isDefined (e))
10019 if (e->kind == XPR_STMTLIST)
10021 exprNode b = exprData_getPairB (e->edata);
10023 if (exprNode_isDefined (b))
10025 return exprNode_lastStatement (b);
10029 return exprNode_lastStatement (exprData_getPairA (e->edata));
10032 else if (e->kind == XPR_BLOCK)
10034 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
10042 return exprNode_undefined;
10045 static /*@exposed@*/ exprNode
10046 exprNode_firstStatement (/*@returned@*/ exprNode e)
10048 if (exprNode_isDefined (e))
10050 if (e->kind == XPR_STMTLIST)
10052 exprNode b = exprData_getPairA (e->edata);
10054 if (exprNode_isDefined (b))
10056 return exprNode_firstStatement (b);
10060 return exprNode_firstStatement (exprData_getPairB (e->edata));
10063 else if (e->kind == XPR_BLOCK)
10065 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
10073 return exprNode_undefined;
10077 exprNode_mergeUSs (exprNode res, exprNode other)
10079 if (exprNode_isDefined (res) && exprNode_isDefined (other))
10081 res->msets = sRefSet_union (res->msets, other->msets);
10082 res->sets = sRefSet_union (res->sets, other->sets);
10083 res->uses = sRefSet_union (res->uses, other->uses);
10088 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
10090 if (exprNode_isDefined (res))
10092 if (exprNode_isDefined (other1))
10094 res->sets = sRefSet_union (res->sets, other1->sets);
10095 res->msets = sRefSet_union (res->msets, other1->msets);
10096 res->uses = sRefSet_union (res->uses, other1->uses);
10098 if (exprNode_isDefined (other2))
10100 res->sets = sRefSet_union (res->sets, other2->sets);
10101 res->msets = sRefSet_union (res->msets, other2->msets);
10102 res->uses = sRefSet_union (res->uses, other2->uses);
10108 ** modifies e->uses
10110 ** Reports errors is s is not defined.
10114 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
10116 if (exprNode_isDefined (e))
10118 e->uses = sRefSet_insert (e->uses, s);
10123 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
10125 if (sRef_isKnown (s) && !sRef_isConst (s))
10128 ** need to check all outer types are useable
10131 DPRINTF (("Check use: %s / %s",
10132 exprNode_unparse (e), sRef_unparse (s)));
10134 exprNode_addUse (e, s);
10136 if (!context_inProtectVars ())
10139 ** only report the deepest error
10142 sRef errorRef = sRef_undefined;
10143 sRef lastRef = sRef_undefined;
10144 bool deadRef = FALSE;
10145 bool unuseable = FALSE;
10146 bool errorMaybe = FALSE;
10148 while (sRef_isValid (s) && sRef_isKnown (s))
10150 ynm readable = sRef_isValidLvalue (s);
10152 DPRINTF (("Readable: %s / %s",
10153 sRef_unparseFull (s), ynm_unparse (readable)));
10155 if (!(ynm_toBoolStrict (readable)))
10157 if (ynm_isMaybe (readable))
10159 lastRef = errorRef;
10161 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
10162 deadRef = sRef_isPossiblyDead (errorRef);
10163 unuseable = sRef_isUnuseable (errorRef);
10168 lastRef = errorRef;
10170 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
10171 deadRef = sRef_isDead (errorRef);
10172 unuseable = sRef_isUnuseable (errorRef);
10173 errorMaybe = FALSE;
10177 if (!sRef_isPartial (s))
10179 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
10180 sRef_setDefined (s, loc);
10181 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
10186 s = sRef_getBaseSafe (s);
10189 if (sRef_isValid (errorRef))
10191 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
10192 && sRef_isPointer (errorRef))
10194 errorRef = lastRef;
10195 DPRINTF (("errorRef: %s", sRef_unparseFull (errorRef)));
10200 if (sRef_isThroughArrayFetch (errorRef))
10203 (FLG_STRICTUSERELEASED,
10204 message ("%q %q may be used after being released",
10205 sRef_unparseKindNamePlain (errorRef),
10206 sRef_unparse (errorRef)),
10209 sRef_showRefKilled (errorRef);
10211 if (sRef_isKept (errorRef))
10213 sRef_clearAliasState (errorRef, loc);
10219 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
10223 message ("%q %q %qused after being released",
10224 sRef_unparseKindNamePlain (errorRef),
10225 sRef_unparse (errorRef),
10226 cstring_makeLiteral (errorMaybe
10227 ? "may be " : "")),
10230 sRef_showRefKilled (errorRef);
10232 if (sRef_isKept (errorRef))
10234 sRef_clearAliasState (errorRef, loc);
10239 else if (unuseable)
10243 message ("%q %q%qused in inconsistent state",
10244 sRef_unparseKindName (errorRef),
10245 sRef_unparseOpt (errorRef),
10246 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10249 sRef_showStateInconsistent (errorRef);
10254 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
10258 message ("%q %q%qused before definition",
10259 sRef_unparseKindName (errorRef),
10260 sRef_unparseOpt (errorRef),
10261 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10267 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
10270 sRef_setDefined (errorRef, loc);
10272 if (sRef_isAddress (errorRef))
10274 sRef_setDefined (sRef_getRootBase (errorRef), loc);
10276 } /* end is error */
10284 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
10286 if (exprNode_isDefined (e) && sRef_isKnown (s))
10288 e->uses = sRefSet_insert (e->uses, s);
10293 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
10295 if (exprNode_isDefined (e))
10297 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
10302 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
10304 sRef defines = sRef_undefined;
10306 if (sRef_isValid (s) && !sRef_isNothing (s))
10308 uentry ue = sRef_getBaseUentry (s);
10310 if (uentry_isValid (ue))
10312 uentry_setLset (ue);
10315 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10317 voptgenerror (FLG_USEDEF,
10318 message ("Attempt to set unuseable storage: %q",
10323 if (sRef_isMeaningful (s))
10325 if (sRef_isDead (s))
10327 sRef base = sRef_getBaseSafe (s);
10329 if (sRef_isValid (base)
10330 && sRef_isDead (base))
10332 sRef_setPartial (s, exprNode_loc (e));
10335 defines = s; /* okay - modifies for only param */
10337 else if (sRef_isPartial (s))
10339 sRef eref = exprNode_getSref (e);
10341 if (!sRef_isPartial (eref))
10344 ** should do something different here???
10347 sRef_setDefinedComplete (eref, exprNode_loc (e));
10351 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
10354 if (sRef_isMeaningful (eref))
10363 else if (sRef_isAllocated (s))
10365 sRef eref = exprNode_getSref (e);
10368 if (!sRef_isAllocated (eref))
10370 sRef_setDefinedComplete (eref, exprNode_loc (e));
10374 sRef base = sRef_getBaseSafe (eref);
10376 if (sRef_isValid (base))
10378 sRef_setPdefined (base, exprNode_loc (e));
10386 sRef_setDefinedNCComplete (s, exprNode_loc (e));
10391 else /* not meaningful...but still need to insert it */
10397 if (exprNode_isDefined (e) && sRef_isValid (defines))
10399 e->sets = sRefSet_insert (e->sets, defines);
10404 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
10406 if (sRef_isValid (s) && !sRef_isNothing (s))
10408 uentry ue = sRef_getBaseUentry (s);
10410 if (uentry_isValid (ue))
10412 uentry_setLset (ue);
10415 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10417 voptgenerror (FLG_USEDEF,
10418 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
10422 if (sRef_isMeaningful (s))
10424 sRef_setDefinedComplete (s, exprNode_loc (e));
10427 if (exprNode_isDefined (e))
10429 e->msets = sRefSet_insert (e->msets, s);
10435 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
10437 checkAnyCall (fcn, cstring_undefined, params, args,
10438 FALSE, sRefSet_undefined, FALSE, 0);
10442 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
10443 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
10447 if (uentry_isYield (ucurrent))
10449 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
10450 exprNode_checkSet (current, current->sref);
10454 if (uentry_isSefParam (ucurrent))
10456 sRefSet sets = current->sets;
10457 sRef ref = exprNode_getSref (current);
10459 if (sRef_isMacroParamRef (ref))
10461 uentry ue = sRef_getUentry (ref);
10463 if (!uentry_isSefParam (ue))
10468 ("Parameter %d to %s is declared sef, but "
10469 "the argument is a macro parameter declared "
10471 argno, exprNode_unparse (fcn),
10472 exprNode_unparse (current)),
10473 exprNode_loc (current));
10477 if (!sRefSet_isEmpty (sets))
10479 sRefSet reported = sRefSet_undefined;
10481 sRefSet_realElements (current->sets, el)
10483 if (sRefSet_isSameNameMember (reported, el))
10485 ; /* don't report again */
10489 if (sRef_isUnconstrained (el))
10494 ("Parameter %d to %s is declared sef, but "
10495 "the argument calls unconstrained function %s "
10496 "(no guarantee it will not modify something): %s",
10497 argno, exprNode_unparse (fcn),
10498 sRef_unconstrainedName (el),
10499 exprNode_unparse (current)),
10500 exprNode_loc (current));
10507 ("Parameter %d to %s is declared sef, but "
10508 "the argument may modify %q: %s",
10509 argno, exprNode_unparse (fcn),
10511 exprNode_unparse (current)),
10512 exprNode_loc (current));
10515 } end_sRefSet_realElements;
10519 transferChecks_passParam (current, ucurrent, isSpec, fcn, argno, totargs);
10520 exprNode_mergeUSs (fcn, current);
10525 checkAnyCall (/*@dependent@*/ exprNode fcn,
10526 /*@dependent@*/ cstring fname,
10529 bool hasMods, sRefSet mods,
10534 int nargs = exprNodeList_size (args);
10539 ** concat all args ud's to f, add each arg sref as a use unless
10540 ** it was specified as "out", in which case it is a def.
10543 uentryList_reset (pn);
10546 ** aliasing checks:
10548 ** if paramn is only or unique, no other arg may alias argn
10551 exprNodeList_elements (args, current)
10555 if (exprNode_isDefined (current))
10557 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
10559 uentry ucurrent = uentryList_current (pn);
10561 if (specialArgs == 0
10562 || (paramno < specialArgs))
10564 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
10566 if (context_maybeSet (FLG_ALIASUNIQUE))
10568 if (uentry_isOnly (ucurrent)
10569 || uentry_isUnique (ucurrent))
10571 checkUniqueParams (fcn, current, args,
10572 paramno, ucurrent);
10577 else /* uentry is undefined */
10579 if (specialArgs == 0)
10581 exprNode_checkUseParam (current);
10584 exprNode_mergeUSs (fcn, current);
10587 uentryList_advanceSafe (pn);
10588 } end_exprNodeList_elements;
10594 sRefSet_allElements (mods, s)
10597 sRef rb = sRef_getRootBase (s);
10599 if (sRef_isFileOrGlobalScope (rb))
10601 context_usedGlobal (rb);
10604 fb = sRef_fixBaseParam (s, args);
10606 if (!sRef_isMacroParamRef (fb))
10608 if (sRef_isNothing (fb))
10614 if (sRef_isValid (fb))
10616 uentry ue = sRef_getBaseUentry (s);
10618 if (uentry_isValid (ue))
10620 uentry_setLset (ue);
10624 fcn->sets = sRefSet_insert (fcn->sets, fb);
10627 sRef_clearDerivedComplete (s);
10628 } end_sRefSet_allElements;
10634 if (context_hasMods ())
10636 if (context_maybeSet (FLG_MODUNCON))
10640 message ("Undetected modification possible "
10641 "from call to unconstrained function %s: %s",
10643 exprNode_unparse (fcn)),
10644 exprNode_loc (fcn));
10649 if (context_maybeSet (FLG_MODUNCONNOMODS)
10650 && !(context_inIterDef () || context_inIterEnd ()))
10653 (FLG_MODUNCONNOMODS,
10654 message ("Undetected modification possible "
10655 "from call to unconstrained function %s: %s",
10657 exprNode_unparse (fcn)),
10658 exprNode_loc (fcn));
10662 exprNode_checkSetAny (fcn, fname);
10666 void exprNode_checkUseParam (exprNode current)
10668 if (exprNode_isDefined (current))
10670 exprNode_checkUse (current, current->sref, current->loc);
10675 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10676 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10681 if (!ctype_match (tr1, tr2))
10683 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10684 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10686 DPRINTF (("No error: [%s] %s / [%s] %s",
10687 exprNode_unparse (e1), ctype_unparse (tr1),
10688 exprNode_unparse (e2), ctype_unparse (tr2)));
10691 ** evans 2003-06-15: changed this so if either type is a literal,
10692 ** the other type is used.
10693 ** (Need to look at the ISO C99 rules on this...)
10696 if (exprNode_isNumLiteral (e1)) {
10698 } else if (exprNode_isNumLiteral (e2)) {
10701 ret = ctype_biggerType (tr1, tr2);
10706 if (ctype_isNumAbstract (tr1)
10707 && exprNode_isNumLiteral (e2)
10708 && context_flagOn (FLG_NUMABSTRACTLIT, e1->loc))
10710 ret = tr1; /* No error */
10712 else if (ctype_isNumAbstract (tr2)
10713 && exprNode_isNumLiteral (e1)
10714 && context_flagOn (FLG_NUMABSTRACTLIT, e1->loc))
10722 message ("Incompatible types for %s (%s, %s): %s %s %s",
10723 lltok_unparse (op),
10724 ctype_unparse (te1),
10725 ctype_unparse (te2),
10726 exprNode_unparse (e1), lltok_unparse (op),
10727 exprNode_unparse (e2)),
10730 ret = ctype_unknown;
10734 ret = ctype_biggerType (tr1, tr2);
10741 if (ctype_isNumAbstract (tr1))
10745 else if (ctype_isForceRealNumeric (&tr1)
10746 && ctype_isForceRealNumeric (&tr2))
10748 ret = ctype_resolveNumerics (tr1, tr2);
10750 else if (!context_msgStrictOps ())
10752 if (ctype_isPointer (tr1))
10754 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10758 else if (ctype_isInt (tr2))
10764 ret = ctype_unknown;
10767 else if (ctype_isPointer (tr2))
10769 if (ctype_isPointer (tr1))
10773 else if (ctype_isInt (tr1))
10779 ret = ctype_unknown;
10784 ret = ctype_resolveNumerics (tr1, tr2);
10789 int opid = lltok_getTok (op);
10790 bool comparop = (opid == EQ_OP || opid == NE_OP
10791 || opid == TLT || opid == TGT
10792 || opid == LE_OP || opid == GE_OP);
10794 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10797 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10798 || (ctype_isBool (tr1) && ctype_isBool (tr2))
10799 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10805 if (ctype_sameName (te1, te2))
10809 message ("Operands of %s are non-numeric (%t): %s %s %s",
10810 lltok_unparse (op), te1,
10811 exprNode_unparse (e1), lltok_unparse (op),
10812 exprNode_unparse (e2)),
10819 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10820 lltok_unparse (op), te1, te2,
10821 exprNode_unparse (e1), lltok_unparse (op),
10822 exprNode_unparse (e2)),
10827 else if (!ctype_isNumeric (tr1))
10831 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10832 lltok_unparse (op), te1,
10833 exprNode_unparse (e1), lltok_unparse (op),
10834 exprNode_unparse (e2)),
10839 if (!ctype_isNumeric (tr2))
10843 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10844 lltok_unparse (op), te2,
10845 exprNode_unparse (e1), lltok_unparse (op),
10846 exprNode_unparse (e2)),
10851 ret = ctype_unknown;
10859 abstractOpError (ctype tr1, ctype tr2, lltok op,
10860 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10861 fileloc loc1, fileloc loc2)
10863 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10865 if (ctype_match (tr1, tr2))
10867 if (ctype_isRealNumAbstract (tr1))
10869 ; /* No warning for numabstract types */
10873 if (lltok_isEqOp (op) || lltok_isNotEqOp (op))
10876 (FLG_ABSTRACTCOMPARE,
10877 message ("Object equality comparison (%s) on objects of abstract type (%t): %s %s %s",
10878 lltok_unparse (op), tr1,
10879 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10886 message ("Operands of %s are abstract type (%t): %s %s %s",
10887 lltok_unparse (op), tr1,
10888 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10895 if (ctype_isRealNumAbstract (tr1) && ctype_isRealNumAbstract (tr2))
10900 ("Operands of %s are different numabstract types (%t, %t): %s %s %s",
10901 lltok_unparse (op), tr1, tr2,
10902 exprNode_unparse (e1),
10903 lltok_unparse (op), exprNode_unparse (e2)),
10910 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10911 lltok_unparse (op), tr1, tr2,
10912 exprNode_unparse (e1), lltok_unparse (op),
10913 exprNode_unparse (e2)),
10918 else if (ctype_isRealAbstract (tr1) && !ctype_isRealNumAbstract (tr1))
10922 message ("Left operand of %s is abstract type (%t): %s %s %s",
10923 lltok_unparse (op), tr1,
10924 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10929 if (ctype_isRealAbstract (tr2) && !ctype_isRealNumAbstract (tr2))
10933 message ("Right operand of %s is abstract type (%t): %s %s %s",
10934 lltok_unparse (op), tr2,
10935 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10946 ** requies e1 and e2 and not error exprNode's.
10950 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10951 ** the rep of the abstract type is exposed.
10953 ** The order is very important:
10955 ** check rep expose (move into check transfer)
10961 ** This isn't really a sensible procedure, but the indententation
10962 ** was getting too deep.
10966 checkOneRepExpose (sRef ysr, sRef base,
10967 /*@notnull@*/ exprNode e1,
10968 /*@notnull@*/ exprNode e2, ctype ct,
10971 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
10972 || sRef_isOwned (ysr)
10973 || sRef_isExposed (ysr)))
10975 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10976 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10979 if (sRef_isIReference (ysr))
10981 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10986 ("Assignment of mutable component of parameter %q "
10987 "to component of abstract "
10988 "type %s exposes rep: %s = %s",
10989 sRef_unparse (base),
10990 ctype_unparse (ct),
10991 exprNode_unparse (e1), exprNode_unparse (e2)),
10999 ("Assignment of mutable component of parameter %q "
11000 "(through alias %q) to component of abstract "
11001 "type %s exposes rep: %s = %s",
11002 sRef_unparse (base),
11003 sRef_unparse (e2->sref),
11004 ctype_unparse (ct),
11005 exprNode_unparse (e1), exprNode_unparse (e2)),
11011 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
11015 message ("Assignment of mutable parameter %q "
11016 "to component of abstract type %s "
11017 "exposes rep: %s = %s",
11018 sRef_unparse (base),
11019 ctype_unparse (ct),
11020 exprNode_unparse (e1),
11021 exprNode_unparse (e2)),
11028 message ("Assignment of mutable parameter %q "
11029 "(through alias %q) to "
11030 "component of abstract type %s exposes "
11032 sRef_unparse (base),
11033 sRef_unparse (e2->sref),
11034 ctype_unparse (ct),
11035 exprNode_unparse (e1),
11036 exprNode_unparse (e2)),
11042 if (sRef_isFileOrGlobalScope (s2b))
11044 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
11048 message ("Assignment of global %q "
11050 "abstract type %s exposes rep: %s = %s",
11051 sRef_unparse (base),
11052 ctype_unparse (ct),
11053 exprNode_unparse (e1), exprNode_unparse (e2)),
11060 message ("Assignment of global %q (through alias %q) "
11062 "abstract type %s exposes rep: %s = %s",
11063 sRef_unparse (base),
11064 sRef_unparse (e2->sref),
11065 ctype_unparse (ct),
11066 exprNode_unparse (e1), exprNode_unparse (e2)),
11074 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
11076 DPRINTF (("Do assign: %s <- %s",
11077 exprNode_unparse (e1), exprNode_unparse (e2)));
11078 DPRINTF (("Ctype: %s", ctype_unparse (exprNode_getType (e1))));
11080 if (ctype_isRealFunction (exprNode_getType (e1))
11081 && !ctype_isRealPointer (exprNode_getType (e1)))
11085 message ("Invalid left-hand side of assignment (function type %s): %s",
11086 ctype_unparse (exprNode_getType (e1)),
11087 exprNode_unparse (e1)),
11091 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
11093 ctype t2 = exprNode_getType (e2);
11094 sRef sr = sRef_getRootBase (e1->sref);
11095 ctype ct = sRef_getType (sr);
11097 if (ctype_isAbstract (t2)
11098 && !ctype_isNumAbstract (t2)
11099 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
11101 /* it is immutable, okay to reference */
11102 goto donerepexpose;
11105 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
11107 sRef s2b = sRef_getRootBase (e2->sref);
11108 sRef s1 = e1->sref;
11109 sRef s1b = sRef_getRootBase (s1);
11112 aliases = usymtab_canAlias (e2->sref);
11114 if (!sRef_similar (s2b, s1b)
11115 && !sRef_isExposed (s1)
11116 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
11118 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
11119 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
11120 && !sRef_isExposed (s2b))
11122 if (sRef_isIReference (e2->sref))
11127 ("Assignment of mutable component of parameter %q "
11128 "to component of abstract type %s exposes rep: %s = %s",
11129 sRef_unparse (s2b),
11130 ctype_unparse (ct),
11131 exprNode_unparse (e1), exprNode_unparse (e2)),
11138 message ("Assignment of mutable parameter %q to "
11139 "component of abstract type %s exposes rep: %s = %s",
11140 sRef_unparse (s2b),
11141 ctype_unparse (ct),
11142 exprNode_unparse (e1), exprNode_unparse (e2)),
11147 if (sRef_isFileOrGlobalScope (s2b))
11151 message ("Assignment of global %q to component of "
11152 "abstract type %s exposes rep: %s = %s",
11153 sRef_unparse (s2b),
11154 ctype_unparse (ct),
11155 exprNode_unparse (e1), exprNode_unparse (e2)),
11159 sRefSet_realElements (aliases, ysr)
11161 sRef base = sRef_getRootBase (ysr);
11163 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
11164 || sRef_sameName (base, s1b))
11166 ; /* error already reported or same sref */
11170 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
11172 } end_sRefSet_realElements;
11174 sRefSet_free (aliases);
11181 ** function variables don't really work...
11184 if (!ctype_isFunction (ctype_realType (e2->typ)))
11188 DPRINTF (("Check init: %s / %s",
11189 exprNode_unparse (e1), exprNode_unparse (e2)));
11190 transferChecks_initialization (e1, e2);
11194 transferChecks_assign (e1, e2);
11199 sRef fref = e2->sref;
11201 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
11202 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
11204 /* Need to typecheck the annotation on the parameters */
11206 if (ctype_isRealFunction (e1->typ)) {
11207 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
11208 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
11210 if (!uentryList_isMissingParams (e1p)
11211 && !uentryList_isMissingParams (e2p)
11212 && uentryList_size (e1p) > 0) {
11213 if (uentryList_size (e1p) == uentryList_size (e2p)) {
11216 uentryList_elements (e1p, el1) {
11219 el2 = uentryList_getN (e2p, n);
11221 uentry_checkMatchParam (el1, el2, n, e2);
11222 } end_uentryList_elements;
11228 if (exprNode_isStringLiteral (e2))
11230 exprNode_checkStringLiteralLength (exprNode_getType (e1), e2);
11233 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
11239 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
11240 updateAliases (e1, e2);
11245 checkMacroParen (exprNode e)
11247 if (exprNode_isError (e) || e->kind == XPR_CAST)
11253 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
11257 message ("Macro parameter used without parentheses: %s",
11258 exprNode_unparse (e)),
11265 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
11269 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
11273 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
11280 ** if e2 is a parameter or global derived location which
11281 ** can be modified (that is, e2 is a mutable abstract type,
11282 ** or a derived pointer), then e1 can alias e2.
11284 ** e1 can alias everything which e2 can alias.
11286 ** Also, if e1 is guarded, remove from guard sets!
11289 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
11291 if (!context_inProtectVars ())
11294 ** depends on types of e1 and e2
11297 sRef s1 = e1->sref;
11298 sRef s2 = e2->sref;
11299 ctype t1 = exprNode_getType (e1);
11301 /* handle pointer sRefs, record fields, arrays, etc... */
11303 if (!ctype_isRealSU (t1))
11305 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
11306 sRef_copyRealDerivedComplete (s1, s2);
11311 ** Fields should alias
11314 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
11317 if (ctype_isMutable (t1) && sRef_isKnown (s1))
11319 usymtab_clearAlias (s1);
11320 usymtab_addMustAlias (s1, s2);
11321 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
11325 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
11328 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
11330 usymtab_unguard (s1);
11335 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
11337 if (exprNode_isDefined (e))
11339 e->loc = fileloc_update (e->loc, loc);
11343 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
11349 static void checkUniqueParams (exprNode fcn,
11350 /*@notnull@*/ exprNode current,
11352 int paramno, uentry ucurrent)
11355 sRef thisref = exprNode_getSref (current);
11358 ** Check if any argument could match this argument.
11361 exprNodeList_elements (args, icurrent)
11365 if (iparamno != paramno)
11367 sRef sr = exprNode_getSref (icurrent);
11369 if (sRef_similarRelaxed (thisref, sr))
11371 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
11376 ("Parameter %d (%s) to function %s is declared %s but "
11377 "is aliased by parameter %d (%s)",
11379 exprNode_unparse (current),
11380 exprNode_unparse (fcn),
11381 alkind_unparse (uentry_getAliasKind (ucurrent)),
11382 iparamno, exprNode_unparse (icurrent)),
11388 sRefSet aliases = usymtab_canAlias (sr);
11390 sRefSet_allElements (aliases, asr)
11392 if (ctype_isUnknown (sRef_getType (thisref)))
11394 sRef_setType (thisref, uentry_getType (ucurrent));
11397 if (sRef_similarRelaxed (thisref, asr))
11399 if (sRef_isExternal (asr))
11401 if (sRef_isLocalState (thisref))
11407 sRef base = sRef_getRootBase (asr);
11409 if (!sRef_similar (sRef_getBase (asr), thisref))
11411 if (sRef_isUnique (base) || sRef_isOnly (base)
11412 || sRef_isKept (base)
11413 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
11414 || (sRef_isAddress (thisref)
11415 && sRef_isLocalVar (sRef_getRootBase (thisref))))
11417 ; /* okay, no error */
11422 (FLG_MAYALIASUNIQUE,
11424 ("Parameter %d (%s) to function %s is declared %s but "
11425 "may be aliased externally by parameter %d (%s)",
11427 exprNode_unparse (current),
11428 exprNode_unparse (fcn),
11429 alkind_unparse (uentry_getAliasKind (ucurrent)),
11430 iparamno, exprNode_unparse (icurrent)),
11441 ("Parameter %d (%s) to function %s is declared %s but "
11442 "is aliased externally by parameter %d (%s) through "
11445 exprNode_unparse (current),
11446 exprNode_unparse (fcn),
11447 alkind_unparse (uentry_getAliasKind (ucurrent)),
11448 iparamno, exprNode_unparse (icurrent),
11449 sRef_unparse (asr)),
11453 } end_sRefSet_allElements;
11454 sRefSet_free (aliases);
11457 } end_exprNodeList_elements;
11460 long exprNode_getLongValue (exprNode e)
11464 if (exprNode_hasValue (e) && multiVal_isInt (exprNode_getValue (e)))
11466 value = multiVal_forceInt (exprNode_getValue (e));
11470 value = 0; /* Unknown value */
11476 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
11479 ** Returns the location of the sequence point following e.
11481 ** Only works for statements (for now).
11484 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
11485 lltok t = exprData_getUopTok (e->edata);
11486 return fileloc_copy(lltok_getLoc (t));
11488 /* drl possible problem : warning fix
11489 llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
11491 return fileloc_undefined;
11495 exprNode exprNode_createNew(ctype c)
11499 ret = exprNode_createPlain (c);
11504 bool exprNode_isInitBlock (exprNode e)
11506 return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);
11509 /*drl 3/2/2003 moved this function out of constraint.c */
11510 exprNode exprNode_copyConstraints (/*@returned@*/ exprNode dst, exprNode src)
11513 llassert (exprNode_isDefined (dst) );
11514 llassert (exprNode_isDefined (src) );
11516 constraintList_free (dst->ensuresConstraints);
11517 constraintList_free (dst->requiresConstraints);
11518 constraintList_free (dst->trueEnsuresConstraints);
11519 constraintList_free (dst->falseEnsuresConstraints);
11521 dst->ensuresConstraints = constraintList_copy (src->ensuresConstraints);
11522 dst->requiresConstraints = constraintList_copy (src->requiresConstraints);
11523 dst->trueEnsuresConstraints = constraintList_copy (src->trueEnsuresConstraints);
11524 dst->falseEnsuresConstraints = constraintList_copy (src->falseEnsuresConstraints);
11528 void exprNode_revealState (exprNode e)
11530 if (exprNode_isDefined (e)) {
11531 llmsg (message ("%s: State of %s: %s", fileloc_unparse (exprNode_loc (e)),
11532 exprNode_unparse (e), sRef_unparseFull (e->sref)));
11534 llmsg (message ("%s: Reveal state undefined", fileloc_unparse (g_currentloc)));