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;
1934 case 'X': /* unsigned int */
1935 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1936 /*@switchbreak@*/ break;
1943 /* printf is double, scanf is float! */
1945 if (modifier == 'l')
1947 expecttype = ctype_makePointer (ctype_double);
1949 else if (modifier == 'L')
1951 expecttype = ctype_makePointer (ctype_ldouble);
1955 llassert (modifier == '\0');
1956 expecttype = ctype_makePointer (ctype_float);
1958 /*@switchbreak@*/ break;
1960 case 'c': /* int converted to char (check its a char?) */
1961 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1962 /*@switchbreak@*/ break;
1964 case 's': /* string */
1965 expecttype = ctype_string;
1966 /*@switchbreak@*/ break;
1970 while (((key = *(++code)) != ']')
1973 codetext = cstring_appendChar (codetext, key);
1974 fileloc_incColumn (formatloc);
1980 (message ("Bad character set format: %s",
1981 cstring_fromChars (origcode)));
1984 expecttype = ctype_string;
1985 /*@switchbreak@*/ break;
1988 case 'p': /* pointer */
1991 message ("Format code should not be used in scanf: %s",
1992 cstring_fromChars (origcode)),
1993 fileloc_isDefined (formatloc)
1994 ? formatloc : g_currentloc);
1996 expecttype = ctype_unknown;
1997 /*@switchbreak@*/ break;
1999 case 'n': /* pointer to int, modified by call! */
2000 expecttype = ctype_makePointer (ctype_int);
2001 /*@switchbreak@*/ break;
2004 expecttype = ctype_unknown;
2008 message ("Unrecognized format code: %s",
2009 cstring_fromChars (origcode)),
2010 fileloc_isDefined (formatloc)
2011 ? formatloc : g_currentloc);
2013 /*@switchbreak@*/ break;
2016 if (!(exprNode_matchArgType (expecttype, a)))
2018 if (ctype_isVoidPointer (expecttype)
2019 && ctype_isRealAbstract (a->typ)
2020 && (context_getFlag (FLG_ABSTVOIDP)))
2026 if (llgenformattypeerror
2027 (expecttype, exprNode_undefined,
2029 message ("Format argument %d to %q (%%%s) expects "
2032 uentry_getName (fcn),
2033 codetext, expecttype,
2034 a->typ, exprNode_unparse (a)),
2037 if (fileloc_isDefined (formatloc)
2038 && context_getFlag (FLG_SHOWCOL))
2041 (cstring_makeLiteral
2042 ("Corresponding format code"),
2049 uentry_setType (outArg, expecttype);
2050 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
2051 uentry_setType (outArg, ctype_unknown);
2052 uentry_fixupSref (outArg);
2056 exprNode_checkCallModifyVal (a->sref, args, f, ret);
2061 /* a->sref = sRef_undefined; */
2068 cstring_free (codetext);
2073 voptgenerror (FLG_TYPE,
2074 message ("Format string for %q has %d arg%&, given %d",
2075 uentry_getName (fcn), i - argno, nargs - argno),
2081 /* no checking possible for compile-time unknown format strings */
2084 fileloc_free (formatloc);
2088 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
2091 /*@unused@*/ int argno)
2094 ** the last argument before the elips is the format string
2097 int nargs = exprNodeList_size (args);
2102 a = exprNodeList_getN (args, argno - 1);
2103 formatloc = fileloc_copy (exprNode_loc (a));
2105 if (ctype_isUnknown (cstringType)) {
2106 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
2108 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
2112 if (ctype_isUnknown (ctypeType)) {
2113 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
2115 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
2119 if (ctype_isUnknown (filelocType)) {
2120 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
2122 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
2126 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
2127 && exprNode_knownStringValue (a))
2129 cstring format = multiVal_forceString (exprNode_getValue (a));
2130 char *code = cstring_toCharsSafe (format);
2133 nargs = exprNodeList_size (args);
2135 while ((code = strchr (code, '%')) != NULL)
2137 char *origcode = code;
2138 char key = *(++code);
2139 cstring codetext = cstring_newEmpty ();
2140 bool isOnly = FALSE;
2142 codetext = cstring_appendChar (codetext, key);
2144 fileloc_addColumn (formatloc, code - ocode);
2146 while (key >= '0' && key <= '9')
2149 codetext = cstring_appendChar (codetext, key);
2150 fileloc_incColumn (formatloc);
2154 fileloc_incColumn (formatloc);
2158 if (key == '&') /* plural marker */
2167 message ("Message missing format arg %d (%%%s): \"%s\"",
2168 i + 1, codetext, format),
2174 a = exprNodeList_getN (args, i);
2178 if (!exprNode_isError (a))
2182 /*@-loopswitchbreak@*/
2188 expecttype = ctype_char; break;
2190 expecttype = cstringType; break;
2192 expecttype = cstringType; isOnly = TRUE; break;
2194 expecttype = cstringType; isOnly = TRUE; break;
2195 case 'd': expecttype = ctype_int; break;
2196 case 'u': expecttype = ctype_uint; break;
2197 case 'w': expecttype = ctype_ulint; break;
2198 case 'f': expecttype = ctype_float; break;
2199 case 'b': expecttype = ctype_bool; break;
2200 case 't': expecttype = ctypeType; break;
2202 expecttype = ctype_makePointer (ctype_void);
2203 /* need not be defined */
2204 uentry_setDefState (regArg, SS_RELDEF);
2205 sRef_setPosNull (uentry_getSref (regArg),
2208 /*@switchbreak@*/ break;
2209 case 'l': expecttype = filelocType; break;
2210 case '&': /* a wee bit of a hack methinks */
2211 expecttype = ctype_int;
2213 case 'r': expecttype = ctype_bool; break;
2215 expecttype = ctype_unknown;
2218 message ("Unrecognized format code: %s",
2219 cstring_fromChars (origcode)),
2220 fileloc_isDefined (formatloc)
2221 ? formatloc : g_currentloc);
2224 /*@=loopswitchbreak@*/
2226 if (!(exprNode_matchArgType (expecttype, a)))
2228 if (ctype_isVoidPointer (expecttype)
2229 && ctype_isRealAbstract (a->typ)
2230 && (context_getFlag (FLG_ABSTVOIDP)))
2236 if (llgenformattypeerror
2237 (expecttype, exprNode_undefined,
2239 message ("Format argument %d to %q (%%%s) expects "
2242 uentry_getName (fcn),
2243 codetext, expecttype,
2244 a->typ, exprNode_unparse (a)),
2247 if (fileloc_isDefined (formatloc)
2248 && context_getFlag (FLG_SHOWCOL))
2251 (cstring_makeLiteral
2252 ("Corresponding format code"),
2259 if (ctype_equal (expecttype, cstringType))
2263 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2264 uentry_fixupSref (csOnlyArg);
2268 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2269 uentry_fixupSref (csArg);
2274 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2275 uentry_fixupSref (regArg);
2281 cstring_free (codetext);
2286 voptgenerror (FLG_TYPE,
2287 message ("Format string for %q has %d arg%&, given %d",
2288 uentry_getName (fcn), i - argno, nargs -argno),
2294 /* no checking possible for compile-time unknown format strings */
2297 fileloc_free (formatloc);
2301 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2302 /*@notnull@*/ exprNode e2,
2308 bool hadUncon = FALSE;
2310 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
2311 sRefSet_hasUnconstrained (sets2))
2314 (FLG_EVALORDERUNCON,
2316 ("Expression may have undefined behavior (%q used in right operand "
2317 "may set global variable %q used in left operand): %s %s %s",
2318 sRefSet_unparseUnconstrained (sets2),
2319 sRef_unparse (sRef_getRootBase (e1->sref)),
2320 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2324 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
2325 sRefSet_hasUnconstrained (sets1))
2328 (FLG_EVALORDERUNCON,
2330 ("Expression has undefined behavior (%q used in left operand "
2331 "may set global variable %q used in right operand): %s %s %s",
2332 sRefSet_unparseUnconstrained (sets1),
2333 sRef_unparse (e2->sref),
2334 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2338 sRefSet_realElements (e1->uses, sr)
2340 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2345 ("Expression has undefined behavior (left operand uses %q, "
2346 "modified by right operand): %s %s %s",
2348 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2351 } end_sRefSet_realElements;
2353 sRefSet_realElements (sets1, sr)
2355 if (sRef_isMeaningful (sr))
2357 if (sRef_same (sr, e2->sref))
2362 ("Expression has undefined behavior (value of right operand "
2363 "modified by left operand): %s %s %s",
2364 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2367 else if (sRefSet_member (e2->uses, sr))
2372 ("Expression has undefined behavior (left operand modifies %q, "
2373 "used by right operand): %s %s %s",
2375 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2380 if (sRefSet_member (sets2, sr))
2382 if (sRef_isUnconstrained (sr))
2390 hadUncon = optgenerror
2391 (FLG_EVALORDERUNCON,
2393 ("Expression may have undefined behavior. Left operand "
2394 "calls %q; right operand calls %q. The unconstrained "
2395 "functions may modify global state used by "
2396 "the other operand): %s %s %s",
2397 sRefSet_unparseUnconstrained (sets1),
2398 sRefSet_unparseUnconstrained (sets2),
2399 exprNode_unparse (e1), lltok_unparse (op),
2400 exprNode_unparse (e2)),
2409 ("Expression has undefined behavior (both "
2410 "operands modify %q): %s %s %s",
2412 exprNode_unparse (e1),
2413 lltok_unparse (op), exprNode_unparse (e2)),
2419 } end_sRefSet_realElements;
2422 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2424 bool hasError = FALSE;
2426 if (exprNode_isError (e1) || exprNode_isError (e2))
2431 if (sRefSet_member (e2->sets, e1->sref))
2433 if (e2->kind == XPR_CALL)
2439 hasError = optgenerror
2441 message ("Expression has undefined behavior "
2442 "(value of left operand %s is modified "
2443 "by right operand %s): %s %s %s",
2444 exprNode_unparse (e1),
2445 exprNode_unparse (e2),
2446 exprNode_unparse (e1), lltok_unparse (op),
2447 exprNode_unparse (e2)),
2452 if (context_getFlag (FLG_EVALORDERUNCON))
2454 if (sRefSet_member (e2->msets, e1->sref))
2456 if (e2->kind == XPR_CALL)
2462 hasError = optgenerror
2465 ("Expression has undefined behavior (value of left "
2466 "operand may be modified by right operand): %s %s %s",
2467 exprNode_unparse (e1), lltok_unparse (op),
2468 exprNode_unparse (e2)),
2476 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2478 if (context_maybeSet (FLG_EVALORDERUNCON))
2480 checkExpressionDefinedAux (e1, e2, e1->msets,
2481 e2->msets, op, FLG_EVALORDERUNCON);
2486 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2489 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2490 exprNodeList args, bool isIter, exprNode ret)
2494 if (!exprNode_isError (f))
2496 if (!uentryList_isMissingParams (cl))
2498 int nargs = exprNodeList_size (args);
2499 int expectargs = uentryList_size (cl);
2503 if (expectargs == 0)
2511 message ("Iter %q invoked with %d args, "
2513 uentry_getName (fcn),
2521 message ("Function %s called with %d args, "
2523 exprNode_unparse (f), nargs),
2530 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2532 exprNodeList_reset (args);
2534 uentryList_elements (cl, current)
2536 ctype ct = uentry_getType (current);
2539 if (ctype_isElips (ct))
2542 ** do special checking for printf/scanf library functions
2544 ** this is kludgey code, just for handling the special case
2548 if (uentry_isPrintfLike (fcn))
2550 checkPrintfArgs (f, fcn, args, ret, i);
2553 else if (uentry_isScanfLike (fcn))
2555 checkScanfArgs (f, fcn, args, ret, i);
2558 else if (uentry_isMessageLike (fcn))
2560 checkMessageArgs (f, fcn, args, i);
2565 llassert (!uentry_isSpecialFunction (fcn));
2568 nargs = expectargs; /* avoid errors */
2573 if (i >= nargs) break;
2575 a = exprNodeList_current (args);
2576 exprNodeList_advance (args);
2580 if (exprNode_isError (a))
2587 probably necessary? I'm not sure about this one
2588 checkMacroParen (a);
2591 f->guards = guardSet_union (f->guards, a->guards);
2593 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2595 if (!(exprNode_matchArgType (ct, a)))
2597 DPRINTF (("Args mismatch!"));
2599 if (ctype_isVoidPointer (ct)
2600 && (ctype_isPointer (a->typ)
2601 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2606 ("Pointer to abstract type (%t) used "
2608 "(arg %d to %q): %s",
2610 uentry_getName (fcn),
2611 exprNode_unparse (a)),
2619 (ct, exprNode_undefined,
2622 ("Iter %q expects arg %d to "
2623 "be %t gets %t: %s",
2624 uentry_getName (fcn),
2625 i, ct, a->typ, exprNode_unparse (a)),
2636 ("Function %q expects arg %d to be %t gets %t: %s",
2637 uentry_getName (fcn),
2638 i, ct, a->typ, exprNode_unparse (a)),
2641 DPRINTF (("Types: %s / %s",
2643 ctype_unparse (a->typ)));
2647 ** Clear null marker for abstract types.
2648 ** (It is not revealed, so suppress future messages.)
2651 if (ctype_isAbstract (a->typ))
2653 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2660 } end_uentryList_elements ;
2663 if (expectargs != nargs) /* note: not != since we may have ... */
2665 if (ctype_isElips (last))
2669 message ("Function %s called with %d args, expects at least %d",
2670 exprNode_unparse (f),
2671 nargs, expectargs - 1),
2680 message ("Iter %q invoked with %d args, expects %d",
2681 uentry_getName (fcn), nargs, expectargs),
2688 message ("Function %s called with %d args, expects %d",
2689 exprNode_unparse (f),
2702 ** Check for undefined code sequences in function arguments:
2704 ** one parameter sets something used by another parameter
2705 ** one parameter sets something set by another parameter
2709 checkSequencingOne (exprNode f, exprNodeList args,
2710 /*@notnull@*/ exprNode el, int argno)
2713 ** Do second loop, iff +undefunspec
2717 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2719 for (checkloop = 0; checkloop < numloops; checkloop++)
2725 thissets = el->sets;
2729 llassert (checkloop == 1);
2730 thissets = el->msets;
2733 sRefSet_realElements (thissets, thisset)
2737 /*@access exprNodeList@*/
2738 for (j = 0; j < args->nelements; j++)
2740 exprNode jl = args->elements[j];
2741 int thisargno = j + 1;
2743 if (thisargno != argno && exprNode_isDefined (jl))
2745 sRefSet otheruses = jl->uses;
2747 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
2748 sRefSet_hasUnconstrained (thissets))
2751 (FLG_EVALORDERUNCON,
2754 ("%q used in argument %d may set "
2755 "global variable %q used by argument %d: %s(%q)",
2756 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2759 sRef_unparse (sRef_getRootBase (jl->sref)),
2761 exprNode_unparse (f), exprNodeList_unparse (args)),
2765 if (sRefSet_member (otheruses, thisset))
2767 if (sRef_isUnconstrained (thisset))
2770 (FLG_EVALORDERUNCON,
2772 ("Unconstrained functions used in arguments %d (%q) "
2773 "and %d (%s) may modify "
2774 "or use global state in undefined way: %s(%q)",
2776 sRefSet_unparseUnconstrainedPlain (otheruses),
2778 sRef_unconstrainedName (thisset),
2779 exprNode_unparse (f),
2780 exprNodeList_unparse (args)),
2788 ("Argument %d modifies %q, used by argument %d "
2789 "(order of evaluation of actual parameters is "
2790 "undefined): %s(%q)",
2791 argno, sRef_unparse (thisset), thisargno,
2792 exprNode_unparse (f), exprNodeList_unparse (args)),
2798 sRefSet othersets = jl->sets;
2800 if (sRefSet_member (othersets, thisset))
2802 if (sRef_isUnconstrained (thisset))
2805 (FLG_EVALORDERUNCON,
2807 ("Unconstrained functions used in "
2808 "arguments %d (%q) and %d (%s) may modify "
2809 "or use global state in undefined way: %s(%q)",
2811 sRefSet_unparseUnconstrainedPlain (othersets),
2813 sRef_unconstrainedName (thisset),
2814 exprNode_unparse (f), exprNodeList_unparse (args)),
2822 ("Argument %d modifies %q, set by argument %d (order of"
2823 " evaluation of actual parameters is undefined): %s(%q)",
2824 argno, sRef_unparse (thisset), thisargno,
2825 exprNode_unparse (f), exprNodeList_unparse (args)),
2832 /*@noaccess exprNodeList@*/
2833 } end_sRefSet_realElements;
2838 checkSequencing (exprNode f, exprNodeList args)
2840 if (exprNodeList_size (args) > 1)
2845 /*@access exprNodeList*/
2847 for (i = 0; i < args->nelements; i++)
2849 el = args->elements[i];
2851 if (!exprNode_isError (el))
2853 checkSequencingOne (f, args, el, i + 1);
2856 /*@noaccess exprNodeList*/
2861 ** requires le = exprNode_getUentry (f)
2865 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2866 uentry le, exprNodeList args,
2867 /*@notnull@*/ exprNode ret, int specialArgs)
2869 bool isSpec = FALSE;
2870 bool hasMods = FALSE;
2872 globSet usesGlobs = globSet_undefined;
2873 sRefSet mods = sRefSet_undefined;
2874 bool freshMods = FALSE;
2875 uentryList params = uentryList_undefined;
2877 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2880 ** check globals and modifies
2885 if (!uentry_isValid (le))
2887 ctype fr = ctype_realType (f->typ);
2889 if (ctype_isFunction (fr))
2891 params = ctype_argsFunction (fr);
2895 params = uentryList_missingParams;
2898 if (!context_getFlag (FLG_MODNOMODS)
2899 && !context_getFlag (FLG_GLOBUNSPEC))
2901 checkUnspecCall (f, params, args);
2907 fname = uentry_rawName (le);
2911 if (uentry_isFunction (le))
2913 params = uentry_getParams (le);
2914 mods = uentry_getMods (le);
2915 hasMods = uentry_hasMods (le);
2916 usesGlobs = uentry_getGlobs (le);
2917 isSpec = uentry_isSpecified (le);
2919 else /* not a function */
2921 ctype ct = ctype_realType (uentry_getType (le));
2923 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2924 ("checkModGlobs: uentry not a function: %s",
2925 uentry_unparse (le)));
2927 params = ctype_argsFunction (ct);
2928 return; /* No checking for non-function */
2937 globSet_allElements (usesGlobs, el)
2939 if (sRef_isValid (el))
2941 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2943 context_usedGlobal (el);
2944 exprNode_checkUse (f, el, f->loc);
2946 if (context_checkInternalUse ())
2948 if (!context_globAccess (el))
2950 if (sRef_isSystemState (el)
2951 && !context_getFlag (FLG_MODFILESYSTEM))
2960 ("Called procedure %s may access %q, but "
2961 "globals list does not include globals %s",
2962 exprNode_unparse (f),
2964 cstring_makeLiteralTemp (sRef_isInternalState (el)
2972 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2978 uentry gle = sRef_getUentry (el);
2979 sRef sr = sRef_updateSref (el);
2981 if (sRef_isUndefGlob (el))
2983 sRef_setDefined (sr, f->loc);
2984 exprNode_checkSet (f, sr);
2992 if (sRef_isAllocated (el))
2994 exprNode_checkSet (f, sr);
2998 if (sRef_isStateUndefined (sr))
3003 ("%s %q used by function undefined before call: %s",
3004 sRef_getScopeName (sr),
3006 exprNode_unparse (f)),
3008 sRef_setDefined (sr, f->loc);
3010 exprNode_checkUse (f, sr, f->loc);
3013 checkGlobUse (gle, TRUE, f);
3016 if (sRef_isKilledGlob (el))
3018 sRef_kill (sr, f->loc);
3019 context_usedGlobal (sr);
3023 } end_globSet_allElements;
3029 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
3031 sRefSet smods = sRefSet_undefined;
3034 ** NEED to check for modifies anything
3038 ** check each sRef that called function modifies (ml), is
3044 sRefSet_allElements (mods, s) /* s is something which may be modified */
3046 DPRINTF (("Check modify: %s", sRef_unparse (s)));
3048 if (sRef_isKindSpecial (s))
3050 if (sRef_isSpecInternalState (s))
3052 if (context_getFlag (FLG_MODINTERNALSTRICT))
3054 exprNode_checkCallModifyVal (s, args, f, ret);
3058 sRefSet mmods = context_modList ();
3060 sRefSet_allElements (mmods, el)
3062 if (sRef_isInternalState (el))
3064 sRef_setModified (el);
3066 } end_sRefSet_allElements ;
3071 exprNode_checkCallModifyVal (s, args, f, ret);
3076 sRef rb = sRef_getRootBase (s);
3078 if (sRef_isFileOrGlobalScope (rb))
3080 context_usedGlobal (rb);
3083 if (sRef_isFileStatic (s)
3084 && !fileId_equal (fileloc_fileId (f->loc),
3085 fileloc_fileId (uentry_whereDefined (le))))
3087 smods = sRefSet_insert (smods, s);
3091 exprNode_checkCallModifyVal (s, args, f, ret);
3094 } end_sRefSet_allElements;
3099 ** Static elements in modifies set can have nasty consequences.
3100 ** (I think...have not been able to reproduce a possible bug.)
3103 if (!sRefSet_isDefined (smods))
3105 mods = sRefSet_newCopy (mods);
3108 sRefSet_allElements (smods, el)
3110 bool res = sRefSet_delete (mods, el);
3113 } end_sRefSet_allElements;
3115 sRefSet_free (smods);
3120 else if (sRefSet_isDefined (mods))
3121 { /* just check observers */
3124 sRefSet_allElements (mods, s) /* s is something which may be modified */
3126 sRef rb = sRef_getRootBase (s);
3130 if (sRef_isParam (rb))
3132 sRef b = sRef_fixBaseParam (s, args);
3134 if (sRef_isObserver (b))
3136 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
3140 message ("Function call may modify observer%q: %s",
3141 sRef_unparsePreOpt (b), exprNode_unparse (e)),
3144 sRef_showExpInfo (b);
3148 } end_sRefSet_allElements;
3152 if (!hasMods) /* no specified modifications */
3154 if (context_getFlag (FLG_MODOBSERVERUNCON))
3156 exprNodeList_elements (args, e)
3158 if (exprNode_isDefined (e))
3160 sRef s = exprNode_getSref (e);
3162 if (sRef_isObserver (s)
3163 && ctype_isMutable (sRef_getType (s)))
3166 (FLG_MODOBSERVERUNCON,
3168 ("Call to unconstrained function %s may modify observer%q: %s",
3169 exprNode_unparse (f),
3170 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3173 sRef_showExpInfo (s);
3177 } end_exprNodeList_elements;
3182 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3184 ret->uses = sRefSet_union (ret->uses, f->uses);
3185 ret->sets = sRefSet_union (ret->sets, f->sets);
3186 ret->msets = sRefSet_union (ret->msets, f->msets);
3191 ** Spurious errors reported, because splint can't tell
3192 ** mods must be fresh if freshMods is true.
3195 /*@i@*/ sRefSet_free (mods);
3201 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3203 if (uentry_isVar (glob))
3205 if (context_inFunctionLike ())
3207 sRef sr = uentry_getSref (glob);
3209 context_usedGlobal (sr);
3211 if (context_checkGlobUse (glob))
3213 if (!context_globAccess (sr))
3219 message ("Called procedure %s may access %s %q",
3220 exprNode_unparse (e),
3221 sRef_unparseScope (sr),
3222 uentry_getName (glob)),
3229 message ("Undocumented use of %s %s",
3230 sRef_unparseScope (sr),
3231 exprNode_unparse (e)),
3240 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3245 reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
3247 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3248 exprNode_unparse (f), exprNodeList_unparse (args),
3249 uentry_unparseFull (le),
3250 stateClauseList_unparse (uentry_getStateClauseList (le))));
3252 if (uentry_isValid (le) && uentry_isFunction (le))
3254 stateClauseList sclauses = uentry_getStateClauseList (le);
3256 if (stateClauseList_isDefined (sclauses))
3258 DPRINTF (("Reflect ensures: %s / %s / %s",
3259 uentry_unparse (le),
3260 exprNode_unparse (f), exprNodeList_unparse (args)));
3262 stateClauseList_elements (sclauses, cl)
3264 if (stateClause_hasEnsures (cl))
3266 /* Same in usymtab.c:1904 */
3267 if (stateClause_setsMetaState (cl))
3269 qual q = stateClause_getMetaQual (cl);
3270 annotationInfo ainfo = qual_getAnnotationInfo (q);
3271 metaStateInfo minfo = annotationInfo_getState (ainfo);
3272 cstring key = metaStateInfo_getName (minfo);
3273 int mvalue = annotationInfo_getValue (ainfo);
3275 sRefSet osrs = sRefSet_undefined;
3278 if (stateClause_isGlobal (cl))
3280 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3285 srs = stateClause_getRefs (cl);
3288 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3291 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3293 sRefSet_elements (srs, sel)
3297 if (sRef_isResult (sRef_getRootBase (sel)))
3299 s = exprNode_getSref (ret);
3303 s = sRef_fixBaseParam (sel, args);
3306 DPRINTF (("Reflecting state clause on: %s / %s",
3307 sRef_unparse (sel), sRef_unparse (s)));
3309 sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3310 } end_sRefSet_elements;
3312 sRefSet_free (osrs);
3316 sRefSet srs = stateClause_getRefs (cl);
3317 sRefModVal modf = stateClause_getEnsuresFunction (cl);
3318 int eparam = stateClause_getStateParameter (cl);
3320 llassert (modf != NULL);
3322 DPRINTF (("Reflect after clause: %s / %s",
3323 stateClause_unparse (cl),
3324 sRefSet_unparse (srs)));
3326 sRefSet_elements (srs, sel)
3330 DPRINTF (("elements: %s", sRef_unparse (sel)));
3331 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3333 if (sRef_isResult (sRef_getRootBase (sel)))
3335 DPRINTF (("Fix base: %s / %s",
3336 sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
3337 s = sRef_fixBase (sel, exprNode_getSref (ret));
3338 DPRINTF (("==> %s", sRef_unparseFull (s)));
3342 s = sRef_fixBaseParam (sel, args);
3345 DPRINTF (("elements: %s", sRef_unparse (s)));
3346 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3348 DPRINTF (("Reflecting state clause on: %s / %s",
3349 sRef_unparseFull (sel), sRef_unparseFull (s)));
3351 /* evans 2001-08-24 - added aliasSetCompleteParam */
3352 sRef_aliasSetCompleteParam (modf, s, eparam, exprNode_loc (f));
3354 DPRINTF (("After reflecting state clause on: %s / %s",
3355 sRef_unparseFull (sel), sRef_unparseFull (s)));
3356 } end_sRefSet_elements;
3359 } end_stateClauseList_elements ;
3362 DPRINTF (("Here: %s / %s",
3363 uentry_unparseFull (le),
3364 bool_unparse (uentry_hasMetaStateEnsures (le))));
3366 if (uentry_hasMetaStateEnsures (le))
3368 fileloc loc = exprNode_loc (f);
3370 metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3372 metaStateConstraintList_elements (mscl, msc)
3374 metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3375 metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3376 metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
3377 cstring key = metaStateInfo_getName (msinfo);
3378 sRef mlsr = metaStateSpecifier_getSref (msspec);
3380 sRef lastref = sRef_undefined;
3381 stateValue sval = stateValue_undefined;
3383 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3384 metaStateConstraint_unparse (msc)));
3385 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3387 if (sRef_isResult (sRef_getRootBase (mlsr)))
3389 s = exprNode_getSref (ret);
3393 s = sRef_fixBaseParam (mlsr, args);
3396 DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3398 while (metaStateExpression_isDefined (msexpr))
3400 metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
3401 metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
3404 DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3406 if (metaStateExpression_isMerge (msexpr))
3408 msexpr = metaStateExpression_getRest (msexpr);
3412 msexpr = metaStateExpression_undefined;
3415 if (metaStateInfo_isDefined (msi))
3417 /* Must match lhs state */
3418 llassert (metaStateInfo_equal (msinfo, msi));
3421 if (metaStateSpecifier_isElipsis (ms))
3424 ** For elipsis, we need to merge all the relevant elipsis parameters
3428 uentryList params = uentry_getParams (le);
3429 int paramno = uentryList_size (params) - 1;
3431 if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
3435 message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3436 uentry_getName (le)),
3437 uentry_whereLast (le));
3438 /*@innerbreak@*/ break;
3441 while (paramno < exprNodeList_size (args))
3443 exprNode arg = exprNodeList_getN (args, paramno);
3444 fs = exprNode_getSref (arg);
3445 DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3447 /* cut and pasted... gack*/
3448 if (stateValue_isDefined (sval))
3450 /* Use combination table to merge old state value with new one: */
3451 stateValue tval = sRef_getMetaStateValue (fs, key);
3453 if (stateValue_isDefined (tval))
3455 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3456 cstring msg = cstring_undefined;
3457 int nval = stateCombinationTable_lookup (sctable,
3458 stateValue_getValue (sval),
3459 stateValue_getValue (tval),
3461 DPRINTF (("Combining: %s + %s -> %d",
3462 stateValue_unparseValue (sval, msinfo),
3463 stateValue_unparseValue (tval, msinfo),
3466 if (nval == stateValue_error)
3471 ("Attributes merged in ensures clause in states that "
3472 "cannot be combined (%q is %q, %q is %q)%q",
3473 sRef_unparse (lastref),
3474 stateValue_unparseValue (sval, msinfo),
3476 stateValue_unparseValue (tval, msinfo),
3477 cstring_isDefined (msg) ?
3478 message (": %s", msg) : cstring_undefined),
3481 sRef_showMetaStateInfo (fs, key);
3485 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3486 loc = exprNode_loc (arg);
3490 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3495 sval = sRef_getMetaStateValue (fs, key);
3500 if (stateValue_isError (sval))
3502 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3511 msr = metaStateSpecifier_getSref (ms);
3514 llassert (sRef_isParam (sRef_getRootBase (msr)));
3515 fs = sRef_fixBaseParam (msr, args);
3517 if (stateValue_isDefined (sval))
3519 /* Use combination table to merge old state value with new one: */
3520 stateValue tval = sRef_getMetaStateValue (fs, key);
3522 if (stateValue_isDefined (tval))
3524 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3525 cstring msg = cstring_undefined;
3526 int nval = stateCombinationTable_lookup (sctable,
3527 stateValue_getValue (sval),
3528 stateValue_getValue (tval),
3530 DPRINTF (("Combining: %s + %s -> %d",
3531 stateValue_unparseValue (sval, msinfo),
3532 stateValue_unparseValue (tval, msinfo),
3535 if (nval == stateValue_error)
3540 ("Attributes merged in ensures clause in states that "
3541 "cannot be combined (%q is %q, %q is %q)%q",
3542 sRef_unparse (lastref),
3543 stateValue_unparseValue (sval, msinfo),
3545 stateValue_unparseValue (tval, msinfo),
3546 cstring_isDefined (msg)
3547 ? message (": %s", msg) : cstring_undefined),
3550 sRef_showMetaStateInfo (fs, key);
3554 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3558 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3563 sval = sRef_getMetaStateValue (fs, key);
3568 if (stateValue_isError (sval))
3570 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3575 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3577 if (stateValue_isDefined (sval))
3579 sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
3583 DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
3585 } end_metaStateConstraintList_elements ;
3587 metaStateConstraintList_free (mscl);
3593 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3595 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3596 exprNode_unparse (f), exprNodeList_unparse (args),
3597 uentry_unparseFull (le),
3598 stateClauseList_unparse (uentry_getStateClauseList (le))));
3600 if (uentry_isValid (le) && uentry_isFunction (le))
3602 stateClauseList sclauses = uentry_getStateClauseList (le);
3604 if (stateClauseList_isDefined (sclauses))
3606 DPRINTF (("Check requires: %s / %s / %s",
3607 uentry_unparse (le),
3608 exprNode_unparse (f), exprNodeList_unparse (args)));
3610 stateClauseList_elements (sclauses, cl)
3612 DPRINTF (("Check clause: %s / %s",
3613 stateClause_unparse (cl),
3614 bool_unparse (stateClause_hasRequires (cl))));
3616 if (stateClause_hasRequires (cl))
3618 sRefSet osrs = sRefSet_undefined;
3621 if (stateClause_isGlobal (cl))
3623 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3628 srs = stateClause_getRefs (cl);
3631 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3633 if (stateClause_setsMetaState (cl))
3635 qual q = stateClause_getMetaQual (cl);
3636 annotationInfo ainfo = qual_getAnnotationInfo (q);
3637 metaStateInfo minfo = annotationInfo_getState (ainfo);
3638 cstring key = metaStateInfo_getName (minfo);
3639 int mvalue = annotationInfo_getValue (ainfo);
3641 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3643 sRefSet_elements (srs, sel)
3645 sRef s = sRef_fixBaseParam (sel, args);
3647 if (sRef_isResult (sRef_getRootBase (sel)))
3653 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3654 sRef_unparseFull (sel), sRef_unparseFull (s),
3657 if (!sRef_checkMetaStateValue (s, key, mvalue))
3659 DPRINTF (("HERE: %s", sRef_unparse (s)));
3663 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3664 uentry_getName (le),
3665 sRef_isGlobalMarker (s)
3667 : message (" by %q", sRef_unparse (s)),
3668 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3670 stateClause_unparse (cl)),
3673 sRef_showAliasInfo (s);
3677 DPRINTF (("Error supressed!"));
3678 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3679 DPRINTF (("Context supress: %s",
3680 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3684 } end_sRefSet_elements;
3688 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3689 int eparam = stateClause_getStateParameter (cl);
3691 DPRINTF (("Reflect after clause: %s / %s",
3692 stateClause_unparse (cl),
3693 sRefSet_unparse (srs)));
3695 llassert (modf != NULL);
3697 sRefSet_elements (srs, sel)
3701 DPRINTF (("elements: %s", sRef_unparse (sel)));
3702 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3704 s = sRef_fixBaseParam (sel, args);
3706 DPRINTF (("elements: %s", sRef_unparse (s)));
3707 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3709 if (sRef_isResult (sRef_getRootBase (sel)))
3711 ; /* what do we do about results? */
3715 DPRINTF (("Reflecting state clause on: %s / %s",
3716 sRef_unparse (sel), sRef_unparse (s)));
3718 modf (s, eparam, exprNode_loc (f));
3720 } end_sRefSet_elements;
3723 sRefSet_free (osrs);
3725 } end_stateClauseList_elements ;
3730 static /*@only@*/ exprNode
3731 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3732 ctype t, /*@keep@*/ exprNodeList args)
3734 /* requires f is a non-error exprNode, with type function */
3735 cstring fname = exprNode_unparse (f);
3736 uentry le = exprNode_getUentry (f);
3737 exprNode ret = exprNode_createPartialCopy (f);
3742 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3744 ret->typ = ctype_getReturnType (t);
3745 ret->kind = XPR_CALL;
3747 ret->edata = exprData_makeCall (f, args);
3750 ** Order of these steps is very important!
3752 ** Must check for argument dependencies before messing up uses and sets.
3755 if (context_getFlag (FLG_EVALORDER))
3757 exprNodeList_elements (args, current)
3759 if (exprNode_isDefined (current))
3761 exprNode_addUse (current, current->sref);
3763 } end_exprNodeList_elements;
3765 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3767 checkSequencing (f, args);
3770 exprNodeList_elements (args, current)
3772 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3774 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3776 } end_exprNodeList_elements ;
3779 special = checkArgs (le, f, t, args, ret);
3780 checkGlobMods (f, le, args, ret, special);
3781 checkRequiresClause (le, f, args);
3784 if (uentry_isValid (le)
3785 && (uentry_isFunction (le)
3786 || (uentry_isVariable (le)
3787 && ctype_isFunction (uentry_getType (le)))))
3789 exitkind exk = uentry_getExitCode (le);
3791 /* f->typ is already set to the return type */
3793 DPRINTF (("Function: %s", uentry_unparseFull (le)));
3794 ret->sref = uentry_returnedRef (le, args, exprNode_loc (f));
3795 DPRINTF (("Returned: %s / %s",
3796 uentry_unparseFull (le),
3797 sRef_unparseFull (ret->sref)));
3799 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3801 qual nullPred = uentry_nullPred (le);
3803 if (qual_isTrueNull (nullPred))
3805 exprNode arg = exprNodeList_head (args);
3807 if (exprNode_isDefined (arg))
3809 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3812 else if (qual_isFalseNull (nullPred))
3814 exprNode arg = exprNodeList_head (args);
3816 if (exprNode_isDefined (arg))
3818 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3823 llassert (qual_isUnknown (nullPred));
3827 if (exitkind_isConditionalExit (exk))
3831 ** if (arg0) then { exit! } else { ; }
3833 ** if (arg0) then { ; } else { exit! }
3838 llassert (!exprNodeList_isEmpty (args));
3839 firstArg = exprNodeList_head (args);
3841 if (exprNode_isDefined (firstArg)
3842 && !guardSet_isEmpty (firstArg->guards))
3844 usymtab_trueBranch (guardSet_undefined);
3845 usymtab_altBranch (guardSet_undefined);
3847 if (exitkind_isTrueExit (exk))
3849 usymtab_popBranches (firstArg,
3850 exprNode_makeMustExit (),
3852 TRUE, TRUEEXITCLAUSE);
3856 usymtab_popBranches (firstArg,
3858 exprNode_makeMustExit (),
3859 TRUE, FALSEEXITCLAUSE);
3863 ret->exitCode = XK_MAYEXIT;
3865 else if (exitkind_mustExit (exk))
3867 ret->exitCode = XK_MUSTEXIT;
3869 else if (exitkind_couldExit (exk))
3871 ret->exitCode = XK_MAYEXIT;
3878 if (cstring_equalLit (fname, "exit"))
3880 if (exprNodeList_size (args) == 1)
3882 exprNode arg = exprNodeList_head (args);
3884 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3886 long int val = multiVal_forceInt (exprNode_getValue (arg));
3893 ("Argument to exit has implementation defined behavior: %s",
3894 exprNode_unparse (arg)),
3895 exprNode_loc (arg));
3903 ret->sref = sRef_undefined;
3904 exprNode_checkSetAny (ret, uentry_rawName (le));
3907 DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3908 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3909 reflectEnsuresClause (ret, le, f, args);
3912 DPRINTF (("Here: %s", sRef_unparseFull (ret->sref)));
3917 ** this is yucky! should keep the uentry as part of exprNode!
3920 uentry exprNode_getUentry (exprNode e)
3922 if (exprNode_isError (e))
3924 return uentry_undefined;
3928 cstring s = exprNode_rootVarName (e);
3929 uentry ue = usymtab_lookupSafe (s);
3936 ** Returns true iff e1 and e2 are both exactly the same storage
3940 static bool exprNode_sameStorage (exprNode e1, exprNode e2)
3942 sRef s1 = exprNode_getSref (e1);
3943 sRef s2 = exprNode_getSref (e2);
3945 return (sRef_realSame (s1, s2));
3949 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3951 exprNode ret = exprNode_createPlain (ctype_unknown);
3953 ret->kind = XPR_INITBLOCK;
3954 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3955 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3961 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3966 usymtab_checkAllValid ();
3969 if (exprNode_isUndefined (f))
3972 exprNodeList_free (args);
3973 return exprNode_undefined;
3976 t = exprNode_getType (f);
3978 if (sRef_isLocalVar (f->sref))
3980 exprNode_checkUse (f, f->sref, f->loc);
3982 if (sRef_possiblyNull (f->sref))
3984 if (!usymtab_isGuarded (f->sref))
3986 if (optgenerror (FLG_NULLDEREF,
3987 message ("Function call using %s pointer %q",
3988 sRef_nullMessage (f->sref),
3989 sRef_unparse (f->sref)),
3992 sRef_showNullInfo (f->sref);
3993 sRef_setNullError (f->sref);
4001 if (ctype_isRealFunction (t))
4003 exprNode ret = functionCallSafe (f, t, args);
4007 else if (ctype_isUnknown (t))
4009 exprNode ret = exprNode_createPartialCopy (f);
4015 exprNodeList_elements (args, current)
4017 if (exprNode_isDefined (current))
4019 exprNode_checkUse (ret, current->sref, ret->loc);
4022 ** also, anything derivable from current->sref may be used
4025 exprNode_addUse (ret, sRef_makeDerived (current->sref));
4026 exprNode_mergeUSs (ret, current);
4028 } end_exprNodeList_elements;
4030 ret->edata = exprData_makeCall (f, args);
4031 ret->kind = XPR_CALL;
4033 tstring = cstring_copy (exprNode_unparse (f));
4035 cstring_markOwned (tstring);
4036 exprNode_checkSetAny (ret, tstring);
4042 voptgenerror (FLG_TYPE,
4043 message ("Call to non-function (type %t): %s", t,
4044 exprNode_unparse (f)),
4047 exprNodeList_free (args);
4049 return (exprNode_makeError ());
4054 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4055 /*@only@*/ cstring f)
4057 exprNode ret = exprNode_createPartialCopy (s);
4059 ret->kind = XPR_FACCESS;
4061 if (exprNode_isError (s))
4063 ret->edata = exprData_makeField (s, f);
4068 ctype t = exprNode_getType (s);
4069 ctype tr = ctype_realType (t);
4071 checkMacroParen (s);
4073 ret->edata = exprData_makeField (s, f);
4075 if (ctype_isStructorUnion (tr))
4077 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
4079 if (uentry_isUndefined (tf))
4081 voptgenerror (FLG_TYPE,
4082 message ("Access non-existent field %s of %t: %s", f, t,
4083 exprNode_unparse (ret)),
4085 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
4090 uentry_setUsed (tf, exprNode_loc (ret));
4092 ret->typ = uentry_getType (tf);
4093 checkSafeUse (ret, s->sref);
4095 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
4096 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
4100 else /* isStructorUnion */
4102 if (ctype_isRealAbstract (tr))
4106 message ("Access field of abstract type (%t): %s.%s",
4107 t, exprNode_unparse (s), f),
4109 ret->typ = ctype_unknown;
4113 if (ctype_isKnown (tr))
4118 ("Access field of non-struct or union (%t): %s.%s",
4119 t, exprNode_unparse (s), f),
4122 ret->typ = ctype_unknown;
4126 cstring sn = cstring_copy (f);
4128 checkSafeUse (ret, s->sref);
4129 cstring_markOwned (sn);
4130 ret->sref = sRef_makeField (s->sref, sn);
4142 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
4143 /*@only@*/ cstring f)
4145 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
4151 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
4153 exprNode ret = exprNode_createPartialCopy (e);
4155 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
4156 ret->kind = XPR_PARENS;
4157 ret->edata = exprData_makeUop (e, lpar);
4159 if (!exprNode_isError (e))
4161 ret->exitCode = e->exitCode;
4162 ret->canBreak = e->canBreak;
4163 ret->mustBreak = e->mustBreak;
4164 ret->isJumpPoint = e->isJumpPoint;
4165 ret->sref = e->sref;
4172 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4173 /*@only@*/ cstring f)
4175 exprNode ret = exprNode_createPartialCopy (s);
4177 ret->edata = exprData_makeField (s, f);
4178 ret->kind = XPR_ARROW;
4180 if (exprNode_isError (s))
4186 ctype t = exprNode_getType (s);
4187 ctype tr = ctype_realType (t);
4189 checkMacroParen (s);
4191 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4193 if (ctype_isRealPointer (tr))
4195 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4197 if (ctype_isStructorUnion (b))
4199 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4201 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4203 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4207 message ("Arrow access from %s pointer%q: %s",
4208 sRef_nullMessage (s->sref),
4209 sRef_unparsePreOpt (s->sref),
4210 exprNode_unparse (ret)),
4213 sRef_showNullInfo (s->sref);
4214 sRef_setNullError (s->sref);
4219 if (uentry_isUndefined (fentry))
4223 message ("Access non-existent field %s of %t: %s",
4224 f, t, exprNode_unparse (ret)),
4226 ret->typ = ctype_unknown;
4232 ** was safeUse: shouldn't be safe!
4235 ** rec must be defined,
4236 ** *rec must be allocated
4237 ** rec->field need only be defined it if is an rvalue
4240 uentry_setUsed (fentry, exprNode_loc (ret));
4241 ret->typ = uentry_getType (fentry);
4243 exprNode_checkUse (ret, s->sref, s->loc);
4245 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4246 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4250 else /* Pointer to something that is not a struct or union*/
4252 if (ctype_isRealAbstract (tr))
4254 ctype xrt = ctype_forceRealType (tr);
4258 message ("Arrow access field of abstract type (%t): %s->%s",
4259 t, exprNode_unparse (s), f),
4263 ** Set the state correctly, as if the abstraction is broken.
4266 if (ctype_isRealPointer (xrt) &&
4267 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4268 ctype_isStructorUnion (b)))
4270 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4271 ret->typ = uentry_getType (fentry);
4272 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4276 ret->typ = ctype_unknown;
4277 ret->sref = sRef_undefined;
4280 else /* not a struct, union or abstract */
4282 if (ctype_isUnknown (tr)) {
4283 cstring sn = cstring_copy (f);
4285 DPRINTF (("Here: %s", exprNode_unparse (s)));
4287 exprNode_checkUse (ret, s->sref, s->loc);
4288 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4290 cstring_markOwned (sn);
4291 ret->sref = sRef_makeArrow (s->sref, sn);
4293 ret->kind = XPR_ARROW;
4298 message ("Arrow access field of non-struct or union "
4299 "pointer (%t): %s->%s",
4300 t, exprNode_unparse (s), f),
4303 ret->typ = ctype_unknown;
4304 ret->sref = sRef_undefined;
4309 else /* its not a pointer */
4311 if (!ctype_isUnknown (tr))
4315 message ("Arrow access of non-pointer (%t): %s->%s",
4316 t, exprNode_unparse (s), f),
4319 ret->typ = ctype_unknown;
4320 ret->sref = sRef_undefined;
4324 cstring sn = cstring_copy (f);
4326 DPRINTF (("Here: %s", exprNode_unparse (s)));
4328 exprNode_checkUse (ret, s->sref, s->loc);
4329 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4331 cstring_markOwned (sn);
4332 ret->sref = sRef_makeArrow (s->sref, sn);
4334 ret->kind = XPR_ARROW;
4345 exprNode_arrowAccess (/*@only@*/ exprNode s,
4346 /*@only@*/ lltok arrow,
4347 /*@only@*/ cstring f)
4349 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4355 ** only postOp's in C: i++ and i--
4359 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4361 /* check modification also */
4362 /* cstring opname = lltok_unparse (op);*/
4364 exprNode ret = exprNode_createPartialCopy (e);
4366 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4367 ret->kind = XPR_POSTOP;
4368 ret->edata = exprData_makeUop (e, op);
4370 if (!exprNode_isDefined (e))
4375 checkMacroParen (e);
4377 exprNode_checkUse (ret, e->sref, e->loc);
4378 exprNode_checkSet (ret, e->sref);
4380 t = exprNode_getType (e);
4382 if (sRef_isUnsafe (e->sref))
4384 voptgenerror (FLG_MACROPARAMS,
4385 message ("Operand of %s is macro parameter (non-functional): %s%s",
4386 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4388 sRef_makeSafe (e->sref);
4389 sRef_makeSafe (ret->sref);
4392 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4398 if (ctype_isRealAbstract (t))
4400 if (ctype_isRealNumAbstract (t)) {
4401 ; /* Allow operations on numabstract types */
4405 message ("Operand of %s is abstract type (%t): %s",
4406 lltok_unparse (op), t, exprNode_unparse (e)),
4414 message ("Operand of %s is non-numeric (%t): %s",
4415 lltok_unparse (op), t, exprNode_unparse (e)),
4418 ret->typ = ctype_unknown;
4421 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4423 exprNode_checkModify (e, ret);
4425 /* added 7/11/2000 D.L */
4427 /* updateEnvironmentForPostOp (e); */
4429 /* start modifications */
4430 /* added by Seejo on 4/16/2000 */
4432 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4434 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4436 ret->sref = sRef_copy (e->sref);
4439 if (lltok_getTok (op) == INC_OP) {
4440 if (sRef_getSize(e->sref) > 0) {
4442 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4444 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4445 /* Assumption: there is only 1 \0 in the buffer */
4446 /* This will not be correct if there are 2 \0's in the buffer */
4447 sRef_setNotNullTerminatedState(ret->sref);
4448 sRef_resetLen(ret->sref);
4450 sRef_setNullTerminatedState(ret->sref);
4451 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4453 if (sRef_isNullTerminated (ret->sref))
4454 printf ("ret->sref is Null Terminated\n");
4455 else if (sRef_isPossiblyNullTerminated (ret->sref))
4456 printf ("ret->sref is Possibly Null Terminated\n");
4457 else if (sRef_isNotNullTerminated (ret->sref))
4458 printf ("ret->sref is Not Null Terminated\n");
4465 if (lltok_getTok (op) == DEC_OP) {
4466 if (sRef_getSize(e->sref) >= 0) {
4467 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4468 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4472 /* end modifications */
4478 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4480 bool checkMod = FALSE;
4482 int opid = lltok_getTok (op);
4483 exprNode ret = exprNode_createSemiCopy (e);
4485 exprNode_copySets (ret, e);
4487 multiVal_free (ret->val);
4488 ret->val = multiVal_undefined;
4489 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4490 ret->kind = XPR_PREOP;
4491 ret->edata = exprData_makeUop (e, op);
4493 if (exprNode_isError (e))
4498 checkMacroParen (e);
4500 te = exprNode_getType (e);
4501 tr = ctype_realType (te);
4503 if (opid != TAMPERSAND)
4505 exprNode_checkUse (ret, e->sref, e->loc);
4507 if (ctype_isRealAbstract (tr)
4508 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4510 if (ctype_isRealNumAbstract (tr))
4512 ; /* no warning for numabstract types */
4516 if (optgenerror (FLG_ABSTRACT,
4517 message ("Operand of %s is abstract type (%t): %s",
4518 lltok_unparse (op), tr,
4519 exprNode_unparse (ret)),
4522 tr = te = ctype_unknown;
4523 ret->typ = ctype_unknown;
4524 sRef_setNullError (e->sref);
4533 case DEC_OP: /* should also check modification! */
4534 if (sRef_isMacroParamRef (e->sref))
4538 message ("Operand of %s is macro parameter (non-functional): %s",
4539 lltok_unparse (op), exprNode_unparse (ret)),
4544 exprNode_checkSet (ret, e->sref);
4547 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4552 if (context_msgStrictOps ())
4556 message ("Operand of %s is non-numeric (%t): %s",
4557 lltok_unparse (op), te, exprNode_unparse (ret)),
4560 ret->typ = ctype_int;
4563 /* start modifications */
4564 /* added by Seejo on 4/16/2000 */
4566 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4568 if ((sRef_isPossiblyNullTerminated (e->sref))
4569 || (sRef_isNullTerminated(e->sref))) {
4570 ret->sref = sRef_copy (e->sref);
4573 if (lltok_getTok (op) == INC_OP) {
4574 if (sRef_getSize(e->sref) > 0) {
4576 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4578 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4579 /* Assumption: there is only 1 \0 in the buffer */
4580 /* This will not be correct if there are 2 \0's in the buffer */
4581 sRef_setNotNullTerminatedState(ret->sref);
4582 sRef_resetLen (ret->sref);
4584 sRef_setNullTerminatedState(ret->sref);
4585 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4591 if (lltok_getTok (op) == DEC_OP) {
4592 if (sRef_getSize(e->sref) >= 0) {
4593 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4594 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4599 /* end modifications */
4606 if (ctype_isForceRealNumeric (&tr))
4610 ret->val = multiVal_invert (exprNode_getValue (e));
4614 ret->val = multiVal_copy (exprNode_getValue (e));
4619 if (context_msgStrictOps ())
4623 message ("Operand of %s is non-numeric (%t): %s",
4624 lltok_unparse (op), te, exprNode_unparse (ret)),
4628 ret->typ = ctype_int;
4632 case TEXCL: /* maybe this should be restricted */
4633 guardSet_flip (ret->guards);
4635 if (ctype_isRealBool (te) || ctype_isUnknown (te))
4641 if (ctype_isRealPointer (tr))
4643 if (sRef_isKnown (e->sref))
4645 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4649 (FLG_BOOLOPS, FLG_PTRNEGATE,
4650 message ("Operand of %s is non-boolean (%t): %s",
4651 lltok_unparse (op), te, exprNode_unparse (ret)),
4658 message ("Operand of %s is non-boolean (%t): %s",
4659 lltok_unparse (op), te, exprNode_unparse (ret)),
4663 ret->typ = ctype_bool;
4668 if (ctype_isForceRealInt (&tr))
4673 if (context_msgStrictOps ())
4677 message ("Operand of %s is non-integer (%t): %s",
4678 lltok_unparse (op), te, exprNode_unparse (ret)),
4682 if (ctype_isInt (e->typ))
4688 ret->typ = ctype_int;
4694 ret->typ = ctype_makePointer (e->typ);
4696 if (sRef_isKnown (e->sref))
4698 ret->sref = sRef_makeAddress (e->sref);
4705 if (ctype_isAP (tr))
4707 ret->typ = ctype_baseArrayPtr (e->typ);
4711 if (ctype_isKnown (te))
4713 if (ctype_isFunction (te))
4719 message ("Dereference of function type (%t): %s",
4720 te, exprNode_unparse (ret)),
4725 voptgenerror (FLG_TYPE,
4726 message ("Dereference of non-pointer (%t): %s",
4727 te, exprNode_unparse (ret)),
4729 ret->typ = ctype_unknown;
4734 ret->typ = ctype_unknown;
4739 if (sRef_isKnown (e->sref))
4741 DPRINTF (("Checking possibly null: %s", sRef_unparseFull (e->sref)));
4743 if (sRef_possiblyNull (e->sref))
4745 DPRINTF (("Checking possibly null: %s", sRef_unparse (e->sref)));
4746 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4750 message ("Dereference of %s pointer %q: %s",
4751 sRef_nullMessage (e->sref),
4752 sRef_unparse (e->sref),
4753 exprNode_unparse (ret)),
4756 sRef_showNullInfo (e->sref);
4757 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4762 ret->sref = sRef_makePointer (e->sref);
4767 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4772 exprNode_checkModify (e, ret);
4779 ** any reason to disallow sizeof (abstract type) ?
4783 ** used by both sizeof
4787 ctype sizeof_resultType (void)
4789 static ctype sizet = ctype_unknown;
4791 if (ctype_isUnknown (sizet))
4793 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4795 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4799 sizet = ctype_ulint;
4806 exprNode_sizeofType (/*@only@*/ qtype qt)
4808 exprNode ret = exprNode_create (sizeof_resultType ());
4809 ctype ct = qtype_getType (qt);
4811 ret->kind = XPR_SIZEOFT;
4812 ret->edata = exprData_makeSizeofType (qt);
4814 voptgenerror (FLG_SIZEOFTYPE,
4815 message ("Parameter to sizeof is type %s: %s",
4817 exprNode_unparse (ret)),
4824 exprNode_alignofType (/*@only@*/ qtype qt)
4826 exprNode ret = exprNode_create (sizeof_resultType ());
4827 ctype ct = qtype_getType (qt);
4829 ret->kind = XPR_ALIGNOFT;
4830 ret->edata = exprData_makeSizeofType (qt);
4832 voptgenerror (FLG_SIZEOFTYPE,
4833 message ("Parameter to alignof is type %s: %s",
4835 exprNode_unparse (ret)),
4841 exprNode exprNode_offsetof (qtype qt, cstringList s)
4843 exprNode ret = exprNode_create (sizeof_resultType ());
4844 ctype ct = qtype_getType (qt);
4846 ret->kind = XPR_OFFSETOF;
4847 ret->edata = exprData_makeOffsetof (qt, s);
4849 if (!ctype_isRealSU (ct))
4851 voptgenerror (FLG_TYPE,
4852 message ("First parameter to offsetof is not a "
4853 "struct or union type (type %s): %s",
4855 exprNode_unparse (ret)),
4862 cstringList_elements (s, el) {
4866 if (ctype_isUndefined (lt))
4870 else if (!ctype_isRealSU (lt))
4872 voptgenerror (FLG_TYPE,
4873 message ("Inner offsetof type is not a "
4874 "struct or union type (type %s before field %s): %s",
4875 ctype_unparse (lt), el,
4876 exprNode_unparse (ret)),
4882 fields = ctype_getFields (ctype_realType (lt));
4883 fld = uentryList_lookupField (fields, el);
4884 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4886 if (uentry_isUndefined (fld))
4888 if (ctype_equal (lt, ct)) {
4889 voptgenerror (FLG_TYPE,
4890 message ("Field %s in offsetof is not the "
4891 "name of a field of %s: %s",
4894 exprNode_unparse (ret)),
4897 voptgenerror (FLG_TYPE,
4898 message ("Deep field %s in offsetof is not the "
4899 "name of a field of %s: %s",
4902 exprNode_unparse (ret)),
4908 lt = uentry_getType (fld);
4911 } end_cstringList_elements;
4913 /* Should report error if its a bit field - behavior is undefined! */
4920 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4924 if (exprNode_isUndefined (e))
4926 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4927 ret->edata = exprData_makeSingle (e);
4928 ret->typ = sizeof_resultType ();
4929 ret->kind = XPR_SIZEOF;
4933 uentry u = exprNode_getUentry (e);
4935 ret = exprNode_createPartialCopy (e);
4936 ret->edata = exprData_makeSingle (e);
4938 ret->typ = sizeof_resultType ();
4939 ret->kind = XPR_SIZEOF;
4941 if (uentry_isValid (u)
4942 && uentry_isRefParam (u)
4943 && ctype_isRealArray (uentry_getType (u)))
4946 (FLG_SIZEOFFORMALARRAY,
4947 message ("Parameter to sizeof is an array-type function parameter: %s",
4948 exprNode_unparse (ret)),
4954 ** sizeof (x) doesn't "really" use x
4961 exprNode_alignofExpr (/*@only@*/ exprNode e)
4965 if (exprNode_isUndefined (e))
4967 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4971 ret = exprNode_createPartialCopy (e);
4974 ret->edata = exprData_makeSingle (e);
4975 ret->typ = sizeof_resultType ();
4976 ret->kind = XPR_ALIGNOF;
4979 ** sizeof (x) doesn't "really" use x
4986 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4992 if (exprNode_isError (e))
4996 return exprNode_undefined;
4999 checkMacroParen (e);
5001 c = qtype_getType (q);
5002 t = exprNode_getType (e);
5004 ret = exprNode_createPartialCopy (e);
5006 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
5008 ret->kind = XPR_CAST;
5009 ret->edata = exprData_makeCast (tok, e, q);
5011 ret->sref = sRef_copy (e->sref);
5013 DPRINTF (("Cast: -> %s", sRef_unparseFull (ret->sref)));
5015 constraintList_castConstraints (ret->requiresConstraints, t, c);
5016 constraintList_castConstraints (ret->ensuresConstraints, t, c);
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 int val = (int) multiVal_forceInt (e1->val);
5602 /* Operator : + or += */
5603 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5604 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5605 val should not result in a
5606 size < 0 (size = 0 is ok !) */
5608 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5610 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5611 sRef_setNotNullTerminatedState(ret->sref);
5612 sRef_resetLen (ret->sref);
5614 sRef_setNullTerminatedState(ret->sref);
5615 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5620 /* Operator : - or -= */
5621 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5622 if (sRef_getSize(e2->sref) >= 0) {
5623 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5624 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5628 /* end modifications */
5630 sRef_setNullError (ret->sref);
5633 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5634 ** since is points to storage that should not be deallocated
5635 ** through this pointer.
5638 if (sRef_isOnly (ret->sref)
5639 || sRef_isFresh (ret->sref)) {
5640 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5644 ret->sref = e2->sref;
5648 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5657 case TAMPERSAND: /* bitwise & */
5659 case TCIRC: /* ^ (XOR) */
5664 bool reported = FALSE;
5670 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5671 || opid == RIGHT_OP || opid == RIGHT_ASSIGN)
5674 ** evans 2002-01-01: fixed this to follow ISO 6.5.7.
5677 if (!ctype_isUnsigned (tr2)
5678 && !exprNode_isNonNegative (e2))
5680 reported = optgenerror
5682 message ("Right operand of %s may be negative (%t): %s",
5683 lltok_unparse (op), te2,
5684 exprNode_unparse (ret)),
5688 if (!ctype_isUnsigned (tr1)
5689 && !exprNode_isNonNegative (e1))
5691 reported = optgenerror
5692 (FLG_SHIFTIMPLEMENTATION,
5693 message ("Left operand of %s may be negative (%t): %s",
5694 lltok_unparse (op), te1,
5695 exprNode_unparse (ret)),
5700 ** Should check size of right operand also...
5706 if (!ctype_isUnsigned (tr1))
5708 if (exprNode_isNonNegative (e1)) {
5711 reported = optgenerror
5713 message ("Left operand of %s is not unsigned value (%t): %s",
5714 lltok_unparse (op), te1,
5715 exprNode_unparse (ret)),
5725 if (!ctype_isUnsigned (tr2))
5727 if (!exprNode_isNonNegative (e2)) {
5728 reported = optgenerror
5730 message ("Right operand of %s is not unsigned value (%t): %s",
5731 lltok_unparse (op), te2,
5732 exprNode_unparse (ret)),
5741 if (!checkIntegral (e1, e2, ret, op)) {
5742 te1 = ctype_unknown;
5746 DPRINTF (("Set: %s", ctype_unparse (te1)));
5749 ** tret is the widest type of te1 and te2
5752 tret = ctype_widest (te1, te2);
5757 if (checkIntegral (e1, e2, ret, op)) {
5760 tret = ctype_unknown;
5765 case TLT: /* comparisons */
5766 case TGT: /* numeric, numeric -> bool */
5768 DPRINTF (("Here we go: %s / %s",
5769 ctype_unparse (tr1), ctype_unparse (tr2)));
5771 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5772 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5775 bool fepsilon = FALSE;
5777 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5782 if (opid == TLT || opid == TGT)
5784 uentry ue1 = exprNode_getUentry (e1);
5785 uentry ue2 = exprNode_getUentry (e2);
5788 ** FLT_EPSILON, etc. really is a variable, not
5792 if (uentry_isVariable (ue1))
5794 cstring uname = uentry_rawName (ue1);
5796 if (cstring_equalLit (uname, "FLT_EPSILON")
5797 || cstring_equalLit (uname, "DBL_EPSILON")
5798 || cstring_equalLit (uname, "LDBL_EPSILON"))
5804 if (uentry_isVariable (ue2))
5806 cstring uname = uentry_rawName (ue2);
5808 if (cstring_equalLit (uname, "FLT_EPSILON")
5809 || cstring_equalLit (uname, "DBL_EPSILON")
5810 || cstring_equalLit (uname, "LDBL_EPSILON"))
5819 ; /* Don't complain. */
5825 message ("Dangerous comparison involving %s types: %s",
5826 ctype_unparse (rtype),
5827 exprNode_unparse (ret)),
5836 ** Types should match.
5839 DPRINTF (("Match types: %s / %s", exprNode_unparse (e1),
5840 exprNode_unparse (e2)));
5842 if (!exprNode_matchTypes (e1, e2))
5844 hasError = gentypeerror
5846 message ("Operands of %s have incompatible types (%t, %t): %s",
5847 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5853 || (ctype_isForceRealNumeric (&tr1)
5854 && ctype_isForceRealNumeric (&tr2)) ||
5855 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5861 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5862 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5866 message ("Comparison of pointer and numeric (%t, %t): %s",
5867 te1, te2, exprNode_unparse (ret)),
5872 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5877 /* certain comparisons on unsigned's and zero look suspicious */
5879 if (opid == TLT || opid == LE_OP || opid == GE_OP)
5881 if ((ctype_isUnsigned (tr1) && exprNode_isZero (e2))
5882 || (ctype_isUnsigned (tr2) && exprNode_isZero (e1)))
5885 (FLG_UNSIGNEDCOMPARE,
5886 message ("Comparison of unsigned value involving zero: %s",
5887 exprNode_unparse (ret)),
5892 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5894 if ((opid == EQ_OP || opid == NE_OP) &&
5895 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5898 ** is one a variable?
5901 if (uentry_isVariable (exprNode_getUentry (e1))
5902 || uentry_isVariable (exprNode_getUentry (e2)))
5905 ** comparisons with FALSE are okay
5908 if (exprNode_isFalseConstant (e1)
5909 || exprNode_isFalseConstant (e2))
5918 ("Use of %q with %s variables (risks inconsistency because "
5919 "of multiple true values): %s",
5920 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5921 context_printBoolName (), exprNode_unparse (ret)),
5928 case AND_OP: /* bool, bool -> bool */
5930 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5936 if (context_maybeSet (FLG_BOOLOPS))
5938 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5940 if (ctype_sameName (te1, te2))
5944 message ("Operands of %s are non-boolean (%t): %s",
5945 lltok_unparse (op), te1,
5946 exprNode_unparse (ret)),
5954 ("Operands of %s are non-booleans (%t, %t): %s",
5955 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5959 else if (!ctype_isRealBool (te1))
5963 message ("Left operand of %s is non-boolean (%t): %s",
5964 lltok_unparse (op), te1, exprNode_unparse (ret)),
5967 else if (!ctype_isRealBool (te2))
5971 message ("Right operand of %s is non-boolean (%t): %s",
5972 lltok_unparse (op), te2, exprNode_unparse (ret)),
5985 (cstring_makeLiteral
5986 ("There has been a problem in the parser. This is believed to result "
5987 "from a problem with bison v. 1.25. Please try rebuidling Splint "
5988 "using the pre-compiled grammar files by commenting out the "
5989 "BISON= line in the top-level Makefile."));
5994 DPRINTF (("Return type %s: %s", exprNode_unparse (ret), ctype_unparse (tret)));
5996 exprNode_checkUse (ret, e1->sref, e1->loc);
5997 exprNode_mergeUSs (ret, e2);
5998 exprNode_checkUse (ret, e2->sref, e2->loc);
6004 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
6005 /*@only@*/ lltok op)
6009 checkMacroParen (e1);
6010 checkMacroParen (e2);
6012 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
6014 checkExpressionDefined (e1, e2, op);
6017 ret = exprNode_makeOp (e1, e2, op);
6022 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
6025 ** This is somewhat bogus!
6027 ** Assigning to a nested observer in a non-observer datatype
6028 ** should not produce an error.
6031 sRef ref = exprNode_getSref (e1);
6033 DPRINTF (("Check assign mod: %s",
6034 sRef_unparseFull (ref)));
6036 if (sRef_isObserver (ref)
6037 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
6038 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
6040 sRef base = sRef_getBase (ref);
6042 if (sRef_isValid (base) && sRef_isObserver (base))
6044 exprNode_checkModify (e1, ret);
6048 exprNode_checkModifyVal (e1, ret);
6053 exprNode_checkModify (e1, ret);
6058 exprNode_assign (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2, /*@only@*/ lltok op)
6060 bool isalloc = FALSE;
6061 bool isjustalloc = FALSE;
6062 bool noalias = FALSE;
6065 DPRINTF (("%s [%s] <- %s [%s]",
6066 exprNode_unparse (e1),
6067 ctype_unparse (e1->typ),
6068 exprNode_unparse (e2),
6069 ctype_unparse (e2->typ)));
6071 if (lltok_getTok (op) != TASSIGN)
6073 ret = exprNode_makeOp (e1, e2, op);
6075 DPRINTF (("Here goes: %s %s",
6076 ctype_unparse (e1->typ),
6077 ctype_unparse (e2->typ)));
6079 if (exprNode_isDefined (e1)
6080 && exprNode_isDefined (e2))
6082 if (ctype_isNumeric (e2->typ)
6083 || ctype_isNumeric (e1->typ))
6085 /* Its a pointer arithmetic expression like ptr += i */
6092 ret = exprNode_createPartialCopy (e1);
6093 ret->kind = XPR_ASSIGN;
6094 ret->edata = exprData_makeOp (e1, e2, op);
6096 if (!exprNode_isError (e2))
6098 ret->sets = sRefSet_union (ret->sets, e2->sets);
6099 ret->msets = sRefSet_union (ret->msets, e2->msets);
6100 ret->uses = sRefSet_union (ret->uses, e2->uses);
6104 checkExpressionDefined (e1, e2, op);
6106 if (exprNode_isError (e1))
6108 if (!exprNode_isError (e2))
6110 ret->loc = fileloc_update (ret->loc, e2->loc);
6114 ret->loc = fileloc_update (ret->loc, g_currentloc);
6118 if (!exprNode_isError (e2))
6120 checkMacroParen (e2);
6123 if (exprNode_isDefined (e1))
6125 if (sRef_isMacroParamRef (e1->sref))
6127 if (context_inIterDef ())
6129 uentry ue = sRef_getUentry (e1->sref);
6131 if (uentry_isYield (ue))
6137 if (fileloc_isDefined (e1->loc))
6141 message ("Assignment to non-yield iter parameter: %q",
6142 sRef_unparse (e1->sref)),
6149 message ("Assignment to non-yield iter parameter: %q",
6150 sRef_unparse (e1->sref)),
6157 if (fileloc_isDefined (e1->loc))
6161 message ("Assignment to macro parameter: %q",
6162 sRef_unparse (e1->sref)),
6169 message ("Assignment to macro parameter: %q",
6170 sRef_unparse (e1->sref)),
6174 exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
6179 exprNode_checkAssignMod (e1, ret);
6182 if (exprNode_isDefined (e2))
6184 if (lltok_getTok (op) == TASSIGN)
6186 ctype te1 = exprNode_getType (e1);
6187 ctype te2 = exprNode_getType (e2);
6189 if (ctype_isVoid (te2))
6193 message ("Assignment of void value to %t: %s %s %s",
6194 te1, exprNode_unparse (e1),
6196 exprNode_unparse (e2)),
6199 else if (!ctype_forceMatch (te1, te2))
6201 if (exprNode_matchLiteral (te1, e2))
6203 DPRINTF (("Literals match: %s / %s",
6204 ctype_unparse (te1), exprNode_unparse (e2)));
6205 if (ctype_isNumAbstract (te1)) {
6206 if (!context_flagOn (FLG_NUMABSTRACTLIT, e1->loc)) {
6207 (void) llgenhinterror
6210 ("Assignment of %t literal to numabstract type %t: %s %s %s",
6212 exprNode_unparse (e1),
6214 exprNode_unparse (e2)),
6216 ("Use +numabstractlit to allow numeric literals to be used as numabstract values"),
6225 message ("Assignment of %t to %t: %s %s %s",
6226 te2, te1, exprNode_unparse (e1),
6228 exprNode_unparse (e2)),
6234 /* Type checks okay */
6238 exprNode_mergeUSs (ret, e2);
6239 exprNode_checkUse (ret, e2->sref, e2->loc);
6241 DPRINTF (("Do assign! %s %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6248 doAssign (e1, e2, FALSE);
6251 ret->sref = e1->sref;
6255 if (exprNode_isDefined (e2))
6257 exprNode_mergeUSs (ret, e2);
6258 exprNode_checkUse (ret, e2->sref, e2->loc);
6262 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
6264 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
6267 isjustalloc = sRef_isJustAllocated (e1->sref);
6268 isalloc = sRef_isAllocated (e1->sref);
6270 if (sRef_isField (e1->sref))
6272 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
6274 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
6276 exprNode_checkUse (ret, root, e1->loc);
6282 ** be careful! this defines e1->sref.
6285 /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
6287 DPRINTF (("Setting: %s -> %s", exprNode_unparse (ret), sRef_unparse (e1->sref)));
6288 exprNode_checkSet (ret, e1->sref);
6292 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
6293 ? e2->loc : e1->loc);
6299 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
6308 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
6309 /*@keep@*/ exprNode elseclause)
6313 if (!exprNode_isError (pred))
6315 ret = exprNode_createPartialCopy (pred);
6316 checkMacroParen (pred);
6317 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
6319 if (!exprNode_isError (ifclause))
6321 checkMacroParen (ifclause); /* update macro counts! */
6323 if (!exprNode_isError (elseclause))
6325 checkMacroParen (elseclause);
6327 if (!exprNode_matchTypes (ifclause, elseclause))
6330 (exprNode_getType (ifclause),
6332 exprNode_getType (elseclause),
6334 message ("Conditional clauses are not of same type: "
6336 exprNode_unparse (ifclause),
6337 exprNode_getType (ifclause),
6338 exprNode_unparse (elseclause),
6339 exprNode_getType (elseclause)),
6342 ret->sref = sRef_undefined;
6343 ret->typ = ctype_unknown;
6348 /* for now...should merge the states */
6349 ret->sref = ifclause->sref;
6350 ret->typ = ifclause->typ;
6352 if (exprNode_isNullValue (ifclause))
6354 ret->typ = elseclause->typ;
6358 exprNode_checkUse (ret, pred->sref, pred->loc);
6359 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6360 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6362 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6367 ret->typ = ifclause->typ;
6369 exprNode_checkUse (pred, pred->sref, pred->loc);
6370 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6372 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6377 if (!exprNode_isError (elseclause))
6379 ret->typ = elseclause->typ;
6381 exprNode_checkUse (pred, pred->sref, pred->loc);
6382 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6384 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6388 else /* pred is error */
6390 if (!exprNode_isError (ifclause))
6392 ret = exprNode_createSemiCopy (ifclause);
6394 checkMacroParen (ifclause); /* update macro counts! */
6396 if (!exprNode_isError (elseclause))
6398 checkMacroParen (elseclause);
6400 ret->typ = ifclause->typ;
6402 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6405 (exprNode_getType (ifclause),
6407 exprNode_getType (elseclause),
6409 message ("Conditional clauses are not of same type: "
6411 exprNode_unparse (ifclause),
6412 exprNode_getType (ifclause),
6413 exprNode_unparse (elseclause),
6414 exprNode_getType (elseclause)),
6417 ret->typ = ctype_unknown;
6421 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6422 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6424 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6427 else if (!exprNode_isError (elseclause)) /* pred, if errors */
6429 ret = exprNode_createSemiCopy (ifclause);
6431 ret->typ = elseclause->typ;
6432 checkMacroParen (elseclause);
6434 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6435 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6437 else /* all errors! */
6439 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6443 ret->kind = XPR_COND;
6444 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
6446 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6448 exprNode_combineControl (ret, ifclause, elseclause);
6455 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6457 ctype totype = qtype_getType (qt);
6459 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6463 ** check use of va_arg : <valist>, type -> type
6466 if (exprNode_isError (arg))
6471 targ = exprNode_getType (arg);
6474 ** arg should have be a pointer
6477 if (!ctype_isUA (targ) ||
6478 (!typeId_equal (ctype_typeId (targ),
6479 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6483 message ("First argument to va_arg is not a va_list (type %t): %s",
6484 targ, exprNode_unparse (arg)),
6488 exprNode_checkSet (ret, arg->sref);
6492 ** return type is totype
6496 ret->kind = XPR_VAARG;
6497 ret->edata = exprData_makeCast (tok, arg, qt);
6502 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6504 exprNode ret = exprNode_createPlain (ctype_undefined);
6505 ret->kind = XPR_LABEL;
6506 ret->edata = exprData_makeLiteral (label);
6507 ret->isJumpPoint = TRUE;
6509 return (ret); /* for now, ignore label */
6512 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6514 if (exprNode_isDefined (stmt))
6516 stmt->isJumpPoint = TRUE;
6518 /* This prevent stray no return path errors, etc. */
6519 stmt->exitCode = XK_MUSTEXIT;
6525 bool exprNode_isDefaultMarker (exprNode e)
6527 if (exprNode_isDefined (e))
6529 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6535 bool exprNode_isCaseMarker (exprNode e)
6537 if (exprNode_isDefined (e))
6539 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6545 bool exprNode_isLabelMarker (exprNode e)
6547 if (exprNode_isDefined (e))
6549 return (e->kind == XPR_LABEL);
6555 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6557 exprNode ret = exprNode_createPartialCopy (test);
6559 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6561 if (exprNode_isError (test)) {
6565 exprNode_checkUse (ret, test->sref, test->loc);
6567 usymtab_setExitCode (ret->exitCode);
6571 usymtab_setMustBreak ();
6574 ret->edata = exprData_makeSingle (test);
6575 ret->isJumpPoint = TRUE;
6581 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6583 exprNode ret = exprNode_createPartialCopy (test);
6585 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6586 ret->edata = exprData_makePair (test, stmt);
6587 ret->isJumpPoint = TRUE;
6589 if (exprNode_isError (test))
6594 exprNode_checkUse (ret, test->sref, test->loc);
6596 if (exprNode_isError (stmt))
6601 exprNode_mergeUSs (ret, stmt);
6603 ret->exitCode = stmt->exitCode;
6604 ret->mustBreak = stmt->mustBreak;
6605 ret->canBreak = stmt->canBreak;
6607 usymtab_setExitCode (ret->exitCode);
6611 usymtab_setMustBreak ();
6618 /*@notnull@*/ /*@only@*/ exprNode
6619 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6621 exprNode ret = exprNode_createTok (def);
6623 ret->isJumpPoint = TRUE;
6624 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6629 exprNode_mayEscape (exprNode e)
6631 if (exprNode_isDefined (e))
6633 return exitkind_couldEscape (e->exitCode);
6639 exprNode_mustBreak (exprNode e)
6641 if (exprNode_isDefined (e))
6643 return e->mustBreak;
6650 exprNode_mustEscape (exprNode e)
6652 if (exprNode_isDefined (e))
6654 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6661 exprNode_errorEscape (exprNode e)
6663 if (exprNode_isDefined (e))
6665 return exitkind_isError (e->exitCode);
6671 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6673 exprNode ret = exprNode_createPartialCopy (e1);
6675 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6677 ret->edata = exprData_makePair (e1, e2);
6678 ret->kind = XPR_STMTLIST;
6680 if (exprNode_isDefined (e1))
6682 ret->isJumpPoint = e1->isJumpPoint;
6683 ret->canBreak = e1->canBreak;
6687 if (exprNode_isDefined (e2))
6689 ret->loc = fileloc_update (ret->loc, e2->loc);
6693 if (exprNode_isDefined (e2))
6695 ret->exitCode = e2->exitCode;
6696 ret->mustBreak = e2->mustBreak;
6697 if (e2->canBreak) ret->canBreak = TRUE;
6701 ** if e1 must return, then e2 is unreachable!
6704 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6706 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6707 && !(e2->isJumpPoint))
6709 if (context_getFlag (FLG_UNREACHABLE))
6713 if (e2->kind == XPR_STMT)
6715 nr = exprData_getUopNode (e2->edata);
6718 if ((nr->kind == XPR_TOK
6719 && lltok_isSemi (exprData_getTok (nr->edata))))
6721 /* okay to have unreachable ";" */
6722 ret->exitCode = XK_MUSTEXIT;
6723 ret->canBreak = TRUE;
6727 if (optgenerror (FLG_UNREACHABLE,
6728 message ("Unreachable code: %s",
6729 exprNode_unparseFirst (nr)),
6732 ret->isJumpPoint = TRUE;
6733 ret->mustBreak = FALSE;
6734 ret->exitCode = XK_ERROR;
6735 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6739 ret->exitCode = XK_MUSTEXIT;
6740 ret->canBreak = TRUE;
6748 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6751 ** We want a warning anytime we have:
6753 ** yyy; <<<- no break or return
6757 exprNode lastStmt = exprNode_lastStatement (e1);
6759 if (exprNode_isDefined (lastStmt)
6760 && !exprNode_mustEscape (lastStmt)
6761 && !exprNode_mustBreak (lastStmt)
6762 && !exprNode_isCaseMarker (lastStmt)
6763 && !exprNode_isDefaultMarker (lastStmt)
6764 && !exprNode_isLabelMarker (lastStmt))
6766 voptgenerror (FLG_CASEBREAK,
6768 ("Fall through case (no preceding break)"),
6775 exprNode_mergeUSs (ret, e2);
6777 usymtab_setExitCode (ret->exitCode);
6781 usymtab_setMustBreak ();
6784 DPRINTF (("==> %s", exprNode_unparse (ret)));
6788 exprNode exprNode_createTok (/*@only@*/ lltok t)
6790 exprNode ret = exprNode_create (ctype_unknown);
6791 ret->kind = XPR_TOK;
6792 ret->edata = exprData_makeTok (t);
6796 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6798 if (!exprNode_isError (e))
6800 exprChecks_checkStatementEffect(e);
6803 return (exprNode_statementError (e, t));
6806 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6808 exprNode ret = exprNode_createPartialCopy (e);
6810 if (!exprNode_isError (e))
6812 if (e->kind != XPR_ASSIGN)
6814 exprNode_checkUse (ret, e->sref, e->loc);
6817 ret->exitCode = e->exitCode;
6818 ret->canBreak = e->canBreak;
6819 ret->mustBreak = e->mustBreak;
6822 ret->edata = exprData_makeUop (e, t);
6823 ret->kind = XPR_STMT;
6828 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6830 if (!exprNode_isError (e))
6832 if (e->kind != XPR_ASSIGN)
6834 exprNode_checkUse (e, e->sref, e->loc);
6841 void exprNode_produceGuards (exprNode pred)
6843 if (!exprNode_isError (pred))
6845 if (ctype_isRealPointer (pred->typ))
6847 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6850 exprNode_checkUse (pred, pred->sref, pred->loc);
6851 exprNode_resetSref (pred);
6855 exprNode exprNode_compoundStatementExpression (/*@only@*/ lltok tlparen, /*@only@*/ exprNode e)
6859 DPRINTF (("Compound: %s", exprNode_unparse (e)));
6861 if (!context_flagOn (FLG_GNUEXTENSIONS, exprNode_loc (e)))
6863 (void) llgenhinterror
6865 message ("Compound statement expressions is not supported by ISO C99"),
6866 message ("Use +gnuextensions to allow compound statement expressions (and other GNU language extensions) "
6867 "without this warning"),
6872 ** The type of a compoundStatementExpression is the type of the last statement
6875 llassert (exprNode_isBlock (e));
6876 laststmt = exprNode_lastStatement (e);
6878 DPRINTF (("Last statement: %s / %s", exprNode_unparse (laststmt), ctype_unparse (exprNode_getType (laststmt))));
6879 DPRINTF (("e: %s", exprNode_unparse (e)));
6880 e->typ = exprNode_getType (laststmt);
6881 return exprNode_addParens (tlparen, e);
6885 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6887 exprNode ret = exprNode_createPartialCopy (e);
6889 if (!exprNode_isError (e))
6891 ret->exitCode = e->exitCode;
6892 ret->canBreak = e->canBreak;
6893 ret->mustBreak = e->mustBreak;
6896 DPRINTF (("Block e: %s", exprNode_unparse (e)));
6897 ret->edata = exprData_makeSingle (e);
6898 ret->kind = XPR_BLOCK;
6899 DPRINTF (("Block: %s", exprNode_unparse (ret)));
6903 bool exprNode_isBlock (exprNode e)
6905 return (exprNode_isDefined (e)
6906 && ((e)->kind == XPR_BLOCK));
6909 bool exprNode_isStatement (exprNode e)
6911 return (exprNode_isDefined (e)
6912 && ((e)->kind == XPR_STMT));
6915 bool exprNode_isAssign (exprNode e)
6917 if (exprNode_isDefined (e))
6919 return (e->kind == XPR_ASSIGN);
6925 bool exprNode_isEmptyStatement (exprNode e)
6927 return (exprNode_isDefined (e)
6928 && (e->kind == XPR_TOK)
6929 && (lltok_isSemi (exprData_getTok (e->edata))));
6932 bool exprNode_isMultiStatement (exprNode e)
6934 return (exprNode_isDefined (e)
6935 && ((e->kind == XPR_FOR)
6936 || (e->kind == XPR_FORPRED)
6937 || (e->kind == XPR_IF)
6938 || (e->kind == XPR_IFELSE)
6939 || (e->kind == XPR_WHILE)
6940 || (e->kind == XPR_WHILEPRED)
6941 || (e->kind == XPR_DOWHILE)
6942 || (e->kind == XPR_BLOCK)
6943 || (e->kind == XPR_STMT)
6944 || (e->kind == XPR_STMTLIST)
6945 || (e->kind == XPR_SWITCH)));
6948 void exprNode_checkIfPred (exprNode pred)
6950 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6953 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6956 bool emptyErr = FALSE;
6958 if (context_maybeSet (FLG_IFEMPTY))
6960 if (exprNode_isEmptyStatement (tclause))
6962 emptyErr = optgenerror (FLG_IFEMPTY,
6964 ("Body of if statement is empty"),
6965 exprNode_loc (tclause));
6969 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6971 if (exprNode_isDefined (tclause)
6972 && !exprNode_isBlock (tclause))
6974 voptgenerror (FLG_IFBLOCK,
6976 ("Body of if statement is not a block: %s",
6977 exprNode_unparse (tclause)),
6978 exprNode_loc (tclause));
6982 if (exprNode_isError (pred))
6984 if (exprNode_isError (tclause))
6986 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6990 ret = exprNode_createPartialCopy (tclause);
6995 if (exprNode_mustEscape (pred))
6999 message ("Predicate always exits: %s", exprNode_unparse (pred)),
7000 exprNode_loc (pred));
7003 exprNode_checkUse (pred, pred->sref, pred->loc);
7005 if (!exprNode_isError (tclause))
7007 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
7010 ret = exprNode_createPartialCopy (pred);
7014 ret->edata = exprData_makePair (pred, tclause);
7016 ret->exitCode = XK_UNKNOWN;
7018 if (exprNode_isDefined (tclause))
7020 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
7021 ret->canBreak = tclause->canBreak;
7022 ret->sets = sRefSet_union (ret->sets, tclause->sets);
7023 ret->msets = sRefSet_union (ret->msets, tclause->msets);
7024 ret->uses = sRefSet_union (ret->uses, tclause->uses);
7027 ret->mustBreak = FALSE;
7032 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
7033 /*@only@*/ exprNode tclause,
7034 /*@only@*/ exprNode eclause)
7037 bool tEmptyErr = FALSE;
7038 bool eEmptyErr = FALSE;
7040 if (context_maybeSet (FLG_IFEMPTY))
7042 if (exprNode_isEmptyStatement (tclause))
7044 tEmptyErr = optgenerror
7047 ("Body of if clause of if statement is empty"),
7048 exprNode_loc (tclause));
7051 if (exprNode_isEmptyStatement (eclause))
7053 eEmptyErr = optgenerror
7056 ("Body of else clause of if statement is empty"),
7057 exprNode_loc (eclause));
7061 if (context_maybeSet (FLG_IFBLOCK))
7064 && exprNode_isDefined (tclause)
7065 && !exprNode_isBlock (tclause))
7067 voptgenerror (FLG_IFBLOCK,
7069 ("Body of if clause of if statement is not a block: %s",
7070 exprNode_unparse (tclause)),
7071 exprNode_loc (tclause));
7075 && exprNode_isDefined (eclause)
7076 && !exprNode_isBlock (eclause)
7077 && !(eclause->kind == XPR_IF)
7078 && !(eclause->kind == XPR_IFELSE))
7083 ("Body of else clause of if statement is not a block: %s",
7084 exprNode_unparse (eclause)),
7085 exprNode_loc (eclause));
7089 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
7091 if (exprNode_isDefined (eclause)
7092 && (eclause->kind == XPR_IF))
7094 voptgenerror (FLG_ELSEIFCOMPLETE,
7095 message ("Incomplete else if logic (no final else): %s",
7096 exprNode_unparse (eclause)),
7097 exprNode_loc (eclause));
7101 if (exprNode_isError (pred))
7103 if (exprNode_isError (tclause))
7105 if (exprNode_isError (eclause))
7107 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7111 ret = exprNode_createPartialCopy (eclause);
7116 ret = exprNode_createPartialCopy (tclause);
7119 else /* pred is okay */
7121 ret = exprNode_createPartialCopy (pred);
7123 if (exprNode_mustEscape (pred))
7127 message ("Predicate always exits: %s", exprNode_unparse (pred)),
7128 exprNode_loc (pred));
7131 exprNode_checkUse (ret, pred->sref, pred->loc);
7132 exprNode_mergeCondUSs (ret, tclause, eclause);
7135 ret->kind = XPR_IFELSE;
7136 ret->edata = exprData_makeCond (pred, tclause, eclause);
7138 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
7140 exprNode_combineControl (ret, tclause, eclause);
7141 ret->loc = fileloc_update (ret->loc, eclause->loc);
7148 ** *allpaths <- TRUE iff all executions paths must go through the switch
7152 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
7154 exprNodeSList el = exprNode_flatten (e);
7155 bool mustReturn = TRUE; /* find a branch that doesn't */
7156 bool thisReturn = FALSE;
7157 bool hasDefault = FALSE;
7158 bool hasAllMembers = FALSE;
7159 bool inSwitch = FALSE;
7160 bool isEnumSwitch = FALSE;
7161 bool canBreak = FALSE;
7162 bool fallThrough = FALSE;
7163 ctype ct = ctype_unknown;
7164 enumNameSList usedEnums;
7167 if (exprNode_isDefined (test))
7172 ttype = ctype_realType (ct);
7174 if (ctype_isEnum (ttype))
7176 isEnumSwitch = TRUE;
7177 enums = ctype_elist (ttype);
7178 usedEnums = enumNameSList_new ();
7182 exprNodeSList_elements (el, current)
7185 DPRINTF ((message("checkSwitchExpr current = %s ", exprNode_unparse(current) ) ));
7187 if (exprNode_isDefined (current))
7189 switch (current->kind)
7196 (FLG_DUPLICATECASES,
7197 message ("Duplicate default cases in switch"),
7198 exprNode_loc (current));
7203 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
7211 exprNode st = exprData_getSingle (current->edata);
7212 uentry ue = exprNode_getUentry (st);
7214 if (uentry_isValid (ue))
7216 cstring cname = uentry_rawName (ue);
7218 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
7220 if (enumNameSList_member
7221 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
7224 (FLG_DUPLICATECASES,
7225 message ("Duplicate case in switch: %s",
7231 enumNameSList_addh (usedEnums, cname);
7238 message ("Case in switch not %s member: %s",
7239 ctype_unparse (ct), cname),
7246 if (inSwitch && !fallThrough)
7248 if (!thisReturn || canBreak)
7258 /*@switchbreak@*/ break;
7260 thisReturn = thisReturn || exprNode_mustEscape (current);
7261 canBreak = canBreak || current->canBreak;
7262 if (canBreak) fallThrough = FALSE;
7265 } end_exprNodeSList_elements;
7267 if (inSwitch) /* check the last one! */
7269 if (!thisReturn || canBreak)
7278 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
7279 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
7281 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
7283 voptgenerror (FLG_MISSCASE,
7284 message ("Missing case%s in switch: %q",
7285 cstring_makeLiteralTemp
7286 ((enumNameSList_size (unused) > 1) ? "s" : ""),
7287 enumNameSList_unparse (unused)),
7290 enumNameSList_free (unused);
7291 *allpaths = FALSE; /* evans 2002-01-01 */
7295 hasAllMembers = TRUE;
7299 enumNameSList_free (usedEnums);
7303 *allpaths = hasDefault;
7306 exprNodeSList_free (el);
7307 return ((hasDefault || hasAllMembers) && mustReturn);
7310 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
7312 exprNode ret = exprNode_createPartialCopy (e);
7315 DPRINTF (("Switch: %s", exprNode_unparse (s)));
7317 ret->kind = XPR_SWITCH;
7318 ret->edata = exprData_makePair (e, s);
7320 if (!exprNode_isError (s))
7322 exprNode fs = exprNode_firstStatement (s);
7323 ret->loc = fileloc_update (ret->loc, s->loc);
7325 if (exprNode_isUndefined (fs)
7326 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
7327 || exprNode_isDefaultMarker (fs)) {
7330 voptgenerror (FLG_FIRSTCASE,
7332 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
7337 if (!exprNode_isError (e))
7339 if (checkSwitchExpr (e, s, &allpaths))
7341 ret->exitCode = XK_MUSTRETURN;
7345 ret->exitCode = e->exitCode;
7348 ret->canBreak = e->canBreak;
7349 ret->mustBreak = e->mustBreak;
7353 ** exprNode.c:3883,32: Variable allpaths used before definition
7360 DPRINTF (("Context exit switch!"));
7361 context_exitSwitch (ret, allpaths);
7362 DPRINTF (("Context exit switch done!"));
7367 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
7368 /*@notnull@*/ exprNode body)
7370 sRefSet tuses = test->uses;
7372 if (!sRefSet_isEmpty (test->uses))
7374 sRefSet sets = sRefSet_newCopy (body->sets);
7375 bool hasError = TRUE;
7376 bool innerState = FALSE;
7377 sRefSet tuncon = sRefSet_undefined;
7379 sets = sRefSet_union (sets, test->sets);
7380 sets = sRefSet_union (sets, body->msets);
7381 sets = sRefSet_union (sets, test->msets);
7383 sRefSet_allElements (tuses, el)
7385 if (sRef_isUnconstrained (el))
7387 tuncon = sRefSet_insert (tuncon, el);
7391 if (sRefSet_member (sets, el))
7398 if (sRef_isInternalState (el)
7399 || sRef_isFileStatic (sRef_getRootBase (el)))
7403 } end_sRefSet_allElements ;
7407 sRefSet suncon = sRefSet_undefined;
7408 bool sinner = FALSE;
7410 sRefSet_allElements (sets, el)
7412 if (sRef_isUnconstrained (el))
7414 suncon = sRefSet_insert (suncon, el);
7416 else if (sRef_isInternalState (el))
7424 } end_sRefSet_allElements ;
7426 if (sinner && innerState)
7430 else if (sRefSet_isEmpty (tuncon)
7431 && sRefSet_isEmpty (suncon))
7436 ("Suspected infinite loop. No value used in loop test (%q) "
7437 "is modified by test or loop body.",
7438 sRefSet_unparsePlain (tuses)),
7443 if (sRefSet_isEmpty (tuncon))
7447 message ("Suspected infinite loop. No condition values "
7448 "modified. Modification possible through "
7449 "unconstrained calls: %q",
7450 sRefSet_unparsePlain (suncon)),
7457 message ("Suspected infinite loop. No condition values "
7458 "modified. Possible undetected dependency through "
7459 "unconstrained calls in loop test: %q",
7460 sRefSet_unparsePlain (tuncon)),
7466 sRefSet_free (sets);
7470 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7473 bool emptyErr = FALSE;
7475 if (context_maybeSet (FLG_WHILEEMPTY))
7477 if (exprNode_isEmptyStatement (b))
7479 emptyErr = optgenerror
7482 ("Body of while statement is empty"),
7487 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7489 if (exprNode_isDefined (b)
7490 && !exprNode_isBlock (b))
7492 if (context_inIterDef ()
7493 && (b->kind == XPR_STMTLIST
7494 || b->kind == XPR_TOK))
7500 voptgenerror (FLG_WHILEBLOCK,
7502 ("Body of while statement is not a block: %s",
7503 exprNode_unparse (b)),
7509 if (exprNode_isError (t))
7511 if (exprNode_isError (b))
7513 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7517 ret = exprNode_createPartialCopy (b);
7524 ret = exprNode_createPartialCopy (t);
7526 llassert (t->kind == XPR_WHILEPRED);
7528 test = exprData_getSingle (t->edata);
7530 if (!exprNode_isError (b) && exprNode_isDefined (test))
7532 if (context_maybeSet (FLG_INFLOOPS)
7533 || context_maybeSet (FLG_INFLOOPSUNCON))
7536 ** check that some variable in the predicate is set by the body
7537 ** if the predicate uses any variables
7540 checkInfiniteLoop (test, b);
7543 exprNode_mergeUSs (ret, b);
7545 if (exprNode_isDefined (b))
7547 ret->exitCode = exitkind_makeConditional (b->exitCode);
7552 ret->edata = exprData_makePair (t, b);
7553 ret->kind = XPR_WHILE;
7555 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7559 message ("Predicate always exits: %s", exprNode_unparse (t)),
7563 ret->exitCode = XK_NEVERESCAPE;
7566 ** If loop is infinite, and there is no break inside,
7567 ** exit code is never reach.
7570 if (exprNode_knownIntValue (t))
7572 if (!exprNode_isZero (t))
7574 if (exprNode_isDefined (b))
7578 /* Really, it means never reached. */
7579 ret->exitCode = XK_MUSTEXIT;
7589 ret->canBreak = FALSE;
7590 ret->mustBreak = FALSE;
7596 ** do { b } while (t);
7598 ** note: body passed as first argument
7601 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7605 DPRINTF (("Do while: %s / %s",
7606 exprNode_unparse (b), exprNode_unparse (t)));
7608 if (exprNode_isError (t))
7610 if (exprNode_isError (b))
7612 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7616 ret = exprNode_createPartialCopy (b);
7618 ret->exitCode = exitkind_makeConditional (b->exitCode);
7619 exprNode_checkUse (ret, b->sref, b->loc);
7620 ret->exitCode = b->exitCode;
7621 ret->canBreak = b->canBreak;
7622 ret->mustBreak = FALSE;
7627 DPRINTF (("Do while: %s / %s",
7628 exitkind_unparse (t->exitCode),
7629 exitkind_unparse (b->exitCode)));
7631 ret = exprNode_createPartialCopy (t);
7632 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7634 if (!exprNode_isError (b))
7637 ** forgot the copy's --- why wasn't this detected??
7640 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7641 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7642 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
7644 /* left this out --- causes and aliasing bug (infinite loop)
7645 should be detected?? */
7647 exprNode_checkUse (ret, b->sref, b->loc);
7648 exprNode_mergeUSs (ret, t);
7649 exprNode_checkUse (ret, t->sref, t->loc);
7651 /* evans 2001-10-05: while loop can break */
7652 ret->exitCode = exitkind_makeConditional (b->exitCode);
7654 DPRINTF (("Do while: %s",
7655 exitkind_unparse (ret->exitCode)));
7657 ret->canBreak = b->canBreak;
7659 /* Always FALSE for doWhile loops - break's when test is false */
7660 ret->mustBreak = FALSE; /* b->mustBreak; */
7664 context_exitDoWhileClause (t);
7666 ret->kind = XPR_DOWHILE;
7667 ret->edata = exprData_makePair (t, b);
7671 bool exprNode_loopMustExec (exprNode forPred)
7674 ** Returns true if it is obvious that the loop always executes at least once
7676 ** For now, we only identify the most obvious cases. Should be true anytime
7677 ** we can prove init => !test.
7680 if (exprNode_isDefined (forPred))
7682 exprNode init, test, inc;
7685 llassert (forPred->kind == XPR_FORPRED);
7687 edata = forPred->edata;
7688 init = exprData_getTripleInit (edata);
7689 test = exprData_getTripleTest (edata);
7690 inc = exprData_getTripleInc (edata);
7692 if (exprNode_isAssign (init))
7694 exprNode loopVar = exprData_getOpA (init->edata);
7695 exprNode loopInit = exprData_getOpB (init->edata);
7697 if (exprNode_isDefined (test) && test->kind == XPR_OP)
7699 exprNode testVar = exprData_getOpA (test->edata);
7700 exprNode testVal = exprData_getOpB (test->edata);
7701 lltok comp = exprData_getOpTok (test->edata);
7702 int opid = lltok_getTok (comp);
7704 DPRINTF (("Same storage: %s / %s", exprNode_unparse (loopVar),
7705 exprNode_unparse (testVar)));
7707 if (exprNode_sameStorage (loopVar, testVar))
7709 multiVal valinit = exprNode_getValue (loopInit);
7710 multiVal valtest = exprNode_getValue (testVal);
7712 DPRINTF (("Values: %s / %s", multiVal_unparse (valinit),
7713 multiVal_unparse (valtest)));
7715 if (multiVal_isInt (valinit) && multiVal_isInt (valtest))
7717 long v1 = multiVal_forceInt (valinit);
7718 long v2 = multiVal_forceInt (valtest);
7720 DPRINTF (("Here: %ld %ld", v1, v2));
7722 if ((opid == EQ_OP && v1 < v2)
7723 || (opid == NE_OP && v1 != v2)
7724 || (opid == TLT && v1 <= v2)
7725 || (opid == TGT && v1 >= v2)
7726 || (opid == LE_OP && v1 < v2)
7727 || (opid == GE_OP && v1 > v2))
7729 DPRINTF (("mustexec if inc"));
7738 DPRINTF (("loop must exec: FALSE"));
7742 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7745 bool emptyErr = FALSE;
7747 if (context_maybeSet (FLG_FOREMPTY))
7749 if (exprNode_isEmptyStatement (body))
7751 emptyErr = optgenerror
7754 ("Body of for statement is empty"),
7755 exprNode_loc (body));
7759 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7761 if (exprNode_isDefined (body)
7762 && !exprNode_isBlock (body))
7764 if (context_inIterDef ()
7765 && (body->kind == XPR_STMTLIST
7766 || body->kind == XPR_TOK))
7772 voptgenerror (FLG_FORBLOCK,
7774 ("Body of for statement is not a block: %s",
7775 exprNode_unparse (body)),
7776 exprNode_loc (body));
7782 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7785 if (exprNode_isError (body))
7787 ret = exprNode_createPartialCopy (inc);
7791 ret = exprNode_createPartialCopy (body);
7793 ret->exitCode = exitkind_makeConditional (body->exitCode);
7795 exprNode_mergeUSs (inc, body);
7797 if (exprNode_isDefined (inc))
7801 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7803 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7804 exprNode_freeShallow (tmp);
7806 context_clearMessageAnnote ();
7807 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7809 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7810 exprNode_freeShallow (tmp);
7812 context_clearMessageAnnote ();
7814 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7815 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7816 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7820 ret->kind = XPR_FOR;
7821 ret->edata = exprData_makePair (inc, body);
7823 if (exprNode_isDefined (inc)) {
7824 exprNode test = exprData_getTripleTest (inc->edata);
7826 if (exprNode_isUndefined (test)) {
7827 if (exprNode_isDefined (body)) {
7828 if (!body->canBreak) {
7829 /* Really, it means never reached. */
7830 ret->exitCode = XK_MUSTEXIT;
7840 ** for (init; test; inc)
7843 ** while (test) { body; inc; }
7845 ** Now: check use of init (may set vars for test)
7846 ** check use of test
7850 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7854 if (exprNode_isError (pred)) return guardSet_undefined;
7856 llassert (pred->kind == XPR_FORPRED);
7858 test = exprData_getTripleTest (pred->edata);
7860 if (!exprNode_isError (test))
7862 return (test->guards);
7865 return guardSet_undefined;
7868 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7870 exprNode ret = exprNode_createSemiCopy (test);
7872 if (exprNode_isDefined (test))
7874 exprNode_copySets (ret, test);
7875 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7876 exprNode_checkUse (ret, test->sref, test->loc);
7878 exprNode_produceGuards (test);
7880 ret->guards = guardSet_copy (test->guards);
7883 ret->edata = exprData_makeSingle (test);
7884 ret->kind = XPR_WHILEPRED;
7888 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7889 /*@only@*/ exprNode inc)
7894 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7897 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7899 if (!exprNode_isError (inc))
7901 ret = exprNode_createPartialCopy (inc);
7905 if (!exprNode_isError (init))
7907 ret = exprNode_createPartialCopy (init);
7909 else if (!exprNode_isError (test))
7911 ret = exprNode_createPartialCopy (test);
7915 ret = exprNode_createUnknown ();
7919 exprNode_mergeUSs (ret, init);
7921 if (exprNode_isDefined (init))
7923 exprNode_checkUse (ret, init->sref, init->loc);
7926 exprNode_mergeUSs (ret, test);
7928 if (exprNode_isDefined (test))
7930 exprNode_checkUse (ret, test->sref, test->loc);
7933 ret->kind = XPR_FORPRED;
7934 ret->edata = exprData_makeFor (init, test, inc);
7938 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7940 exprNode ret = exprNode_createUnknown ();
7942 if (context_inMacro ())
7944 voptgenerror (FLG_MACROSTMT,
7945 message ("Macro %s uses goto (not functional)",
7946 context_inFunctionName ()),
7950 ret->kind = XPR_GOTO;
7951 ret->edata = exprData_makeLiteral (label);
7952 ret->mustBreak = TRUE;
7953 ret->exitCode = XK_GOTO;
7954 ret->canBreak = TRUE;
7958 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7960 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7962 ret->kind = XPR_CONTINUE;
7963 ret->edata = exprData_makeTok (l);
7964 ret->canBreak = TRUE;
7965 ret->mustBreak = TRUE;
7967 if (qcontinue == QSAFEBREAK)
7971 else if (qcontinue == QINNERCONTINUE)
7973 if (!context_inDeepLoop ())
7976 (FLG_LOOPLOOPCONTINUE,
7977 cstring_makeLiteral ("Continue statement marked with innercontinue "
7978 "is not inside a nested loop"),
7979 exprNode_loc (ret));
7982 else if (qcontinue == BADTOK)
7984 if (context_inDeepLoop ())
7987 (FLG_LOOPLOOPCONTINUE,
7988 cstring_makeLiteral ("Continue statement in nested loop"),
7989 exprNode_loc (ret));
7994 llbuglit ("exprNode_continue: bad qcontinue");
8000 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
8002 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
8003 clause breakClause = context_breakClause ();
8005 ret->kind = XPR_BREAK;
8006 ret->edata = exprData_makeTok (l);
8007 ret->canBreak = TRUE;
8008 ret->mustBreak = TRUE;
8010 if (breakClause == NOCLAUSE)
8014 cstring_makeLiteral ("Break not inside while, for or switch statement"),
8015 exprNode_loc (ret));
8019 if (bqual != BADTOK)
8026 if (breakClause == SWITCHCLAUSE)
8028 if (!context_inDeepSwitch ())
8030 voptgenerror (FLG_SYNTAX,
8032 ("Break preceded by innerbreak is not in a deep switch"),
8033 exprNode_loc (ret));
8038 if (!context_inDeepLoop ())
8040 voptgenerror (FLG_SYNTAX,
8042 ("Break preceded by innerbreak is not in a deep loop"),
8043 exprNode_loc (ret));
8048 if (breakClause == SWITCHCLAUSE)
8050 voptgenerror (FLG_SYNTAX,
8052 ("Break preceded by loopbreak is breaking a switch"),
8053 exprNode_loc (ret));
8057 if (breakClause != SWITCHCLAUSE)
8061 message ("Break preceded by switchbreak is breaking %s",
8062 cstring_makeLiteralTemp
8063 ((breakClause == WHILECLAUSE
8064 || breakClause == DOWHILECLAUSE) ? "a while loop"
8065 : (breakClause == FORCLAUSE) ? "a for loop"
8066 : (breakClause == ITERCLAUSE) ? "an iterator"
8068 exprNode_loc (ret));
8076 if (breakClause == SWITCHCLAUSE)
8078 clause nextBreakClause = context_nextBreakClause ();
8080 switch (nextBreakClause)
8082 case NOCLAUSE: break;
8088 (FLG_LOOPSWITCHBREAK,
8089 cstring_makeLiteral ("Break statement in switch inside loop"),
8090 exprNode_loc (ret));
8094 (FLG_SWITCHSWITCHBREAK,
8095 cstring_makeLiteral ("Break statement in switch inside switch"),
8096 exprNode_loc (ret));
8103 if (context_inDeepLoop ())
8107 cstring_makeLiteral ("Break statement in nested loop"),
8108 exprNode_loc (ret));
8112 if (context_inDeepLoopSwitch ())
8115 (FLG_SWITCHLOOPBREAK,
8116 cstring_makeLiteral ("Break statement in loop inside switch"),
8117 exprNode_loc (ret));
8127 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
8129 fileloc loc = lltok_getLoc (t);
8130 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
8132 context_returnFunction ();
8133 exprChecks_checkNullReturn (loc);
8135 ret->kind = XPR_NULLRETURN;
8136 ret->edata = exprData_makeTok (t);
8137 ret->exitCode = XK_MUSTRETURN;
8141 exprNode exprNode_return (/*@only@*/ exprNode e)
8145 if (exprNode_isError (e))
8147 ret = exprNode_createUnknown ();
8151 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
8153 exprNode_checkUse (ret, e->sref, e->loc);
8154 exprNode_checkReturn (e);
8157 context_returnFunction ();
8158 ret->kind = XPR_RETURN;
8159 ret->edata = exprData_makeSingle (e);
8160 ret->exitCode = XK_MUSTRETURN;
8165 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
8169 if (exprNode_isError (e1))
8171 if (exprNode_isError (e2))
8173 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
8177 ret = exprNode_createPartialCopy (e2);
8178 exprNode_checkUse (ret, e2->sref, e2->loc);
8179 ret->sref = e2->sref;
8184 ret = exprNode_createPartialCopy (e1);
8186 exprNode_checkUse (ret, e1->sref, e1->loc);
8188 if (!exprNode_isError (e2))
8190 exprNode_mergeUSs (ret, e2);
8191 exprNode_checkUse (ret, e2->sref, e2->loc);
8192 ret->sref = e2->sref;
8196 ret->kind = XPR_COMMA;
8197 ret->edata = exprData_makePair (e1, e2);
8199 if (exprNode_isDefined (e1))
8201 if (exprNode_isDefined (e2))
8205 if (exprNode_mustEscape (e1) || e1->mustBreak)
8209 message ("Second clause of comma expression is unreachable: %s",
8210 exprNode_unparse (e2)),
8214 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
8215 ret->mustBreak = e1->mustBreak || e2->mustBreak;
8216 ret->canBreak = e1->canBreak || e2->canBreak;
8220 if (exprNode_mustEscape (e1) || e1->mustBreak)
8224 message ("Second clause of comma expression is unreachable: %s",
8225 exprNode_unparse (e2)),
8229 ret->exitCode = e1->exitCode;
8230 ret->canBreak = e1->canBreak;
8235 if (exprNode_isDefined (e2))
8237 ret->exitCode = e2->exitCode;
8238 ret->mustBreak = e2->mustBreak;
8239 ret->canBreak = e2->canBreak;
8246 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
8248 ctype t1 = exprNode_getType (el);
8249 ctype t2 = exprNode_getType (val);
8250 bool hasError = FALSE;
8252 DPRINTF (("Check one init: %s / %s",
8253 exprNode_unparse (el),
8254 exprNode_unparse (val)));
8256 if (ctype_isUnknown (t1))
8258 voptgenerror (FLG_IMPTYPE,
8259 message ("Variable has unknown (implicitly int) type: %s",
8260 exprNode_unparse (el)),
8264 el->typ = ctype_int;
8267 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
8269 exprNodeList vals = exprData_getArgs (val->edata);
8271 DPRINTF (("Check one init: %s", exprNodeList_unparse (vals)));
8272 DPRINTF (("Type: %s", ctype_unparse (t1)));
8274 if (ctype_isRealAP (t1))
8279 if (ctype_isFixedArray (t1))
8281 size_t nelements = ctype_getArraySize (t1);
8283 DPRINTF (("Checked array: %s / %d",
8284 ctype_unparse (t1), nelements));
8286 if (exprNode_isStringLiteral (val))
8288 exprNode_checkStringLiteralLength (t1, val);
8292 if (exprNodeList_size (vals) != size_toInt (nelements))
8294 hasError = optgenerror
8295 (exprNodeList_size (vals) > size_toInt (nelements)
8296 ? FLG_INITSIZE : FLG_INITALLELEMENTS,
8297 message ("Initializer block for "
8298 "%s has %d element%&, but declared as %s: %q",
8299 exprNode_unparse (el),
8300 exprNodeList_size (vals),
8302 exprNodeList_unparse (vals)),
8308 exprNodeList_elements (vals, oneval)
8310 cstring istring = message ("%d", i);
8313 (exprNode_fakeCopy (el),
8314 exprNode_numLiteral (ctype_int, istring,
8315 fileloc_copy (el->loc), i));
8317 if (exprNode_isDefined (newel))
8319 if (exprNodeList_size (vals) == 1
8320 && ctype_isString (exprNode_getType (oneval))
8321 && ctype_isChar (exprNode_getType (newel)))
8323 exprNode_freeIniter (newel);
8327 if (exprNode_checkOneInit (newel, oneval))
8332 if (nerrors > 3 && exprNodeList_size (vals) > 6)
8335 (message ("Additional initialization errors "
8336 "for %s not reported",
8337 exprNode_unparse (el)),
8339 exprNode_freeIniter (newel);
8344 exprNode_freeIniter (newel);
8349 exprNode_freeIniter (newel);
8354 cstring_free (istring);
8357 } end_exprNodeList_elements;
8360 else if (ctype_isStruct (ctype_realType (t1)))
8362 uentryList fields = ctype_getFields (t1);
8365 if (uentryList_size (fields) != exprNodeList_size (vals))
8367 if (uentryList_size (fields) > exprNodeList_size (vals))
8369 hasError = optgenerror
8371 message ("Initializer block for "
8372 "%s has %d field%&, but %s has %d field%&: %q",
8373 exprNode_unparse (el),
8374 exprNodeList_size (vals),
8376 uentryList_size (fields),
8377 exprNodeList_unparse (vals)),
8382 hasError = optgenerror
8384 message ("Initializer block for "
8385 "%s has %d field%&, but %s has %d field%&: %q",
8386 exprNode_unparse (el),
8387 exprNodeList_size (vals),
8389 uentryList_size (fields),
8390 exprNodeList_unparse (vals)),
8396 exprNodeList_elements (vals, oneval)
8398 uentry thisfield = uentryList_getN (fields, i);
8400 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8402 uentry_getName (thisfield));
8404 if (exprNode_isDefined (newel))
8406 if (exprNode_checkOneInit (newel, oneval))
8411 exprNode_freeIniter (newel);
8415 } end_exprNodeList_elements;
8418 /* evans 2001-12-30: added to fix bug reported by Jim Zelenka */
8419 else if (ctype_isUnion (ctype_realType (t1)))
8421 uentryList fields = ctype_getFields (t1);
8425 ** Union initializers set the first member always.
8428 DPRINTF (("Union initializer: %s / %s",
8429 exprNode_unparse (el), ctype_unparse (ctype_realType (t1))));
8431 if (exprNodeList_size (vals) != 1)
8433 hasError = optgenerror
8435 message ("Initializer block for union "
8436 "%s has %d elements, union initializers should have one element: %q",
8437 exprNode_unparse (el),
8438 exprNodeList_size (vals),
8439 exprNodeList_unparse (vals)),
8444 exprNode oneval = exprNodeList_head (vals);
8445 uentry thisfield = uentryList_getN (fields, i);
8447 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8449 uentry_getName (thisfield));
8451 if (exprNode_isDefined (newel))
8453 if (exprNode_checkOneInit (newel, oneval))
8458 exprNode_freeIniter (newel);
8464 hasError = optgenerror
8466 message ("Initializer block used for "
8467 "%s where %t is expected: %s",
8468 exprNode_unparse (el), t1, exprNode_unparse (val)),
8474 if (exprNode_isDefined (val))
8476 doAssign (el, val, TRUE);
8478 if (!exprNode_matchType (t1, val))
8480 hasError = gentypeerror
8482 message ("Initial value of %s is type %t, "
8484 exprNode_unparse (el),
8485 t2, t1, exprNode_unparse (val)),
8494 static /*@notnull@*/ exprNode
8495 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
8499 DPRINTF (("Initialization: %s", idDecl_unparse (t)));
8501 if (usymtab_exists (idDecl_observeId (t)))
8503 uentry ue = usymtab_lookup (idDecl_observeId (t));
8504 ret = exprNode_createId (ue);
8510 DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
8512 ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
8513 ret = exprNode_fromIdentifierAux (ue);
8516 ** No error - this happens in old style declarations:
8520 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8527 exprData_free (ret->edata, ret->kind);
8528 ret->edata = exprData_undefined;
8529 ret->exitCode = XK_NEVERESCAPE;
8530 ret->mustBreak = FALSE;
8531 ret->kind = XPR_INIT;
8535 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8537 exprNode ret = exprNode_makeInitializationAux (t);
8538 llassert (ret->edata == exprData_undefined);
8539 ret->edata = exprData_makeInit (t, exprNode_undefined);
8543 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8544 /*@only@*/ exprNode e)
8546 uentry ue = usymtab_lookup (idDecl_observeId (t));
8547 exprNode ret = exprNode_makeInitializationAux (t);
8548 fileloc loc = exprNode_loc (e);
8550 DPRINTF (("initialization: %s = %s", idDecl_unparse (t), exprNode_unparse (e)));
8552 if (exprNode_isError (e))
8554 e = exprNode_createUnknown ();
8555 /* error: assume initializer is defined */
8556 sRef_setDefined (ret->sref, g_currentloc);
8557 ret->edata = exprData_makeInit (t, e);
8561 ctype ct = ctype_realishType (ret->typ);
8566 ** was addSafeUse --- what's the problem?
8568 ** int x = 3, y = x ?
8571 exprData_free (ret->edata, ret->kind);
8572 ret->edata = exprData_makeInit (t, e);
8573 DPRINTF (("ret: %s", exprNode_unparse (ret)));
8575 exprNode_checkUse (ret, e->sref, e->loc);
8577 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8579 exprNode lhs = exprNode_createId (ue);
8582 ** static storage should be undefined before initializing
8585 if (uentry_isStatic (ue))
8587 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8590 (void) exprNode_checkOneInit (lhs, e);
8592 if (uentry_isStatic (ue))
8594 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8597 exprNode_free (lhs);
8601 if (!exprNode_matchType (ct, e))
8603 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
8610 (exprNode_getType (e), e, exprNode_getType (ret), ret,
8612 ("Variable %q initialized to type %t, expects %t: %s",
8613 uentry_getName (ue), exprNode_getType (e),
8614 exprNode_getType (ret),
8615 exprNode_unparse (e)),
8621 if (uentry_isStatic (ue))
8623 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8626 if (exprNode_isStringLiteral (e)
8627 && (ctype_isArray (ct))
8628 && (ctype_isChar (ctype_realType (ctype_baseArrayPtr (ct)))))
8631 ** If t is a char [], the literal is copied.
8634 exprNode_checkStringLiteralLength (ct, e);
8635 sRef_setDefState (ret->sref, SS_DEFINED, e->loc);
8636 ret->val = multiVal_copy (e->val);
8638 sRef_setNullTerminatedState (ret->sref);
8640 if (multiVal_isDefined (e->val))
8642 cstring slit = multiVal_forceString (e->val);
8643 sRef_setLen (ret->sref, size_toInt (cstring_length (slit) + 1));
8646 if (ctype_isFixedArray (ct))
8648 sRef_setSize (ret->sref, size_toInt (ctype_getArraySize (ct)));
8653 doAssign (ret, e, TRUE);
8656 if (uentry_isStatic (ue))
8658 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8662 if (context_inIterDef ())
8664 /* should check if it is yield */
8665 uentry_setUsed (ue, loc);
8672 exprNode_mergeUSs (ret, e);
8673 DPRINTF (("Ret: %s %p %p",
8674 exprNode_unparse (ret),
8675 ret->requiresConstraints,
8676 ret->ensuresConstraints));
8678 DPRINTF (("Ret: %s %s %s",
8679 exprNode_unparse (ret),
8680 constraintList_unparse (ret->requiresConstraints),
8681 constraintList_unparse (ret->ensuresConstraints)));
8685 exprNode exprNode_iter (/*@observer@*/ uentry name,
8686 /*@only@*/ exprNodeList alist,
8687 /*@only@*/ exprNode body,
8688 /*@observer@*/ uentry end)
8693 llassert (uentry_isValid (name));
8695 uentry_setUsed (name, exprNode_loc (body));
8697 ret = exprNode_createPartialCopy (body);
8698 iname = uentry_getName (name);
8700 if (uentry_isInvalid (end))
8702 llerror (FLG_ITERBALANCE,
8703 message ("Iter %s not balanced with end_%s", iname, iname));
8707 cstring ename = uentry_getName (end);
8709 if (!cstring_equalPrefixLit (ename, "end_"))
8711 llerror (FLG_ITERBALANCE, message ("Iter %s not balanced with end_%s: %s",
8712 iname, iname, ename));
8716 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8718 llerror (FLG_ITERBALANCE,
8719 message ("Iter %s not balanced with end_%s: %s",
8720 iname, iname, ename));
8724 cstring_free (ename);
8727 context_exitIterClause (body);
8729 ret->kind = XPR_ITER;
8730 ret->edata = exprData_makeIter (name, alist, body, end);
8732 if (uentry_isIter (name))
8734 (void) checkArgsReal (name, body,
8735 uentry_getParams (name), alist, TRUE, ret);
8738 cstring_free (iname);
8744 exprNode_iterNewId (/*@only@*/ cstring s)
8746 exprNode e = exprNode_new ();
8747 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8749 llassert (processingIterVars ());
8751 e->loc = context_getSaveLocation ();
8753 if (fileloc_isUndefined (e->loc))
8755 fileloc_free (e->loc);
8756 e->loc = fileloc_copy (g_currentloc);
8759 e->uses = sRefSet_new ();
8760 e->sets = sRefSet_new ();
8761 e->msets = sRefSet_new ();
8763 e->val = multiVal_unknown ();
8764 e->guards = guardSet_new ();
8765 e->sref = sRef_undefined;
8766 e->isJumpPoint = FALSE;
8767 e->exitCode = XK_NEVERESCAPE;
8769 /*> missing fields, detected by splint <*/
8770 e->canBreak = FALSE;
8771 e->mustBreak = FALSE;
8772 e->etext = cstring_undefined;
8774 if (uentry_isYield (ue))
8776 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8777 fileloc_copy (e->loc),
8781 uue = usymtab_supEntrySrefReturn (uue);
8783 sr = uentry_getSref (uue);
8784 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8785 sr = uentry_getSref (uue);
8786 sRef_setDefined (sr, e->loc);
8788 e->typ = uentry_getType (uue);
8790 e->edata = exprData_makeId (uue);
8791 uentry_setUsed (uue, g_currentloc);
8797 sRef_setGlobalScope ();
8798 uue = uentry_makeVariableLoc (s, ctype_unknown);
8800 e->typ = ctype_unknown;
8801 e->edata = exprData_makeId (uue);
8803 uentry_setUsed (uue, e->loc);
8804 uentry_setHasNameError (uue);
8806 if (context_getFlag (FLG_REPEATUNRECOG))
8808 uentry_markOwned (uue);
8812 usymtab_supGlobalEntry (uue);
8815 sRef_clearGlobalScope ();
8817 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8824 exprNode_defineConstraints(e);
8829 exprNode_iterExpr (/*@returned@*/ exprNode e)
8831 if (!processingIterVars ())
8833 llcontbuglit ("checkIterParam: not in iter");
8837 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8840 if (exprNode_isDefined (e))
8842 if (fileloc_isDefined (e->loc))
8846 message ("Yield parameter is not simple identifier: %s",
8847 exprNode_unparse (e)),
8854 message ("Yield parameter is not simple identifier: %s",
8855 exprNode_unparse (e)),
8865 exprNode_iterId (/*@observer@*/ uentry c)
8869 llassert (processingIterVars ());
8871 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8874 if (uentry_isYield (ue))
8876 ctype ct = uentry_getType (ue);
8877 exprNode e = exprNode_createPlain (ct);
8878 cstring name = uentry_getName (c);
8879 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8881 uentry_setUsed (ue, g_currentloc);
8882 uentry_setHasNameError (ue);
8884 cstring_free (name);
8887 e->edata = exprData_makeId (le);
8888 e->loc = context_getSaveLocation ();
8889 e->sref = uentry_getSref (le);
8891 usymtab_supEntrySref (le);
8893 if (!context_inHeader ())
8897 message ("Yield parameter shadows local declaration: %q",
8898 uentry_getName (c)),
8899 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8901 uentry_showWhereDeclared (c);
8908 return (exprNode_fromIdentifierAux (c));
8911 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8913 exprNode ret = exprNode_create (ctype_unknown);
8915 ret->kind = XPR_ITERCALL;
8916 ret->edata = exprData_makeIterCall (name, alist);
8918 if (uentry_isIter (name))
8920 uentryList params = uentry_getParams (name);
8922 if (context_inIterDef ()
8923 && uentryList_size (params) == exprNodeList_size (alist))
8927 exprNodeList_elements (alist, arg)
8929 uentry parg = uentryList_getN (params, i);
8931 if (uentry_isYield (parg))
8933 uentry ue = exprNode_getUentry (arg);
8935 if (uentry_isValid (ue))
8942 } end_exprNodeList_elements;
8945 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8946 checkUnspecCall (ret, params, alist);
8952 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8954 if (exprNode_isDefined (e))
8956 if (sRef_isInvalid (e->sref))
8959 e->sref = sRef_makeUnknown ();
8960 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8971 return sRef_undefined;
8975 /*@observer@*/ cstring
8976 exprNode_unparseFirst (exprNode e)
8978 if (exprNode_isDefined (e))
8982 if (e->kind == XPR_STMTLIST
8983 || e->kind == XPR_COMMA || e->kind == XPR_COND)
8985 exprNode first = exprData_getPairA (e->edata);
8987 if (exprNode_isDefined (first))
8989 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8993 return (cstring_makeLiteralTemp ("..."));
8997 ret = cstring_elide (exprNode_unparse (e), 20);
8998 cstring_markOwned (ret);
9004 return cstring_makeLiteralTemp ("<error>");
9008 /*@observer@*/ cstring
9009 exprNode_unparse (/*@temp@*/ exprNode e)
9011 if (exprNode_isError (e))
9013 return cstring_makeLiteralTemp ("<error>");
9016 if (cstring_isDefined (e->etext))
9022 cstring ret = exprNode_doUnparse (e);
9024 /*@-modifies@*/ /* benevolent */
9031 /*@observer@*/ fileloc
9032 exprNode_loc (exprNode e)
9034 if (exprNode_isError (e))
9036 return (g_currentloc);
9045 ** executes exprNode e
9046 ** recursively rexecutes as though in original parse using
9047 ** information in e->edata
9050 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
9052 exprNodeList ret = exprNodeList_new ();
9054 exprNodeList_elements (e, current)
9056 exprNodeList_addh (ret, exprNode_effect (current));
9057 } end_exprNodeList_elements;
9062 static /*@only@*/ exprNode exprNode_effect (exprNode e)
9063 /*@globals internalState@*/
9065 bool innerEffect = inEffect;
9071 context_clearJustPopped ();
9073 if (exprNode_isError (e))
9075 ret = exprNode_undefined;
9080 ** Turn off expose and dependent transfer checking.
9081 ** Need to pass exposed internal nodes,
9082 ** [ copying would be a waste! ]
9083 ** [ Actually, I think I wasted a lot more time than its worth ]
9084 ** [ trying to do this. ]
9088 /*@-observertrans@*/
9089 /*@-dependenttrans@*/
9096 ret = exprNode_addParens (exprData_getUopTok (data),
9097 exprNode_effect (exprData_getUopNode (data)));
9100 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
9101 exprNode_effect (exprData_getOpB (data)),
9102 exprData_getOpTok (data));
9105 ret = exprNode_undefined;
9108 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
9109 exprNodeList_effect (exprData_getArgs (data)));
9122 cstring id = exprData_getId (data);
9123 uentry ue = usymtab_lookupSafe (id);
9125 ret = exprNode_fromIdentifierAux (ue);
9126 ret->loc = fileloc_update (ret->loc, e->loc);
9133 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
9134 exprNode_effect (exprData_getPairB (data)));
9138 ** evans 2002-03-15: for && and ||, need to do the guards also
9139 ** this is what cgrammar.y does - should be
9140 ** able to avoid duplication, but need to
9141 ** time with grammar productions.
9144 DPRINTF (("Effect: %s", exprNode_unparse (e)));
9146 if (lltok_getTok (exprData_getOpTok (data)) == AND_OP)
9148 exprNode e1 = exprNode_effect (exprData_getOpA (data));
9150 exprNode_produceGuards (e1);
9151 context_enterAndClause (e1);
9152 e2 = exprNode_effect (exprData_getOpB (data));
9154 ret = exprNode_op (e1, e2,
9155 exprData_getOpTok (data));
9157 context_exitAndClause (ret, e2);
9159 else if (lltok_getTok (exprData_getOpTok (data)) == OR_OP)
9161 exprNode e1 = exprNode_effect (exprData_getOpA (data));
9163 exprNode_produceGuards (e1);
9164 context_enterOrClause (e1);
9165 e2 = exprNode_effect (exprData_getOpB (data));
9167 ret = exprNode_op (e1, e2,
9168 exprData_getOpTok (data));
9170 context_exitOrClause (ret, e2);
9174 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
9175 exprNode_effect (exprData_getOpB (data)),
9176 exprData_getOpTok (data));
9181 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
9182 exprData_getUopTok (data));
9185 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
9186 exprData_getUopTok (data));
9198 ret = exprNode_vaArg (exprData_getCastTok (data),
9199 exprNode_effect (exprData_getCastNode (data)),
9200 exprData_getCastType (data));
9204 ret = exprNode_cast (exprData_getCastTok (data),
9205 exprNode_effect (exprData_getCastNode (data)),
9206 exprData_getCastType (data));
9209 ret = exprNode_iterStart (exprData_getIterCallIter (data),
9211 (exprData_getIterCallArgs (data)));
9215 ret = exprNode_iter (exprData_getIterSname (data),
9216 exprNodeList_effect (exprData_getIterAlist (data)),
9217 exprNode_effect (exprData_getIterBody (data)),
9218 exprData_getIterEname (data));
9222 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
9223 exprNode_effect (exprData_getPairB (data)));
9227 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
9228 exprNode_effect (exprData_getTripleTest (data)),
9229 exprNode_effect (exprData_getTripleInc (data)));
9233 ret = exprNode_createTok (exprData_getTok (data));
9237 ret = exprNode_goto (exprData_getLiteral (data));
9238 ret->loc = fileloc_update (ret->loc, e->loc);
9242 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
9246 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
9250 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
9253 case XPR_NULLRETURN:
9254 ret = exprNode_nullReturn (exprData_getTok (data));
9258 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
9259 exprNode_effect (exprData_getPairB (data)));
9263 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
9264 exprNode_effect (exprData_getTripleTrue (data)),
9265 exprNode_effect (exprData_getTripleFalse (data)));
9268 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
9269 exprNode_effect (exprData_getPairB (data)));
9273 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
9274 exprNode_effect (exprData_getTripleTrue (data)),
9275 exprNode_effect (exprData_getTripleFalse (data)));
9278 ret = exprNode_whilePred (exprData_getSingle (data));
9282 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
9283 exprNode_effect (exprData_getPairB (data)));
9287 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
9288 exprNode_effect (exprData_getPairB (data)));
9292 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
9296 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
9297 exprData_getUopTok (data));
9301 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
9302 exprNode_effect (exprData_getPairB (data)));
9307 ret = exprNode_caseMarker
9308 (exprNode_effect (exprData_getSingle (data)),
9314 ret = exprNode_createTok (exprData_getTok (data));
9318 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
9319 exprNode_effect (exprData_getPairB (data)));
9323 ret = exprNode_makeInitialization
9324 (exprData_getInitId (data),
9325 exprNode_effect (exprData_getInitNode (data)));
9329 ret = exprNode_fieldAccessAux
9330 (exprNode_effect (exprData_getFieldNode (data)),
9331 exprNode_loc (exprData_getFieldNode (data)),
9332 cstring_copy (exprData_getFieldName (data)));
9336 ret = exprNode_arrowAccessAux
9337 (exprNode_effect (exprData_getFieldNode (data)),
9338 exprNode_loc (exprData_getFieldNode (data)),
9339 cstring_copy (exprData_getFieldName (data)));
9342 case XPR_STRINGLITERAL:
9356 /*@=observertrans@*/
9358 /*@=dependenttrans@*/
9369 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
9374 if (exprNode_isError (e))
9376 return cstring_undefined;
9384 ret = exprNode_rootVarName (exprData_getUopNode (data));
9387 ret = exprNode_rootVarName (exprData_getOpA (data));
9391 ret = exprData_getId (data);
9394 ret = idDecl_getName (exprData_getInitId (data));
9419 case XPR_NULLRETURN:
9441 case XPR_STRINGLITERAL:
9442 ret = cstring_undefined;
9449 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
9454 if (exprNode_isError (e))
9456 static /*@only@*/ cstring error = cstring_undefined;
9458 if (!cstring_isDefined (error))
9460 error = cstring_makeLiteral ("<error>");
9471 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
9474 ret = message ("%s %s %s",
9475 exprNode_unparse (exprData_getOpA (data)),
9476 lltok_unparse (exprData_getOpTok (data)),
9477 exprNode_unparse (exprData_getOpB (data)));
9480 ret = message ("%s(%q)",
9481 exprNode_unparse (exprData_getFcn (data)),
9482 exprNodeList_unparse (exprData_getArgs (data)));
9485 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
9488 ret = cstring_undefined;
9491 ret = message ("%s:", exprData_getId (data));
9495 ret = cstring_copy (exprData_getId (data));
9498 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
9499 exprNode_unparse (exprData_getPairB (data)));
9502 ret = message ("<body>");
9505 ret = message ("%s %s %s",
9506 exprNode_unparse (exprData_getOpA (data)),
9507 lltok_unparse (exprData_getOpTok (data)),
9508 exprNode_unparse (exprData_getOpB (data)));
9512 ret = message ("%s%s",
9513 lltok_unparse (exprData_getUopTok (data)),
9514 exprNode_unparse (exprData_getUopNode (data)));
9518 ret = message ("%s%s",
9519 exprNode_unparse (exprData_getUopNode (data)),
9520 lltok_unparse (exprData_getUopTok (data)));
9524 ret = message ("offsetof(%s,%q)",
9525 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
9526 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
9530 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9534 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
9538 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9542 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
9546 ret = message ("va_arg(%s, %q)",
9547 exprNode_unparse (exprData_getCastNode (data)),
9548 qtype_unparse (exprData_getCastType (data)));
9552 ret = message ("%q(%q)",
9553 uentry_getName (exprData_getIterCallIter (data)),
9554 exprNodeList_unparse (exprData_getIterCallArgs (data)));
9557 ret = message ("%q(%q) %s %q",
9558 uentry_getName (exprData_getIterSname (data)),
9559 exprNodeList_unparse (exprData_getIterAlist (data)),
9560 exprNode_unparse (exprData_getIterBody (data)),
9561 uentry_getName (exprData_getIterEname (data)));
9564 ret = message ("(%q)%s",
9565 qtype_unparse (exprData_getCastType (data)),
9566 exprNode_unparse (exprData_getCastNode (data)));
9570 ret = message ("%s %s",
9571 exprNode_unparse (exprData_getPairA (data)),
9572 exprNode_unparse (exprData_getPairB (data)));
9576 ret = message ("for (%s; %s; %s)",
9577 exprNode_unparse (exprData_getTripleInit (data)),
9578 exprNode_unparse (exprData_getTripleTest (data)),
9579 exprNode_unparse (exprData_getTripleInc (data)));
9583 ret = message ("goto %s", exprData_getLiteral (data));
9587 ret = cstring_makeLiteral ("continue");
9591 ret = cstring_makeLiteral ("break");
9595 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
9598 case XPR_NULLRETURN:
9599 ret = cstring_makeLiteral ("return");
9603 ret = message ("%s, %s",
9604 exprNode_unparse (exprData_getPairA (data)),
9605 exprNode_unparse (exprData_getPairB (data)));
9609 ret = message ("%s ? %s : %s",
9610 exprNode_unparse (exprData_getTriplePred (data)),
9611 exprNode_unparse (exprData_getTripleTrue (data)),
9612 exprNode_unparse (exprData_getTripleFalse (data)));
9615 ret = message ("if (%s) %s",
9616 exprNode_unparse (exprData_getPairA (data)),
9617 exprNode_unparse (exprData_getPairB (data)));
9621 ret = message ("if (%s) %s else %s",
9622 exprNode_unparse (exprData_getTriplePred (data)),
9623 exprNode_unparse (exprData_getTripleTrue (data)),
9624 exprNode_unparse (exprData_getTripleFalse (data)));
9627 ret = message ("while (%s) %s",
9628 exprNode_unparse (exprData_getPairA (data)),
9629 exprNode_unparse (exprData_getPairB (data)));
9633 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9637 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9641 ret = message ("do { %s } while (%s)",
9642 exprNode_unparse (exprData_getPairB (data)),
9643 exprNode_unparse (exprData_getPairA (data)));
9647 ret = message ("{ %s }", exprNode_unparse (exprData_getSingle (data)));
9648 /* evans 2002-02-20 was unparseFirst! */
9652 ret = message ("%s;", exprNode_unparse (exprData_getUopNode (data)));
9656 if (exprNode_isStatement (exprData_getPairA (data)))
9659 ** statement expressions already print the ;
9662 ret = message ("%s %s",
9663 exprNode_unparse (exprData_getPairA (data)),
9664 exprNode_unparse (exprData_getPairB (data)));
9668 ret = message ("%s; %s",
9669 exprNode_unparse (exprData_getPairA (data)),
9670 exprNode_unparse (exprData_getPairB (data)));
9676 ret = cstring_makeLiteral ("default:");
9680 ret = message ("switch (%s) %s",
9681 exprNode_unparse (exprData_getPairA (data)),
9682 exprNode_unparse (exprData_getPairB (data)));
9687 ret = message ("case %s:",
9688 exprNode_unparse (exprData_getSingle (data)));
9692 if (exprNode_isError (exprData_getInitNode (data)))
9694 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9698 ret = message ("%q = %s",
9699 idDecl_unparseC (exprData_getInitId (data)),
9700 exprNode_unparse (exprData_getInitNode (data)));
9705 ret = message ("%s.%s",
9706 exprNode_unparse (exprData_getFieldNode (data)),
9707 exprData_getFieldName (data));
9711 ret = message ("%s->%s",
9712 exprNode_unparse (exprData_getFieldNode (data)),
9713 exprData_getFieldName (data));
9716 case XPR_STRINGLITERAL:
9717 if (ctype_isWideString (e->typ))
9719 ret = message ("L\"%s\"", exprData_getLiteral (data));
9723 ret = message ("\"%s\"", exprData_getLiteral (data));
9728 ret = cstring_copy (exprData_getLiteral (data));
9732 ret = cstring_makeLiteral ("<node>");
9740 exprNode_isInitializer (exprNode e)
9742 return (exprNode_isDefined (e)
9743 && e->kind == XPR_INIT);
9747 exprNode_isCharLiteral (exprNode e)
9749 if (exprNode_isDefined (e))
9751 return (multiVal_isChar (exprNode_getValue (e)));
9760 exprNode_isNumLiteral (exprNode e)
9762 if (exprNode_isDefined (e))
9764 return (multiVal_isInt (exprNode_getValue (e)));
9773 exprNode_isFalseConstant (exprNode e)
9775 if (exprNode_isDefined (e))
9777 cstring s = exprNode_rootVarName (e);
9779 if (cstring_equal (s, context_getFalseName ()))
9789 exprNode_matchLiteral (ctype expected, exprNode e)
9791 if (exprNode_isDefined (e))
9793 multiVal m = exprNode_getValue (e);
9795 if (multiVal_isDefined (m))
9797 if (multiVal_isInt (m))
9799 long int val = multiVal_forceInt (m);
9801 if (ctype_isNumAbstract (expected)
9802 && context_flagOn (FLG_NUMABSTRACTLIT, exprNode_loc (e)))
9807 if (ctype_isDirectBool (ctype_realishType (expected)))
9811 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9819 if (ctype_isRealInt (expected))
9822 ** unsigned <- [ constant >= 0 is okay ]
9825 if (ctype_isUnsigned (expected))
9834 ** No checks on sizes of integers...maybe add
9838 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9839 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9840 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9842 if (context_getFlag (FLG_NUMLITERAL)
9843 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9849 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9853 else if (ctype_isChar (expected))
9857 else if (ctype_isArrayPtr (expected))
9860 ** evans 2001-10-14: We allow 0 to match any pointer, but only if the type matches or is void *.
9865 if (ctype_match (exprNode_getType (e), expected)
9866 || ctype_isVoidPointer (exprNode_getType (e)))
9876 else if (ctype_isAnyFloat (expected))
9878 return (context_getFlag (FLG_NUMLITERAL));
9885 else if (multiVal_isDouble (m))
9887 if (ctype_isAnyFloat (expected))
9892 else if (multiVal_isChar (m))
9894 /*signed? */ char val = multiVal_forceChar (m);
9896 if (ctype_isChar (expected))
9898 if (ctype_isUnsigned (expected) && ((int) val) < 0)
9919 exprNode_matchType (ctype expected, exprNode e)
9923 if (!exprNode_isDefined (e)) return TRUE;
9925 actual = ctype_realishType (exprNode_getType (e));
9927 if (ctype_match (ctype_realishType (expected), actual))
9932 llassert (!exprNode_isError (e));
9933 return (exprNode_matchLiteral (expected, e));
9937 exprNode_matchTypes (exprNode e1, exprNode e2)
9942 if (!exprNode_isDefined (e1)) return TRUE;
9943 if (!exprNode_isDefined (e2)) return TRUE;
9946 ** realish type --- keep bools, bools
9949 t1 = ctype_realishType (exprNode_getType (e1));
9950 t2 = ctype_realishType (exprNode_getType (e2));
9952 if (ctype_match (t1, t2))
9957 DPRINTF (("Matching literal! %s %s %s %s",
9958 ctype_unparse (t1), exprNode_unparse (e2),
9959 ctype_unparse (t2), exprNode_unparse (e1)));
9961 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9969 exprNode_matchArgType (ctype ct, exprNode e)
9973 if (!exprNode_isDefined (e))
9978 et = ctype_realType (exprNode_getType (e));
9980 if (ctype_matchArg (ct, et)) return TRUE;
9982 llassert (!exprNode_isError (e));
9983 return (exprNode_matchLiteral (ct, e));
9986 static /*@only@*/ exprNodeSList
9987 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9989 if (exprNode_isDefined (e))
9991 if (e->kind == XPR_STMTLIST)
9993 return (exprNodeSList_append
9994 (exprNode_flatten (exprData_getPairA (e->edata)),
9995 exprNode_flatten (exprData_getPairB (e->edata))));
9997 else if (e->kind == XPR_BLOCK)
9999 return (exprNode_flatten (exprData_getSingle (e->edata)));
10003 return (exprNodeSList_singleton (e));
10007 return exprNodeSList_new ();
10010 static /*@exposed@*/ exprNode
10011 exprNode_lastStatement (/*@returned@*/ exprNode e)
10013 if (exprNode_isDefined (e))
10015 if (e->kind == XPR_STMTLIST)
10017 exprNode b = exprData_getPairB (e->edata);
10019 if (exprNode_isDefined (b))
10021 return exprNode_lastStatement (b);
10025 return exprNode_lastStatement (exprData_getPairA (e->edata));
10028 else if (e->kind == XPR_BLOCK)
10030 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
10038 return exprNode_undefined;
10041 static /*@exposed@*/ exprNode
10042 exprNode_firstStatement (/*@returned@*/ exprNode e)
10044 if (exprNode_isDefined (e))
10046 if (e->kind == XPR_STMTLIST)
10048 exprNode b = exprData_getPairA (e->edata);
10050 if (exprNode_isDefined (b))
10052 return exprNode_firstStatement (b);
10056 return exprNode_firstStatement (exprData_getPairB (e->edata));
10059 else if (e->kind == XPR_BLOCK)
10061 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
10069 return exprNode_undefined;
10073 exprNode_mergeUSs (exprNode res, exprNode other)
10075 if (exprNode_isDefined (res) && exprNode_isDefined (other))
10077 res->msets = sRefSet_union (res->msets, other->msets);
10078 res->sets = sRefSet_union (res->sets, other->sets);
10079 res->uses = sRefSet_union (res->uses, other->uses);
10084 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
10086 if (exprNode_isDefined (res))
10088 if (exprNode_isDefined (other1))
10090 res->sets = sRefSet_union (res->sets, other1->sets);
10091 res->msets = sRefSet_union (res->msets, other1->msets);
10092 res->uses = sRefSet_union (res->uses, other1->uses);
10094 if (exprNode_isDefined (other2))
10096 res->sets = sRefSet_union (res->sets, other2->sets);
10097 res->msets = sRefSet_union (res->msets, other2->msets);
10098 res->uses = sRefSet_union (res->uses, other2->uses);
10104 ** modifies e->uses
10106 ** Reports errors is s is not defined.
10110 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
10112 if (exprNode_isDefined (e))
10114 e->uses = sRefSet_insert (e->uses, s);
10119 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
10121 if (sRef_isKnown (s) && !sRef_isConst (s))
10124 ** need to check all outer types are useable
10127 DPRINTF (("Check use: %s / %s",
10128 exprNode_unparse (e), sRef_unparse (s)));
10130 exprNode_addUse (e, s);
10132 if (!context_inProtectVars ())
10135 ** only report the deepest error
10138 sRef errorRef = sRef_undefined;
10139 sRef lastRef = sRef_undefined;
10140 bool deadRef = FALSE;
10141 bool unuseable = FALSE;
10142 bool errorMaybe = FALSE;
10144 while (sRef_isValid (s) && sRef_isKnown (s))
10146 ynm readable = sRef_isValidLvalue (s);
10148 DPRINTF (("Readable: %s / %s",
10149 sRef_unparseFull (s), ynm_unparse (readable)));
10151 if (!(ynm_toBoolStrict (readable)))
10153 if (ynm_isMaybe (readable))
10155 lastRef = errorRef;
10157 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
10158 deadRef = sRef_isPossiblyDead (errorRef);
10159 unuseable = sRef_isUnuseable (errorRef);
10164 lastRef = errorRef;
10166 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
10167 deadRef = sRef_isDead (errorRef);
10168 unuseable = sRef_isUnuseable (errorRef);
10169 errorMaybe = FALSE;
10173 if (!sRef_isPartial (s))
10175 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
10176 sRef_setDefined (s, loc);
10177 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
10182 s = sRef_getBaseSafe (s);
10185 if (sRef_isValid (errorRef))
10187 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
10188 && sRef_isPointer (errorRef))
10190 errorRef = lastRef;
10191 DPRINTF (("errorRef: %s", sRef_unparseFull (errorRef)));
10196 if (sRef_isThroughArrayFetch (errorRef))
10199 (FLG_STRICTUSERELEASED,
10200 message ("%q %q may be used after being released",
10201 sRef_unparseKindNamePlain (errorRef),
10202 sRef_unparse (errorRef)),
10205 sRef_showRefKilled (errorRef);
10207 if (sRef_isKept (errorRef))
10209 sRef_clearAliasState (errorRef, loc);
10215 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
10219 message ("%q %q %qused after being released",
10220 sRef_unparseKindNamePlain (errorRef),
10221 sRef_unparse (errorRef),
10222 cstring_makeLiteral (errorMaybe
10223 ? "may be " : "")),
10226 sRef_showRefKilled (errorRef);
10228 if (sRef_isKept (errorRef))
10230 sRef_clearAliasState (errorRef, loc);
10235 else if (unuseable)
10239 message ("%q %q%qused in inconsistent state",
10240 sRef_unparseKindName (errorRef),
10241 sRef_unparseOpt (errorRef),
10242 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10245 sRef_showStateInconsistent (errorRef);
10250 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
10254 message ("%q %q%qused before definition",
10255 sRef_unparseKindName (errorRef),
10256 sRef_unparseOpt (errorRef),
10257 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10263 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
10266 sRef_setDefined (errorRef, loc);
10268 if (sRef_isAddress (errorRef))
10270 sRef_setDefined (sRef_getRootBase (errorRef), loc);
10272 } /* end is error */
10280 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
10282 if (exprNode_isDefined (e) && sRef_isKnown (s))
10284 e->uses = sRefSet_insert (e->uses, s);
10289 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
10291 if (exprNode_isDefined (e))
10293 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
10298 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
10300 sRef defines = sRef_undefined;
10302 if (sRef_isValid (s) && !sRef_isNothing (s))
10304 uentry ue = sRef_getBaseUentry (s);
10306 if (uentry_isValid (ue))
10308 uentry_setLset (ue);
10311 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10313 voptgenerror (FLG_USEDEF,
10314 message ("Attempt to set unuseable storage: %q",
10319 if (sRef_isMeaningful (s))
10321 if (sRef_isDead (s))
10323 sRef base = sRef_getBaseSafe (s);
10325 if (sRef_isValid (base)
10326 && sRef_isDead (base))
10328 sRef_setPartial (s, exprNode_loc (e));
10331 defines = s; /* okay - modifies for only param */
10333 else if (sRef_isPartial (s))
10335 sRef eref = exprNode_getSref (e);
10337 if (!sRef_isPartial (eref))
10340 ** should do something different here???
10343 sRef_setDefinedComplete (eref, exprNode_loc (e));
10347 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
10350 if (sRef_isMeaningful (eref))
10359 else if (sRef_isAllocated (s))
10361 sRef eref = exprNode_getSref (e);
10364 if (!sRef_isAllocated (eref))
10366 sRef_setDefinedComplete (eref, exprNode_loc (e));
10370 sRef base = sRef_getBaseSafe (eref);
10372 if (sRef_isValid (base))
10374 sRef_setPdefined (base, exprNode_loc (e));
10382 sRef_setDefinedNCComplete (s, exprNode_loc (e));
10387 else /* not meaningful...but still need to insert it */
10393 if (exprNode_isDefined (e) && sRef_isValid (defines))
10395 e->sets = sRefSet_insert (e->sets, defines);
10400 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
10402 if (sRef_isValid (s) && !sRef_isNothing (s))
10404 uentry ue = sRef_getBaseUentry (s);
10406 if (uentry_isValid (ue))
10408 uentry_setLset (ue);
10411 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10413 voptgenerror (FLG_USEDEF,
10414 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
10418 if (sRef_isMeaningful (s))
10420 sRef_setDefinedComplete (s, exprNode_loc (e));
10423 if (exprNode_isDefined (e))
10425 e->msets = sRefSet_insert (e->msets, s);
10431 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
10433 checkAnyCall (fcn, cstring_undefined, params, args,
10434 FALSE, sRefSet_undefined, FALSE, 0);
10438 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
10439 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
10443 if (uentry_isYield (ucurrent))
10445 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
10446 exprNode_checkSet (current, current->sref);
10450 if (uentry_isSefParam (ucurrent))
10452 sRefSet sets = current->sets;
10453 sRef ref = exprNode_getSref (current);
10455 if (sRef_isMacroParamRef (ref))
10457 uentry ue = sRef_getUentry (ref);
10459 if (!uentry_isSefParam (ue))
10464 ("Parameter %d to %s is declared sef, but "
10465 "the argument is a macro parameter declared "
10467 argno, exprNode_unparse (fcn),
10468 exprNode_unparse (current)),
10469 exprNode_loc (current));
10473 if (!sRefSet_isEmpty (sets))
10475 sRefSet reported = sRefSet_undefined;
10477 sRefSet_realElements (current->sets, el)
10479 if (sRefSet_isSameNameMember (reported, el))
10481 ; /* don't report again */
10485 if (sRef_isUnconstrained (el))
10490 ("Parameter %d to %s is declared sef, but "
10491 "the argument calls unconstrained function %s "
10492 "(no guarantee it will not modify something): %s",
10493 argno, exprNode_unparse (fcn),
10494 sRef_unconstrainedName (el),
10495 exprNode_unparse (current)),
10496 exprNode_loc (current));
10503 ("Parameter %d to %s is declared sef, but "
10504 "the argument may modify %q: %s",
10505 argno, exprNode_unparse (fcn),
10507 exprNode_unparse (current)),
10508 exprNode_loc (current));
10511 } end_sRefSet_realElements;
10515 transferChecks_passParam (current, ucurrent, isSpec, fcn, argno, totargs);
10516 exprNode_mergeUSs (fcn, current);
10521 checkAnyCall (/*@dependent@*/ exprNode fcn,
10522 /*@dependent@*/ cstring fname,
10525 bool hasMods, sRefSet mods,
10530 int nargs = exprNodeList_size (args);
10535 ** concat all args ud's to f, add each arg sref as a use unless
10536 ** it was specified as "out", in which case it is a def.
10539 uentryList_reset (pn);
10542 ** aliasing checks:
10544 ** if paramn is only or unique, no other arg may alias argn
10547 exprNodeList_elements (args, current)
10551 if (exprNode_isDefined (current))
10553 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
10555 uentry ucurrent = uentryList_current (pn);
10557 if (specialArgs == 0
10558 || (paramno < specialArgs))
10560 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
10562 if (context_maybeSet (FLG_ALIASUNIQUE))
10564 if (uentry_isOnly (ucurrent)
10565 || uentry_isUnique (ucurrent))
10567 checkUniqueParams (fcn, current, args,
10568 paramno, ucurrent);
10573 else /* uentry is undefined */
10575 if (specialArgs == 0)
10577 exprNode_checkUseParam (current);
10580 exprNode_mergeUSs (fcn, current);
10583 uentryList_advanceSafe (pn);
10584 } end_exprNodeList_elements;
10590 sRefSet_allElements (mods, s)
10593 sRef rb = sRef_getRootBase (s);
10595 if (sRef_isFileOrGlobalScope (rb))
10597 context_usedGlobal (rb);
10600 fb = sRef_fixBaseParam (s, args);
10602 if (!sRef_isMacroParamRef (fb))
10604 if (sRef_isNothing (fb))
10610 if (sRef_isValid (fb))
10612 uentry ue = sRef_getBaseUentry (s);
10614 if (uentry_isValid (ue))
10616 uentry_setLset (ue);
10620 fcn->sets = sRefSet_insert (fcn->sets, fb);
10623 sRef_clearDerivedComplete (s);
10624 } end_sRefSet_allElements;
10630 if (context_hasMods ())
10632 if (context_maybeSet (FLG_MODUNCON))
10636 message ("Undetected modification possible "
10637 "from call to unconstrained function %s: %s",
10639 exprNode_unparse (fcn)),
10640 exprNode_loc (fcn));
10645 if (context_maybeSet (FLG_MODUNCONNOMODS)
10646 && !(context_inIterDef () || context_inIterEnd ()))
10649 (FLG_MODUNCONNOMODS,
10650 message ("Undetected modification possible "
10651 "from call to unconstrained function %s: %s",
10653 exprNode_unparse (fcn)),
10654 exprNode_loc (fcn));
10658 exprNode_checkSetAny (fcn, fname);
10662 void exprNode_checkUseParam (exprNode current)
10664 if (exprNode_isDefined (current))
10666 exprNode_checkUse (current, current->sref, current->loc);
10671 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10672 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10677 if (!ctype_match (tr1, tr2))
10679 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10680 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10682 DPRINTF (("No error: [%s] %s / [%s] %s",
10683 exprNode_unparse (e1), ctype_unparse (tr1),
10684 exprNode_unparse (e2), ctype_unparse (tr2)));
10686 ret = ctype_biggerType (tr1, tr2);
10690 if (ctype_isNumAbstract (tr1)
10691 && exprNode_isNumLiteral (e2)
10692 && context_flagOn (FLG_NUMABSTRACTLIT, e1->loc))
10694 ret = tr1; /* No error */
10696 else if (ctype_isNumAbstract (tr2)
10697 && exprNode_isNumLiteral (e1)
10698 && context_flagOn (FLG_NUMABSTRACTLIT, e1->loc))
10706 message ("Incompatible types for %s (%s, %s): %s %s %s",
10707 lltok_unparse (op),
10708 ctype_unparse (te1),
10709 ctype_unparse (te2),
10710 exprNode_unparse (e1), lltok_unparse (op),
10711 exprNode_unparse (e2)),
10714 ret = ctype_unknown;
10718 ret = ctype_biggerType (tr1, tr2);
10725 if (ctype_isNumAbstract (tr1))
10729 else if (ctype_isForceRealNumeric (&tr1)
10730 && ctype_isForceRealNumeric (&tr2))
10732 ret = ctype_resolveNumerics (tr1, tr2);
10734 else if (!context_msgStrictOps ())
10736 if (ctype_isPointer (tr1))
10738 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10742 else if (ctype_isInt (tr2))
10748 ret = ctype_unknown;
10751 else if (ctype_isPointer (tr2))
10753 if (ctype_isPointer (tr1))
10757 else if (ctype_isInt (tr1))
10763 ret = ctype_unknown;
10768 ret = ctype_resolveNumerics (tr1, tr2);
10773 int opid = lltok_getTok (op);
10774 bool comparop = (opid == EQ_OP || opid == NE_OP
10775 || opid == TLT || opid == TGT
10776 || opid == LE_OP || opid == GE_OP);
10778 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10781 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10782 || (ctype_isBool (tr1) && ctype_isBool (tr2))
10783 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10789 if (ctype_sameName (te1, te2))
10793 message ("Operands of %s are non-numeric (%t): %s %s %s",
10794 lltok_unparse (op), te1,
10795 exprNode_unparse (e1), lltok_unparse (op),
10796 exprNode_unparse (e2)),
10803 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10804 lltok_unparse (op), te1, te2,
10805 exprNode_unparse (e1), lltok_unparse (op),
10806 exprNode_unparse (e2)),
10811 else if (!ctype_isNumeric (tr1))
10815 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10816 lltok_unparse (op), te1,
10817 exprNode_unparse (e1), lltok_unparse (op),
10818 exprNode_unparse (e2)),
10823 if (!ctype_isNumeric (tr2))
10827 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10828 lltok_unparse (op), te2,
10829 exprNode_unparse (e1), lltok_unparse (op),
10830 exprNode_unparse (e2)),
10835 ret = ctype_unknown;
10843 abstractOpError (ctype tr1, ctype tr2, lltok op,
10844 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10845 fileloc loc1, fileloc loc2)
10847 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10849 if (ctype_match (tr1, tr2))
10851 if (ctype_isRealNumAbstract (tr1))
10853 ; /* No warning for numabstract types */
10857 if (lltok_isEqOp (op) || lltok_isNotEqOp (op))
10860 (FLG_ABSTRACTCOMPARE,
10861 message ("Object equality comparison (%s) on objects of abstract type (%t): %s %s %s",
10862 lltok_unparse (op), tr1,
10863 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10870 message ("Operands of %s are abstract type (%t): %s %s %s",
10871 lltok_unparse (op), tr1,
10872 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10879 if (ctype_isRealNumAbstract (tr1) && ctype_isRealNumAbstract (tr2))
10884 ("Operands of %s are different numabstract types (%t, %t): %s %s %s",
10885 lltok_unparse (op), tr1, tr2,
10886 exprNode_unparse (e1),
10887 lltok_unparse (op), exprNode_unparse (e2)),
10894 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10895 lltok_unparse (op), tr1, tr2,
10896 exprNode_unparse (e1), lltok_unparse (op),
10897 exprNode_unparse (e2)),
10902 else if (ctype_isRealAbstract (tr1) && !ctype_isRealNumAbstract (tr1))
10906 message ("Left operand of %s is abstract type (%t): %s %s %s",
10907 lltok_unparse (op), tr1,
10908 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10913 if (ctype_isRealAbstract (tr2) && !ctype_isRealNumAbstract (tr2))
10917 message ("Right operand of %s is abstract type (%t): %s %s %s",
10918 lltok_unparse (op), tr2,
10919 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10930 ** requies e1 and e2 and not error exprNode's.
10934 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10935 ** the rep of the abstract type is exposed.
10937 ** The order is very important:
10939 ** check rep expose (move into check transfer)
10945 ** This isn't really a sensible procedure, but the indententation
10946 ** was getting too deep.
10950 checkOneRepExpose (sRef ysr, sRef base,
10951 /*@notnull@*/ exprNode e1,
10952 /*@notnull@*/ exprNode e2, ctype ct,
10955 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
10956 || sRef_isOwned (ysr)
10957 || sRef_isExposed (ysr)))
10959 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10960 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10963 if (sRef_isIReference (ysr))
10965 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10970 ("Assignment of mutable component of parameter %q "
10971 "to component of abstract "
10972 "type %s exposes rep: %s = %s",
10973 sRef_unparse (base),
10974 ctype_unparse (ct),
10975 exprNode_unparse (e1), exprNode_unparse (e2)),
10983 ("Assignment of mutable component of parameter %q "
10984 "(through alias %q) to component of abstract "
10985 "type %s exposes rep: %s = %s",
10986 sRef_unparse (base),
10987 sRef_unparse (e2->sref),
10988 ctype_unparse (ct),
10989 exprNode_unparse (e1), exprNode_unparse (e2)),
10995 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10999 message ("Assignment of mutable parameter %q "
11000 "to component of abstract type %s "
11001 "exposes rep: %s = %s",
11002 sRef_unparse (base),
11003 ctype_unparse (ct),
11004 exprNode_unparse (e1),
11005 exprNode_unparse (e2)),
11012 message ("Assignment of mutable parameter %q "
11013 "(through alias %q) to "
11014 "component of abstract type %s exposes "
11016 sRef_unparse (base),
11017 sRef_unparse (e2->sref),
11018 ctype_unparse (ct),
11019 exprNode_unparse (e1),
11020 exprNode_unparse (e2)),
11026 if (sRef_isFileOrGlobalScope (s2b))
11028 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
11032 message ("Assignment of global %q "
11034 "abstract type %s exposes rep: %s = %s",
11035 sRef_unparse (base),
11036 ctype_unparse (ct),
11037 exprNode_unparse (e1), exprNode_unparse (e2)),
11044 message ("Assignment of global %q (through alias %q) "
11046 "abstract type %s exposes rep: %s = %s",
11047 sRef_unparse (base),
11048 sRef_unparse (e2->sref),
11049 ctype_unparse (ct),
11050 exprNode_unparse (e1), exprNode_unparse (e2)),
11058 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
11060 DPRINTF (("Do assign: %s <- %s",
11061 exprNode_unparse (e1), exprNode_unparse (e2)));
11062 DPRINTF (("Ctype: %s", ctype_unparse (exprNode_getType (e1))));
11064 if (ctype_isRealFunction (exprNode_getType (e1))
11065 && !ctype_isRealPointer (exprNode_getType (e1)))
11069 message ("Invalid left-hand side of assignment (function type %s): %s",
11070 ctype_unparse (exprNode_getType (e1)),
11071 exprNode_unparse (e1)),
11075 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
11077 ctype t2 = exprNode_getType (e2);
11078 sRef sr = sRef_getRootBase (e1->sref);
11079 ctype ct = sRef_getType (sr);
11081 if (ctype_isAbstract (t2)
11082 && !ctype_isNumAbstract (t2)
11083 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
11085 /* it is immutable, okay to reference */
11086 goto donerepexpose;
11089 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
11091 sRef s2b = sRef_getRootBase (e2->sref);
11092 sRef s1 = e1->sref;
11093 sRef s1b = sRef_getRootBase (s1);
11096 aliases = usymtab_canAlias (e2->sref);
11098 if (!sRef_similar (s2b, s1b)
11099 && !sRef_isExposed (s1)
11100 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
11102 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
11103 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
11104 && !sRef_isExposed (s2b))
11106 if (sRef_isIReference (e2->sref))
11111 ("Assignment of mutable component of parameter %q "
11112 "to component of abstract type %s exposes rep: %s = %s",
11113 sRef_unparse (s2b),
11114 ctype_unparse (ct),
11115 exprNode_unparse (e1), exprNode_unparse (e2)),
11122 message ("Assignment of mutable parameter %q to "
11123 "component of abstract type %s exposes rep: %s = %s",
11124 sRef_unparse (s2b),
11125 ctype_unparse (ct),
11126 exprNode_unparse (e1), exprNode_unparse (e2)),
11131 if (sRef_isFileOrGlobalScope (s2b))
11135 message ("Assignment of global %q to component of "
11136 "abstract type %s exposes rep: %s = %s",
11137 sRef_unparse (s2b),
11138 ctype_unparse (ct),
11139 exprNode_unparse (e1), exprNode_unparse (e2)),
11143 sRefSet_realElements (aliases, ysr)
11145 sRef base = sRef_getRootBase (ysr);
11147 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
11148 || sRef_sameName (base, s1b))
11150 ; /* error already reported or same sref */
11154 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
11156 } end_sRefSet_realElements;
11158 sRefSet_free (aliases);
11165 ** function variables don't really work...
11168 if (!ctype_isFunction (ctype_realType (e2->typ)))
11172 DPRINTF (("Check init: %s / %s",
11173 exprNode_unparse (e1), exprNode_unparse (e2)));
11174 transferChecks_initialization (e1, e2);
11178 transferChecks_assign (e1, e2);
11183 sRef fref = e2->sref;
11185 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
11186 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
11188 /* Need to typecheck the annotation on the parameters */
11190 if (ctype_isRealFunction (e1->typ)) {
11191 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
11192 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
11194 if (!uentryList_isMissingParams (e1p)
11195 && !uentryList_isMissingParams (e2p)
11196 && uentryList_size (e1p) > 0) {
11197 if (uentryList_size (e1p) == uentryList_size (e2p)) {
11200 uentryList_elements (e1p, el1) {
11203 el2 = uentryList_getN (e2p, n);
11205 uentry_checkMatchParam (el1, el2, n, e2);
11206 } end_uentryList_elements;
11212 if (exprNode_isStringLiteral (e2))
11214 exprNode_checkStringLiteralLength (exprNode_getType (e1), e2);
11217 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
11223 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
11224 updateAliases (e1, e2);
11229 checkMacroParen (exprNode e)
11231 if (exprNode_isError (e) || e->kind == XPR_CAST)
11237 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
11241 message ("Macro parameter used without parentheses: %s",
11242 exprNode_unparse (e)),
11249 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
11253 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
11257 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
11264 ** if e2 is a parameter or global derived location which
11265 ** can be modified (that is, e2 is a mutable abstract type,
11266 ** or a derived pointer), then e1 can alias e2.
11268 ** e1 can alias everything which e2 can alias.
11270 ** Also, if e1 is guarded, remove from guard sets!
11273 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
11275 if (!context_inProtectVars ())
11278 ** depends on types of e1 and e2
11281 sRef s1 = e1->sref;
11282 sRef s2 = e2->sref;
11283 ctype t1 = exprNode_getType (e1);
11285 /* handle pointer sRefs, record fields, arrays, etc... */
11287 if (!ctype_isRealSU (t1))
11289 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
11290 sRef_copyRealDerivedComplete (s1, s2);
11295 ** Fields should alias
11298 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
11301 if (ctype_isMutable (t1) && sRef_isKnown (s1))
11303 usymtab_clearAlias (s1);
11304 usymtab_addMustAlias (s1, s2);
11305 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
11309 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
11312 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
11314 usymtab_unguard (s1);
11319 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
11321 if (exprNode_isDefined (e))
11323 e->loc = fileloc_update (e->loc, loc);
11327 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
11333 static void checkUniqueParams (exprNode fcn,
11334 /*@notnull@*/ exprNode current,
11336 int paramno, uentry ucurrent)
11339 sRef thisref = exprNode_getSref (current);
11342 ** Check if any argument could match this argument.
11345 exprNodeList_elements (args, icurrent)
11349 if (iparamno != paramno)
11351 sRef sr = exprNode_getSref (icurrent);
11353 if (sRef_similarRelaxed (thisref, sr))
11355 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
11360 ("Parameter %d (%s) to function %s is declared %s but "
11361 "is aliased by parameter %d (%s)",
11363 exprNode_unparse (current),
11364 exprNode_unparse (fcn),
11365 alkind_unparse (uentry_getAliasKind (ucurrent)),
11366 iparamno, exprNode_unparse (icurrent)),
11372 sRefSet aliases = usymtab_canAlias (sr);
11374 sRefSet_allElements (aliases, asr)
11376 if (ctype_isUnknown (sRef_getType (thisref)))
11378 sRef_setType (thisref, uentry_getType (ucurrent));
11381 if (sRef_similarRelaxed (thisref, asr))
11383 if (sRef_isExternal (asr))
11385 if (sRef_isLocalState (thisref))
11391 sRef base = sRef_getRootBase (asr);
11393 if (!sRef_similar (sRef_getBase (asr), thisref))
11395 if (sRef_isUnique (base) || sRef_isOnly (base)
11396 || sRef_isKept (base)
11397 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
11398 || (sRef_isAddress (thisref)
11399 && sRef_isLocalVar (sRef_getRootBase (thisref))))
11401 ; /* okay, no error */
11406 (FLG_MAYALIASUNIQUE,
11408 ("Parameter %d (%s) to function %s is declared %s but "
11409 "may be aliased externally by parameter %d (%s)",
11411 exprNode_unparse (current),
11412 exprNode_unparse (fcn),
11413 alkind_unparse (uentry_getAliasKind (ucurrent)),
11414 iparamno, exprNode_unparse (icurrent)),
11425 ("Parameter %d (%s) to function %s is declared %s but "
11426 "is aliased externally by parameter %d (%s) through "
11429 exprNode_unparse (current),
11430 exprNode_unparse (fcn),
11431 alkind_unparse (uentry_getAliasKind (ucurrent)),
11432 iparamno, exprNode_unparse (icurrent),
11433 sRef_unparse (asr)),
11437 } end_sRefSet_allElements;
11438 sRefSet_free (aliases);
11441 } end_exprNodeList_elements;
11444 long exprNode_getLongValue (exprNode e)
11448 if (exprNode_hasValue (e) && multiVal_isInt (exprNode_getValue (e)))
11450 value = multiVal_forceInt (exprNode_getValue (e));
11454 value = 0; /* Unknown value */
11460 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
11463 ** Returns the location of the sequence point following e.
11465 ** Only works for statements (for now).
11468 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
11469 lltok t = exprData_getUopTok (e->edata);
11470 return fileloc_copy(lltok_getLoc (t));
11472 /* drl possible problem : warning fix
11473 llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
11475 return fileloc_undefined;
11479 exprNode exprNode_createNew(ctype c)
11483 ret = exprNode_createPlain (c);
11488 bool exprNode_isInitBlock (exprNode e)
11490 return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);
11493 /*drl 3/2/2003 moved this function out of constraint.c */
11494 exprNode exprNode_copyConstraints (/*@returned@*/ exprNode dst, exprNode src)
11497 llassert (exprNode_isDefined (dst) );
11498 llassert (exprNode_isDefined (src) );
11500 constraintList_free (dst->ensuresConstraints);
11501 constraintList_free (dst->requiresConstraints);
11502 constraintList_free (dst->trueEnsuresConstraints);
11503 constraintList_free (dst->falseEnsuresConstraints);
11505 dst->ensuresConstraints = constraintList_copy (src->ensuresConstraints);
11506 dst->requiresConstraints = constraintList_copy (src->requiresConstraints);
11507 dst->trueEnsuresConstraints = constraintList_copy (src->trueEnsuresConstraints);
11508 dst->falseEnsuresConstraints = constraintList_copy (src->falseEnsuresConstraints);