2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 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 "cgrammar_tokens.h"
35 # include "exprChecks.h"
36 # include "transferChecks.h"
37 # include "exprNodeSList.h"
39 static bool exprNode_sameStorage (exprNode p_e1, exprNode p_e2) /*@*/ ;
40 static bool exprNode_isEmptyStatement (exprNode p_e);
41 static /*@exposed@*/ exprNode exprNode_firstStatement (/*@returned@*/ exprNode p_e);
42 static bool exprNode_isFalseConstant (exprNode p_e) /*@*/ ;
43 static bool exprNode_isStatement (exprNode p_e);
44 static void checkGlobUse (uentry p_glob, bool p_isCall, /*@notnull@*/ exprNode p_e);
45 static void exprNode_addUse (exprNode p_e, /*@exposed@*/ sRef p_s);
46 static bool exprNode_matchArgType (ctype p_ct, exprNode p_e);
47 static exprNode exprNode_fakeCopy (exprNode p_e) /*@*/ ;
48 static exprNode exprNode_statementError (/*@only@*/ exprNode p_e, /*@only@*/ lltok p_t);
49 static bool exprNode_matchTypes (exprNode p_e1, exprNode p_e2);
50 static void checkUniqueParams (exprNode p_fcn,
51 /*@notnull@*/ exprNode p_current, exprNodeList p_args,
52 int p_paramno, uentry p_ucurrent);
53 static void updateAliases (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2);
54 static bool abstractOpError (ctype p_tr1, ctype p_tr2, lltok p_op,
55 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2,
56 fileloc p_loc1, fileloc p_loc2)
57 /*@modifies g_warningstream@*/ ;
58 static ctype checkNumerics (ctype p_tr1, ctype p_tr2, ctype p_te1, ctype p_te2,
59 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, lltok p_op);
60 static void doAssign (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, bool p_isInit);
61 static void checkSafeUse (exprNode p_e, /*@exposed@*/ sRef p_s);
62 static void reflectNullTest (/*@notnull@*/ exprNode p_e, bool p_isnull);
63 static void checkMacroParen (exprNode p_e);
64 static exprNodeSList exprNode_flatten (/*@dependent@*/ exprNode p_e);
65 static void exprNode_checkSetAny (exprNode p_e, /*@dependent@*/ cstring p_name);
66 static void exprNode_checkUse (exprNode p_e, /*@exposed@*/ sRef p_s, fileloc p_loc);
67 static void exprNode_mergeUSs (exprNode p_res, exprNode p_other);
68 static void exprNode_mergeCondUSs (exprNode p_res, exprNode p_other1, exprNode p_other2);
69 static /*@only@*/ /*@notnull@*/ exprNode exprNode_fromIdentifierAux (/*@observer@*/ uentry p_c);
70 static void checkAnyCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn,
71 /*@dependent@*/ cstring p_fname,
72 uentryList p_pn, exprNodeList p_args,
73 bool p_hasMods, sRefSet p_mods, bool p_isSpec,
75 static void checkOneArg (uentry p_ucurrent, /*@notnull@*/ exprNode p_current,
76 /*@dependent@*/ exprNode p_fcn, bool p_isSpec, int p_argno, int p_totargs);
78 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn, uentryList p_params, exprNodeList p_args);
80 static /*@only@*/ exprNode exprNode_effect (exprNode p_e)
81 /*@globals internalState@*/ ;
82 static /*@only@*/ cstring exprNode_doUnparse (exprNode p_e);
83 static /*@observer@*/ cstring exprNode_rootVarName (exprNode p_e);
84 static /*@exposed@*/ exprNode
85 exprNode_lastStatement (/*@returned@*/ exprNode p_e);
87 static /*@only@*/ exprNode s_mustExitNode = exprNode_undefined;
89 static int checkArgsReal (uentry p_fcn, /*@dependent@*/ exprNode p_f,
91 exprNodeList p_args, bool p_isIter, exprNode p_ret);
93 static bool inEffect = FALSE;
94 static int nowalloc = 0;
95 static int totalloc = 0;
96 static int maxalloc = 0;
98 static /*@only@*/ uentry regArg;
99 static /*@only@*/ uentry outArg;
100 static /*@only@*/ uentry outStringArg;
101 static /*@exposed@*/ sRef stdinRef;
102 static /*@exposed@*/ sRef stdoutRef;
103 static /*@only@*/ uentry csArg;
104 static /*@only@*/ uentry csOnlyArg;
105 static ctype cstringType;
106 static ctype ctypeType;
107 static ctype filelocType;
108 static bool initMod = FALSE;
110 /*@function void exprNode_swap (sef exprNode, sef exprNode)@*/
112 # define exprNode_swap(e1,e2) do { exprNode m_tmp = (e1); (e1) = (e2); (e2) = m_tmp; } while (FALSE)
115 static void exprNode_defineConstraints(/*@sef@*/ /*@special@*/ /*@notnull@*/ exprNode e)
116 /*@defines e->requiresConstraints, e->ensuresConstraints,
117 e->trueEnsuresConstraints, e->falseEnsuresConstraints @*/
119 e->requiresConstraints = constraintList_makeNew ();
120 e->ensuresConstraints = constraintList_makeNew ();
121 e->trueEnsuresConstraints = constraintList_makeNew ();
122 e->falseEnsuresConstraints = constraintList_makeNew ();
126 ** must occur after library has been read
129 void exprNode_initMod (void)
130 /*@globals undef regArg, undef outArg, undef outStringArg,
131 undef csOnlyArg, undef csArg;
138 cstringType = ctype_unknown;
139 ctypeType = ctype_unknown;
140 filelocType = ctype_unknown;
142 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
144 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
147 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
149 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
152 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
154 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
157 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdin")))
159 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdin"));
161 else /* define stdin */
163 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdin"),
165 fileloc_getBuiltin (),
167 uentry_setHasNameError (ue);
168 ue = usymtab_supGlobalEntryReturn (ue);
171 stdinRef = sRef_makePointer (uentry_getSref (ue));
173 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdout")))
175 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdout"));
179 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdout"),
181 fileloc_getBuiltin (),
183 uentry_setHasNameError (ue);
184 ue = usymtab_supGlobalEntryReturn (ue);
187 stdoutRef = sRef_makePointer (uentry_getSref (ue));
189 tmp = idDecl_create (cstring_undefined, qtype_create (ctype_unknown));
191 regArg = uentry_makeParam (tmp, PARAMUNKNOWN);
194 qtype_addQual (qtype_create (ctype_makePointer (ctype_unknown)),
197 outArg = uentry_makeParam (tmp, PARAMUNKNOWN);
199 idDecl_setTyp (tmp, qtype_addQual (qtype_create (ctype_string),
202 outStringArg = uentry_makeParam (tmp, PARAMUNKNOWN);
204 idDecl_setTyp (tmp, qtype_addQual (qtype_addQual (qtype_create (cstringType),
206 qual_createNull ()));
208 csOnlyArg = uentry_makeParam (tmp, PARAMUNKNOWN);
210 idDecl_setTyp (tmp, qtype_addQual (qtype_create (cstringType), qual_createNull ()));
211 csArg = uentry_makeParam (tmp, PARAMUNKNOWN);
217 exprNode_destroyMod (void)
218 /*@globals killed regArg, killed outArg, killed outStringArg,
219 killed s_mustExitNode, initMod @*/
223 /* evans 2002-07-12: changed uentry_free to uentry_freeComplete */
224 uentry_freeComplete (regArg);
225 uentry_freeComplete (outArg);
226 uentry_freeComplete (outStringArg);
228 exprNode_free (s_mustExitNode);
235 static void exprNode_resetSref (/*@notnull@*/ exprNode e)
237 e->sref = sRef_undefined;
240 exprNode exprNode_fakeCopy (exprNode e)
242 /*@-temptrans@*/ /*@-retalias@*/
244 /*@=temptrans@*/ /*@=retalias@*/
247 static bool isFlagKey (char key)
249 return (key == '-' || key == '+' || key == ' ' || key == '#');
252 static void exprNode_combineControl (/*@notnull@*/ exprNode ret,
253 /*@notnull@*/ exprNode ifclause,
254 /*@notnull@*/ exprNode elseclause)
256 ret->canBreak = ifclause->canBreak || elseclause->canBreak;
259 (ifclause->mustBreak || exprNode_mustEscape (ifclause))
260 && (elseclause->mustBreak || exprNode_mustEscape (elseclause));
262 ret->exitCode = exitkind_combine (ifclause->exitCode,
263 elseclause->exitCode);
268 ** For exprNode's returned by exprNode_effect.
271 static bool shallowKind (exprKind kind)
273 return (kind == XPR_STRINGLITERAL
274 || kind == XPR_NUMLIT
277 || kind == XPR_NODE);
281 exprNode_freeIniter (/*@only@*/ exprNode e)
283 if (!exprNode_isError (e))
289 ** Its a fake copy, don't free the field->rec and field->field
294 sfree (e->edata->field);
300 exprNode_free (e->edata->op->b);
301 /*@-compdestroy@*/ sfree (e->edata->op); /*@=compdestroy@*/
305 llbug (message ("other: %s", exprNode_unparse (e)));
308 multiVal_free (e->val);
309 cstring_free (e->etext);
310 fileloc_free (e->loc);
311 sRefSet_free (e->uses);
312 sRefSet_free (e->sets);
313 sRefSet_free (e->msets);
314 guardSet_free (e->guards);
316 constraintList_free(e->requiresConstraints);
317 constraintList_free(e->ensuresConstraints);
318 constraintList_free(e->trueEnsuresConstraints);
319 constraintList_free(e->falseEnsuresConstraints);
321 e->requiresConstraints = NULL;
322 e->ensuresConstraints = NULL;
323 e->trueEnsuresConstraints = NULL;
324 e->falseEnsuresConstraints = NULL;
331 exprNode_freeShallow (/*@only@*/ exprNode e)
333 if (!exprNode_isError (e))
335 if (shallowKind (e->kind))
342 if (e->kind == XPR_EMPTY
343 || e->kind == XPR_BODY
344 || e->kind == XPR_STRINGLITERAL
345 || e->kind == XPR_NUMLIT
346 || e->kind == XPR_NODE
347 || e->kind == XPR_OFFSETOF
348 || e->kind == XPR_ALIGNOFT
349 || e->kind == XPR_ALIGNOF
350 || e->kind == XPR_SIZEOFT
351 || e->kind == XPR_SIZEOF)
353 /* don't free anything */
357 /* multiVal_free (e->val); */
358 cstring_free (e->etext);
359 fileloc_free (e->loc);
360 sRefSet_free (e->uses);
361 sRefSet_free (e->sets);
362 sRefSet_free (e->msets);
363 guardSet_free (e->guards);
364 exprData_freeShallow (e->edata, e->kind);
366 /*@-compdestroy@*/ sfree (e); /*@=compdestroy@*/
375 exprNode_free (exprNode e)
377 if (!exprNode_isError (e))
381 multiVal_free (e->val);
382 cstring_free (e->etext);
383 fileloc_free (e->loc);
384 sRefSet_free (e->uses);
385 sRefSet_free (e->sets);
386 sRefSet_free (e->msets);
387 guardSet_free (e->guards);
388 exprData_free (e->edata, e->kind);
390 constraintList_free(e->requiresConstraints);
391 constraintList_free(e->ensuresConstraints);
392 constraintList_free(e->trueEnsuresConstraints);
393 constraintList_free(e->falseEnsuresConstraints);
395 e->requiresConstraints = NULL;
396 e->ensuresConstraints = NULL;
397 e->trueEnsuresConstraints = NULL;
398 e->falseEnsuresConstraints = NULL;
408 exprNode_makeError ()
410 return exprNode_undefined;
413 static /*@out@*/ /*@only@*/ /*@notnull@*/ exprNode
416 exprNode ret = (exprNode) dmalloc (sizeof (*ret));
417 /* static int lastexpnodes = 0; */
422 if (nowalloc > maxalloc)
430 static /*@notnull@*/ /*@special@*/ exprNode
431 exprNode_createPlain (ctype c)
433 /*@ensures isnull result->edata, result->loc, result->val, result->guards,
434 result->uses, result->sets, result->msets, result->etext @*/
437 exprNode e = exprNode_new ();
441 e->val = multiVal_undefined;
442 e->sref = sRef_undefined;
443 e->etext = cstring_undefined;
444 e->loc = fileloc_undefined;
445 e->guards = guardSet_undefined;
446 e->uses = sRefSet_undefined;
447 e->sets = sRefSet_undefined;
448 e->msets = sRefSet_undefined;
449 e->edata = exprData_undefined;
450 e->exitCode = XK_NEVERESCAPE;
452 e->mustBreak = FALSE;
453 e->isJumpPoint = FALSE;
455 exprNode_defineConstraints(e);
460 /*@observer@*/ exprNode exprNode_makeMustExit (void)
462 if (exprNode_isUndefined (s_mustExitNode))
464 s_mustExitNode = exprNode_createPlain (ctype_unknown);
465 s_mustExitNode->exitCode = XK_MUSTEXIT;
468 return s_mustExitNode;
472 static /*@notnull@*/ /*@special@*/ exprNode exprNode_create (ctype c)
474 /*@post:isnull result->edata, result->guards, result->val,
475 result->uses, result->sets, result->msets@*/
478 exprNode e = exprNode_createPlain (c);
479 e->loc = fileloc_copy (g_currentloc);
483 static /*@notnull@*/ /*@special@*/ exprNode exprNode_createUnknown (void)
485 /*@post:isnull result->edata, result->guards,
486 result->uses, result->sets, result->msets@*/
489 return (exprNode_create (ctype_unknown));
492 static /*@notnull@*/ /*@special@*/ exprNode
493 exprNode_createLoc (ctype c, /*@keep@*/ fileloc loc)
495 /*@post:isnull result->edata, result->guards, result->val,
496 result->uses, result->sets, result->msets@*/
499 exprNode e = exprNode_createPlain (c);
505 exprNode_copySets (/*@special@*/ /*@notnull@*/ exprNode ret, exprNode e)
506 /*@defines ret->guards, ret->uses, ret->sets, ret->msets@*/
508 if (exprNode_isDefined (e))
510 ret->guards = guardSet_copy (e->guards);
511 ret->uses = sRefSet_newCopy (e->uses);
512 ret->sets = sRefSet_newCopy (e->sets);
513 ret->msets = sRefSet_newCopy (e->msets);
517 ret->guards = guardSet_undefined;
518 ret->uses = sRefSet_undefined;
519 ret->sets = sRefSet_undefined;
520 ret->msets = sRefSet_undefined;
524 static /*@notnull@*/ /*@special@*/ exprNode
525 exprNode_createPartialLocCopy (exprNode e, /*@only@*/ fileloc loc)
527 /*@post:isnull result->edata, result->etext@*/
530 exprNode ret = exprNode_new ();
532 if (exprNode_isError (e))
534 ret->typ = ctype_unknown;
535 ret->val = multiVal_undefined;
537 ret->guards = guardSet_undefined;
538 ret->uses = sRefSet_undefined;
539 ret->sets = sRefSet_undefined;
540 ret->msets = sRefSet_undefined;
545 ret->val = multiVal_copy (e->val);
547 ret->guards = guardSet_copy (e->guards);
548 ret->uses = sRefSet_newCopy (e->uses);
549 ret->sets = sRefSet_newCopy (e->sets);
550 ret->msets = sRefSet_newCopy (e->msets);
553 ret->kind = XPR_EMPTY;
554 ret->sref = sRef_undefined;
555 ret->etext = cstring_undefined;
556 ret->exitCode = XK_NEVERESCAPE;
557 ret->canBreak = FALSE;
558 ret->mustBreak = FALSE;
559 ret->isJumpPoint = FALSE;
560 ret->edata = exprData_undefined;
562 exprNode_defineConstraints(ret);
568 static /*@notnull@*/ /*@special@*/ exprNode
569 exprNode_createPartialCopy (exprNode e)
571 /*@post:isnull result->edata, result->etext@*/
574 return (exprNode_createPartialLocCopy (e, fileloc_copy (exprNode_loc (e))));
577 static /*@notnull@*/ /*@special@*/ exprNode
578 exprNode_createPartialNVCopy (exprNode e)
580 /*@post:isnull result->edata, result->etext, result->val @*/
583 exprNode ret = exprNode_new ();
585 if (exprNode_isError (e))
587 ret->typ = ctype_unknown;
588 ret->loc = fileloc_undefined;
589 ret->guards = guardSet_undefined;
590 ret->uses = sRefSet_undefined;
591 ret->sets = sRefSet_undefined;
592 ret->msets = sRefSet_undefined;
597 ret->loc = fileloc_copy (e->loc);
598 ret->guards = guardSet_copy (e->guards);
599 ret->uses = sRefSet_newCopy (e->uses);
600 ret->sets = sRefSet_newCopy (e->sets);
601 ret->msets = sRefSet_newCopy (e->msets);
604 ret->val = multiVal_undefined;
605 ret->kind = XPR_EMPTY;
606 ret->sref = sRef_undefined;
607 ret->etext = cstring_undefined;
608 ret->exitCode = XK_NEVERESCAPE;
609 ret->canBreak = FALSE;
610 ret->mustBreak = FALSE;
611 ret->isJumpPoint = FALSE;
612 ret->edata = exprData_undefined;
614 exprNode_defineConstraints(ret);
619 static /*@notnull@*/ /*@special@*/ exprNode
620 exprNode_createSemiCopy (exprNode e)
622 /*@post:isnull result->edata, result->etext, result->sets,
623 result->msets, result->uses, result->guards@*/
626 if (exprNode_isError (e))
628 return exprNode_createPlain (ctype_unknown);
632 exprNode ret = exprNode_new ();
635 ret->val = multiVal_copy (e->val);
636 ret->loc = fileloc_copy (e->loc);
637 ret->guards = guardSet_undefined;
638 ret->uses = sRefSet_undefined;
639 ret->sets = sRefSet_undefined;
640 ret->msets = sRefSet_undefined;
642 ret->kind = XPR_EMPTY;
643 ret->sref = sRef_undefined;
644 ret->etext = cstring_undefined;
645 ret->exitCode = XK_NEVERESCAPE;
646 ret->canBreak = FALSE;
647 ret->mustBreak = FALSE;
648 ret->isJumpPoint = FALSE;
649 ret->edata = exprData_undefined;
651 exprNode_defineConstraints(ret);
658 exprNode_isNullValue (exprNode e)
660 if (exprNode_isDefined (e))
662 multiVal m = exprNode_getValue (e);
664 if (multiVal_isInt (m))
666 return (multiVal_forceInt (m) == 0);
674 exprNode_isUnknownConstant (/*@notnull@*/ exprNode e)
676 while (e->kind == XPR_PARENS)
678 e = exprData_getUopNode (e->edata);
680 if (!exprNode_isDefined (e))
685 /* evans 2002-02-05: was llassert (exprNode_isDefined (e)); but this can fail */
688 if (e->kind == XPR_CONST)
690 multiVal m = exprNode_getValue (e);
692 if (multiVal_isUnknown (m))
702 exprNode_numLiteral (ctype c, /*@temp@*/ cstring t,
703 /*@only@*/ fileloc loc, long val)
705 exprNode e = exprNode_createLoc (c, loc);
707 e->kind = XPR_NUMLIT;
709 llassert (multiVal_isUndefined (e->val));
710 e->val = multiVal_makeInt (val);
711 e->edata = exprData_makeLiteral (cstring_copy (t));
715 e->sref = sRef_makeUnknown ();
716 sRef_setDefNull (e->sref, e->loc);
719 DPRINTF (("Num lit: %s / %s", exprNode_unparse (e), ctype_unparse (exprNode_getType (e))));
724 exprNode_charLiteral (char c, cstring text, /*@only@*/ fileloc loc)
726 exprNode e = exprNode_createLoc (ctype_char, loc);
728 if (context_getFlag (FLG_CHARINTLITERAL))
730 e->typ = ctype_makeConj (ctype_char, ctype_int);
733 e->kind = XPR_NUMLIT;
734 e->val = multiVal_makeChar (c);
736 e->edata = exprData_makeLiteral (cstring_copy (text));
741 exprNode_floatLiteral (double d, ctype ct, cstring text, /*@only@*/ fileloc loc)
743 exprNode e = exprNode_createLoc (ct, loc);
745 e->kind = XPR_NUMLIT;
746 e->val = multiVal_makeDouble (d);
747 e->edata = exprData_makeLiteral (cstring_copy (text));
751 multiVal exprNode_getValue (exprNode e)
753 while (exprNode_isInParens (e)) {
754 if (e->edata != NULL) {
755 e = exprData_getUopNode (e->edata);
761 if (exprNode_isDefined (e)) {
764 return multiVal_undefined;
769 exprNode_combineLiterals (exprNode e, exprNode rest)
773 /* Both must be string literals. */
775 if (exprNode_isUndefined (rest) || exprNode_isUndefined (e))
777 exprNode_free (rest);
781 if (!exprNode_isStringLiteral (e))
785 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e),
786 exprNode_unparse (rest)),
788 exprNode_free (rest);
792 if (!exprNode_isStringLiteral (rest))
796 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e), exprNode_unparse (rest)),
799 exprNode_free (rest);
803 ns = cstring_concat (multiVal_forceString (exprNode_getValue (e)),
804 multiVal_forceString (exprNode_getValue (rest)));
806 multiVal_free (e->val);
807 exprData_free (e->edata, e->kind);
808 e->edata = exprData_makeLiteral (cstring_copy (ns));
809 e->val = multiVal_makeString (ns);
810 exprNode_free (rest);
815 exprNode_rawStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
817 exprNode e = exprNode_createLoc (ctype_string, loc);
818 size_t len = cstring_length (t);
820 if (context_getFlag (FLG_STRINGLITERALLEN))
822 if (len > size_fromInt (context_getValue (FLG_STRINGLITERALLEN)))
824 voptgenerror (FLG_STRINGLITERALLEN,
826 ("String literal length (%d) exceeds maximum "
827 "length (%d): \"%s\"",
829 context_getValue (FLG_STRINGLITERALLEN),
835 e->kind = XPR_STRINGLITERAL;
836 e->val = multiVal_makeString (cstring_copy (t));
837 e->edata = exprData_makeLiteral (t);
838 e->sref = sRef_makeConst (ctype_string);
840 if (context_getFlag (FLG_READONLYSTRINGS))
842 sRef_setAliasKind (e->sref, AK_STATIC, fileloc_undefined);
843 sRef_setExKind (e->sref, XO_OBSERVER, loc);
847 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
850 return (e); /* s released */
854 exprNode_wideStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
856 exprNode res = exprNode_stringLiteral (t, loc);
857 res->typ = ctype_makeWideString ();
862 exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
864 size_t len = size_fromInt (size_toInt (cstring_length (t)) - 2);
865 char *ts = cstring_toCharsSafe (t);
866 char *s = cstring_toCharsSafe (cstring_create (len + 1));
868 llassert (*ts == '\"' && *(ts + len + 1) == '\"');
869 strncpy (s, ts+1, len);
872 return exprNode_rawStringLiteral (cstring_fromCharsO (s), loc);
875 exprNode exprNode_fromUIO (cstring c)
877 fileloc loc = context_getSaveLocation ();
878 exprNode e = exprNode_createPlain (ctype_unknown);
882 if (fileloc_isUndefined (loc))
884 loc = fileloc_copy (g_currentloc);
887 e->loc = loc; /* save loc was mangled */
888 e->sref = sRef_undefined;
890 if (usymtab_exists (c))
892 uentry ue = usymtab_lookupEither (c);
894 if (uentry_isDatatype (ue)
895 && uentry_isSpecified (ue))
898 (message ("%q: Specified datatype %s used in code, but not defined. "
899 "(Cannot continue reasonably from this error.)",
900 fileloc_unparse (e->loc), c));
908 llassertprint (!usymtab_exists (c), ("Entry exists: %s", c));
911 ** was supercedeGlobalEntry...is this better?
914 if (!context_inIterEnd ())
916 if (context_inMacro ())
918 if (context_getFlag (FLG_UNRECOG))
922 message ("Unrecognized identifier in macro definition: %s", c), e->loc);
926 flagcode_recordSuppressed (FLG_UNRECOG);
932 (FLG_UNRECOG, message ("Unrecognized identifier: %s", c), e->loc);
936 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
938 /* No alias errors for unrecognized identifiers */
939 sRef_setAliasKind (e->sref, AK_ERROR, loc);
944 exprNode exprNode_makeConstantString (cstring c, /*@only@*/ fileloc loc)
946 exprNode e = exprNode_createPlain (ctype_unknown);
949 e->sref = sRef_makeConst (ctype_string);
950 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
951 e->typ = ctype_string;
953 /* No alias errors for unrecognized identifiers */
954 sRef_setAliasKind (e->sref, AK_STATIC, loc);
955 sRef_setExKind (e->sref, XO_OBSERVER, loc);
960 exprNode exprNode_createId (/*@observer@*/ uentry c)
962 if (uentry_isValid (c))
964 exprNode e = exprNode_new ();
966 DPRINTF (("create id: %s", uentry_unparse (c)));
968 e->typ = uentry_getType (c);
970 if (uentry_isFunction (c)
971 && !sRef_isLocalVar (uentry_getSref (c)))
973 e->sref = sRef_undefined;
977 e->sref = uentry_getSref (c);
980 if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
982 sRef_setDefined (e->sref, fileloc_undefined);
986 ** yoikes! leaving this out was a heinous bug...that would have been
987 ** caught if i had splint working first. gag!
990 e->etext = cstring_undefined;
992 if (uentry_isEitherConstant (c))
995 e->val = multiVal_copy (uentry_getConstantValue (c));
1000 e->val = multiVal_unknown ();
1003 e->edata = exprData_makeId (c);
1004 e->loc = context_getSaveLocation ();
1006 if (fileloc_isUndefined (e->loc))
1008 fileloc_free (e->loc);
1009 e->loc = fileloc_copy (g_currentloc);
1012 e->guards = guardSet_new ();
1013 e->sets = sRefSet_new ();
1014 e->msets = sRefSet_new ();
1015 e->uses = sRefSet_new ();
1017 /*> missing fields, detected by splint <*/
1018 e->exitCode = XK_NEVERESCAPE;
1019 e->isJumpPoint = FALSE;
1020 e->canBreak = FALSE;
1021 e->mustBreak = FALSE;
1023 exprNode_defineConstraints (e);
1028 return exprNode_createUnknown ();
1032 /*@notnull@*/ exprNode
1033 exprNode_fromIdentifier (/*@observer@*/ uentry c)
1037 if (context_justPopped ()) /* watch out! c could be dead */
1039 uentry ce = usymtab_lookupSafe (cscanner_observeLastIdentifier ());
1041 if (uentry_isValid (ce))
1047 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
1051 ret = exprNode_fromIdentifierAux (c);
1055 static void exprNode_checkStringLiteralLength (ctype t1, exprNode e2)
1057 multiVal mval = exprNode_getValue (e2);
1061 if (ctype_isFixedArray (t1))
1063 size_t nelements = ctype_getArraySize (t1);
1065 llassert (multiVal_isString (mval));
1066 slit = multiVal_forceString (mval);
1068 len = cstring_lengthExpandEscapes (slit);
1070 llassert (exprNode_isDefined (e2));
1072 if (len == nelements)
1076 temp = cstring_expandEscapes (slit);
1078 if (temp[len-1] == '\0')
1081 (FLG_STRINGLITNOROOMFINALNULL,
1082 message ("String literal with %d character%& "
1083 "is assigned to %s (no room for final null terminator): %s",
1084 size_toInt (len + 1),
1086 exprNode_unparse (e2)),
1092 (FLG_STRINGLITNOROOM,
1093 message ("String literal with %d character%& "
1094 "is assigned to %s (no room for null terminator): %s",
1095 size_toInt (len + 1),
1097 exprNode_unparse (e2)),
1101 else if (len > nelements)
1104 (FLG_STRINGLITTOOLONG,
1105 message ("String literal with %d character%& (counting null terminator) "
1106 "is assigned to %s (insufficient storage available): %s",
1107 size_toInt (len + 1),
1109 exprNode_unparse (e2)),
1112 else if (len < nelements - 1)
1115 (FLG_STRINGLITSMALLER,
1116 message ("String literal with %d character%& is assigned to %s (possible waste of storage): %s",
1117 size_toInt (len + 1),
1119 exprNode_unparse (e2)),
1129 static /*@only@*/ /*@notnull@*/ exprNode
1130 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
1132 exprNode e = exprNode_createId (c);
1135 uentry_setUsed (c, e->loc);
1137 if (uentry_isVar (c) && sRef_isFileOrGlobalScope (sr))
1139 checkGlobUse (c, FALSE, e);
1146 exprNode_isZero (exprNode e)
1148 if (exprNode_isDefined (e))
1150 multiVal m = exprNode_getValue (e);
1152 if (multiVal_isInt (m))
1154 return (multiVal_forceInt (m) == 0);
1162 exprNode_isNonNegative (exprNode e)
1164 if (exprNode_isDefined (e))
1166 multiVal m = exprNode_getValue (e);
1168 if (multiVal_isInt (m))
1170 return (multiVal_forceInt (m) >= 0);
1174 ** This is not always true if programmer defines enum
1175 ** values, but then the constant should be known.
1178 if (ctype_isEnum (ctype_realType (e->typ)))
1188 ** a[x] - uses a but NOT a[]
1189 ** result sref = a[] (set/use in assignment)
1191 ** The syntax x[a] is also legal in C, and has the same
1192 ** semantics. If ind is an array, and arr is an int, flip
1197 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
1200 ** error in arr, error propagates (no new messages)
1201 ** error in ind, assume valid and continue
1204 DPRINTF (("Array fetch: %s / %s",
1205 exprNode_unparse (e1), exprNode_unparse (e2)));
1207 if (exprNode_isError (e1))
1210 return (exprNode_makeError ());
1216 ctype carr = exprNode_getType (e1);
1217 ctype crarr = ctype_realType (carr);
1220 ** this sets up funny aliasing, that leads to spurious
1221 ** splint errors. Hence, the i2 comments.
1224 /* evans 2001-09-09 added ctype_isKnown so there is no swap when e1 type is unknown */
1225 if (ctype_isKnown (crarr)
1226 && !ctype_isRealArray (crarr)
1227 && ctype_isRealNumeric (crarr)
1228 && !exprNode_isError (e2)
1229 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1234 carr = exprNode_getType (arr);
1235 crarr = ctype_realType (carr);
1243 DPRINTF (("arr: %s", exprNode_unparse (arr)));
1245 if (sRef_possiblyNull (arr->sref))
1247 if (!usymtab_isGuarded (arr->sref))
1249 if (optgenerror (FLG_NULLDEREF,
1250 message ("Index of %s pointer %q: %s",
1251 sRef_nullMessage (arr->sref),
1252 sRef_unparse (arr->sref),
1253 exprNode_unparse (arr)),
1256 DPRINTF (("ref: %s", sRef_unparseFull (arr->sref)));
1257 sRef_showNullInfo (arr->sref);
1259 /* suppress future messages */
1260 sRef_setNullError (arr->sref);
1265 if (exprNode_isError (ind))
1267 if ((ctype_isArrayPtr (crarr)
1268 && !ctype_isFunction (crarr))
1269 || ctype_isUnknown (carr))
1271 exprNode ret = exprNode_createPartialCopy (arr);
1273 if (ctype_isKnown (carr))
1275 ret->typ = ctype_baseArrayPtr (crarr);
1279 ret->typ = ctype_unknown;
1282 ret->sref = sRef_makeArrayFetch (arr->sref);
1284 ret->kind = XPR_FETCH;
1287 ** Because of funny aliasing (when arr and ind are
1288 ** flipped) spurious errors would be reported here.
1291 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1292 checkSafeUse (ret, arr->sref);
1297 voptgenerror (FLG_TYPE,
1298 message ("Array fetch from non-array (%t): %s[%s]", carr,
1299 exprNode_unparse (e1), exprNode_unparse (e2)),
1301 exprNode_free (arr);
1302 return (exprNode_makeError ());
1307 if (!ctype_isForceRealInt (&(ind->typ)))
1309 ctype rt = ctype_realType (ind->typ);
1311 if (ctype_isChar (rt))
1315 message ("Array fetch using non-integer, %t: %s[%s]",
1317 exprNode_unparse (e1), exprNode_unparse (e2)),
1320 else if (ctype_isEnum (rt))
1324 message ("Array fetch using non-integer, %t: %s[%s]",
1326 exprNode_unparse (e1), exprNode_unparse (e2)),
1333 message ("Array fetch using non-integer, %t: %s[%s]",
1335 exprNode_unparse (e1), exprNode_unparse (e2)),
1339 multiVal_free (ind->val);
1340 ind->val = multiVal_unknown ();
1343 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1345 exprNode ret = exprNode_createSemiCopy (arr);
1346 multiVal m = exprNode_getValue (ind);
1348 ret->typ = ctype_baseArrayPtr (crarr);
1349 ret->kind = XPR_FETCH;
1351 if (multiVal_isInt (m))
1353 int i = (int) multiVal_forceInt (m);
1355 if (sRef_isValid (arr->sref)) {
1356 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1358 ret->sref = sRef_undefined;
1363 ret->sref = sRef_makeArrayFetch (arr->sref);
1366 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1367 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1368 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1370 /* (see comment on spurious errors above) */
1371 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1373 exprNode_checkUse (ret, ind->sref, ind->loc);
1374 exprNode_checkUse (ret, arr->sref, arr->loc);
1380 if (ctype_isUnknown (carr))
1382 exprNode ret = exprNode_createPartialCopy (arr);
1384 ret->kind = XPR_FETCH;
1385 ret->typ = ctype_unknown;
1386 ret->sets = sRefSet_union (ret->sets, ind->sets);
1387 ret->msets = sRefSet_union (ret->msets, ind->msets);
1388 ret->uses = sRefSet_union (ret->uses, ind->uses);
1390 /* (see comment on spurious errors above) */
1391 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1393 exprNode_checkUse (ret, ind->sref, ind->loc);
1394 exprNode_checkUse (ret, arr->sref, arr->loc);
1401 message ("Array fetch from non-array (%t): %s[%s]", carr,
1402 exprNode_unparse (e1), exprNode_unparse (e2)),
1405 exprNode_free (arr);
1406 exprNode_free (ind);
1408 return (exprNode_makeError ());
1418 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1419 exprNodeList args, exprNode ret)
1421 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1425 ** checkPrintfArgs --- checks arguments for printf-like functions
1426 ** Arguments before ... have already been checked.
1427 ** The argument before the ... is a char *.
1428 ** argno is the format string argument.
1432 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1433 exprNodeList args, exprNode ret, int argno)
1436 ** the last argument before the elips is the format string
1441 int nargs = exprNodeList_size (args);
1442 uentryList params = uentry_getParams (fcn);
1446 ** These should be ensured by checkSpecialFunction
1449 llassert (uentryList_size (params) == argno + 1);
1450 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1452 a = exprNodeList_getN (args, argno - 1);
1453 formatloc = fileloc_copy (exprNode_loc (a));
1455 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1456 && exprNode_knownStringValue (a))
1458 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1459 char *code = format;
1462 nargs = exprNodeList_size (args);
1464 while ((code = strchr (code, '%')) != NULL)
1466 char *origcode = code;
1467 cstring codetext = cstring_newEmpty ();
1468 char key = *(++code);
1469 ctype modtype = ctype_int;
1470 bool modified = FALSE;
1472 fileloc_addColumn (formatloc, code - ocode);
1474 codetext = cstring_appendChar (codetext, key);
1477 while (isFlagKey (key))
1480 codetext = cstring_appendChar (codetext, key);
1481 fileloc_incColumn (formatloc);
1484 if (key == 'm') /* skipped in syslog */
1489 /* ignore field width */
1490 while (isdigit ((int) key) != 0)
1493 codetext = cstring_appendChar (codetext, key);
1494 fileloc_incColumn (formatloc);
1497 /* ignore precision */
1501 codetext = cstring_appendChar (codetext, key);
1502 fileloc_incColumn (formatloc);
1505 ** In printf, '*' means: read the next arg as an int for the
1506 ** field width. This seems to be missing from my copy of the
1507 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1508 ** later) but never does.
1513 ; /* don't do anything --- handle later */
1517 while (isdigit ((int) key) != 0)
1520 codetext = cstring_appendChar (codetext, key);
1521 fileloc_incColumn (formatloc);
1528 modtype = ctype_sint; /* short */
1530 codetext = cstring_appendChar (codetext, key);
1531 fileloc_incColumn (formatloc);
1533 else if (key == 'l' || key == 'L')
1535 modtype = ctype_lint; /* long */
1537 codetext = cstring_appendChar (codetext, key);
1538 fileloc_incColumn (formatloc);
1540 if (key == 'l' || key == 'L') {
1541 modtype = ctype_llint; /* long long */
1543 codetext = cstring_appendChar (codetext, key);
1544 fileloc_incColumn (formatloc);
1552 /* now, key = type of conversion to apply */
1554 fileloc_incColumn (formatloc);
1562 message ("No argument corresponding to %q format "
1563 "code %d (%%%s): \"%s\"",
1564 uentry_getName (fcn),
1566 cstring_fromChars (format)),
1569 if (fileloc_isDefined (formatloc)
1570 && context_getFlag (FLG_SHOWCOL))
1572 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1580 a = exprNodeList_getN (args, i);
1583 if (!exprNode_isError (a))
1589 case '*': /* int argument for fieldwidth */
1590 expecttype = ctype_int;
1591 *(--code) = '%'; /* convert it for next code */
1592 fileloc_subColumn (formatloc, 1);
1593 /*@switchbreak@*/ break;
1596 expecttype = ctype_combine (ctype_uint, modtype);
1597 /*@switchbreak@*/ break;
1599 case 'i': /* int argument */
1601 expecttype = ctype_combine (ctype_int, modtype);
1602 /*@switchbreak@*/ break;
1604 case 'x': /* unsigned int */
1606 expecttype = ctype_combine (ctype_uint, modtype);
1608 /*@switchbreak@*/ break;
1614 case 'f': /* double */
1615 expecttype = ctype_combine (ctype_double, modtype);
1616 /*@switchbreak@*/ break;
1618 case 'c': /* int converted to char (check its a char?) */
1619 expecttype = ctype_makeConj (ctype_int,
1620 ctype_makeConj (ctype_char,
1623 /* evans 2001-10-05 - changed to reflect correct ISO spec:
1624 int converted to char */
1626 /* expecttype = ctype_makeConj (ctype_char, ctype_uchar); */
1627 /*@switchbreak@*/ break;
1629 case 's': /* string */
1630 expecttype = ctype_string;
1631 /*@switchbreak@*/ break;
1634 while (((key = *(++code)) != ']')
1637 codetext = cstring_appendChar (codetext, key);
1638 fileloc_incColumn (formatloc);
1644 (message ("Bad character set format: %s",
1645 cstring_fromChars (origcode)));
1648 expecttype = ctype_string;
1649 /*@switchbreak@*/ break;
1651 case 'p': /* pointer */
1652 expecttype = ctype_makePointer (ctype_void);
1653 /* need not be defined */
1654 uentry_setDefState (regArg, SS_RELDEF);
1655 sRef_setPosNull (uentry_getSref (regArg),
1658 /*@switchbreak@*/ break;
1660 case 'n': /* pointer to int, modified by call! */
1661 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1663 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1664 /*@switchbreak@*/ break;
1666 case 'm': /* in a syslog, it doesn't consume an argument */
1667 /* should check we're really doing syslog */
1669 /*@switchbreak@*/ break;
1673 expecttype = ctype_unknown;
1677 message ("Unrecognized format code: %s",
1678 cstring_fromChars (origcode)),
1679 fileloc_isDefined (formatloc)
1680 ? formatloc : g_currentloc);
1682 /*@switchbreak@*/ break;
1685 if (!(exprNode_matchArgType (expecttype, a)))
1687 if (ctype_isVoidPointer (expecttype)
1688 && ctype_isRealAbstract (a->typ)
1689 && (context_getFlag (FLG_ABSTVOIDP)))
1695 if (llgenformattypeerror
1696 (expecttype, exprNode_undefined,
1698 message ("Format argument %d to %q (%%%s) expects "
1701 uentry_getName (fcn),
1704 a->typ, exprNode_unparse (a)),
1707 if (fileloc_isDefined (formatloc)
1708 && context_getFlag (FLG_SHOWCOL))
1711 (cstring_makeLiteral
1712 ("Corresponding format code"),
1719 uentry_setType (regArg, expecttype);
1720 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1722 if (ctype_equal (expecttype, ctype_string))
1724 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1727 uentry_setType (regArg, ctype_unknown);
1728 uentry_fixupSref (regArg);
1732 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1743 cstring_free (codetext);
1748 voptgenerror (FLG_TYPE,
1749 message ("Format string for %q has %d arg%&, given %d",
1750 uentry_getName (fcn), i - argno, nargs - argno),
1756 /* no checking possible for compile-time unknown format strings */
1757 if (exprNode_isDefined (a))
1761 message ("Format string parameter to %s is not a compile-time constant: %s",
1762 exprNode_unparse (f),
1763 exprNode_unparse (a)),
1768 fileloc_free (formatloc);
1772 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1773 exprNodeList args, exprNode ret, int argno)
1777 int nargs = exprNodeList_size (args);
1778 uentryList params = uentry_getParams (fcn);
1782 ** These should be ensured by checkSpecialFunction
1785 llassert (uentryList_size (params) == argno + 1);
1786 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1788 a = exprNodeList_getN (args, argno - 1);
1789 formatloc = fileloc_copy (exprNode_loc (a));
1791 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1792 && exprNode_knownStringValue (a))
1794 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1795 char *code = format;
1798 nargs = exprNodeList_size (args);
1800 while ((code = strchr (code, '%')) != NULL)
1802 char *origcode = code;
1803 char key = *(++code);
1804 cstring codetext = cstring_newEmpty ();
1805 ctype modtype = ctype_int;
1806 char modifier = '\0';
1807 bool modified = TRUE;
1808 bool ignore = FALSE;
1810 codetext = cstring_appendChar (codetext, key);
1811 fileloc_addColumn (formatloc, code - ocode);
1814 ** this is based on ANSI standard library description of fscanf
1815 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1818 /* '*' suppresses assignment (does not need match argument) */
1823 codetext = cstring_appendChar (codetext, key);
1826 fileloc_incColumn (formatloc);
1829 /* ignore field width */
1830 while (isdigit ((int) key) != 0)
1833 codetext = cstring_appendChar (codetext, key);
1834 fileloc_incColumn (formatloc);
1839 modtype = ctype_sint; /* short */
1841 codetext = cstring_appendChar (codetext, key);
1842 fileloc_incColumn (formatloc);
1844 else if (key == 'l' || key == 'L')
1846 modtype = ctype_lint; /* long */
1850 codetext = cstring_appendChar (codetext, key);
1852 fileloc_incColumn (formatloc);
1854 if (key == 'l' || key == 'L') {
1855 modtype = ctype_llint; /* long long */
1857 codetext = cstring_appendChar (codetext, key);
1858 fileloc_incColumn (formatloc);
1866 /* now, key = type of conversion to apply */
1868 fileloc_incColumn (formatloc);
1882 message ("No argument corresponding to %q format "
1883 "code %d (%%%s): \"%s\"",
1884 uentry_getName (fcn),
1886 cstring_fromChars (format)),
1889 if (fileloc_isDefined (formatloc)
1890 && context_getFlag (FLG_SHOWCOL))
1893 (cstring_makeLiteral ("Corresponding format code"),
1901 a = exprNodeList_getN (args, i);
1904 if (!exprNode_isError (a))
1910 case '*': /* int argument for fieldwidth */
1911 expecttype = ctype_makePointer (ctype_int);
1912 *(--code) = '%'; /* convert it for next code */
1913 fileloc_subColumn (formatloc, 1);
1914 /*@switchbreak@*/ break;
1917 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1918 /*@switchbreak@*/ break;
1923 case 'X': /* unsigned int */
1924 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1925 /*@switchbreak@*/ break;
1932 /* printf is double, scanf is float! */
1934 if (modifier == 'l')
1936 expecttype = ctype_makePointer (ctype_double);
1938 else if (modifier == 'L')
1940 expecttype = ctype_makePointer (ctype_ldouble);
1944 llassert (modifier == '\0');
1945 expecttype = ctype_makePointer (ctype_float);
1947 /*@switchbreak@*/ break;
1949 case 'c': /* int converted to char (check its a char?) */
1950 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1951 /*@switchbreak@*/ break;
1953 case 's': /* string */
1954 expecttype = ctype_string;
1955 /*@switchbreak@*/ break;
1959 while (((key = *(++code)) != ']')
1962 codetext = cstring_appendChar (codetext, key);
1963 fileloc_incColumn (formatloc);
1969 (message ("Bad character set format: %s",
1970 cstring_fromChars (origcode)));
1973 expecttype = ctype_string;
1974 /*@switchbreak@*/ break;
1977 case 'p': /* pointer */
1980 message ("Format code should not be used in scanf: %s",
1981 cstring_fromChars (origcode)),
1982 fileloc_isDefined (formatloc)
1983 ? formatloc : g_currentloc);
1985 expecttype = ctype_unknown;
1986 /*@switchbreak@*/ break;
1988 case 'n': /* pointer to int, modified by call! */
1989 expecttype = ctype_makePointer (ctype_int);
1990 /*@switchbreak@*/ break;
1993 expecttype = ctype_unknown;
1997 message ("Unrecognized format code: %s",
1998 cstring_fromChars (origcode)),
1999 fileloc_isDefined (formatloc)
2000 ? formatloc : g_currentloc);
2002 /*@switchbreak@*/ break;
2005 if (!(exprNode_matchArgType (expecttype, a)))
2007 if (ctype_isVoidPointer (expecttype)
2008 && ctype_isRealAbstract (a->typ)
2009 && (context_getFlag (FLG_ABSTVOIDP)))
2015 if (llgenformattypeerror
2016 (expecttype, exprNode_undefined,
2018 message ("Format argument %d to %q (%%%s) expects "
2021 uentry_getName (fcn),
2022 codetext, expecttype,
2023 a->typ, exprNode_unparse (a)),
2026 if (fileloc_isDefined (formatloc)
2027 && context_getFlag (FLG_SHOWCOL))
2030 (cstring_makeLiteral
2031 ("Corresponding format code"),
2038 uentry_setType (outArg, expecttype);
2039 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
2040 uentry_setType (outArg, ctype_unknown);
2041 uentry_fixupSref (outArg);
2045 exprNode_checkCallModifyVal (a->sref, args, f, ret);
2050 /* a->sref = sRef_undefined; */
2057 cstring_free (codetext);
2062 voptgenerror (FLG_TYPE,
2063 message ("Format string for %q has %d arg%&, given %d",
2064 uentry_getName (fcn), i - argno, nargs - argno),
2070 /* no checking possible for compile-time unknown format strings */
2073 fileloc_free (formatloc);
2077 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
2080 /*@unused@*/ int argno)
2083 ** the last argument before the elips is the format string
2086 int nargs = exprNodeList_size (args);
2091 a = exprNodeList_getN (args, argno - 1);
2092 formatloc = fileloc_copy (exprNode_loc (a));
2094 if (ctype_isUnknown (cstringType)) {
2095 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
2097 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
2101 if (ctype_isUnknown (ctypeType)) {
2102 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
2104 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
2108 if (ctype_isUnknown (filelocType)) {
2109 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
2111 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
2115 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
2116 && exprNode_knownStringValue (a))
2118 cstring format = multiVal_forceString (exprNode_getValue (a));
2119 char *code = cstring_toCharsSafe (format);
2122 nargs = exprNodeList_size (args);
2124 while ((code = strchr (code, '%')) != NULL)
2126 char *origcode = code;
2127 char key = *(++code);
2128 cstring codetext = cstring_newEmpty ();
2129 bool isOnly = FALSE;
2131 codetext = cstring_appendChar (codetext, key);
2133 fileloc_addColumn (formatloc, code - ocode);
2135 while (key >= '0' && key <= '9')
2138 codetext = cstring_appendChar (codetext, key);
2139 fileloc_incColumn (formatloc);
2143 fileloc_incColumn (formatloc);
2147 if (key == '&') /* plural marker */
2156 message ("Message missing format arg %d (%%%s): \"%s\"",
2157 i + 1, codetext, format),
2163 a = exprNodeList_getN (args, i);
2167 if (!exprNode_isError (a))
2171 /*@-loopswitchbreak@*/
2177 expecttype = ctype_char; break;
2179 expecttype = cstringType; break;
2181 expecttype = cstringType; isOnly = TRUE; break;
2183 expecttype = cstringType; isOnly = TRUE; break;
2184 case 'd': expecttype = ctype_int; break;
2185 case 'u': expecttype = ctype_uint; break;
2186 case 'w': expecttype = ctype_ulint; break;
2187 case 'f': expecttype = ctype_float; break;
2188 case 'b': expecttype = ctype_bool; break;
2189 case 't': expecttype = ctypeType; break;
2191 expecttype = ctype_makePointer (ctype_void);
2192 /* need not be defined */
2193 uentry_setDefState (regArg, SS_RELDEF);
2194 sRef_setPosNull (uentry_getSref (regArg),
2197 /*@switchbreak@*/ break;
2198 case 'l': expecttype = filelocType; break;
2199 case '&': /* a wee bit of a hack methinks */
2200 expecttype = ctype_int;
2202 case 'r': expecttype = ctype_bool; break;
2204 expecttype = ctype_unknown;
2207 message ("Unrecognized format code: %s",
2208 cstring_fromChars (origcode)),
2209 fileloc_isDefined (formatloc)
2210 ? formatloc : g_currentloc);
2213 /*@=loopswitchbreak@*/
2215 if (!(exprNode_matchArgType (expecttype, a)))
2217 if (ctype_isVoidPointer (expecttype)
2218 && ctype_isRealAbstract (a->typ)
2219 && (context_getFlag (FLG_ABSTVOIDP)))
2225 if (llgenformattypeerror
2226 (expecttype, exprNode_undefined,
2228 message ("Format argument %d to %q (%%%s) expects "
2231 uentry_getName (fcn),
2232 codetext, expecttype,
2233 a->typ, exprNode_unparse (a)),
2236 if (fileloc_isDefined (formatloc)
2237 && context_getFlag (FLG_SHOWCOL))
2240 (cstring_makeLiteral
2241 ("Corresponding format code"),
2248 if (ctype_equal (expecttype, cstringType))
2252 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2253 uentry_fixupSref (csOnlyArg);
2257 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2258 uentry_fixupSref (csArg);
2263 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2264 uentry_fixupSref (regArg);
2270 cstring_free (codetext);
2275 voptgenerror (FLG_TYPE,
2276 message ("Format string for %q has %d arg%&, given %d",
2277 uentry_getName (fcn), i - argno, nargs -argno),
2283 /* no checking possible for compile-time unknown format strings */
2286 fileloc_free (formatloc);
2290 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2291 /*@notnull@*/ exprNode e2,
2297 bool hadUncon = FALSE;
2299 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
2300 sRefSet_hasUnconstrained (sets2))
2303 (FLG_EVALORDERUNCON,
2305 ("Expression may have undefined behavior (%q used in right operand "
2306 "may set global variable %q used in left operand): %s %s %s",
2307 sRefSet_unparseUnconstrained (sets2),
2308 sRef_unparse (sRef_getRootBase (e1->sref)),
2309 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2313 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
2314 sRefSet_hasUnconstrained (sets1))
2317 (FLG_EVALORDERUNCON,
2319 ("Expression has undefined behavior (%q used in left operand "
2320 "may set global variable %q used in right operand): %s %s %s",
2321 sRefSet_unparseUnconstrained (sets1),
2322 sRef_unparse (e2->sref),
2323 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2327 sRefSet_realElements (e1->uses, sr)
2329 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2334 ("Expression has undefined behavior (left operand uses %q, "
2335 "modified by right operand): %s %s %s",
2337 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2340 } end_sRefSet_realElements;
2342 sRefSet_realElements (sets1, sr)
2344 if (sRef_isMeaningful (sr))
2346 if (sRef_same (sr, e2->sref))
2351 ("Expression has undefined behavior (value of right operand "
2352 "modified by left operand): %s %s %s",
2353 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2356 else if (sRefSet_member (e2->uses, sr))
2361 ("Expression has undefined behavior (left operand modifies %q, "
2362 "used by right operand): %s %s %s",
2364 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2369 if (sRefSet_member (sets2, sr))
2371 if (sRef_isUnconstrained (sr))
2379 hadUncon = optgenerror
2380 (FLG_EVALORDERUNCON,
2382 ("Expression may have undefined behavior. Left operand "
2383 "calls %q; right operand calls %q. The unconstrained "
2384 "functions may modify global state used by "
2385 "the other operand): %s %s %s",
2386 sRefSet_unparseUnconstrained (sets1),
2387 sRefSet_unparseUnconstrained (sets2),
2388 exprNode_unparse (e1), lltok_unparse (op),
2389 exprNode_unparse (e2)),
2398 ("Expression has undefined behavior (both "
2399 "operands modify %q): %s %s %s",
2401 exprNode_unparse (e1),
2402 lltok_unparse (op), exprNode_unparse (e2)),
2408 } end_sRefSet_realElements;
2411 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2413 bool hasError = FALSE;
2415 if (exprNode_isError (e1) || exprNode_isError (e2))
2420 if (sRefSet_member (e2->sets, e1->sref))
2422 if (e2->kind == XPR_CALL)
2428 hasError = optgenerror
2430 message ("Expression has undefined behavior "
2431 "(value of left operand %s is modified "
2432 "by right operand %s): %s %s %s",
2433 exprNode_unparse (e1),
2434 exprNode_unparse (e2),
2435 exprNode_unparse (e1), lltok_unparse (op),
2436 exprNode_unparse (e2)),
2441 if (context_getFlag (FLG_EVALORDERUNCON))
2443 if (sRefSet_member (e2->msets, e1->sref))
2445 if (e2->kind == XPR_CALL)
2451 hasError = optgenerror
2454 ("Expression has undefined behavior (value of left "
2455 "operand may be modified by right operand): %s %s %s",
2456 exprNode_unparse (e1), lltok_unparse (op),
2457 exprNode_unparse (e2)),
2465 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2467 if (context_maybeSet (FLG_EVALORDERUNCON))
2469 checkExpressionDefinedAux (e1, e2, e1->msets,
2470 e2->msets, op, FLG_EVALORDERUNCON);
2475 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2478 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2479 exprNodeList args, bool isIter, exprNode ret)
2483 if (!exprNode_isError (f))
2485 if (!uentryList_isMissingParams (cl))
2487 int nargs = exprNodeList_size (args);
2488 int expectargs = uentryList_size (cl);
2492 if (expectargs == 0)
2500 message ("Iter %q invoked with %d args, "
2502 uentry_getName (fcn),
2510 message ("Function %s called with %d args, "
2512 exprNode_unparse (f), nargs),
2519 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2521 exprNodeList_reset (args);
2523 uentryList_elements (cl, current)
2525 ctype ct = uentry_getType (current);
2528 if (ctype_isElips (ct))
2531 ** do special checking for printf/scanf library functions
2533 ** this is kludgey code, just for handling the special case
2537 if (uentry_isPrintfLike (fcn))
2539 checkPrintfArgs (f, fcn, args, ret, i);
2542 else if (uentry_isScanfLike (fcn))
2544 checkScanfArgs (f, fcn, args, ret, i);
2547 else if (uentry_isMessageLike (fcn))
2549 checkMessageArgs (f, fcn, args, i);
2554 llassert (!uentry_isSpecialFunction (fcn));
2557 nargs = expectargs; /* avoid errors */
2562 if (i >= nargs) break;
2564 a = exprNodeList_current (args);
2565 exprNodeList_advance (args);
2569 if (exprNode_isError (a))
2576 probably necessary? I'm not sure about this one
2577 checkMacroParen (a);
2580 f->guards = guardSet_union (f->guards, a->guards);
2582 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2584 if (!(exprNode_matchArgType (ct, a)))
2586 DPRINTF (("Args mismatch!"));
2588 if (ctype_isVoidPointer (ct)
2589 && (ctype_isPointer (a->typ)
2590 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2595 ("Pointer to abstract type (%t) used "
2597 "(arg %d to %q): %s",
2599 uentry_getName (fcn),
2600 exprNode_unparse (a)),
2608 (ct, exprNode_undefined,
2611 ("Iter %q expects arg %d to "
2612 "be %t gets %t: %s",
2613 uentry_getName (fcn),
2614 i, ct, a->typ, exprNode_unparse (a)),
2625 ("Function %q expects arg %d to be %t gets %t: %s",
2626 uentry_getName (fcn),
2627 i, ct, a->typ, exprNode_unparse (a)),
2630 DPRINTF (("Types: %s / %s",
2632 ctype_unparse (a->typ)));
2636 ** Clear null marker for abstract types.
2637 ** (It is not revealed, so suppress future messages.)
2640 if (ctype_isAbstract (a->typ))
2642 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2649 } end_uentryList_elements ;
2652 if (expectargs != nargs) /* note: not != since we may have ... */
2654 if (ctype_isElips (last))
2658 message ("Function %s called with %d args, expects at least %d",
2659 exprNode_unparse (f),
2660 nargs, expectargs - 1),
2669 message ("Iter %q invoked with %d args, expects %d",
2670 uentry_getName (fcn), nargs, expectargs),
2677 message ("Function %s called with %d args, expects %d",
2678 exprNode_unparse (f),
2691 ** Check for undefined code sequences in function arguments:
2693 ** one parameter sets something used by another parameter
2694 ** one parameter sets something set by another parameter
2698 checkSequencingOne (exprNode f, exprNodeList args,
2699 /*@notnull@*/ exprNode el, int argno)
2702 ** Do second loop, iff +undefunspec
2706 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2708 for (checkloop = 0; checkloop < numloops; checkloop++)
2714 thissets = el->sets;
2718 llassert (checkloop == 1);
2719 thissets = el->msets;
2722 sRefSet_realElements (thissets, thisset)
2726 /*@access exprNodeList@*/
2727 for (j = 0; j < args->nelements; j++)
2729 exprNode jl = args->elements[j];
2730 int thisargno = j + 1;
2732 if (thisargno != argno && exprNode_isDefined (jl))
2734 sRefSet otheruses = jl->uses;
2736 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
2737 sRefSet_hasUnconstrained (thissets))
2740 (FLG_EVALORDERUNCON,
2743 ("%q used in argument %d may set "
2744 "global variable %q used by argument %d: %s(%q)",
2745 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2748 sRef_unparse (sRef_getRootBase (jl->sref)),
2750 exprNode_unparse (f), exprNodeList_unparse (args)),
2754 if (sRefSet_member (otheruses, thisset))
2756 if (sRef_isUnconstrained (thisset))
2759 (FLG_EVALORDERUNCON,
2761 ("Unconstrained functions used in arguments %d (%q) "
2762 "and %d (%s) may modify "
2763 "or use global state in undefined way: %s(%q)",
2765 sRefSet_unparseUnconstrainedPlain (otheruses),
2767 sRef_unconstrainedName (thisset),
2768 exprNode_unparse (f),
2769 exprNodeList_unparse (args)),
2777 ("Argument %d modifies %q, used by argument %d "
2778 "(order of evaluation of actual parameters is "
2779 "undefined): %s(%q)",
2780 argno, sRef_unparse (thisset), thisargno,
2781 exprNode_unparse (f), exprNodeList_unparse (args)),
2787 sRefSet othersets = jl->sets;
2789 if (sRefSet_member (othersets, thisset))
2791 if (sRef_isUnconstrained (thisset))
2794 (FLG_EVALORDERUNCON,
2796 ("Unconstrained functions used in "
2797 "arguments %d (%q) and %d (%s) may modify "
2798 "or use global state in undefined way: %s(%q)",
2800 sRefSet_unparseUnconstrainedPlain (othersets),
2802 sRef_unconstrainedName (thisset),
2803 exprNode_unparse (f), exprNodeList_unparse (args)),
2811 ("Argument %d modifies %q, set by argument %d (order of"
2812 " evaluation of actual parameters is undefined): %s(%q)",
2813 argno, sRef_unparse (thisset), thisargno,
2814 exprNode_unparse (f), exprNodeList_unparse (args)),
2821 /*@noaccess exprNodeList@*/
2822 } end_sRefSet_realElements;
2827 checkSequencing (exprNode f, exprNodeList args)
2829 if (exprNodeList_size (args) > 1)
2834 /*@access exprNodeList*/
2836 for (i = 0; i < args->nelements; i++)
2838 el = args->elements[i];
2840 if (!exprNode_isError (el))
2842 checkSequencingOne (f, args, el, i + 1);
2845 /*@noaccess exprNodeList*/
2850 ** requires le = exprNode_getUentry (f)
2854 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2855 uentry le, exprNodeList args,
2856 /*@notnull@*/ exprNode ret, int specialArgs)
2858 bool isSpec = FALSE;
2859 bool hasMods = FALSE;
2861 globSet usesGlobs = globSet_undefined;
2862 sRefSet mods = sRefSet_undefined;
2863 bool freshMods = FALSE;
2864 uentryList params = uentryList_undefined;
2866 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2869 ** check globals and modifies
2874 if (!uentry_isValid (le))
2876 ctype fr = ctype_realType (f->typ);
2878 if (ctype_isFunction (fr))
2880 params = ctype_argsFunction (fr);
2884 params = uentryList_missingParams;
2887 if (!context_getFlag (FLG_MODNOMODS)
2888 && !context_getFlag (FLG_GLOBUNSPEC))
2890 checkUnspecCall (f, params, args);
2896 fname = uentry_rawName (le);
2900 if (uentry_isFunction (le))
2902 params = uentry_getParams (le);
2903 mods = uentry_getMods (le);
2904 hasMods = uentry_hasMods (le);
2905 usesGlobs = uentry_getGlobs (le);
2906 isSpec = uentry_isSpecified (le);
2908 else /* not a function */
2910 ctype ct = ctype_realType (uentry_getType (le));
2912 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2913 ("checkModGlobs: uentry not a function: %s",
2914 uentry_unparse (le)));
2916 params = ctype_argsFunction (ct);
2917 return; /*@32 ! remove this? */
2926 globSet_allElements (usesGlobs, el)
2928 if (sRef_isValid (el))
2930 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2932 context_usedGlobal (el);
2933 exprNode_checkUse (f, el, f->loc);
2935 if (context_checkInternalUse ())
2937 if (!context_globAccess (el))
2939 if (sRef_isSystemState (el)
2940 && !context_getFlag (FLG_MODFILESYSTEM))
2949 ("Called procedure %s may access %q, but "
2950 "globals list does not include globals %s",
2951 exprNode_unparse (f),
2953 cstring_makeLiteralTemp (sRef_isInternalState (el)
2961 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2967 uentry gle = sRef_getUentry (el);
2968 sRef sr = sRef_updateSref (el);
2970 if (sRef_isUndefGlob (el))
2972 sRef_setDefined (sr, f->loc);
2973 exprNode_checkSet (f, sr);
2981 if (sRef_isAllocated (el))
2983 exprNode_checkSet (f, sr);
2987 if (sRef_isStateUndefined (sr))
2992 ("%s %q used by function undefined before call: %s",
2993 sRef_getScopeName (sr),
2995 exprNode_unparse (f)),
2997 sRef_setDefined (sr, f->loc);
2999 exprNode_checkUse (f, sr, f->loc);
3002 checkGlobUse (gle, TRUE, f);
3005 if (sRef_isKilledGlob (el))
3007 sRef_kill (sr, f->loc);
3008 context_usedGlobal (sr);
3012 } end_globSet_allElements;
3018 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
3020 sRefSet smods = sRefSet_undefined;
3023 ** NEED to check for modifies anything
3027 ** check each sRef that called function modifies (ml), is
3033 sRefSet_allElements (mods, s) /* s is something which may be modified */
3035 DPRINTF (("Check modify: %s", sRef_unparse (s)));
3037 if (sRef_isKindSpecial (s))
3039 if (sRef_isSpecInternalState (s))
3041 if (context_getFlag (FLG_MODINTERNALSTRICT))
3043 exprNode_checkCallModifyVal (s, args, f, ret);
3047 sRefSet mmods = context_modList ();
3049 sRefSet_allElements (mmods, el)
3051 if (sRef_isInternalState (el))
3053 sRef_setModified (el);
3055 } end_sRefSet_allElements ;
3060 exprNode_checkCallModifyVal (s, args, f, ret);
3065 sRef rb = sRef_getRootBase (s);
3067 if (sRef_isFileOrGlobalScope (rb))
3069 context_usedGlobal (rb);
3072 if (sRef_isFileStatic (s)
3073 && !fileId_equal (fileloc_fileId (f->loc),
3074 fileloc_fileId (uentry_whereDefined (le))))
3076 smods = sRefSet_insert (smods, s);
3080 exprNode_checkCallModifyVal (s, args, f, ret);
3083 } end_sRefSet_allElements;
3088 ** Static elements in modifies set can have nasty consequences.
3089 ** (I think...have not been able to reproduce a possible bug.)
3092 if (!sRefSet_isDefined (smods))
3094 mods = sRefSet_newCopy (mods);
3097 sRefSet_allElements (smods, el)
3099 bool res = sRefSet_delete (mods, el);
3102 } end_sRefSet_allElements;
3104 sRefSet_free (smods);
3109 else if (sRefSet_isDefined (mods))
3110 { /* just check observers */
3113 sRefSet_allElements (mods, s) /* s is something which may be modified */
3115 sRef rb = sRef_getRootBase (s);
3119 if (sRef_isParam (rb))
3121 sRef b = sRef_fixBaseParam (s, args);
3123 if (sRef_isObserver (b))
3125 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
3129 message ("Function call may modify observer%q: %s",
3130 sRef_unparsePreOpt (b), exprNode_unparse (e)),
3133 sRef_showExpInfo (b);
3137 } end_sRefSet_allElements;
3141 if (!hasMods) /* no specified modifications */
3143 if (context_getFlag (FLG_MODOBSERVERUNCON))
3145 exprNodeList_elements (args, e)
3147 if (exprNode_isDefined (e))
3149 sRef s = exprNode_getSref (e);
3151 if (sRef_isObserver (s)
3152 && ctype_isMutable (sRef_getType (s)))
3155 (FLG_MODOBSERVERUNCON,
3157 ("Call to unconstrained function %s may modify observer%q: %s",
3158 exprNode_unparse (f),
3159 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3162 sRef_showExpInfo (s);
3166 } end_exprNodeList_elements;
3171 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3173 ret->uses = sRefSet_union (ret->uses, f->uses);
3174 ret->sets = sRefSet_union (ret->sets, f->sets);
3175 ret->msets = sRefSet_union (ret->msets, f->msets);
3180 ** Spurious errors reported, because splint can't tell
3181 ** mods must be fresh if freshMods is true.
3184 /*@i@*/ sRefSet_free (mods);
3190 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3192 if (uentry_isVar (glob))
3194 if (context_inFunctionLike ())
3196 sRef sr = uentry_getSref (glob);
3198 context_usedGlobal (sr);
3200 if (context_checkGlobUse (glob))
3202 if (!context_globAccess (sr))
3208 message ("Called procedure %s may access %s %q",
3209 exprNode_unparse (e),
3210 sRef_unparseScope (sr),
3211 uentry_getName (glob)),
3218 message ("Undocumented use of %s %s",
3219 sRef_unparseScope (sr),
3220 exprNode_unparse (e)),
3229 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3234 reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
3236 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3237 exprNode_unparse (f), exprNodeList_unparse (args),
3238 uentry_unparseFull (le),
3239 stateClauseList_unparse (uentry_getStateClauseList (le))));
3241 if (uentry_isValid (le) && uentry_isFunction (le))
3243 stateClauseList sclauses = uentry_getStateClauseList (le);
3245 if (stateClauseList_isDefined (sclauses))
3247 DPRINTF (("Reflect ensures: %s / %s / %s",
3248 uentry_unparse (le),
3249 exprNode_unparse (f), exprNodeList_unparse (args)));
3251 stateClauseList_elements (sclauses, cl)
3253 if (stateClause_hasEnsures (cl))
3255 /* Same in usymtab.c:1904 */
3256 if (stateClause_setsMetaState (cl))
3258 qual q = stateClause_getMetaQual (cl);
3259 annotationInfo ainfo = qual_getAnnotationInfo (q);
3260 metaStateInfo minfo = annotationInfo_getState (ainfo);
3261 cstring key = metaStateInfo_getName (minfo);
3262 int mvalue = annotationInfo_getValue (ainfo);
3264 sRefSet osrs = sRefSet_undefined;
3267 if (stateClause_isGlobal (cl))
3269 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3274 srs = stateClause_getRefs (cl);
3277 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3280 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3282 sRefSet_elements (srs, sel)
3286 if (sRef_isResult (sRef_getRootBase (sel)))
3288 s = exprNode_getSref (ret);
3292 s = sRef_fixBaseParam (sel, args);
3295 DPRINTF (("Reflecting state clause on: %s / %s",
3296 sRef_unparse (sel), sRef_unparse (s)));
3298 sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3299 } end_sRefSet_elements;
3301 sRefSet_free (osrs);
3305 sRefSet srs = stateClause_getRefs (cl);
3306 sRefModVal modf = stateClause_getEnsuresFunction (cl);
3307 int eparam = stateClause_getStateParameter (cl);
3309 llassert (modf != NULL);
3311 DPRINTF (("Reflect after clause: %s / %s",
3312 stateClause_unparse (cl),
3313 sRefSet_unparse (srs)));
3315 sRefSet_elements (srs, sel)
3319 DPRINTF (("elements: %s", sRef_unparse (sel)));
3320 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3322 if (sRef_isResult (sRef_getRootBase (sel)))
3324 DPRINTF (("Fix base: %s / %s",
3325 sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
3326 s = sRef_fixBase (sel, exprNode_getSref (ret));
3327 DPRINTF (("==> %s", sRef_unparseFull (s)));
3331 s = sRef_fixBaseParam (sel, args);
3334 DPRINTF (("elements: %s", sRef_unparse (s)));
3335 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3337 DPRINTF (("Reflecting state clause on: %s / %s",
3338 sRef_unparseFull (sel), sRef_unparseFull (s)));
3340 /* evans 2001-08-24 - added aliasSetCompleteParam */
3341 sRef_aliasSetCompleteParam (modf, s, eparam, exprNode_loc (f));
3343 DPRINTF (("After reflecting state clause on: %s / %s",
3344 sRef_unparseFull (sel), sRef_unparseFull (s)));
3345 } end_sRefSet_elements;
3348 } end_stateClauseList_elements ;
3351 DPRINTF (("Here: %s / %s",
3352 uentry_unparseFull (le),
3353 bool_unparse (uentry_hasMetaStateEnsures (le))));
3355 if (uentry_hasMetaStateEnsures (le))
3357 fileloc loc = exprNode_loc (f);
3359 metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3361 metaStateConstraintList_elements (mscl, msc)
3363 metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3364 metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3365 metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
3366 cstring key = metaStateInfo_getName (msinfo);
3367 sRef mlsr = metaStateSpecifier_getSref (msspec);
3369 sRef lastref = sRef_undefined;
3370 stateValue sval = stateValue_undefined;
3372 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3373 metaStateConstraint_unparse (msc)));
3374 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3376 if (sRef_isResult (sRef_getRootBase (mlsr)))
3378 s = exprNode_getSref (ret);
3382 s = sRef_fixBaseParam (mlsr, args);
3385 DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3387 while (metaStateExpression_isDefined (msexpr))
3389 metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
3390 metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
3393 DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3395 if (metaStateExpression_isMerge (msexpr))
3397 msexpr = metaStateExpression_getRest (msexpr);
3401 msexpr = metaStateExpression_undefined;
3404 if (metaStateInfo_isDefined (msi))
3406 /* Must match lhs state */
3407 llassert (metaStateInfo_equal (msinfo, msi));
3410 if (metaStateSpecifier_isElipsis (ms))
3413 ** For elipsis, we need to merge all the relevant elipsis parameters
3417 uentryList params = uentry_getParams (le);
3418 int paramno = uentryList_size (params) - 1;
3420 if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
3424 message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3425 uentry_getName (le)),
3426 uentry_whereLast (le));
3427 /*@innerbreak@*/ break;
3430 while (paramno < exprNodeList_size (args))
3432 exprNode arg = exprNodeList_getN (args, paramno);
3433 fs = exprNode_getSref (arg);
3434 DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3436 /* cut and pasted... gack*/
3437 if (stateValue_isDefined (sval))
3439 /* Use combination table to merge old state value with new one: */
3440 stateValue tval = sRef_getMetaStateValue (fs, key);
3442 if (stateValue_isDefined (tval))
3444 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3445 cstring msg = cstring_undefined;
3446 int nval = stateCombinationTable_lookup (sctable,
3447 stateValue_getValue (sval),
3448 stateValue_getValue (tval),
3450 DPRINTF (("Combining: %s + %s -> %d",
3451 stateValue_unparseValue (sval, msinfo),
3452 stateValue_unparseValue (tval, msinfo),
3455 if (nval == stateValue_error)
3460 ("Attributes merged in ensures clause in states that "
3461 "cannot be combined (%q is %q, %q is %q)%q",
3462 sRef_unparse (lastref),
3463 stateValue_unparseValue (sval, msinfo),
3465 stateValue_unparseValue (tval, msinfo),
3466 cstring_isDefined (msg) ?
3467 message (": %s", msg) : cstring_undefined),
3470 sRef_showMetaStateInfo (fs, key);
3474 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3475 loc = exprNode_loc (arg);
3479 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3484 sval = sRef_getMetaStateValue (fs, key);
3489 if (stateValue_isError (sval))
3491 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3500 msr = metaStateSpecifier_getSref (ms);
3503 llassert (sRef_isParam (sRef_getRootBase (msr)));
3504 fs = sRef_fixBaseParam (msr, args);
3506 if (stateValue_isDefined (sval))
3508 /* Use combination table to merge old state value with new one: */
3509 stateValue tval = sRef_getMetaStateValue (fs, key);
3511 if (stateValue_isDefined (tval))
3513 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3514 cstring msg = cstring_undefined;
3515 int nval = stateCombinationTable_lookup (sctable,
3516 stateValue_getValue (sval),
3517 stateValue_getValue (tval),
3519 DPRINTF (("Combining: %s + %s -> %d",
3520 stateValue_unparseValue (sval, msinfo),
3521 stateValue_unparseValue (tval, msinfo),
3524 if (nval == stateValue_error)
3529 ("Attributes merged in ensures clause in states that "
3530 "cannot be combined (%q is %q, %q is %q)%q",
3531 sRef_unparse (lastref),
3532 stateValue_unparseValue (sval, msinfo),
3534 stateValue_unparseValue (tval, msinfo),
3535 cstring_isDefined (msg)
3536 ? message (": %s", msg) : cstring_undefined),
3539 sRef_showMetaStateInfo (fs, key);
3543 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3547 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3552 sval = sRef_getMetaStateValue (fs, key);
3557 if (stateValue_isError (sval))
3559 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3564 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3566 if (stateValue_isDefined (sval))
3568 sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
3572 DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
3574 } end_metaStateConstraintList_elements ;
3576 metaStateConstraintList_free (mscl);
3582 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3584 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3585 exprNode_unparse (f), exprNodeList_unparse (args),
3586 uentry_unparseFull (le),
3587 stateClauseList_unparse (uentry_getStateClauseList (le))));
3589 if (uentry_isValid (le) && uentry_isFunction (le))
3591 stateClauseList sclauses = uentry_getStateClauseList (le);
3593 if (stateClauseList_isDefined (sclauses))
3595 DPRINTF (("Check requires: %s / %s / %s",
3596 uentry_unparse (le),
3597 exprNode_unparse (f), exprNodeList_unparse (args)));
3599 stateClauseList_elements (sclauses, cl)
3601 DPRINTF (("Check clause: %s / %s",
3602 stateClause_unparse (cl),
3603 bool_unparse (stateClause_hasRequires (cl))));
3605 if (stateClause_hasRequires (cl))
3607 sRefSet osrs = sRefSet_undefined;
3610 if (stateClause_isGlobal (cl))
3612 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3617 srs = stateClause_getRefs (cl);
3620 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3622 if (stateClause_setsMetaState (cl))
3624 qual q = stateClause_getMetaQual (cl);
3625 annotationInfo ainfo = qual_getAnnotationInfo (q);
3626 metaStateInfo minfo = annotationInfo_getState (ainfo);
3627 cstring key = metaStateInfo_getName (minfo);
3628 int mvalue = annotationInfo_getValue (ainfo);
3630 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3632 sRefSet_elements (srs, sel)
3634 sRef s = sRef_fixBaseParam (sel, args);
3636 if (sRef_isResult (sRef_getRootBase (sel)))
3642 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3643 sRef_unparseFull (sel), sRef_unparseFull (s),
3646 if (!sRef_checkMetaStateValue (s, key, mvalue))
3648 DPRINTF (("HERE: %s", sRef_unparse (s)));
3652 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3653 uentry_getName (le),
3654 sRef_isGlobalMarker (s)
3656 : message (" by %q", sRef_unparse (s)),
3657 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3659 stateClause_unparse (cl)),
3662 sRef_showAliasInfo (s);
3666 DPRINTF (("Error supressed!"));
3667 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3668 DPRINTF (("Context supress: %s",
3669 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3673 } end_sRefSet_elements;
3677 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3678 int eparam = stateClause_getStateParameter (cl);
3680 DPRINTF (("Reflect after clause: %s / %s",
3681 stateClause_unparse (cl),
3682 sRefSet_unparse (srs)));
3684 llassert (modf != NULL);
3686 sRefSet_elements (srs, sel)
3690 DPRINTF (("elements: %s", sRef_unparse (sel)));
3691 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3693 s = sRef_fixBaseParam (sel, args);
3695 DPRINTF (("elements: %s", sRef_unparse (s)));
3696 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3698 if (sRef_isResult (sRef_getRootBase (sel)))
3700 ; /*@i423 what do we do about results */
3704 DPRINTF (("Reflecting state clause on: %s / %s",
3705 sRef_unparse (sel), sRef_unparse (s)));
3707 modf (s, eparam, exprNode_loc (f));
3709 } end_sRefSet_elements;
3712 sRefSet_free (osrs);
3714 } end_stateClauseList_elements ;
3719 static /*@only@*/ exprNode
3720 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3721 ctype t, /*@keep@*/ exprNodeList args)
3723 /* requires f is a non-error exprNode, with type function */
3724 cstring fname = exprNode_unparse (f);
3725 uentry le = exprNode_getUentry (f);
3726 exprNode ret = exprNode_createPartialCopy (f);
3731 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3733 ret->typ = ctype_getReturnType (t);
3734 ret->kind = XPR_CALL;
3736 ret->edata = exprData_makeCall (f, args);
3739 ** Order of these steps is very important!
3741 ** Must check for argument dependencies before messing up uses and sets.
3744 if (context_getFlag (FLG_EVALORDER))
3746 exprNodeList_elements (args, current)
3748 if (exprNode_isDefined (current))
3750 exprNode_addUse (current, current->sref);
3752 } end_exprNodeList_elements;
3754 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3756 checkSequencing (f, args);
3759 exprNodeList_elements (args, current)
3761 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3763 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3765 } end_exprNodeList_elements ;
3768 special = checkArgs (le, f, t, args, ret);
3769 checkGlobMods (f, le, args, ret, special);
3770 checkRequiresClause (le, f, args);
3773 if (uentry_isValid (le)
3774 && (uentry_isFunction (le)
3775 || (uentry_isVariable (le)
3776 && ctype_isFunction (uentry_getType (le)))))
3778 exitkind exk = uentry_getExitCode (le);
3780 /* f->typ is already set to the return type */
3782 DPRINTF (("Function: %s", uentry_unparseFull (le)));
3783 ret->sref = uentry_returnedRef (le, args, exprNode_loc (f));
3784 DPRINTF (("Returned: %s / %s",
3785 uentry_unparseFull (le),
3786 sRef_unparseFull (ret->sref)));
3788 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3790 qual nullPred = uentry_nullPred (le);
3792 if (qual_isTrueNull (nullPred))
3794 exprNode arg = exprNodeList_head (args);
3796 if (exprNode_isDefined (arg))
3798 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3801 else if (qual_isFalseNull (nullPred))
3803 exprNode arg = exprNodeList_head (args);
3805 if (exprNode_isDefined (arg))
3807 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3812 llassert (qual_isUnknown (nullPred));
3816 if (exitkind_isConditionalExit (exk))
3820 ** if (arg0) then { exit! } else { ; }
3822 ** if (arg0) then { ; } else { exit! }
3827 llassert (!exprNodeList_isEmpty (args));
3828 firstArg = exprNodeList_head (args);
3830 if (exprNode_isDefined (firstArg)
3831 && !guardSet_isEmpty (firstArg->guards))
3833 usymtab_trueBranch (guardSet_undefined);
3834 usymtab_altBranch (guardSet_undefined);
3836 if (exitkind_isTrueExit (exk))
3838 usymtab_popBranches (firstArg,
3839 exprNode_makeMustExit (),
3841 TRUE, TRUEEXITCLAUSE);
3845 usymtab_popBranches (firstArg,
3847 exprNode_makeMustExit (),
3848 TRUE, FALSEEXITCLAUSE);
3852 ret->exitCode = XK_MAYEXIT;
3854 else if (exitkind_mustExit (exk))
3856 ret->exitCode = XK_MUSTEXIT;
3858 else if (exitkind_couldExit (exk))
3860 ret->exitCode = XK_MAYEXIT;
3867 if (cstring_equalLit (fname, "exit"))
3869 if (exprNodeList_size (args) == 1)
3871 exprNode arg = exprNodeList_head (args);
3873 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3875 long int val = multiVal_forceInt (exprNode_getValue (arg));
3882 ("Argument to exit has implementation defined behavior: %s",
3883 exprNode_unparse (arg)),
3884 exprNode_loc (arg));
3892 ret->sref = sRef_undefined;
3893 exprNode_checkSetAny (ret, uentry_rawName (le));
3896 DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3897 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3898 reflectEnsuresClause (ret, le, f, args);
3901 DPRINTF (("Here: %s", sRef_unparseFull (ret->sref)));
3906 ** this is yucky! should keep the uentry as part of exprNode!
3909 uentry exprNode_getUentry (exprNode e)
3911 if (exprNode_isError (e))
3913 return uentry_undefined;
3917 cstring s = exprNode_rootVarName (e);
3918 uentry ue = usymtab_lookupSafe (s);
3925 ** Returns true iff e1 and e2 are both exactly the same storage
3929 static bool exprNode_sameStorage (exprNode e1, exprNode e2)
3931 sRef s1 = exprNode_getSref (e1);
3932 sRef s2 = exprNode_getSref (e2);
3934 return (sRef_realSame (s1, s2));
3938 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3940 exprNode ret = exprNode_createPlain (ctype_unknown);
3942 ret->kind = XPR_INITBLOCK;
3943 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3944 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3950 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3955 usymtab_checkAllValid ();
3958 if (exprNode_isUndefined (f))
3961 exprNodeList_free (args);
3962 return exprNode_undefined;
3965 t = exprNode_getType (f);
3967 if (sRef_isLocalVar (f->sref))
3969 exprNode_checkUse (f, f->sref, f->loc);
3971 if (sRef_possiblyNull (f->sref))
3973 if (!usymtab_isGuarded (f->sref))
3975 if (optgenerror (FLG_NULLDEREF,
3976 message ("Function call using %s pointer %q",
3977 sRef_nullMessage (f->sref),
3978 sRef_unparse (f->sref)),
3981 sRef_showNullInfo (f->sref);
3982 sRef_setNullError (f->sref);
3990 if (ctype_isRealFunction (t))
3992 exprNode ret = functionCallSafe (f, t, args);
3996 else if (ctype_isUnknown (t))
3998 exprNode ret = exprNode_createPartialCopy (f);
4004 exprNodeList_elements (args, current)
4006 if (exprNode_isDefined (current))
4008 exprNode_checkUse (ret, current->sref, ret->loc);
4011 ** also, anything derivable from current->sref may be used
4014 exprNode_addUse (ret, sRef_makeDerived (current->sref));
4015 exprNode_mergeUSs (ret, current);
4017 } end_exprNodeList_elements;
4019 ret->edata = exprData_makeCall (f, args);
4020 ret->kind = XPR_CALL;
4022 tstring = cstring_copy (exprNode_unparse (f));
4024 cstring_markOwned (tstring);
4025 exprNode_checkSetAny (ret, tstring);
4031 voptgenerror (FLG_TYPE,
4032 message ("Call to non-function (type %t): %s", t,
4033 exprNode_unparse (f)),
4036 exprNodeList_free (args);
4038 return (exprNode_makeError ());
4043 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4044 /*@only@*/ cstring f)
4046 exprNode ret = exprNode_createPartialCopy (s);
4048 ret->kind = XPR_FACCESS;
4050 if (exprNode_isError (s))
4052 ret->edata = exprData_makeField (s, f);
4057 ctype t = exprNode_getType (s);
4058 ctype tr = ctype_realType (t);
4060 checkMacroParen (s);
4062 ret->edata = exprData_makeField (s, f);
4064 if (ctype_isStructorUnion (tr))
4066 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
4068 if (uentry_isUndefined (tf))
4070 voptgenerror (FLG_TYPE,
4071 message ("Access non-existent field %s of %t: %s", f, t,
4072 exprNode_unparse (ret)),
4074 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
4079 uentry_setUsed (tf, exprNode_loc (ret));
4081 ret->typ = uentry_getType (tf);
4082 checkSafeUse (ret, s->sref);
4084 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
4085 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
4089 else /* isStructorUnion */
4091 if (ctype_isRealAbstract (tr))
4095 message ("Access field of abstract type (%t): %s.%s",
4096 t, exprNode_unparse (s), f),
4098 ret->typ = ctype_unknown;
4102 if (ctype_isKnown (tr))
4107 ("Access field of non-struct or union (%t): %s.%s",
4108 t, exprNode_unparse (s), f),
4111 ret->typ = ctype_unknown;
4115 cstring sn = cstring_copy (f);
4117 checkSafeUse (ret, s->sref);
4118 cstring_markOwned (sn);
4119 ret->sref = sRef_makeField (s->sref, sn);
4131 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
4132 /*@only@*/ cstring f)
4134 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
4140 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
4142 exprNode ret = exprNode_createPartialCopy (e);
4144 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
4145 ret->kind = XPR_PARENS;
4146 ret->edata = exprData_makeUop (e, lpar);
4148 if (!exprNode_isError (e))
4150 ret->exitCode = e->exitCode;
4151 ret->canBreak = e->canBreak;
4152 ret->mustBreak = e->mustBreak;
4153 ret->isJumpPoint = e->isJumpPoint;
4154 ret->sref = e->sref;
4161 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4162 /*@only@*/ cstring f)
4164 exprNode ret = exprNode_createPartialCopy (s);
4166 ret->edata = exprData_makeField (s, f);
4167 ret->kind = XPR_ARROW;
4169 if (exprNode_isError (s))
4175 ctype t = exprNode_getType (s);
4176 ctype tr = ctype_realType (t);
4178 checkMacroParen (s);
4180 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4182 if (ctype_isRealPointer (tr))
4184 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4186 if (ctype_isStructorUnion (b))
4188 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4190 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4192 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4196 message ("Arrow access from %s pointer%q: %s",
4197 sRef_nullMessage (s->sref),
4198 sRef_unparsePreOpt (s->sref),
4199 exprNode_unparse (ret)),
4202 sRef_showNullInfo (s->sref);
4203 sRef_setNullError (s->sref);
4208 if (uentry_isUndefined (fentry))
4212 message ("Access non-existent field %s of %t: %s",
4213 f, t, exprNode_unparse (ret)),
4215 ret->typ = ctype_unknown;
4221 ** was safeUse: shouldn't be safe!
4224 ** rec must be defined,
4225 ** *rec must be allocated
4226 ** rec->field need only be defined it if is an rvalue
4229 uentry_setUsed (fentry, exprNode_loc (ret));
4230 ret->typ = uentry_getType (fentry);
4232 exprNode_checkUse (ret, s->sref, s->loc);
4234 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4235 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4239 else /* Pointer to something that is not a struct or union*/
4241 if (ctype_isRealAbstract (tr))
4243 ctype xrt = ctype_forceRealType (tr);
4247 message ("Arrow access field of abstract type (%t): %s->%s",
4248 t, exprNode_unparse (s), f),
4252 ** Set the state correctly, as if the abstraction is broken.
4255 if (ctype_isRealPointer (xrt) &&
4256 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4257 ctype_isStructorUnion (b)))
4259 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4260 ret->typ = uentry_getType (fentry);
4261 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4265 ret->typ = ctype_unknown;
4266 ret->sref = sRef_undefined;
4269 else /* not a struct, union or abstract */
4271 if (ctype_isUnknown (tr)) {
4272 cstring sn = cstring_copy (f);
4274 DPRINTF (("Here: %s", exprNode_unparse (s)));
4276 exprNode_checkUse (ret, s->sref, s->loc);
4277 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4279 cstring_markOwned (sn);
4280 ret->sref = sRef_makeArrow (s->sref, sn);
4282 ret->kind = XPR_ARROW;
4287 message ("Arrow access field of non-struct or union "
4288 "pointer (%t): %s->%s",
4289 t, exprNode_unparse (s), f),
4292 ret->typ = ctype_unknown;
4293 ret->sref = sRef_undefined;
4298 else /* its not a pointer */
4300 if (!ctype_isUnknown (tr))
4304 message ("Arrow access of non-pointer (%t): %s->%s",
4305 t, exprNode_unparse (s), f),
4308 ret->typ = ctype_unknown;
4309 ret->sref = sRef_undefined;
4313 cstring sn = cstring_copy (f);
4315 DPRINTF (("Here: %s", exprNode_unparse (s)));
4317 exprNode_checkUse (ret, s->sref, s->loc);
4318 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4320 cstring_markOwned (sn);
4321 ret->sref = sRef_makeArrow (s->sref, sn);
4323 ret->kind = XPR_ARROW;
4334 exprNode_arrowAccess (/*@only@*/ exprNode s,
4335 /*@only@*/ lltok arrow,
4336 /*@only@*/ cstring f)
4338 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4344 ** only postOp's in C: i++ and i--
4348 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4350 /* check modification also */
4351 /* cstring opname = lltok_unparse (op);*/
4353 exprNode ret = exprNode_createPartialCopy (e);
4355 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4356 ret->kind = XPR_POSTOP;
4357 ret->edata = exprData_makeUop (e, op);
4359 if (!exprNode_isDefined (e))
4364 checkMacroParen (e);
4366 exprNode_checkUse (ret, e->sref, e->loc);
4367 exprNode_checkSet (ret, e->sref);
4369 t = exprNode_getType (e);
4371 if (sRef_isUnsafe (e->sref))
4373 voptgenerror (FLG_MACROPARAMS,
4374 message ("Operand of %s is macro parameter (non-functional): %s%s",
4375 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4377 sRef_makeSafe (e->sref);
4378 sRef_makeSafe (ret->sref);
4381 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4387 if (ctype_isRealAbstract (t))
4389 if (ctype_isRealNumAbstract (t)) {
4390 ; /* Allow operations on numabstract types */
4394 message ("Operand of %s is abstract type (%t): %s",
4395 lltok_unparse (op), t, exprNode_unparse (e)),
4403 message ("Operand of %s is non-numeric (%t): %s",
4404 lltok_unparse (op), t, exprNode_unparse (e)),
4407 ret->typ = ctype_unknown;
4410 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4412 exprNode_checkModify (e, ret);
4414 /* added 7/11/2000 D.L */
4416 /*DRL 6/8/01 I decided to disable all Splint warnings here since the code
4417 probably needs a rewrite any way */
4422 /* updateEnvironmentForPostOp (e); */
4424 /* start modifications */
4425 /* added by Seejo on 4/16/2000 */
4427 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4429 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4431 ret->sref = sRef_copy (e->sref);
4434 if (lltok_getTok (op) == INC_OP) {
4435 if (sRef_getSize(e->sref) > 0) {
4437 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4439 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4440 /* Assumption: there is only 1 \0 in the buffer */
4441 /* This will not be correct if there are 2 \0's in the buffer */
4442 sRef_setNotNullTerminatedState(ret->sref);
4443 sRef_resetLen(ret->sref);
4445 sRef_setNullTerminatedState(ret->sref);
4446 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4448 if (sRef_isNullTerminated (ret->sref))
4449 printf ("ret->sref is Null Terminated\n");
4450 else if (sRef_isPossiblyNullTerminated (ret->sref))
4451 printf ("ret->sref is Possibly Null Terminated\n");
4452 else if (sRef_isNotNullTerminated (ret->sref))
4453 printf ("ret->sref is Not Null Terminated\n");
4458 if (lltok_getTok (op) == DEC_OP) {
4459 if (sRef_getSize(e->sref) >= 0) {
4460 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4461 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4466 /* end modifications */
4472 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4474 bool checkMod = FALSE;
4476 int opid = lltok_getTok (op);
4477 exprNode ret = exprNode_createSemiCopy (e);
4479 exprNode_copySets (ret, e);
4481 multiVal_free (ret->val);
4482 ret->val = multiVal_undefined;
4483 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4484 ret->kind = XPR_PREOP;
4485 ret->edata = exprData_makeUop (e, op);
4487 if (exprNode_isError (e))
4492 checkMacroParen (e);
4494 te = exprNode_getType (e);
4495 tr = ctype_realType (te);
4497 if (opid != TAMPERSAND)
4499 exprNode_checkUse (ret, e->sref, e->loc);
4501 if (ctype_isRealAbstract (tr)
4502 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4504 if (ctype_isRealNumAbstract (tr))
4506 ; /* no warning for numabstract types */
4510 if (optgenerror (FLG_ABSTRACT,
4511 message ("Operand of %s is abstract type (%t): %s",
4512 lltok_unparse (op), tr,
4513 exprNode_unparse (ret)),
4516 tr = te = ctype_unknown;
4517 ret->typ = ctype_unknown;
4518 sRef_setNullError (e->sref);
4527 case DEC_OP: /* should also check modification! */
4528 if (sRef_isMacroParamRef (e->sref))
4532 message ("Operand of %s is macro parameter (non-functional): %s",
4533 lltok_unparse (op), exprNode_unparse (ret)),
4538 exprNode_checkSet (ret, e->sref);
4541 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4546 if (context_msgStrictOps ())
4550 message ("Operand of %s is non-numeric (%t): %s",
4551 lltok_unparse (op), te, exprNode_unparse (ret)),
4554 ret->typ = ctype_int;
4557 /* start modifications */
4558 /* added by Seejo on 4/16/2000 */
4560 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4562 if ((sRef_isPossiblyNullTerminated (e->sref))
4563 || (sRef_isNullTerminated(e->sref))) {
4564 ret->sref = sRef_copy (e->sref);
4567 if (lltok_getTok (op) == INC_OP) {
4568 if (sRef_getSize(e->sref) > 0) {
4570 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4572 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4573 /* Assumption: there is only 1 \0 in the buffer */
4574 /* This will not be correct if there are 2 \0's in the buffer */
4575 sRef_setNotNullTerminatedState(ret->sref);
4576 sRef_resetLen (ret->sref);
4578 sRef_setNullTerminatedState(ret->sref);
4579 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4585 if (lltok_getTok (op) == DEC_OP) {
4586 if (sRef_getSize(e->sref) >= 0) {
4587 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4588 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4593 /* end modifications */
4600 if (ctype_isForceRealNumeric (&tr))
4604 ret->val = multiVal_invert (exprNode_getValue (e));
4608 ret->val = multiVal_copy (exprNode_getValue (e));
4613 if (context_msgStrictOps ())
4617 message ("Operand of %s is non-numeric (%t): %s",
4618 lltok_unparse (op), te, exprNode_unparse (ret)),
4622 ret->typ = ctype_int;
4626 case TEXCL: /* maybe this should be restricted */
4627 guardSet_flip (ret->guards);
4629 if (ctype_isRealBool (te) || ctype_isUnknown (te))
4635 if (ctype_isRealPointer (tr))
4637 if (sRef_isKnown (e->sref))
4639 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4643 (FLG_BOOLOPS, FLG_PTRNEGATE,
4644 message ("Operand of %s is non-boolean (%t): %s",
4645 lltok_unparse (op), te, exprNode_unparse (ret)),
4652 message ("Operand of %s is non-boolean (%t): %s",
4653 lltok_unparse (op), te, exprNode_unparse (ret)),
4657 ret->typ = ctype_bool;
4662 if (ctype_isForceRealInt (&tr))
4667 if (context_msgStrictOps ())
4671 message ("Operand of %s is non-integer (%t): %s",
4672 lltok_unparse (op), te, exprNode_unparse (ret)),
4676 if (ctype_isInt (e->typ))
4682 ret->typ = ctype_int;
4688 ret->typ = ctype_makePointer (e->typ);
4690 if (sRef_isKnown (e->sref))
4692 ret->sref = sRef_makeAddress (e->sref);
4699 if (ctype_isAP (tr))
4701 ret->typ = ctype_baseArrayPtr (e->typ);
4705 if (ctype_isKnown (te))
4707 if (ctype_isFunction (te))
4713 message ("Dereference of function type (%t): %s",
4714 te, exprNode_unparse (ret)),
4719 voptgenerror (FLG_TYPE,
4720 message ("Dereference of non-pointer (%t): %s",
4721 te, exprNode_unparse (ret)),
4723 ret->typ = ctype_unknown;
4728 ret->typ = ctype_unknown;
4733 if (sRef_isKnown (e->sref))
4735 DPRINTF (("Checking possibly null: %s", sRef_unparseFull (e->sref)));
4737 if (sRef_possiblyNull (e->sref))
4739 DPRINTF (("Checking possibly null: %s", sRef_unparse (e->sref)));
4740 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4744 message ("Dereference of %s pointer %q: %s",
4745 sRef_nullMessage (e->sref),
4746 sRef_unparse (e->sref),
4747 exprNode_unparse (ret)),
4750 sRef_showNullInfo (e->sref);
4751 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4756 ret->sref = sRef_makePointer (e->sref);
4761 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4766 exprNode_checkModify (e, ret);
4773 ** any reason to disallow sizeof (abstract type) ?
4777 ** used by both sizeof
4781 ctype sizeof_resultType (void)
4783 static ctype sizet = ctype_unknown;
4785 if (ctype_isUnknown (sizet))
4787 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4789 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4793 sizet = ctype_ulint;
4800 exprNode_sizeofType (/*@only@*/ qtype qt)
4802 exprNode ret = exprNode_create (sizeof_resultType ());
4803 ctype ct = qtype_getType (qt);
4805 ret->kind = XPR_SIZEOFT;
4806 ret->edata = exprData_makeSizeofType (qt);
4808 voptgenerror (FLG_SIZEOFTYPE,
4809 message ("Parameter to sizeof is type %s: %s",
4811 exprNode_unparse (ret)),
4818 exprNode_alignofType (/*@only@*/ qtype qt)
4820 exprNode ret = exprNode_create (sizeof_resultType ());
4821 ctype ct = qtype_getType (qt);
4823 ret->kind = XPR_ALIGNOFT;
4824 ret->edata = exprData_makeSizeofType (qt);
4826 voptgenerror (FLG_SIZEOFTYPE,
4827 message ("Parameter to alignof is type %s: %s",
4829 exprNode_unparse (ret)),
4835 exprNode exprNode_offsetof (qtype qt, cstringList s)
4837 exprNode ret = exprNode_create (sizeof_resultType ());
4838 ctype ct = qtype_getType (qt);
4840 ret->kind = XPR_OFFSETOF;
4841 ret->edata = exprData_makeOffsetof (qt, s);
4843 if (!ctype_isRealSU (ct))
4845 voptgenerror (FLG_TYPE,
4846 message ("First parameter to offsetof is not a "
4847 "struct or union type (type %s): %s",
4849 exprNode_unparse (ret)),
4856 cstringList_elements (s, el) {
4860 if (ctype_isUndefined (lt))
4864 else if (!ctype_isRealSU (lt))
4866 voptgenerror (FLG_TYPE,
4867 message ("Inner offsetof type is not a "
4868 "struct or union type (type %s before field %s): %s",
4869 ctype_unparse (lt), el,
4870 exprNode_unparse (ret)),
4876 fields = ctype_getFields (ctype_realType (lt));
4877 fld = uentryList_lookupField (fields, el);
4878 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4880 if (uentry_isUndefined (fld))
4882 if (ctype_equal (lt, ct)) {
4883 voptgenerror (FLG_TYPE,
4884 message ("Field %s in offsetof is not the "
4885 "name of a field of %s: %s",
4888 exprNode_unparse (ret)),
4891 voptgenerror (FLG_TYPE,
4892 message ("Deep field %s in offsetof is not the "
4893 "name of a field of %s: %s",
4896 exprNode_unparse (ret)),
4902 lt = uentry_getType (fld);
4905 } end_cstringList_elements;
4907 /* Should report error if its a bit field - behavior is undefined! */
4914 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4918 if (exprNode_isUndefined (e))
4920 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4921 ret->edata = exprData_makeSingle (e);
4922 ret->typ = sizeof_resultType ();
4923 ret->kind = XPR_SIZEOF;
4927 uentry u = exprNode_getUentry (e);
4929 ret = exprNode_createPartialCopy (e);
4930 ret->edata = exprData_makeSingle (e);
4932 ret->typ = sizeof_resultType ();
4933 ret->kind = XPR_SIZEOF;
4935 if (uentry_isValid (u)
4936 && uentry_isRefParam (u)
4937 && ctype_isRealArray (uentry_getType (u)))
4940 (FLG_SIZEOFFORMALARRAY,
4941 message ("Parameter to sizeof is an array-type function parameter: %s",
4942 exprNode_unparse (ret)),
4948 ** sizeof (x) doesn't "really" use x
4955 exprNode_alignofExpr (/*@only@*/ exprNode e)
4959 if (exprNode_isUndefined (e))
4961 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4965 ret = exprNode_createPartialCopy (e);
4968 ret->edata = exprData_makeSingle (e);
4969 ret->typ = sizeof_resultType ();
4970 ret->kind = XPR_ALIGNOF;
4973 ** sizeof (x) doesn't "really" use x
4980 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4986 if (exprNode_isError (e))
4990 return exprNode_undefined;
4993 checkMacroParen (e);
4995 c = qtype_getType (q);
4996 t = exprNode_getType (e);
4998 ret = exprNode_createPartialCopy (e);
5000 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
5002 ret->kind = XPR_CAST;
5003 ret->edata = exprData_makeCast (tok, e, q);
5005 ret->sref = sRef_copy (e->sref);
5007 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
5009 if (!sRef_isConst (e->sref))
5011 usymtab_addForceMustAlias (ret->sref, e->sref);
5014 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
5015 sRef_setTypeFull (ret->sref, c);
5016 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
5022 ** void * <-> abstract * (if FLG_ABSTVOIDP)
5023 ** abstract * <-> void * (if FLG_ABSTVOIDP)
5026 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
5028 /* evans 2002-07-19: added this warning */
5029 DPRINTF (("Checking: %s / %s", exprNode_unparse (ret), sRef_unparseFull (ret->sref)));
5030 if (sRef_isFresh (ret->sref))
5034 message ("New fresh storage %q(type %s) cast to void (not released): %s",
5035 sRef_unparseOpt (ret->sref),
5036 ctype_unparse (exprNode_getType (ret)),
5037 exprNode_unparse (ret)),
5038 exprNode_loc (ret));
5041 else if (ctype_isRealAP (c)) /* casting to array or pointer */
5043 ctype bc = ctype_getBaseType (c);
5044 ctype bt = ctype_getBaseType (t);
5045 ctype rt = ctype_realType (t);
5047 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
5048 && (ctype_isArrayPtr (rt)
5049 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5053 message ("Cast from function pointer type (%t) to "
5054 "non-function pointer (%t): %s",
5055 c, t, exprNode_unparse (ret)),
5059 if (!ctype_isFunction (ctype_baseArrayPtr (c))
5060 && (ctype_isArrayPtr (rt)
5061 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5065 message ("Cast from non-function pointer type (%t) to "
5066 "function pointer (%t): %s",
5067 c, t, exprNode_unparse (ret)),
5071 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
5072 !(ctype_isRealAbstract (bc)
5073 && context_hasAccess (ctype_typeId (bc))))
5075 ; /* okay to cast zero */
5079 if (ctype_isRealAbstract (bc)
5080 && !context_hasAccess (ctype_typeId (bc)))
5082 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
5086 message ("Cast to underlying abstract type %t: %s",
5087 c, exprNode_unparse (ret)),
5094 message ("Cast to underlying abstract type %t: %s",
5095 c, exprNode_unparse (ret)),
5100 if (ctype_isRealAbstract (bt)
5101 && !context_hasAccess (ctype_typeId (bt)))
5103 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
5107 message ("Cast from underlying abstract type %t: %s",
5108 t, exprNode_unparse (ret)),
5115 message ("Cast from underlying abstract type %t: %s",
5116 t, exprNode_unparse (ret)),
5124 ctype bt = ctype_realType (ctype_getBaseType (t));
5125 ctype bc = ctype_realType (ctype_getBaseType (c));
5127 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
5129 if (ctype_match (c, t))
5131 if (ctype_equal (c, t))
5135 message ("Redundant cast involving abstract type %t: %s",
5136 bt, exprNode_unparse (ret)),
5144 message ("Cast from abstract type %t: %s",
5145 bt, exprNode_unparse (ret)),
5150 if (ctype_isAbstract (bc)
5151 && !context_hasAccess (ctype_typeId (bc)))
5153 if (ctype_match (c, t))
5159 if (ctype_isNumAbstract (bc))
5161 if (exprNode_isNumLiteral (e))
5164 (FLG_NUMABSTRACTCAST,
5165 message ("Cast from literal to numabstract type %t: %s", bc,
5166 exprNode_unparse (ret)),
5173 message ("Cast to numabstract type %t: %s", bc,
5174 exprNode_unparse (ret)),
5180 DPRINTF (("No access to: %s / %d",
5181 ctype_unparse (bc), ctype_typeId (bc)));
5182 DPRINTF (("Context %s %s",
5183 bool_unparse (context_inFunctionLike ()),
5184 context_unparse ()));
5187 message ("Cast to abstract type %t: %s", bc,
5188 exprNode_unparse (ret)),
5195 if (ctype_isAbstract (c))
5197 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
5199 /* okay, cast exposed to abstract */
5200 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
5204 if (ctype_isVisiblySharable (t)
5205 && sRef_isExternallyVisible (e->sref)
5206 && !(ctype_isAbstract (t)
5207 && context_hasAccess (ctype_typeId (t))))
5211 message ("Cast to abstract type from externally visible "
5212 "mutable storage exposes rep of %s: %s",
5214 exprNode_unparse (e)),
5224 evaluationOrderUndefined (lltok op)
5226 int opid = lltok_getTok (op);
5228 return (opid != AND_OP && opid != OR_OP);
5231 static bool checkIntegral (/*@notnull@*/ exprNode e1,
5232 /*@notnull@*/ exprNode e2,
5233 /*@notnull@*/ exprNode ret,
5238 ctype te1 = exprNode_getType (e1);
5239 ctype te2 = exprNode_getType (e2);
5241 ctype tr1 = ctype_realishType (te1);
5242 ctype tr2 = ctype_realishType (te2);
5244 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5250 if (context_msgStrictOps ())
5252 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5254 if (ctype_sameName (te1, te2))
5258 message ("Operands of %s are non-integer (%t): %s",
5259 lltok_unparse (op), te1,
5260 exprNode_unparse (ret)),
5267 message ("Operands of %s are non-integers (%t, %t): %s",
5268 lltok_unparse (op), te1, te2,
5269 exprNode_unparse (ret)),
5273 else if (!ctype_isInt (tr1))
5277 message ("Left operand of %s is non-integer (%t): %s",
5278 lltok_unparse (op), te1, exprNode_unparse (ret)),
5282 /* !ctype_isInt (te2) */
5286 message ("Right operand of %s is non-integer (%t): %s",
5287 lltok_unparse (op), te2, exprNode_unparse (ret)),
5297 ** returns exprNode representing e1 op e2
5299 ** uses msg if there are errors
5300 ** can be used for both assignment ops and regular ops
5305 static /*@only@*/ /*@notnull@*/ exprNode
5306 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
5307 /*@keep@*/ lltok op)
5309 ctype te1, te2, tr1, tr2, tret;
5310 int opid = lltok_getTok (op);
5311 bool hasError = FALSE;
5314 if (exprNode_isError (e1))
5316 ret = exprNode_createPartialNVCopy (e2);
5320 ret = exprNode_createPartialNVCopy (e1);
5323 ret->val = multiVal_undefined;
5326 ret->edata = exprData_makeOp (e1, e2, op);
5328 if (exprNode_isError (e1) || exprNode_isError (e2))
5330 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5331 || opid == EQ_OP || opid == NE_OP
5332 || opid == AND_OP || opid == OR_OP)
5334 ret->typ = ctype_bool;
5337 if (exprNode_isDefined (e1))
5339 exprNode_checkUse (ret, e1->sref, e1->loc);
5342 if (exprNode_isDefined (e2))
5344 exprNode_mergeUSs (ret, e2);
5345 exprNode_checkUse (ret, e2->sref, e2->loc);
5351 tret = ctype_unknown;
5352 te1 = exprNode_getType (e1);
5354 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5356 te2 = exprNode_getType (e2);
5358 tr1 = ctype_realishType (te1);
5359 tr2 = ctype_realishType (te2);
5363 ret->guards = guardSet_or (ret->guards, e2->guards);
5365 else if (opid == AND_OP)
5367 ret->guards = guardSet_and (ret->guards, e2->guards);
5374 if (opid == EQ_OP || opid == NE_OP)
5376 exprNode temp1 = e1, temp2 = e2;
5378 /* could do NULL == x */
5380 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5382 temp1 = e2; temp2 = e1;
5385 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5387 reflectNullTest (temp1, (opid == NE_OP));
5388 guardSet_free (ret->guards);
5389 ret->guards = guardSet_copy (temp1->guards);
5393 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5394 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5399 if (anyAbstract (tr1, tr2) &&
5400 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
5401 (opid == AND_OP || opid == OR_OP
5402 || opid == EQ_OP || opid == NE_OP))))
5404 if (abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc))
5406 tret = ctype_unknown;
5411 if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5413 /* unknown types, no comparisons possible */
5419 case TMULT: /* multiplication and division: */
5421 case MUL_ASSIGN: /* numeric, numeric -> numeric */
5422 case DIV_ASSIGN: /* */
5423 if (opid == TMULT || opid == MUL_ASSIGN)
5425 ret->val = multiVal_multiply (exprNode_getValue (e1),
5426 exprNode_getValue (e2));
5430 ret->val = multiVal_divide (exprNode_getValue (e1),
5431 exprNode_getValue (e2));
5434 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5437 case TPLUS: /* addition and subtraction: */
5438 case TMINUS: /* pointer, int -> pointer */
5439 case SUB_ASSIGN: /* int, pointer -> pointer */
5440 case ADD_ASSIGN: /* numeric, numeric -> numeric */
5441 if (opid == TPLUS || opid == ADD_ASSIGN)
5443 ret->val = multiVal_add (exprNode_getValue (e1),
5444 exprNode_getValue (e2));
5448 ret->val = multiVal_subtract (exprNode_getValue (e1),
5449 exprNode_getValue (e2));
5452 tr1 = ctype_fixArrayPtr (tr1);
5454 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5455 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5459 if (context_msgPointerArith ())
5463 message ("Pointer arithmetic (%t, %t): %s",
5464 te1, te2, exprNode_unparse (ret)),
5469 ** Swap terms so e1 is always the pointer
5472 if (ctype_isRealPointer (tr1))
5478 exprNode_swap (e1, e2);
5481 if (sRef_possiblyNull (e1->sref)
5482 && !usymtab_isGuarded (e1->sref))
5485 (FLG_NULLPOINTERARITH,
5486 message ("Pointer arithmetic involving possibly "
5487 "null pointer %s: %s",
5488 exprNode_unparse (e1),
5489 exprNode_unparse (ret)),
5493 ret->sref = sRef_copy (e1->sref);
5495 /* start modifications */
5496 /* added by Seejo on 4/16/2000 */
5498 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5500 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5503 added ugly fixed to stop
5504 program from crashing on point + int +int
5505 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5507 if (!multiVal_isInt (e2->val) )
5511 val = (int) multiVal_forceInt (e2->val);
5513 /* Operator : + or += */
5514 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5515 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5516 val should not result in a
5517 size < 0 (size = 0 is ok !) */
5519 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5521 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5522 sRef_setNotNullTerminatedState(ret->sref);
5523 sRef_resetLen (ret->sref);
5525 sRef_setNullTerminatedState(ret->sref);
5526 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5531 /* Operator : - or -= */
5532 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5533 if (sRef_getSize(e1->sref) >= 0) {
5534 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5535 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5540 /* end modifications */
5542 sRef_setNullError (ret->sref);
5545 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5546 ** since is points to storage that should not be deallocated
5547 ** through this pointer.
5550 if (sRef_isOnly (ret->sref)
5551 || sRef_isFresh (ret->sref))
5553 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5558 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5559 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5561 if (context_msgPointerArith ())
5565 message ("Pointer arithmetic (%t, %t): %s",
5566 te1, te2, exprNode_unparse (ret)),
5570 if (sRef_possiblyNull (e1->sref)
5571 && !usymtab_isGuarded (e1->sref))
5574 (FLG_NULLPOINTERARITH,
5575 message ("Pointer arithmetic involving possibly "
5576 "null pointer %s: %s",
5577 exprNode_unparse (e2),
5578 exprNode_unparse (ret)),
5582 ret->sref = sRef_copy (e2->sref);
5584 /* start modifications */
5585 /* added by Seejo on 4/16/2000 */
5587 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5590 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5591 int val = (int) multiVal_forceInt (e1->val);
5593 /* Operator : + or += */
5594 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5595 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5596 val should not result in a
5597 size < 0 (size = 0 is ok !) */
5599 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5601 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5602 sRef_setNotNullTerminatedState(ret->sref);
5603 sRef_resetLen (ret->sref);
5605 sRef_setNullTerminatedState(ret->sref);
5606 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5611 /* Operator : - or -= */
5612 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5613 if (sRef_getSize(e2->sref) >= 0) {
5614 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5615 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5619 /* end modifications */
5621 sRef_setNullError (ret->sref);
5624 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5625 ** since is points to storage that should not be deallocated
5626 ** through this pointer.
5629 if (sRef_isOnly (ret->sref)
5630 || sRef_isFresh (ret->sref)) {
5631 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5635 ret->sref = e2->sref;
5639 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5648 case TAMPERSAND: /* bitwise & */
5650 case TCIRC: /* ^ (XOR) */
5655 bool reported = FALSE;
5661 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5662 || opid == RIGHT_OP || opid == RIGHT_ASSIGN)
5665 ** evans 2002-01-01: fixed this to follow ISO 6.5.7.
5668 if (!ctype_isUnsigned (tr2)
5669 && !exprNode_isNonNegative (e2))
5671 reported = optgenerror
5673 message ("Right operand of %s may be negative (%t): %s",
5674 lltok_unparse (op), te2,
5675 exprNode_unparse (ret)),
5679 if (!ctype_isUnsigned (tr1)
5680 && !exprNode_isNonNegative (e1))
5682 reported = optgenerror
5683 (FLG_SHIFTIMPLEMENTATION,
5684 message ("Left operand of %s may be negative (%t): %s",
5685 lltok_unparse (op), te1,
5686 exprNode_unparse (ret)),
5691 ** Should check size of right operand also...
5697 if (!ctype_isUnsigned (tr1))
5699 if (exprNode_isNonNegative (e1)) {
5702 reported = optgenerror
5704 message ("Left operand of %s is not unsigned value (%t): %s",
5705 lltok_unparse (op), te1,
5706 exprNode_unparse (ret)),
5716 if (!ctype_isUnsigned (tr2))
5718 if (!exprNode_isNonNegative (e2)) {
5719 reported = optgenerror
5721 message ("Right operand of %s is not unsigned value (%t): %s",
5722 lltok_unparse (op), te2,
5723 exprNode_unparse (ret)),
5732 if (!checkIntegral (e1, e2, ret, op)) {
5733 te1 = ctype_unknown;
5737 DPRINTF (("Set: %s", ctype_unparse (te1)));
5740 ** tret is the widest type of te1 and te2
5743 tret = ctype_widest (te1, te2);
5748 if (checkIntegral (e1, e2, ret, op)) {
5751 tret = ctype_unknown;
5756 case TLT: /* comparisons */
5757 case TGT: /* numeric, numeric -> bool */
5759 DPRINTF (("Here we go: %s / %s",
5760 ctype_unparse (tr1), ctype_unparse (tr2)));
5762 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5763 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5766 bool fepsilon = FALSE;
5768 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5773 if (opid == TLT || opid == TGT)
5775 uentry ue1 = exprNode_getUentry (e1);
5776 uentry ue2 = exprNode_getUentry (e2);
5779 ** FLT_EPSILON, etc. really is a variable, not
5783 if (uentry_isVariable (ue1))
5785 cstring uname = uentry_rawName (ue1);
5787 if (cstring_equalLit (uname, "FLT_EPSILON")
5788 || cstring_equalLit (uname, "DBL_EPSILON")
5789 || cstring_equalLit (uname, "LDBL_EPSILON"))
5795 if (uentry_isVariable (ue2))
5797 cstring uname = uentry_rawName (ue2);
5799 if (cstring_equalLit (uname, "FLT_EPSILON")
5800 || cstring_equalLit (uname, "DBL_EPSILON")
5801 || cstring_equalLit (uname, "LDBL_EPSILON"))
5810 ; /* Don't complain. */
5816 message ("Dangerous comparison involving %s types: %s",
5817 ctype_unparse (rtype),
5818 exprNode_unparse (ret)),
5827 ** Types should match.
5830 DPRINTF (("Match types: %s / %s", exprNode_unparse (e1),
5831 exprNode_unparse (e2)));
5833 if (!exprNode_matchTypes (e1, e2))
5835 hasError = gentypeerror
5837 message ("Operands of %s have incompatible types (%t, %t): %s",
5838 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5844 || (ctype_isForceRealNumeric (&tr1)
5845 && ctype_isForceRealNumeric (&tr2)) ||
5846 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5852 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5853 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5857 message ("Comparison of pointer and numeric (%t, %t): %s",
5858 te1, te2, exprNode_unparse (ret)),
5863 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5868 /* certain comparisons on unsigned's and zero look suspicious */
5870 if (opid == TLT || opid == LE_OP || opid == GE_OP)
5872 if ((ctype_isUnsigned (tr1) && exprNode_isZero (e2))
5873 || (ctype_isUnsigned (tr2) && exprNode_isZero (e1)))
5876 (FLG_UNSIGNEDCOMPARE,
5877 message ("Comparison of unsigned value involving zero: %s",
5878 exprNode_unparse (ret)),
5883 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5885 if ((opid == EQ_OP || opid == NE_OP) &&
5886 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5889 ** is one a variable?
5892 if (uentry_isVariable (exprNode_getUentry (e1))
5893 || uentry_isVariable (exprNode_getUentry (e2)))
5896 ** comparisons with FALSE are okay
5899 if (exprNode_isFalseConstant (e1)
5900 || exprNode_isFalseConstant (e2))
5909 ("Use of %q with %s variables (risks inconsistency because "
5910 "of multiple true values): %s",
5911 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5912 context_printBoolName (), exprNode_unparse (ret)),
5919 case AND_OP: /* bool, bool -> bool */
5921 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5927 if (context_maybeSet (FLG_BOOLOPS))
5929 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5931 if (ctype_sameName (te1, te2))
5935 message ("Operands of %s are non-boolean (%t): %s",
5936 lltok_unparse (op), te1,
5937 exprNode_unparse (ret)),
5945 ("Operands of %s are non-booleans (%t, %t): %s",
5946 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5950 else if (!ctype_isRealBool (te1))
5954 message ("Left operand of %s is non-boolean (%t): %s",
5955 lltok_unparse (op), te1, exprNode_unparse (ret)),
5958 else if (!ctype_isRealBool (te2))
5962 message ("Right operand of %s is non-boolean (%t): %s",
5963 lltok_unparse (op), te2, exprNode_unparse (ret)),
5976 (cstring_makeLiteral
5977 ("There has been a problem in the parser. This is believed to result "
5978 "from a problem with bison v. 1.25. Please try rebuidling Splint "
5979 "using the pre-compiled grammar files by commenting out the "
5980 "BISON= line in the top-level Makefile."));
5985 DPRINTF (("Return type %s: %s", exprNode_unparse (ret), ctype_unparse (tret)));
5987 exprNode_checkUse (ret, e1->sref, e1->loc);
5988 exprNode_mergeUSs (ret, e2);
5989 exprNode_checkUse (ret, e2->sref, e2->loc);
5995 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5996 /*@only@*/ lltok op)
6000 checkMacroParen (e1);
6001 checkMacroParen (e2);
6003 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
6005 checkExpressionDefined (e1, e2, op);
6008 ret = exprNode_makeOp (e1, e2, op);
6013 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
6016 ** This is somewhat bogus!
6018 ** Assigning to a nested observer in a non-observer datatype
6019 ** should not produce an error.
6022 sRef ref = exprNode_getSref (e1);
6024 DPRINTF (("Check assign mod: %s",
6025 sRef_unparseFull (ref)));
6027 if (sRef_isObserver (ref)
6028 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
6029 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
6031 sRef base = sRef_getBase (ref);
6033 if (sRef_isValid (base) && sRef_isObserver (base))
6035 exprNode_checkModify (e1, ret);
6039 exprNode_checkModifyVal (e1, ret);
6044 exprNode_checkModify (e1, ret);
6049 exprNode_assign (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2, /*@only@*/ lltok op)
6051 bool isalloc = FALSE;
6052 bool isjustalloc = FALSE;
6053 bool noalias = FALSE;
6056 DPRINTF (("%s [%s] <- %s [%s]",
6057 exprNode_unparse (e1),
6058 ctype_unparse (e1->typ),
6059 exprNode_unparse (e2),
6060 ctype_unparse (e2->typ)));
6062 if (lltok_getTok (op) != TASSIGN)
6064 ret = exprNode_makeOp (e1, e2, op);
6066 DPRINTF (("Here goes: %s %s",
6067 ctype_unparse (e1->typ),
6068 ctype_unparse (e2->typ)));
6070 if (exprNode_isDefined (e1)
6071 && exprNode_isDefined (e2))
6073 if (ctype_isNumeric (e2->typ)
6074 || ctype_isNumeric (e1->typ))
6076 /* Its a pointer arithmetic expression like ptr += i */
6083 ret = exprNode_createPartialCopy (e1);
6084 ret->kind = XPR_ASSIGN;
6085 ret->edata = exprData_makeOp (e1, e2, op);
6087 if (!exprNode_isError (e2))
6089 ret->sets = sRefSet_union (ret->sets, e2->sets);
6090 ret->msets = sRefSet_union (ret->msets, e2->msets);
6091 ret->uses = sRefSet_union (ret->uses, e2->uses);
6095 checkExpressionDefined (e1, e2, op);
6097 if (exprNode_isError (e1))
6099 if (!exprNode_isError (e2))
6101 ret->loc = fileloc_update (ret->loc, e2->loc);
6105 ret->loc = fileloc_update (ret->loc, g_currentloc);
6109 if (!exprNode_isError (e2))
6111 checkMacroParen (e2);
6114 if (exprNode_isDefined (e1))
6116 if (sRef_isMacroParamRef (e1->sref))
6118 if (context_inIterDef ())
6120 uentry ue = sRef_getUentry (e1->sref);
6122 if (uentry_isYield (ue))
6128 if (fileloc_isDefined (e1->loc))
6132 message ("Assignment to non-yield iter parameter: %q",
6133 sRef_unparse (e1->sref)),
6140 message ("Assignment to non-yield iter parameter: %q",
6141 sRef_unparse (e1->sref)),
6148 if (fileloc_isDefined (e1->loc))
6152 message ("Assignment to macro parameter: %q",
6153 sRef_unparse (e1->sref)),
6160 message ("Assignment to macro parameter: %q",
6161 sRef_unparse (e1->sref)),
6165 exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
6170 exprNode_checkAssignMod (e1, ret);
6173 if (exprNode_isDefined (e2))
6175 if (lltok_getTok (op) == TASSIGN)
6177 ctype te1 = exprNode_getType (e1);
6178 ctype te2 = exprNode_getType (e2);
6180 if (ctype_isVoid (te2))
6184 message ("Assignment of void value to %t: %s %s %s",
6185 te1, exprNode_unparse (e1),
6187 exprNode_unparse (e2)),
6190 else if (!ctype_forceMatch (te1, te2))
6192 if (exprNode_matchLiteral (te1, e2))
6194 DPRINTF (("Literals match: %s / %s",
6195 ctype_unparse (te1), exprNode_unparse (e2)));
6196 if (ctype_isNumAbstract (te1)) {
6197 if (!context_flagOn (FLG_NUMABSTRACTLIT, e1->loc)) {
6198 (void) llgenhinterror
6201 ("Assignment of %t literal to numabstract type %t: %s %s %s",
6203 exprNode_unparse (e1),
6205 exprNode_unparse (e2)),
6207 ("Use +numabstractlit to allow numeric literals to be used as numabstract values"),
6216 message ("Assignment of %t to %t: %s %s %s",
6217 te2, te1, exprNode_unparse (e1),
6219 exprNode_unparse (e2)),
6225 /* Type checks okay */
6229 exprNode_mergeUSs (ret, e2);
6230 exprNode_checkUse (ret, e2->sref, e2->loc);
6232 DPRINTF (("Do assign! %s %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6239 doAssign (e1, e2, FALSE);
6242 ret->sref = e1->sref;
6246 if (exprNode_isDefined (e2))
6248 exprNode_mergeUSs (ret, e2);
6249 exprNode_checkUse (ret, e2->sref, e2->loc);
6253 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
6255 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
6258 isjustalloc = sRef_isJustAllocated (e1->sref);
6259 isalloc = sRef_isAllocated (e1->sref);
6261 if (sRef_isField (e1->sref))
6263 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
6265 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
6267 exprNode_checkUse (ret, root, e1->loc);
6273 ** be careful! this defines e1->sref.
6276 /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
6278 DPRINTF (("Setting: %s -> %s", exprNode_unparse (ret), sRef_unparse (e1->sref)));
6279 exprNode_checkSet (ret, e1->sref);
6283 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
6284 ? e2->loc : e1->loc);
6290 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
6299 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
6300 /*@keep@*/ exprNode elseclause)
6304 if (!exprNode_isError (pred))
6306 ret = exprNode_createPartialCopy (pred);
6307 checkMacroParen (pred);
6308 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
6310 if (!exprNode_isError (ifclause))
6312 checkMacroParen (ifclause); /* update macro counts! */
6314 if (!exprNode_isError (elseclause))
6316 checkMacroParen (elseclause);
6318 if (!exprNode_matchTypes (ifclause, elseclause))
6321 (exprNode_getType (ifclause),
6323 exprNode_getType (elseclause),
6325 message ("Conditional clauses are not of same type: "
6327 exprNode_unparse (ifclause),
6328 exprNode_getType (ifclause),
6329 exprNode_unparse (elseclause),
6330 exprNode_getType (elseclause)),
6333 ret->sref = sRef_undefined;
6334 ret->typ = ctype_unknown;
6339 /* for now...should merge the states */
6340 ret->sref = ifclause->sref;
6341 ret->typ = ifclause->typ;
6343 if (exprNode_isNullValue (ifclause))
6345 ret->typ = elseclause->typ;
6349 exprNode_checkUse (ret, pred->sref, pred->loc);
6350 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6351 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6353 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6358 ret->typ = ifclause->typ;
6360 exprNode_checkUse (pred, pred->sref, pred->loc);
6361 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6363 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6368 if (!exprNode_isError (elseclause))
6370 ret->typ = elseclause->typ;
6372 exprNode_checkUse (pred, pred->sref, pred->loc);
6373 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6375 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6379 else /* pred is error */
6381 if (!exprNode_isError (ifclause))
6383 ret = exprNode_createSemiCopy (ifclause);
6385 checkMacroParen (ifclause); /* update macro counts! */
6387 if (!exprNode_isError (elseclause))
6389 checkMacroParen (elseclause);
6391 ret->typ = ifclause->typ;
6393 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6396 (exprNode_getType (ifclause),
6398 exprNode_getType (elseclause),
6400 message ("Conditional clauses are not of same type: "
6402 exprNode_unparse (ifclause),
6403 exprNode_getType (ifclause),
6404 exprNode_unparse (elseclause),
6405 exprNode_getType (elseclause)),
6408 ret->typ = ctype_unknown;
6412 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6413 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6415 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6418 else if (!exprNode_isError (elseclause)) /* pred, if errors */
6420 ret = exprNode_createSemiCopy (ifclause);
6422 ret->typ = elseclause->typ;
6423 checkMacroParen (elseclause);
6425 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6426 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6428 else /* all errors! */
6430 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6434 ret->kind = XPR_COND;
6435 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
6437 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6439 exprNode_combineControl (ret, ifclause, elseclause);
6446 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6448 ctype totype = qtype_getType (qt);
6450 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6454 ** check use of va_arg : <valist>, type -> type
6457 if (exprNode_isError (arg))
6462 targ = exprNode_getType (arg);
6465 ** arg should have be a pointer
6468 if (!ctype_isUA (targ) ||
6469 (!usymId_equal (ctype_typeId (targ),
6470 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6474 message ("First argument to va_arg is not a va_list (type %t): %s",
6475 targ, exprNode_unparse (arg)),
6479 exprNode_checkSet (ret, arg->sref);
6483 ** return type is totype
6487 ret->kind = XPR_VAARG;
6488 ret->edata = exprData_makeCast (tok, arg, qt);
6493 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6495 exprNode ret = exprNode_createPlain (ctype_undefined);
6496 ret->kind = XPR_LABEL;
6497 ret->edata = exprData_makeLiteral (label);
6498 ret->isJumpPoint = TRUE;
6500 return (ret); /* for now, ignore label */
6503 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6505 if (exprNode_isDefined (stmt))
6507 stmt->isJumpPoint = TRUE;
6509 /* This prevent stray no return path errors, etc. */
6510 stmt->exitCode = XK_MUSTEXIT;
6516 bool exprNode_isDefaultMarker (exprNode e)
6518 if (exprNode_isDefined (e))
6520 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6526 bool exprNode_isCaseMarker (exprNode e)
6528 if (exprNode_isDefined (e))
6530 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6536 bool exprNode_isLabelMarker (exprNode e)
6538 if (exprNode_isDefined (e))
6540 return (e->kind == XPR_LABEL);
6546 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6548 exprNode ret = exprNode_createPartialCopy (test);
6550 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6552 if (exprNode_isError (test)) {
6556 exprNode_checkUse (ret, test->sref, test->loc);
6558 usymtab_setExitCode (ret->exitCode);
6562 usymtab_setMustBreak ();
6565 ret->edata = exprData_makeSingle (test);
6566 ret->isJumpPoint = TRUE;
6572 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6574 exprNode ret = exprNode_createPartialCopy (test);
6576 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6577 ret->edata = exprData_makePair (test, stmt);
6578 ret->isJumpPoint = TRUE;
6580 if (exprNode_isError (test))
6585 exprNode_checkUse (ret, test->sref, test->loc);
6587 if (exprNode_isError (stmt))
6592 exprNode_mergeUSs (ret, stmt);
6594 ret->exitCode = stmt->exitCode;
6595 ret->mustBreak = stmt->mustBreak;
6596 ret->canBreak = stmt->canBreak;
6598 usymtab_setExitCode (ret->exitCode);
6602 usymtab_setMustBreak ();
6609 /*@notnull@*/ /*@only@*/ exprNode
6610 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6612 exprNode ret = exprNode_createTok (def);
6614 ret->isJumpPoint = TRUE;
6615 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6620 exprNode_mayEscape (exprNode e)
6622 if (exprNode_isDefined (e))
6624 return exitkind_couldEscape (e->exitCode);
6630 exprNode_mustBreak (exprNode e)
6632 if (exprNode_isDefined (e))
6634 return e->mustBreak;
6641 exprNode_mustEscape (exprNode e)
6643 if (exprNode_isDefined (e))
6645 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6652 exprNode_errorEscape (exprNode e)
6654 if (exprNode_isDefined (e))
6656 return exitkind_isError (e->exitCode);
6662 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6664 exprNode ret = exprNode_createPartialCopy (e1);
6666 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6668 ret->edata = exprData_makePair (e1, e2);
6669 ret->kind = XPR_STMTLIST;
6671 if (exprNode_isDefined (e1))
6673 ret->isJumpPoint = e1->isJumpPoint;
6674 ret->canBreak = e1->canBreak;
6678 if (exprNode_isDefined (e2))
6680 ret->loc = fileloc_update (ret->loc, e2->loc);
6684 if (exprNode_isDefined (e2))
6686 ret->exitCode = e2->exitCode;
6687 ret->mustBreak = e2->mustBreak;
6688 if (e2->canBreak) ret->canBreak = TRUE;
6692 ** if e1 must return, then e2 is unreachable!
6695 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6697 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6698 && !(e2->isJumpPoint))
6700 if (context_getFlag (FLG_UNREACHABLE))
6704 if (e2->kind == XPR_STMT)
6706 nr = exprData_getUopNode (e2->edata);
6709 if ((nr->kind == XPR_TOK
6710 && lltok_isSemi (exprData_getTok (nr->edata))))
6712 /* okay to have unreachable ";" */
6713 ret->exitCode = XK_MUSTEXIT;
6714 ret->canBreak = TRUE;
6718 if (optgenerror (FLG_UNREACHABLE,
6719 message ("Unreachable code: %s",
6720 exprNode_unparseFirst (nr)),
6723 ret->isJumpPoint = TRUE;
6724 ret->mustBreak = FALSE;
6725 ret->exitCode = XK_ERROR;
6726 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6730 ret->exitCode = XK_MUSTEXIT;
6731 ret->canBreak = TRUE;
6739 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6742 ** We want a warning anytime we have:
6744 ** yyy; <<<- no break or return
6748 exprNode lastStmt = exprNode_lastStatement (e1);
6750 if (exprNode_isDefined (lastStmt)
6751 && !exprNode_mustEscape (lastStmt)
6752 && !exprNode_mustBreak (lastStmt)
6753 && !exprNode_isCaseMarker (lastStmt)
6754 && !exprNode_isDefaultMarker (lastStmt)
6755 && !exprNode_isLabelMarker (lastStmt))
6757 voptgenerror (FLG_CASEBREAK,
6759 ("Fall through case (no preceding break)"),
6766 exprNode_mergeUSs (ret, e2);
6768 usymtab_setExitCode (ret->exitCode);
6772 usymtab_setMustBreak ();
6775 DPRINTF (("==> %s", exprNode_unparse (ret)));
6779 exprNode exprNode_createTok (/*@only@*/ lltok t)
6781 exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6782 ret = exprNode_create (ctype_unknown);
6783 ret->kind = XPR_TOK;
6784 ret->edata = exprData_makeTok (t);
6788 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6790 if (!exprNode_isError (e))
6792 exprChecks_checkStatementEffect(e);
6795 return (exprNode_statementError (e, t));
6798 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6800 exprNode ret = exprNode_createPartialCopy (e);
6802 if (!exprNode_isError (e))
6804 if (e->kind != XPR_ASSIGN)
6806 exprNode_checkUse (ret, e->sref, e->loc);
6809 ret->exitCode = e->exitCode;
6810 ret->canBreak = e->canBreak;
6811 ret->mustBreak = e->mustBreak;
6814 ret->edata = exprData_makeUop (e, t);
6815 ret->kind = XPR_STMT;
6820 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6822 if (!exprNode_isError (e))
6824 if (e->kind != XPR_ASSIGN)
6826 exprNode_checkUse (e, e->sref, e->loc);
6833 void exprNode_produceGuards (exprNode pred)
6835 if (!exprNode_isError (pred))
6837 if (ctype_isRealPointer (pred->typ))
6839 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6842 exprNode_checkUse (pred, pred->sref, pred->loc);
6843 exprNode_resetSref (pred);
6847 exprNode exprNode_compoundStatementExpression (/*@only@*/ lltok tlparen, /*@only@*/ exprNode e)
6851 DPRINTF (("Compound: %s", exprNode_unparse (e)));
6853 if (!context_flagOn (FLG_GNUEXTENSIONS, exprNode_loc (e)))
6855 (void) llgenhinterror
6857 message ("Compound statement expressions is not supported by ISO C99"),
6858 message ("Use +gnuextensions to allow compound statement expressions (and other GNU language extensions) "
6859 "without this warning"),
6864 ** The type of a compoundStatementExpression is the type of the last statement
6867 llassert (exprNode_isBlock (e));
6868 laststmt = exprNode_lastStatement (e);
6870 DPRINTF (("Last statement: %s / %s", exprNode_unparse (laststmt), ctype_unparse (exprNode_getType (laststmt))));
6871 DPRINTF (("e: %s", exprNode_unparse (e)));
6872 e->typ = exprNode_getType (laststmt);
6873 return exprNode_addParens (tlparen, e);
6877 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6879 exprNode ret = exprNode_createPartialCopy (e);
6881 if (!exprNode_isError (e))
6883 ret->exitCode = e->exitCode;
6884 ret->canBreak = e->canBreak;
6885 ret->mustBreak = e->mustBreak;
6888 DPRINTF (("Block e: %s", exprNode_unparse (e)));
6889 ret->edata = exprData_makeSingle (e);
6890 ret->kind = XPR_BLOCK;
6891 DPRINTF (("Block: %s", exprNode_unparse (ret)));
6895 bool exprNode_isBlock (exprNode e)
6897 return (exprNode_isDefined (e)
6898 && ((e)->kind == XPR_BLOCK));
6901 bool exprNode_isStatement (exprNode e)
6903 return (exprNode_isDefined (e)
6904 && ((e)->kind == XPR_STMT));
6907 bool exprNode_isAssign (exprNode e)
6909 if (exprNode_isDefined (e))
6911 return (e->kind == XPR_ASSIGN);
6917 bool exprNode_isEmptyStatement (exprNode e)
6919 return (exprNode_isDefined (e)
6920 && (e->kind == XPR_TOK)
6921 && (lltok_isSemi (exprData_getTok (e->edata))));
6924 bool exprNode_isMultiStatement (exprNode e)
6926 return (exprNode_isDefined (e)
6927 && ((e->kind == XPR_FOR)
6928 || (e->kind == XPR_FORPRED)
6929 || (e->kind == XPR_IF)
6930 || (e->kind == XPR_IFELSE)
6931 || (e->kind == XPR_WHILE)
6932 || (e->kind == XPR_WHILEPRED)
6933 || (e->kind == XPR_DOWHILE)
6934 || (e->kind == XPR_BLOCK)
6935 || (e->kind == XPR_STMT)
6936 || (e->kind == XPR_STMTLIST)
6937 || (e->kind == XPR_SWITCH)));
6940 void exprNode_checkIfPred (exprNode pred)
6942 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6945 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6948 bool emptyErr = FALSE;
6950 if (context_maybeSet (FLG_IFEMPTY))
6952 if (exprNode_isEmptyStatement (tclause))
6954 emptyErr = optgenerror (FLG_IFEMPTY,
6956 ("Body of if statement is empty"),
6957 exprNode_loc (tclause));
6961 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6963 if (exprNode_isDefined (tclause)
6964 && !exprNode_isBlock (tclause))
6966 voptgenerror (FLG_IFBLOCK,
6968 ("Body of if statement is not a block: %s",
6969 exprNode_unparse (tclause)),
6970 exprNode_loc (tclause));
6974 if (exprNode_isError (pred))
6976 if (exprNode_isError (tclause))
6978 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6982 ret = exprNode_createPartialCopy (tclause);
6987 if (exprNode_mustEscape (pred))
6991 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6992 exprNode_loc (pred));
6995 /*! exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred); */ /*@i523@*/
6996 exprNode_checkUse (pred, pred->sref, pred->loc);
6998 if (!exprNode_isError (tclause))
7000 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
7003 ret = exprNode_createPartialCopy (pred);
7007 ret->edata = exprData_makePair (pred, tclause);
7009 ret->exitCode = XK_UNKNOWN;
7011 if (exprNode_isDefined (tclause))
7013 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
7014 ret->canBreak = tclause->canBreak;
7015 ret->sets = sRefSet_union (ret->sets, tclause->sets);
7016 ret->msets = sRefSet_union (ret->msets, tclause->msets);
7017 ret->uses = sRefSet_union (ret->uses, tclause->uses);
7020 ret->mustBreak = FALSE;
7025 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
7026 /*@only@*/ exprNode tclause,
7027 /*@only@*/ exprNode eclause)
7030 bool tEmptyErr = FALSE;
7031 bool eEmptyErr = FALSE;
7033 if (context_maybeSet (FLG_IFEMPTY))
7035 if (exprNode_isEmptyStatement (tclause))
7037 tEmptyErr = optgenerror
7040 ("Body of if clause of if statement is empty"),
7041 exprNode_loc (tclause));
7044 if (exprNode_isEmptyStatement (eclause))
7046 eEmptyErr = optgenerror
7049 ("Body of else clause of if statement is empty"),
7050 exprNode_loc (eclause));
7054 if (context_maybeSet (FLG_IFBLOCK))
7057 && exprNode_isDefined (tclause)
7058 && !exprNode_isBlock (tclause))
7060 voptgenerror (FLG_IFBLOCK,
7062 ("Body of if clause of if statement is not a block: %s",
7063 exprNode_unparse (tclause)),
7064 exprNode_loc (tclause));
7068 && exprNode_isDefined (eclause)
7069 && !exprNode_isBlock (eclause)
7070 && !(eclause->kind == XPR_IF)
7071 && !(eclause->kind == XPR_IFELSE))
7076 ("Body of else clause of if statement is not a block: %s",
7077 exprNode_unparse (eclause)),
7078 exprNode_loc (eclause));
7082 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
7084 if (exprNode_isDefined (eclause)
7085 && (eclause->kind == XPR_IF))
7087 voptgenerror (FLG_ELSEIFCOMPLETE,
7088 message ("Incomplete else if logic (no final else): %s",
7089 exprNode_unparse (eclause)),
7090 exprNode_loc (eclause));
7094 if (exprNode_isError (pred))
7096 if (exprNode_isError (tclause))
7098 if (exprNode_isError (eclause))
7100 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7104 ret = exprNode_createPartialCopy (eclause);
7109 ret = exprNode_createPartialCopy (tclause);
7112 else /* pred is okay */
7114 ret = exprNode_createPartialCopy (pred);
7116 if (exprNode_mustEscape (pred))
7120 message ("Predicate always exits: %s", exprNode_unparse (pred)),
7121 exprNode_loc (pred));
7124 /*@i3423 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);*/
7125 exprNode_checkUse (ret, pred->sref, pred->loc);
7127 exprNode_mergeCondUSs (ret, tclause, eclause);
7130 ret->kind = XPR_IFELSE;
7131 ret->edata = exprData_makeCond (pred, tclause, eclause);
7133 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
7135 exprNode_combineControl (ret, tclause, eclause);
7136 ret->loc = fileloc_update (ret->loc, eclause->loc);
7143 ** *allpaths <- TRUE iff all executions paths must go through the switch
7147 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
7149 exprNodeSList el = exprNode_flatten (e);
7150 bool mustReturn = TRUE; /* find a branch that doesn't */
7151 bool thisReturn = FALSE;
7152 bool hasDefault = FALSE;
7153 bool hasAllMembers = FALSE;
7154 bool inSwitch = FALSE;
7155 bool isEnumSwitch = FALSE;
7156 bool canBreak = FALSE;
7157 bool fallThrough = FALSE;
7158 ctype ct = ctype_unknown;
7159 enumNameSList usedEnums;
7162 if (exprNode_isDefined (test))
7167 ttype = ctype_realType (ct);
7169 if (ctype_isEnum (ttype))
7171 isEnumSwitch = TRUE;
7172 enums = ctype_elist (ttype);
7173 usedEnums = enumNameSList_new ();
7177 exprNodeSList_elements (el, current)
7180 DPRINTF ((message("checkSwitchExpr current = %s ", exprNode_unparse(current) ) ));
7182 if (exprNode_isDefined (current))
7184 switch (current->kind)
7191 (FLG_DUPLICATECASES,
7192 message ("Duplicate default cases in switch"),
7193 exprNode_loc (current));
7198 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
7206 exprNode st = exprData_getSingle (current->edata);
7207 uentry ue = exprNode_getUentry (st);
7209 if (uentry_isValid (ue))
7211 cstring cname = uentry_rawName (ue);
7213 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
7215 if (enumNameSList_member
7216 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
7219 (FLG_DUPLICATECASES,
7220 message ("Duplicate case in switch: %s",
7226 enumNameSList_addh (usedEnums, cname);
7233 message ("Case in switch not %s member: %s",
7234 ctype_unparse (ct), cname),
7241 if (inSwitch && !fallThrough)
7243 if (!thisReturn || canBreak)
7253 /*@switchbreak@*/ break;
7255 thisReturn = thisReturn || exprNode_mustEscape (current);
7256 canBreak = canBreak || current->canBreak;
7257 if (canBreak) fallThrough = FALSE;
7260 } end_exprNodeSList_elements;
7262 if (inSwitch) /* check the last one! */
7264 if (!thisReturn || canBreak)
7273 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
7274 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
7276 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
7278 voptgenerror (FLG_MISSCASE,
7279 message ("Missing case%s in switch: %q",
7280 cstring_makeLiteralTemp
7281 ((enumNameSList_size (unused) > 1) ? "s" : ""),
7282 enumNameSList_unparse (unused)),
7285 enumNameSList_free (unused);
7286 *allpaths = FALSE; /* evans 2002-01-01 */
7290 hasAllMembers = TRUE;
7294 enumNameSList_free (usedEnums);
7298 *allpaths = hasDefault;
7301 exprNodeSList_free (el);
7302 return ((hasDefault || hasAllMembers) && mustReturn);
7305 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
7307 exprNode ret = exprNode_createPartialCopy (e);
7310 DPRINTF (("Switch: %s", exprNode_unparse (s)));
7312 ret->kind = XPR_SWITCH;
7313 ret->edata = exprData_makePair (e, s);
7315 if (!exprNode_isError (s))
7317 exprNode fs = exprNode_firstStatement (s);
7318 ret->loc = fileloc_update (ret->loc, s->loc);
7320 if (exprNode_isUndefined (fs)
7321 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
7322 || exprNode_isDefaultMarker (fs)) {
7325 voptgenerror (FLG_FIRSTCASE,
7327 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
7332 if (!exprNode_isError (e))
7334 if (checkSwitchExpr (e, s, &allpaths))
7336 ret->exitCode = XK_MUSTRETURN;
7340 ret->exitCode = e->exitCode;
7343 ret->canBreak = e->canBreak;
7344 ret->mustBreak = e->mustBreak;
7348 ** exprNode.c:3883,32: Variable allpaths used before definition
7355 DPRINTF (("Context exit switch!"));
7356 context_exitSwitch (ret, allpaths);
7357 DPRINTF (("Context exit switch done!"));
7362 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
7363 /*@notnull@*/ exprNode body)
7365 sRefSet tuses = test->uses;
7367 if (!sRefSet_isEmpty (test->uses))
7369 sRefSet sets = sRefSet_newCopy (body->sets);
7370 bool hasError = TRUE;
7371 bool innerState = FALSE;
7372 sRefSet tuncon = sRefSet_undefined;
7374 sets = sRefSet_union (sets, test->sets);
7375 sets = sRefSet_union (sets, body->msets);
7376 sets = sRefSet_union (sets, test->msets);
7378 sRefSet_allElements (tuses, el)
7380 if (sRef_isUnconstrained (el))
7382 tuncon = sRefSet_insert (tuncon, el);
7386 if (sRefSet_member (sets, el))
7393 if (sRef_isInternalState (el)
7394 || sRef_isFileStatic (sRef_getRootBase (el)))
7398 } end_sRefSet_allElements ;
7402 sRefSet suncon = sRefSet_undefined;
7403 bool sinner = FALSE;
7405 sRefSet_allElements (sets, el)
7407 if (sRef_isUnconstrained (el))
7409 suncon = sRefSet_insert (suncon, el);
7411 else if (sRef_isInternalState (el))
7419 } end_sRefSet_allElements ;
7421 if (sinner && innerState)
7425 else if (sRefSet_isEmpty (tuncon)
7426 && sRefSet_isEmpty (suncon))
7431 ("Suspected infinite loop. No value used in loop test (%q) "
7432 "is modified by test or loop body.",
7433 sRefSet_unparsePlain (tuses)),
7438 if (sRefSet_isEmpty (tuncon))
7442 message ("Suspected infinite loop. No condition values "
7443 "modified. Modification possible through "
7444 "unconstrained calls: %q",
7445 sRefSet_unparsePlain (suncon)),
7452 message ("Suspected infinite loop. No condition values "
7453 "modified. Possible undetected dependency through "
7454 "unconstrained calls in loop test: %q",
7455 sRefSet_unparsePlain (tuncon)),
7461 sRefSet_free (sets);
7465 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7468 bool emptyErr = FALSE;
7470 if (context_maybeSet (FLG_WHILEEMPTY))
7472 if (exprNode_isEmptyStatement (b))
7474 emptyErr = optgenerror
7477 ("Body of while statement is empty"),
7482 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7484 if (exprNode_isDefined (b)
7485 && !exprNode_isBlock (b))
7487 if (context_inIterDef ()
7488 && (b->kind == XPR_STMTLIST
7489 || b->kind == XPR_TOK))
7495 voptgenerror (FLG_WHILEBLOCK,
7497 ("Body of while statement is not a block: %s",
7498 exprNode_unparse (b)),
7504 if (exprNode_isError (t))
7506 if (exprNode_isError (b))
7508 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7512 ret = exprNode_createPartialCopy (b);
7519 ret = exprNode_createPartialCopy (t);
7521 llassert (t->kind == XPR_WHILEPRED);
7523 test = exprData_getSingle (t->edata);
7525 if (!exprNode_isError (b) && exprNode_isDefined (test))
7527 if (context_maybeSet (FLG_INFLOOPS)
7528 || context_maybeSet (FLG_INFLOOPSUNCON))
7531 ** check that some variable in the predicate is set by the body
7532 ** if the predicate uses any variables
7535 checkInfiniteLoop (test, b);
7538 exprNode_mergeUSs (ret, b);
7540 if (exprNode_isDefined (b))
7542 ret->exitCode = exitkind_makeConditional (b->exitCode);
7547 ret->edata = exprData_makePair (t, b);
7548 ret->kind = XPR_WHILE;
7550 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7554 message ("Predicate always exits: %s", exprNode_unparse (t)),
7558 ret->exitCode = XK_NEVERESCAPE;
7561 ** If loop is infinite, and there is no break inside,
7562 ** exit code is never reach.
7565 if (exprNode_knownIntValue (t))
7567 if (!exprNode_isZero (t))
7569 if (exprNode_isDefined (b))
7573 /* Really, it means never reached. */
7574 ret->exitCode = XK_MUSTEXIT;
7584 ret->canBreak = FALSE;
7585 ret->mustBreak = FALSE;
7591 ** do { b } while (t);
7593 ** note: body passed as first argument
7596 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7600 DPRINTF (("Do while: %s / %s",
7601 exprNode_unparse (b), exprNode_unparse (t)));
7603 if (exprNode_isError (t))
7605 if (exprNode_isError (b))
7607 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7611 ret = exprNode_createPartialCopy (b);
7613 ret->exitCode = exitkind_makeConditional (b->exitCode);
7614 exprNode_checkUse (ret, b->sref, b->loc);
7615 ret->exitCode = b->exitCode;
7616 ret->canBreak = b->canBreak;
7617 ret->mustBreak = FALSE;
7622 DPRINTF (("Do while: %s / %s",
7623 exitkind_unparse (t->exitCode),
7624 exitkind_unparse (b->exitCode)));
7626 ret = exprNode_createPartialCopy (t);
7627 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7629 if (!exprNode_isError (b))
7632 ** forgot the copy's --- why wasn't this detected??
7635 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7636 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7637 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
7639 /* left this out --- causes and aliasing bug (infinite loop)
7640 should be detected?? */
7642 exprNode_checkUse (ret, b->sref, b->loc);
7643 exprNode_mergeUSs (ret, t);
7644 exprNode_checkUse (ret, t->sref, t->loc);
7646 /* evans 2001-10-05: while loop can break */
7647 ret->exitCode = exitkind_makeConditional (b->exitCode);
7649 DPRINTF (("Do while: %s",
7650 exitkind_unparse (ret->exitCode)));
7652 ret->canBreak = b->canBreak;
7654 /* Always FALSE for doWhile loops - break's when test is false */
7655 ret->mustBreak = FALSE; /* b->mustBreak; */
7659 context_exitDoWhileClause (t);
7661 ret->kind = XPR_DOWHILE;
7662 ret->edata = exprData_makePair (t, b);
7666 bool exprNode_loopMustExec (exprNode forPred)
7669 ** Returns true if it is obvious that the loop always executes at least once
7671 ** For now, we only identify the most obvious cases. Should be true anytime
7672 ** we can prove init => !test.
7675 if (exprNode_isDefined (forPred))
7677 exprNode init, test, inc;
7680 llassert (forPred->kind == XPR_FORPRED);
7682 edata = forPred->edata;
7683 init = exprData_getTripleInit (edata);
7684 test = exprData_getTripleTest (edata);
7685 inc = exprData_getTripleInc (edata);
7687 if (exprNode_isAssign (init))
7689 exprNode loopVar = exprData_getOpA (init->edata);
7690 exprNode loopInit = exprData_getOpB (init->edata);
7692 if (exprNode_isDefined (test) && test->kind == XPR_OP)
7694 exprNode testVar = exprData_getOpA (test->edata);
7695 exprNode testVal = exprData_getOpB (test->edata);
7696 lltok comp = exprData_getOpTok (test->edata);
7697 int opid = lltok_getTok (comp);
7699 DPRINTF (("Same storage: %s / %s", exprNode_unparse (loopVar),
7700 exprNode_unparse (testVar)));
7702 if (exprNode_sameStorage (loopVar, testVar))
7704 multiVal valinit = exprNode_getValue (loopInit);
7705 multiVal valtest = exprNode_getValue (testVal);
7707 DPRINTF (("Values: %s / %s", multiVal_unparse (valinit),
7708 multiVal_unparse (valtest)));
7710 if (multiVal_isInt (valinit) && multiVal_isInt (valtest))
7712 long v1 = multiVal_forceInt (valinit);
7713 long v2 = multiVal_forceInt (valtest);
7715 DPRINTF (("Here: %ld %ld", v1, v2));
7717 if ((opid == EQ_OP && v1 < v2)
7718 || (opid == NE_OP && v1 != v2)
7719 || (opid == TLT && v1 <= v2)
7720 || (opid == TGT && v1 >= v2)
7721 || (opid == LE_OP && v1 < v2)
7722 || (opid == GE_OP && v1 > v2))
7724 DPRINTF (("mustexec if inc"));
7733 DPRINTF (("loop must exec: FALSE"));
7737 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7740 bool emptyErr = FALSE;
7742 if (context_maybeSet (FLG_FOREMPTY))
7744 if (exprNode_isEmptyStatement (body))
7746 emptyErr = optgenerror
7749 ("Body of for statement is empty"),
7750 exprNode_loc (body));
7754 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7756 if (exprNode_isDefined (body)
7757 && !exprNode_isBlock (body))
7759 if (context_inIterDef ()
7760 && (body->kind == XPR_STMTLIST
7761 || body->kind == XPR_TOK))
7767 voptgenerror (FLG_FORBLOCK,
7769 ("Body of for statement is not a block: %s",
7770 exprNode_unparse (body)),
7771 exprNode_loc (body));
7777 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7780 if (exprNode_isError (body))
7782 ret = exprNode_createPartialCopy (inc);
7786 ret = exprNode_createPartialCopy (body);
7788 ret->exitCode = exitkind_makeConditional (body->exitCode);
7790 exprNode_mergeUSs (inc, body);
7792 if (exprNode_isDefined (inc))
7796 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7798 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7799 exprNode_freeShallow (tmp);
7801 context_clearMessageAnnote ();
7802 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7804 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7805 exprNode_freeShallow (tmp);
7807 context_clearMessageAnnote ();
7809 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7810 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7811 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7815 ret->kind = XPR_FOR;
7816 ret->edata = exprData_makePair (inc, body);
7818 if (exprNode_isDefined (inc)) {
7819 exprNode test = exprData_getTripleTest (inc->edata);
7821 if (exprNode_isUndefined (test)) {
7822 if (exprNode_isDefined (body)) {
7823 if (!body->canBreak) {
7824 /* Really, it means never reached. */
7825 ret->exitCode = XK_MUSTEXIT;
7835 ** for (init; test; inc)
7838 ** while (test) { body; inc; }
7840 ** Now: check use of init (may set vars for test)
7841 ** check use of test
7845 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7849 if (exprNode_isError (pred)) return guardSet_undefined;
7851 llassert (pred->kind == XPR_FORPRED);
7853 test = exprData_getTripleTest (pred->edata);
7855 if (!exprNode_isError (test))
7857 return (test->guards);
7860 return guardSet_undefined;
7863 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7865 exprNode ret = exprNode_createSemiCopy (test);
7867 if (exprNode_isDefined (test))
7869 exprNode_copySets (ret, test);
7870 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7871 exprNode_checkUse (ret, test->sref, test->loc);
7873 exprNode_produceGuards (test);
7875 ret->guards = guardSet_copy (test->guards);
7878 ret->edata = exprData_makeSingle (test);
7879 ret->kind = XPR_WHILEPRED;
7883 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7884 /*@only@*/ exprNode inc)
7889 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7892 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7894 if (!exprNode_isError (inc))
7896 ret = exprNode_createPartialCopy (inc);
7900 if (!exprNode_isError (init))
7902 ret = exprNode_createPartialCopy (init);
7904 else if (!exprNode_isError (test))
7906 ret = exprNode_createPartialCopy (test);
7910 ret = exprNode_createUnknown ();
7914 exprNode_mergeUSs (ret, init);
7916 if (exprNode_isDefined (init))
7918 exprNode_checkUse (ret, init->sref, init->loc);
7921 exprNode_mergeUSs (ret, test);
7923 if (exprNode_isDefined (test))
7925 exprNode_checkUse (ret, test->sref, test->loc);
7928 ret->kind = XPR_FORPRED;
7929 ret->edata = exprData_makeFor (init, test, inc);
7933 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7935 exprNode ret = exprNode_createUnknown ();
7937 if (context_inMacro ())
7939 voptgenerror (FLG_MACROSTMT,
7940 message ("Macro %s uses goto (not functional)",
7941 context_inFunctionName ()),
7945 ret->kind = XPR_GOTO;
7946 ret->edata = exprData_makeLiteral (label);
7947 ret->mustBreak = TRUE;
7948 ret->exitCode = XK_GOTO;
7949 ret->canBreak = TRUE;
7953 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7955 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7957 ret->kind = XPR_CONTINUE;
7958 ret->edata = exprData_makeTok (l);
7959 ret->canBreak = TRUE;
7960 ret->mustBreak = TRUE;
7962 if (qcontinue == QSAFEBREAK)
7966 else if (qcontinue == QINNERCONTINUE)
7968 if (!context_inDeepLoop ())
7971 (FLG_LOOPLOOPCONTINUE,
7972 cstring_makeLiteral ("Continue statement marked with innercontinue "
7973 "is not inside a nested loop"),
7974 exprNode_loc (ret));
7977 else if (qcontinue == BADTOK)
7979 if (context_inDeepLoop ())
7982 (FLG_LOOPLOOPCONTINUE,
7983 cstring_makeLiteral ("Continue statement in nested loop"),
7984 exprNode_loc (ret));
7989 llbuglit ("exprNode_continue: bad qcontinue");
7995 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
7997 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7998 clause breakClause = context_breakClause ();
8000 ret->kind = XPR_BREAK;
8001 ret->edata = exprData_makeTok (l);
8002 ret->canBreak = TRUE;
8003 ret->mustBreak = TRUE;
8005 if (breakClause == NOCLAUSE)
8009 cstring_makeLiteral ("Break not inside while, for or switch statement"),
8010 exprNode_loc (ret));
8014 if (bqual != BADTOK)
8021 if (breakClause == SWITCHCLAUSE)
8023 if (!context_inDeepSwitch ())
8025 voptgenerror (FLG_SYNTAX,
8027 ("Break preceded by innerbreak is not in a deep switch"),
8028 exprNode_loc (ret));
8033 if (!context_inDeepLoop ())
8035 voptgenerror (FLG_SYNTAX,
8037 ("Break preceded by innerbreak is not in a deep loop"),
8038 exprNode_loc (ret));
8043 if (breakClause == SWITCHCLAUSE)
8045 voptgenerror (FLG_SYNTAX,
8047 ("Break preceded by loopbreak is breaking a switch"),
8048 exprNode_loc (ret));
8052 if (breakClause != SWITCHCLAUSE)
8056 message ("Break preceded by switchbreak is breaking %s",
8057 cstring_makeLiteralTemp
8058 ((breakClause == WHILECLAUSE
8059 || breakClause == DOWHILECLAUSE) ? "a while loop"
8060 : (breakClause == FORCLAUSE) ? "a for loop"
8061 : (breakClause == ITERCLAUSE) ? "an iterator"
8063 exprNode_loc (ret));
8071 if (breakClause == SWITCHCLAUSE)
8073 clause nextBreakClause = context_nextBreakClause ();
8075 switch (nextBreakClause)
8077 case NOCLAUSE: break;
8083 (FLG_LOOPSWITCHBREAK,
8084 cstring_makeLiteral ("Break statement in switch inside loop"),
8085 exprNode_loc (ret));
8089 (FLG_SWITCHSWITCHBREAK,
8090 cstring_makeLiteral ("Break statement in switch inside switch"),
8091 exprNode_loc (ret));
8098 if (context_inDeepLoop ())
8102 cstring_makeLiteral ("Break statement in nested loop"),
8103 exprNode_loc (ret));
8107 if (context_inDeepLoopSwitch ())
8110 (FLG_SWITCHLOOPBREAK,
8111 cstring_makeLiteral ("Break statement in loop inside switch"),
8112 exprNode_loc (ret));
8122 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
8124 fileloc loc = lltok_getLoc (t);
8125 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
8127 context_returnFunction ();
8128 exprChecks_checkNullReturn (loc);
8130 ret->kind = XPR_NULLRETURN;
8131 ret->edata = exprData_makeTok (t);
8132 ret->exitCode = XK_MUSTRETURN;
8136 exprNode exprNode_return (/*@only@*/ exprNode e)
8140 if (exprNode_isError (e))
8142 ret = exprNode_createUnknown ();
8146 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
8148 exprNode_checkUse (ret, e->sref, e->loc);
8149 exprNode_checkReturn (e);
8152 context_returnFunction ();
8153 ret->kind = XPR_RETURN;
8154 ret->edata = exprData_makeSingle (e);
8155 ret->exitCode = XK_MUSTRETURN;
8160 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
8164 if (exprNode_isError (e1))
8166 if (exprNode_isError (e2))
8168 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
8172 ret = exprNode_createPartialCopy (e2);
8173 exprNode_checkUse (ret, e2->sref, e2->loc);
8174 ret->sref = e2->sref;
8179 ret = exprNode_createPartialCopy (e1);
8181 exprNode_checkUse (ret, e1->sref, e1->loc);
8183 if (!exprNode_isError (e2))
8185 exprNode_mergeUSs (ret, e2);
8186 exprNode_checkUse (ret, e2->sref, e2->loc);
8187 ret->sref = e2->sref;
8191 ret->kind = XPR_COMMA;
8192 ret->edata = exprData_makePair (e1, e2);
8194 if (exprNode_isDefined (e1))
8196 if (exprNode_isDefined (e2))
8200 if (exprNode_mustEscape (e1) || e1->mustBreak)
8204 message ("Second clause of comma expression is unreachable: %s",
8205 exprNode_unparse (e2)),
8209 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
8210 ret->mustBreak = e1->mustBreak || e2->mustBreak;
8211 ret->canBreak = e1->canBreak || e2->canBreak;
8215 if (exprNode_mustEscape (e1) || e1->mustBreak)
8219 message ("Second clause of comma expression is unreachable: %s",
8220 exprNode_unparse (e2)),
8224 ret->exitCode = e1->exitCode;
8225 ret->canBreak = e1->canBreak;
8230 if (exprNode_isDefined (e2))
8232 ret->exitCode = e2->exitCode;
8233 ret->mustBreak = e2->mustBreak;
8234 ret->canBreak = e2->canBreak;
8241 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
8243 ctype t1 = exprNode_getType (el);
8244 ctype t2 = exprNode_getType (val);
8245 bool hasError = FALSE;
8247 DPRINTF (("Check one init: %s / %s",
8248 exprNode_unparse (el),
8249 exprNode_unparse (val)));
8251 if (ctype_isUnknown (t1))
8253 voptgenerror (FLG_IMPTYPE,
8254 message ("Variable has unknown (implicitly int) type: %s",
8255 exprNode_unparse (el)),
8259 el->typ = ctype_int;
8262 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
8264 exprNodeList vals = exprData_getArgs (val->edata);
8266 DPRINTF (("Check one init: %s", exprNodeList_unparse (vals)));
8267 DPRINTF (("Type: %s", ctype_unparse (t1)));
8269 if (ctype_isRealAP (t1))
8274 if (ctype_isFixedArray (t1))
8276 size_t nelements = ctype_getArraySize (t1);
8278 DPRINTF (("Checked array: %s / %d",
8279 ctype_unparse (t1), nelements));
8281 if (exprNode_isStringLiteral (val))
8283 exprNode_checkStringLiteralLength (t1, val);
8287 if (exprNodeList_size (vals) != size_toInt (nelements))
8289 hasError = optgenerror
8290 (exprNodeList_size (vals) > size_toInt (nelements)
8291 ? FLG_INITSIZE : FLG_INITALLELEMENTS,
8292 message ("Initializer block for "
8293 "%s has %d element%&, but declared as %s: %q",
8294 exprNode_unparse (el),
8295 exprNodeList_size (vals),
8297 exprNodeList_unparse (vals)),
8303 exprNodeList_elements (vals, oneval)
8305 cstring istring = message ("%d", i);
8308 (exprNode_fakeCopy (el),
8309 exprNode_numLiteral (ctype_int, istring,
8310 fileloc_copy (el->loc), i));
8312 if (exprNode_isDefined (newel))
8314 if (exprNodeList_size (vals) == 1
8315 && ctype_isString (exprNode_getType (oneval))
8316 && ctype_isChar (exprNode_getType (newel)))
8318 exprNode_freeIniter (newel);
8322 if (exprNode_checkOneInit (newel, oneval))
8327 if (nerrors > 3 && exprNodeList_size (vals) > 6)
8330 (message ("Additional initialization errors "
8331 "for %s not reported",
8332 exprNode_unparse (el)),
8334 exprNode_freeIniter (newel);
8339 exprNode_freeIniter (newel);
8344 exprNode_freeIniter (newel);
8349 cstring_free (istring);
8352 } end_exprNodeList_elements;
8355 else if (ctype_isStruct (ctype_realType (t1)))
8357 uentryList fields = ctype_getFields (t1);
8360 if (uentryList_size (fields) != exprNodeList_size (vals))
8362 if (uentryList_size (fields) > exprNodeList_size (vals))
8364 hasError = optgenerror
8366 message ("Initializer block for "
8367 "%s has %d field%&, but %s has %d field%&: %q",
8368 exprNode_unparse (el),
8369 exprNodeList_size (vals),
8371 uentryList_size (fields),
8372 exprNodeList_unparse (vals)),
8377 hasError = optgenerror
8379 message ("Initializer block for "
8380 "%s has %d field%&, but %s has %d field%&: %q",
8381 exprNode_unparse (el),
8382 exprNodeList_size (vals),
8384 uentryList_size (fields),
8385 exprNodeList_unparse (vals)),
8391 exprNodeList_elements (vals, oneval)
8393 uentry thisfield = uentryList_getN (fields, i);
8395 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8397 uentry_getName (thisfield));
8399 if (exprNode_isDefined (newel))
8401 if (exprNode_checkOneInit (newel, oneval))
8406 exprNode_freeIniter (newel);
8410 } end_exprNodeList_elements;
8413 /* evans 2001-12-30: added to fix bug reported by Jim Zelenka */
8414 else if (ctype_isUnion (ctype_realType (t1)))
8416 uentryList fields = ctype_getFields (t1);
8420 ** Union initializers set the first member always.
8423 DPRINTF (("Union initializer: %s / %s",
8424 exprNode_unparse (el), ctype_unparse (ctype_realType (t1))));
8426 if (exprNodeList_size (vals) != 1)
8428 hasError = optgenerror
8430 message ("Initializer block for union "
8431 "%s has %d elements, union initializers should have one element: %q",
8432 exprNode_unparse (el),
8433 exprNodeList_size (vals),
8434 exprNodeList_unparse (vals)),
8439 exprNode oneval = exprNodeList_head (vals);
8440 uentry thisfield = uentryList_getN (fields, i);
8442 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8444 uentry_getName (thisfield));
8446 if (exprNode_isDefined (newel))
8448 if (exprNode_checkOneInit (newel, oneval))
8453 exprNode_freeIniter (newel);
8459 hasError = optgenerror
8461 message ("Initializer block used for "
8462 "%s where %t is expected: %s",
8463 exprNode_unparse (el), t1, exprNode_unparse (val)),
8469 if (exprNode_isDefined (val))
8471 doAssign (el, val, TRUE);
8473 if (!exprNode_matchType (t1, val))
8475 hasError = gentypeerror
8477 message ("Initial value of %s is type %t, "
8479 exprNode_unparse (el),
8480 t2, t1, exprNode_unparse (val)),
8489 static /*@notnull@*/ exprNode
8490 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
8494 DPRINTF (("Initialization: %s", idDecl_unparse (t)));
8496 if (usymtab_exists (idDecl_observeId (t)))
8498 uentry ue = usymtab_lookup (idDecl_observeId (t));
8499 ret = exprNode_createId (ue);
8501 /*@i723 don't do this...but why? */
8503 ct = ctype_realishType (ret->typ);
8505 DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
8507 if (ctype_isUnknown (ct))
8509 if (uentry_isAnyTag (ue))
8513 message ("%s used but not previously declared: %s",
8514 uentry_ekindName (ue),
8515 idDecl_getName (t)),
8523 message ("Variable has unknown (implicitly int) type: %s",
8524 idDecl_getName (t)),
8536 DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
8538 ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
8539 /*!! fileloc_copy (g_currentloc)); */
8540 /*@i32!!! should get error without this */
8542 ret = exprNode_fromIdentifierAux (ue);
8545 ** No error - this happens in old style declarations:
8549 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8556 exprData_free (ret->edata, ret->kind);
8557 ret->edata = exprData_undefined;
8558 ret->exitCode = XK_NEVERESCAPE;
8559 ret->mustBreak = FALSE;
8560 ret->kind = XPR_INIT;
8564 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8566 exprNode ret = exprNode_makeInitializationAux (t);
8567 llassert (ret->edata == exprData_undefined);
8568 ret->edata = exprData_makeInit (t, exprNode_undefined);
8572 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8573 /*@only@*/ exprNode e)
8575 uentry ue = usymtab_lookup (idDecl_observeId (t));
8576 exprNode ret = exprNode_makeInitializationAux (t);
8577 fileloc loc = exprNode_loc (e);
8579 DPRINTF (("initialization: %s = %s", idDecl_unparse (t), exprNode_unparse (e)));
8581 if (exprNode_isError (e))
8583 e = exprNode_createUnknown ();
8584 /* error: assume initializer is defined */
8585 sRef_setDefined (ret->sref, g_currentloc);
8586 ret->edata = exprData_makeInit (t, e);
8590 ctype ct = ctype_realishType (ret->typ);
8595 ** was addSafeUse --- what's the problem?
8597 ** int x = 3, y = x ?
8600 exprData_free (ret->edata, ret->kind);
8601 ret->edata = exprData_makeInit (t, e);
8602 DPRINTF (("ret: %s", exprNode_unparse (ret)));
8604 exprNode_checkUse (ret, e->sref, e->loc);
8606 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8608 exprNode lhs = exprNode_createId (ue);
8611 ** static storage should be undefined before initializing
8614 if (uentry_isStatic (ue))
8616 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8619 (void) exprNode_checkOneInit (lhs, e);
8621 if (uentry_isStatic (ue))
8623 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8626 exprNode_free (lhs);
8630 if (!exprNode_matchType (ct, e))
8632 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
8639 (exprNode_getType (e), e, exprNode_getType (ret), ret,
8641 ("Variable %q initialized to type %t, expects %t: %s",
8642 uentry_getName (ue), exprNode_getType (e),
8643 exprNode_getType (ret),
8644 exprNode_unparse (e)),
8650 if (uentry_isStatic (ue))
8652 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8655 if (exprNode_isStringLiteral (e)
8656 && (ctype_isArray (ct))
8657 && (ctype_isChar (ctype_realType (ctype_baseArrayPtr (ct)))))
8660 ** If t is a char [], the literal is copied.
8663 exprNode_checkStringLiteralLength (ct, e);
8664 sRef_setDefState (ret->sref, SS_DEFINED, e->loc);
8665 ret->val = multiVal_copy (e->val);
8667 sRef_setNullTerminatedState (ret->sref);
8669 if (multiVal_isDefined (e->val))
8671 cstring slit = multiVal_forceString (e->val);
8672 sRef_setLen (ret->sref, size_toInt (cstring_length (slit) + 1));
8675 if (ctype_isFixedArray (ct))
8677 sRef_setSize (ret->sref, size_toInt (ctype_getArraySize (ct)));
8682 doAssign (ret, e, TRUE);
8685 if (uentry_isStatic (ue))
8687 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8691 if (context_inIterDef ())
8693 /* should check if it is yield */
8694 uentry_setUsed (ue, loc);
8701 exprNode_mergeUSs (ret, e);
8702 DPRINTF (("Ret: %s %p %p",
8703 exprNode_unparse (ret),
8704 ret->requiresConstraints,
8705 ret->ensuresConstraints));
8707 DPRINTF (("Ret: %s %s %s",
8708 exprNode_unparse (ret),
8709 constraintList_unparse (ret->requiresConstraints),
8710 constraintList_unparse (ret->ensuresConstraints)));
8714 exprNode exprNode_iter (/*@observer@*/ uentry name,
8715 /*@only@*/ exprNodeList alist,
8716 /*@only@*/ exprNode body,
8717 /*@observer@*/ uentry end)
8722 llassert (uentry_isValid (name));
8724 uentry_setUsed (name, exprNode_loc (body));
8726 ret = exprNode_createPartialCopy (body);
8727 iname = uentry_getName (name);
8729 if (uentry_isInvalid (end))
8731 llerror (FLG_ITERBALANCE,
8732 message ("Iter %s not balanced with end_%s", iname, iname));
8736 cstring ename = uentry_getName (end);
8738 if (!cstring_equalPrefixLit (ename, "end_"))
8740 llerror (FLG_ITERBALANCE, message ("Iter %s not balanced with end_%s: %s",
8741 iname, iname, ename));
8745 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8747 llerror (FLG_ITERBALANCE,
8748 message ("Iter %s not balanced with end_%s: %s",
8749 iname, iname, ename));
8753 cstring_free (ename);
8756 context_exitIterClause (body);
8758 ret->kind = XPR_ITER;
8759 ret->edata = exprData_makeIter (name, alist, body, end);
8761 if (uentry_isIter (name))
8763 (void) checkArgsReal (name, body,
8764 uentry_getParams (name), alist, TRUE, ret);
8767 cstring_free (iname);
8773 exprNode_iterNewId (/*@only@*/ cstring s)
8775 exprNode e = exprNode_new ();
8776 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8778 llassert (processingIterVars ());
8780 e->loc = context_getSaveLocation ();
8782 if (fileloc_isUndefined (e->loc))
8784 fileloc_free (e->loc);
8785 e->loc = fileloc_copy (g_currentloc);
8788 e->uses = sRefSet_new ();
8789 e->sets = sRefSet_new ();
8790 e->msets = sRefSet_new ();
8792 e->val = multiVal_unknown ();
8793 e->guards = guardSet_new ();
8794 e->sref = sRef_undefined;
8795 e->isJumpPoint = FALSE;
8796 e->exitCode = XK_NEVERESCAPE;
8798 /*> missing fields, detected by splint <*/
8799 e->canBreak = FALSE;
8800 e->mustBreak = FALSE;
8801 e->etext = cstring_undefined;
8803 if (uentry_isYield (ue))
8805 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8806 fileloc_copy (e->loc),
8810 uue = usymtab_supEntrySrefReturn (uue);
8812 sr = uentry_getSref (uue);
8813 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8814 sr = uentry_getSref (uue);
8815 sRef_setDefined (sr, e->loc);
8817 e->typ = uentry_getType (uue);
8819 e->edata = exprData_makeId (uue);
8820 uentry_setUsed (uue, g_currentloc);
8826 sRef_setGlobalScope ();
8827 uue = uentry_makeVariableLoc (s, ctype_unknown);
8829 e->typ = ctype_unknown;
8830 e->edata = exprData_makeId (uue);
8832 uentry_setUsed (uue, e->loc);
8833 uentry_setHasNameError (uue);
8835 if (context_getFlag (FLG_REPEATUNRECOG))
8837 uentry_markOwned (uue);
8841 usymtab_supGlobalEntry (uue);
8844 sRef_clearGlobalScope ();
8846 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8853 exprNode_defineConstraints(e);
8858 exprNode_iterExpr (/*@returned@*/ exprNode e)
8860 if (!processingIterVars ())
8862 llcontbuglit ("checkIterParam: not in iter");
8866 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8869 if (exprNode_isDefined (e))
8871 if (fileloc_isDefined (e->loc))
8875 message ("Yield parameter is not simple identifier: %s",
8876 exprNode_unparse (e)),
8883 message ("Yield parameter is not simple identifier: %s",
8884 exprNode_unparse (e)),
8894 exprNode_iterId (/*@observer@*/ uentry c)
8898 llassert (processingIterVars ());
8900 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8903 if (uentry_isYield (ue))
8905 ctype ct = uentry_getType (ue);
8906 exprNode e = exprNode_createPlain (ct);
8907 cstring name = uentry_getName (c);
8908 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8910 uentry_setUsed (ue, g_currentloc);
8911 uentry_setHasNameError (ue);
8913 cstring_free (name);
8916 e->edata = exprData_makeId (le);
8917 e->loc = context_getSaveLocation ();
8918 e->sref = uentry_getSref (le);
8920 usymtab_supEntrySref (le);
8922 if (!context_inHeader ())
8926 message ("Yield parameter shadows local declaration: %q",
8927 uentry_getName (c)),
8928 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8930 uentry_showWhereDeclared (c);
8937 return (exprNode_fromIdentifierAux (c));
8940 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8942 exprNode ret = exprNode_create (ctype_unknown);
8944 ret->kind = XPR_ITERCALL;
8945 ret->edata = exprData_makeIterCall (name, alist);
8947 if (uentry_isIter (name))
8949 uentryList params = uentry_getParams (name);
8951 if (context_inIterDef ()
8952 && uentryList_size (params) == exprNodeList_size (alist))
8956 exprNodeList_elements (alist, arg)
8958 uentry parg = uentryList_getN (params, i);
8960 if (uentry_isYield (parg))
8962 uentry ue = exprNode_getUentry (arg);
8964 if (uentry_isValid (ue))
8971 } end_exprNodeList_elements;
8974 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8975 checkUnspecCall (ret, params, alist);
8981 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8983 if (exprNode_isDefined (e))
8985 if (sRef_isInvalid (e->sref))
8988 e->sref = sRef_makeUnknown ();
8989 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
9000 return sRef_undefined;
9004 /*@observer@*/ cstring
9005 exprNode_unparseFirst (exprNode e)
9007 if (exprNode_isDefined (e))
9011 if (e->kind == XPR_STMTLIST
9012 || e->kind == XPR_COMMA || e->kind == XPR_COND)
9014 exprNode first = exprData_getPairA (e->edata);
9016 if (exprNode_isDefined (first))
9018 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
9022 return (cstring_makeLiteralTemp ("..."));
9026 ret = cstring_elide (exprNode_unparse (e), 20);
9027 cstring_markOwned (ret);
9033 return cstring_makeLiteralTemp ("<error>");
9037 /*@observer@*/ cstring
9038 exprNode_unparse (/*@temp@*/ exprNode e)
9040 if (exprNode_isError (e))
9042 return cstring_makeLiteralTemp ("<error>");
9045 if (cstring_isDefined (e->etext))
9051 cstring ret = exprNode_doUnparse (e);
9053 /*@-modifies@*/ /* benevolent */
9060 /*@observer@*/ fileloc
9061 exprNode_loc (exprNode e)
9063 if (exprNode_isError (e))
9065 return (g_currentloc);
9074 ** executes exprNode e
9075 ** recursively rexecutes as though in original parse using
9076 ** information in e->edata
9079 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
9081 exprNodeList ret = exprNodeList_new ();
9083 exprNodeList_elements (e, current)
9085 exprNodeList_addh (ret, exprNode_effect (current));
9086 } end_exprNodeList_elements;
9091 static /*@only@*/ exprNode exprNode_effect (exprNode e)
9092 /*@globals internalState@*/
9094 bool innerEffect = inEffect;
9100 context_clearJustPopped ();
9102 if (exprNode_isError (e))
9104 ret = exprNode_undefined;
9109 ** Turn off expose and dependent transfer checking.
9110 ** Need to pass exposed internal nodes,
9111 ** [ copying would be a waste! ]
9112 ** [ Actually, I think I wasted a lot more time than its worth ]
9113 ** [ trying to do this. ]
9117 /*@-observertrans@*/
9118 /*@-dependenttrans@*/
9125 ret = exprNode_addParens (exprData_getUopTok (data),
9126 exprNode_effect (exprData_getUopNode (data)));
9129 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
9130 exprNode_effect (exprData_getOpB (data)),
9131 exprData_getOpTok (data));
9134 ret = exprNode_undefined;
9137 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
9138 exprNodeList_effect (exprData_getArgs (data)));
9151 cstring id = exprData_getId (data);
9152 uentry ue = usymtab_lookupSafe (id);
9154 ret = exprNode_fromIdentifierAux (ue);
9155 ret->loc = fileloc_update (ret->loc, e->loc);
9162 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
9163 exprNode_effect (exprData_getPairB (data)));
9167 ** evans 2002-03-15: for && and ||, need to do the guards also
9168 ** this is what cgrammar.y does - should be
9169 ** able to avoid duplication, but need to
9170 ** time with grammar productions.
9173 DPRINTF (("Effect: %s", exprNode_unparse (e)));
9175 if (lltok_getTok (exprData_getOpTok (data)) == AND_OP)
9177 exprNode e1 = exprNode_effect (exprData_getOpA (data));
9179 exprNode_produceGuards (e1);
9180 context_enterAndClause (e1);
9181 e2 = exprNode_effect (exprData_getOpB (data));
9183 ret = exprNode_op (e1, e2,
9184 exprData_getOpTok (data));
9186 context_exitAndClause (ret, e2);
9188 else if (lltok_getTok (exprData_getOpTok (data)) == OR_OP)
9190 exprNode e1 = exprNode_effect (exprData_getOpA (data));
9192 exprNode_produceGuards (e1);
9193 context_enterOrClause (e1);
9194 e2 = exprNode_effect (exprData_getOpB (data));
9196 ret = exprNode_op (e1, e2,
9197 exprData_getOpTok (data));
9199 context_exitOrClause (ret, e2);
9203 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
9204 exprNode_effect (exprData_getOpB (data)),
9205 exprData_getOpTok (data));
9210 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
9211 exprData_getUopTok (data));
9214 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
9215 exprData_getUopTok (data));
9227 ret = exprNode_vaArg (exprData_getCastTok (data),
9228 exprNode_effect (exprData_getCastNode (data)),
9229 exprData_getCastType (data));
9233 ret = exprNode_cast (exprData_getCastTok (data),
9234 exprNode_effect (exprData_getCastNode (data)),
9235 exprData_getCastType (data));
9238 ret = exprNode_iterStart (exprData_getIterCallIter (data),
9240 (exprData_getIterCallArgs (data)));
9244 ret = exprNode_iter (exprData_getIterSname (data),
9245 exprNodeList_effect (exprData_getIterAlist (data)),
9246 exprNode_effect (exprData_getIterBody (data)),
9247 exprData_getIterEname (data));
9251 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
9252 exprNode_effect (exprData_getPairB (data)));
9256 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
9257 exprNode_effect (exprData_getTripleTest (data)),
9258 exprNode_effect (exprData_getTripleInc (data)));
9262 ret = exprNode_createTok (exprData_getTok (data));
9266 ret = exprNode_goto (exprData_getLiteral (data));
9267 ret->loc = fileloc_update (ret->loc, e->loc);
9271 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
9275 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
9279 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
9282 case XPR_NULLRETURN:
9283 ret = exprNode_nullReturn (exprData_getTok (data));
9287 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
9288 exprNode_effect (exprData_getPairB (data)));
9292 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
9293 exprNode_effect (exprData_getTripleTrue (data)),
9294 exprNode_effect (exprData_getTripleFalse (data)));
9297 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
9298 exprNode_effect (exprData_getPairB (data)));
9302 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
9303 exprNode_effect (exprData_getTripleTrue (data)),
9304 exprNode_effect (exprData_getTripleFalse (data)));
9307 ret = exprNode_whilePred (exprData_getSingle (data));
9311 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
9312 exprNode_effect (exprData_getPairB (data)));
9316 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
9317 exprNode_effect (exprData_getPairB (data)));
9321 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
9325 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
9326 exprData_getUopTok (data));
9330 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
9331 exprNode_effect (exprData_getPairB (data)));
9336 ret = exprNode_caseMarker
9337 (exprNode_effect (exprData_getSingle (data)),
9343 ret = exprNode_createTok (exprData_getTok (data));
9347 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
9348 exprNode_effect (exprData_getPairB (data)));
9352 ret = exprNode_makeInitialization
9353 (exprData_getInitId (data),
9354 exprNode_effect (exprData_getInitNode (data)));
9358 ret = exprNode_fieldAccessAux
9359 (exprNode_effect (exprData_getFieldNode (data)),
9360 exprNode_loc (exprData_getFieldNode (data)),
9361 cstring_copy (exprData_getFieldName (data)));
9365 ret = exprNode_arrowAccessAux
9366 (exprNode_effect (exprData_getFieldNode (data)),
9367 exprNode_loc (exprData_getFieldNode (data)),
9368 cstring_copy (exprData_getFieldName (data)));
9371 case XPR_STRINGLITERAL:
9385 /*@=observertrans@*/
9387 /*@=dependenttrans@*/
9398 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
9403 if (exprNode_isError (e))
9405 return cstring_undefined;
9413 ret = exprNode_rootVarName (exprData_getUopNode (data));
9416 ret = exprNode_rootVarName (exprData_getOpA (data));
9420 ret = exprData_getId (data);
9423 ret = idDecl_getName (exprData_getInitId (data));
9448 case XPR_NULLRETURN:
9470 case XPR_STRINGLITERAL:
9471 ret = cstring_undefined;
9478 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
9483 if (exprNode_isError (e))
9485 static /*@only@*/ cstring error = cstring_undefined;
9487 if (!cstring_isDefined (error))
9489 error = cstring_makeLiteral ("<error>");
9500 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
9503 ret = message ("%s %s %s",
9504 exprNode_unparse (exprData_getOpA (data)),
9505 lltok_unparse (exprData_getOpTok (data)),
9506 exprNode_unparse (exprData_getOpB (data)));
9509 ret = message ("%s(%q)",
9510 exprNode_unparse (exprData_getFcn (data)),
9511 exprNodeList_unparse (exprData_getArgs (data)));
9514 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
9517 ret = cstring_undefined;
9520 ret = message ("%s:", exprData_getId (data));
9524 ret = cstring_copy (exprData_getId (data));
9527 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
9528 exprNode_unparse (exprData_getPairB (data)));
9531 ret = message ("<body>");
9534 ret = message ("%s %s %s",
9535 exprNode_unparse (exprData_getOpA (data)),
9536 lltok_unparse (exprData_getOpTok (data)),
9537 exprNode_unparse (exprData_getOpB (data)));
9541 ret = message ("%s%s",
9542 lltok_unparse (exprData_getUopTok (data)),
9543 exprNode_unparse (exprData_getUopNode (data)));
9547 ret = message ("%s%s",
9548 exprNode_unparse (exprData_getUopNode (data)),
9549 lltok_unparse (exprData_getUopTok (data)));
9553 ret = message ("offsetof(%s,%q)",
9554 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
9555 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
9559 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9563 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
9567 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9571 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
9575 ret = message ("va_arg(%s, %q)",
9576 exprNode_unparse (exprData_getCastNode (data)),
9577 qtype_unparse (exprData_getCastType (data)));
9581 ret = message ("%q(%q)",
9582 uentry_getName (exprData_getIterCallIter (data)),
9583 exprNodeList_unparse (exprData_getIterCallArgs (data)));
9586 ret = message ("%q(%q) %s %q",
9587 uentry_getName (exprData_getIterSname (data)),
9588 exprNodeList_unparse (exprData_getIterAlist (data)),
9589 exprNode_unparse (exprData_getIterBody (data)),
9590 uentry_getName (exprData_getIterEname (data)));
9593 ret = message ("(%q)%s",
9594 qtype_unparse (exprData_getCastType (data)),
9595 exprNode_unparse (exprData_getCastNode (data)));
9599 ret = message ("%s %s",
9600 exprNode_unparse (exprData_getPairA (data)),
9601 exprNode_unparse (exprData_getPairB (data)));
9605 ret = message ("for (%s; %s; %s)",
9606 exprNode_unparse (exprData_getTripleInit (data)),
9607 exprNode_unparse (exprData_getTripleTest (data)),
9608 exprNode_unparse (exprData_getTripleInc (data)));
9612 ret = message ("goto %s", exprData_getLiteral (data));
9616 ret = cstring_makeLiteral ("continue");
9620 ret = cstring_makeLiteral ("break");
9624 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
9627 case XPR_NULLRETURN:
9628 ret = cstring_makeLiteral ("return");
9632 ret = message ("%s, %s",
9633 exprNode_unparse (exprData_getPairA (data)),
9634 exprNode_unparse (exprData_getPairB (data)));
9638 ret = message ("%s ? %s : %s",
9639 exprNode_unparse (exprData_getTriplePred (data)),
9640 exprNode_unparse (exprData_getTripleTrue (data)),
9641 exprNode_unparse (exprData_getTripleFalse (data)));
9644 ret = message ("if (%s) %s",
9645 exprNode_unparse (exprData_getPairA (data)),
9646 exprNode_unparse (exprData_getPairB (data)));
9650 ret = message ("if (%s) %s else %s",
9651 exprNode_unparse (exprData_getTriplePred (data)),
9652 exprNode_unparse (exprData_getTripleTrue (data)),
9653 exprNode_unparse (exprData_getTripleFalse (data)));
9656 ret = message ("while (%s) %s",
9657 exprNode_unparse (exprData_getPairA (data)),
9658 exprNode_unparse (exprData_getPairB (data)));
9662 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9666 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9670 ret = message ("do { %s } while (%s)",
9671 exprNode_unparse (exprData_getPairB (data)),
9672 exprNode_unparse (exprData_getPairA (data)));
9676 ret = message ("{ %s }", exprNode_unparse (exprData_getSingle (data)));
9677 /* evans 2002-02-20 was unparseFirst! */
9681 ret = message ("%s;", exprNode_unparse (exprData_getUopNode (data)));
9685 if (exprNode_isStatement (exprData_getPairA (data)))
9688 ** statement expressions already print the ;
9691 ret = message ("%s %s",
9692 exprNode_unparse (exprData_getPairA (data)),
9693 exprNode_unparse (exprData_getPairB (data)));
9697 ret = message ("%s; %s",
9698 exprNode_unparse (exprData_getPairA (data)),
9699 exprNode_unparse (exprData_getPairB (data)));
9705 ret = cstring_makeLiteral ("default:");
9709 ret = message ("switch (%s) %s",
9710 exprNode_unparse (exprData_getPairA (data)),
9711 exprNode_unparse (exprData_getPairB (data)));
9716 ret = message ("case %s:",
9717 exprNode_unparse (exprData_getSingle (data)));
9721 if (exprNode_isError (exprData_getInitNode (data)))
9723 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9727 ret = message ("%q = %s",
9728 idDecl_unparseC (exprData_getInitId (data)),
9729 exprNode_unparse (exprData_getInitNode (data)));
9734 ret = message ("%s.%s",
9735 exprNode_unparse (exprData_getFieldNode (data)),
9736 exprData_getFieldName (data));
9740 ret = message ("%s->%s",
9741 exprNode_unparse (exprData_getFieldNode (data)),
9742 exprData_getFieldName (data));
9745 case XPR_STRINGLITERAL:
9746 if (ctype_isWideString (e->typ))
9748 ret = message ("L\"%s\"", exprData_getLiteral (data));
9752 ret = message ("\"%s\"", exprData_getLiteral (data));
9757 ret = cstring_copy (exprData_getLiteral (data));
9761 ret = cstring_makeLiteral ("<node>");
9769 exprNode_isInitializer (exprNode e)
9771 return (exprNode_isDefined (e)
9772 && e->kind == XPR_INIT);
9776 exprNode_isCharLiteral (exprNode e)
9778 if (exprNode_isDefined (e))
9780 return (multiVal_isChar (exprNode_getValue (e)));
9789 exprNode_isNumLiteral (exprNode e)
9791 if (exprNode_isDefined (e))
9793 return (multiVal_isInt (exprNode_getValue (e)));
9802 exprNode_isFalseConstant (exprNode e)
9804 if (exprNode_isDefined (e))
9806 cstring s = exprNode_rootVarName (e);
9808 if (cstring_equal (s, context_getFalseName ()))
9818 exprNode_matchLiteral (ctype expected, exprNode e)
9820 if (exprNode_isDefined (e))
9822 multiVal m = exprNode_getValue (e);
9824 if (multiVal_isDefined (m))
9826 if (multiVal_isInt (m))
9828 long int val = multiVal_forceInt (m);
9830 if (ctype_isNumAbstract (expected)
9831 && context_flagOn (FLG_NUMABSTRACTLIT, exprNode_loc (e)))
9836 if (ctype_isDirectBool (ctype_realishType (expected)))
9840 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9848 if (ctype_isRealInt (expected))
9851 ** unsigned <- [ constant >= 0 is okay ]
9854 if (ctype_isUnsigned (expected))
9863 ** No checks on sizes of integers...maybe add
9867 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9868 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9869 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9871 if (context_getFlag (FLG_NUMLITERAL)
9872 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9878 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9882 else if (ctype_isChar (expected))
9886 else if (ctype_isArrayPtr (expected))
9889 ** evans 2001-10-14: We allow 0 to match any pointer, but only if the type matches or is void *.
9894 if (ctype_match (exprNode_getType (e), expected)
9895 || ctype_isVoidPointer (exprNode_getType (e)))
9905 else if (ctype_isAnyFloat (expected))
9907 return (context_getFlag (FLG_NUMLITERAL));
9914 else if (multiVal_isDouble (m))
9916 if (ctype_isAnyFloat (expected))
9921 else if (multiVal_isChar (m))
9923 char val = multiVal_forceChar (m);
9925 if (ctype_isChar (expected))
9927 if (ctype_isUnsigned (expected) && ((int)val) < 0)
9948 exprNode_matchType (ctype expected, exprNode e)
9952 if (!exprNode_isDefined (e)) return TRUE;
9954 actual = ctype_realishType (exprNode_getType (e));
9956 if (ctype_match (ctype_realishType (expected), actual))
9961 llassert (!exprNode_isError (e));
9962 return (exprNode_matchLiteral (expected, e));
9966 exprNode_matchTypes (exprNode e1, exprNode e2)
9971 if (!exprNode_isDefined (e1)) return TRUE;
9972 if (!exprNode_isDefined (e2)) return TRUE;
9975 ** realish type --- keep bools, bools
9978 t1 = ctype_realishType (exprNode_getType (e1));
9979 t2 = ctype_realishType (exprNode_getType (e2));
9981 if (ctype_match (t1, t2))
9986 DPRINTF (("Matching literal! %s %s %s %s",
9987 ctype_unparse (t1), exprNode_unparse (e2),
9988 ctype_unparse (t2), exprNode_unparse (e1)));
9990 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9998 exprNode_matchArgType (ctype ct, exprNode e)
10002 if (!exprNode_isDefined (e))
10007 et = ctype_realType (exprNode_getType (e));
10009 if (ctype_matchArg (ct, et)) return TRUE;
10011 llassert (!exprNode_isError (e));
10012 return (exprNode_matchLiteral (ct, e));
10015 static /*@only@*/ exprNodeSList
10016 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
10018 if (exprNode_isDefined (e))
10020 if (e->kind == XPR_STMTLIST)
10022 return (exprNodeSList_append
10023 (exprNode_flatten (exprData_getPairA (e->edata)),
10024 exprNode_flatten (exprData_getPairB (e->edata))));
10026 else if (e->kind == XPR_BLOCK)
10028 return (exprNode_flatten (exprData_getSingle (e->edata)));
10032 return (exprNodeSList_singleton (e));
10036 return exprNodeSList_new ();
10039 static /*@exposed@*/ exprNode
10040 exprNode_lastStatement (/*@returned@*/ exprNode e)
10042 if (exprNode_isDefined (e))
10044 if (e->kind == XPR_STMTLIST)
10046 exprNode b = exprData_getPairB (e->edata);
10048 if (exprNode_isDefined (b))
10050 return exprNode_lastStatement (b);
10054 return exprNode_lastStatement (exprData_getPairA (e->edata));
10057 else if (e->kind == XPR_BLOCK)
10059 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
10067 return exprNode_undefined;
10070 static /*@exposed@*/ exprNode
10071 exprNode_firstStatement (/*@returned@*/ exprNode e)
10073 if (exprNode_isDefined (e))
10075 if (e->kind == XPR_STMTLIST)
10077 exprNode b = exprData_getPairA (e->edata);
10079 if (exprNode_isDefined (b))
10081 return exprNode_firstStatement (b);
10085 return exprNode_firstStatement (exprData_getPairB (e->edata));
10088 else if (e->kind == XPR_BLOCK)
10090 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
10098 return exprNode_undefined;
10102 exprNode_mergeUSs (exprNode res, exprNode other)
10104 if (exprNode_isDefined (res) && exprNode_isDefined (other))
10106 res->msets = sRefSet_union (res->msets, other->msets);
10107 res->sets = sRefSet_union (res->sets, other->sets);
10108 res->uses = sRefSet_union (res->uses, other->uses);
10113 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
10115 if (exprNode_isDefined (res))
10117 if (exprNode_isDefined (other1))
10119 res->sets = sRefSet_union (res->sets, other1->sets);
10120 res->msets = sRefSet_union (res->msets, other1->msets);
10121 res->uses = sRefSet_union (res->uses, other1->uses);
10123 if (exprNode_isDefined (other2))
10125 res->sets = sRefSet_union (res->sets, other2->sets);
10126 res->msets = sRefSet_union (res->msets, other2->msets);
10127 res->uses = sRefSet_union (res->uses, other2->uses);
10133 ** modifies e->uses
10135 ** Reports errors is s is not defined.
10139 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
10141 if (exprNode_isDefined (e))
10143 e->uses = sRefSet_insert (e->uses, s);
10148 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
10150 if (sRef_isKnown (s) && !sRef_isConst (s))
10153 ** need to check all outer types are useable
10156 DPRINTF (("Check use: %s / %s",
10157 exprNode_unparse (e), sRef_unparse (s)));
10159 exprNode_addUse (e, s);
10161 if (!context_inProtectVars ())
10164 ** only report the deepest error
10167 sRef errorRef = sRef_undefined;
10168 sRef lastRef = sRef_undefined;
10169 bool deadRef = FALSE;
10170 bool unuseable = FALSE;
10171 bool errorMaybe = FALSE;
10173 while (sRef_isValid (s) && sRef_isKnown (s))
10175 ynm readable = sRef_isValidLvalue (s);
10177 DPRINTF (("Readable: %s / %s",
10178 sRef_unparseFull (s), ynm_unparse (readable)));
10180 if (!(ynm_toBoolStrict (readable)))
10182 if (ynm_isMaybe (readable))
10184 lastRef = errorRef;
10186 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
10187 deadRef = sRef_isPossiblyDead (errorRef);
10188 unuseable = sRef_isUnuseable (errorRef);
10193 lastRef = errorRef;
10195 deadRef = sRef_isDead (errorRef);
10196 unuseable = sRef_isUnuseable (errorRef);
10197 errorMaybe = FALSE;
10200 if (!sRef_isPartial (s))
10202 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
10203 sRef_setDefined (s, fileloc_undefined);
10207 s = sRef_getBaseSafe (s);
10210 if (sRef_isValid (errorRef))
10212 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
10213 && sRef_isPointer (errorRef))
10215 errorRef = lastRef;
10220 if (sRef_isThroughArrayFetch (errorRef))
10223 (FLG_STRICTUSERELEASED,
10224 message ("%q %q may be used after being released",
10225 sRef_unparseKindNamePlain (errorRef),
10226 sRef_unparse (errorRef)),
10229 sRef_showRefKilled (errorRef);
10231 if (sRef_isKept (errorRef))
10233 sRef_clearAliasState (errorRef, loc);
10239 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
10243 message ("%q %q %qused after being released",
10244 sRef_unparseKindNamePlain (errorRef),
10245 sRef_unparse (errorRef),
10246 cstring_makeLiteral (errorMaybe
10247 ? "may be " : "")),
10250 sRef_showRefKilled (errorRef);
10252 if (sRef_isKept (errorRef))
10254 sRef_clearAliasState (errorRef, loc);
10259 else if (unuseable)
10263 message ("%q %q%qused in inconsistent state",
10264 sRef_unparseKindName (errorRef),
10265 sRef_unparseOpt (errorRef),
10266 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10269 sRef_showStateInconsistent (errorRef);
10274 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
10278 message ("%q %q%qused before definition",
10279 sRef_unparseKindName (errorRef),
10280 sRef_unparseOpt (errorRef),
10281 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10284 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
10287 sRef_setDefined (errorRef, loc);
10289 if (sRef_isAddress (errorRef))
10291 sRef_setDefined (sRef_getRootBase (errorRef), loc);
10293 } /* end is error */
10301 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
10303 if (exprNode_isDefined (e) && sRef_isKnown (s))
10305 e->uses = sRefSet_insert (e->uses, s);
10310 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
10312 if (exprNode_isDefined (e))
10314 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
10319 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
10321 sRef defines = sRef_undefined;
10323 if (sRef_isValid (s) && !sRef_isNothing (s))
10325 uentry ue = sRef_getBaseUentry (s);
10327 if (uentry_isValid (ue))
10329 uentry_setLset (ue);
10332 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10334 voptgenerror (FLG_USEDEF,
10335 message ("Attempt to set unuseable storage: %q",
10340 if (sRef_isMeaningful (s))
10342 if (sRef_isDead (s))
10344 sRef base = sRef_getBaseSafe (s);
10346 if (sRef_isValid (base)
10347 && sRef_isDead (base))
10349 sRef_setPartial (s, exprNode_loc (e));
10352 defines = s; /* okay - modifies for only param */
10354 else if (sRef_isPartial (s))
10356 sRef eref = exprNode_getSref (e);
10358 if (!sRef_isPartial (eref))
10361 ** should do something different here???
10364 sRef_setDefinedComplete (eref, exprNode_loc (e));
10368 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
10371 if (sRef_isMeaningful (eref))
10380 else if (sRef_isAllocated (s))
10382 sRef eref = exprNode_getSref (e);
10385 if (!sRef_isAllocated (eref))
10387 sRef_setDefinedComplete (eref, exprNode_loc (e));
10391 sRef base = sRef_getBaseSafe (eref);
10393 if (sRef_isValid (base))
10395 sRef_setPdefined (base, exprNode_loc (e));
10403 sRef_setDefinedNCComplete (s, exprNode_loc (e));
10408 else /* not meaningful...but still need to insert it */
10414 if (exprNode_isDefined (e) && sRef_isValid (defines))
10416 e->sets = sRefSet_insert (e->sets, defines);
10421 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
10423 if (sRef_isValid (s) && !sRef_isNothing (s))
10425 uentry ue = sRef_getBaseUentry (s);
10427 if (uentry_isValid (ue))
10429 uentry_setLset (ue);
10432 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10434 voptgenerror (FLG_USEDEF,
10435 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
10439 if (sRef_isMeaningful (s))
10441 sRef_setDefinedComplete (s, exprNode_loc (e));
10444 if (exprNode_isDefined (e))
10446 e->msets = sRefSet_insert (e->msets, s);
10452 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
10454 checkAnyCall (fcn, cstring_undefined, params, args,
10455 FALSE, sRefSet_undefined, FALSE, 0);
10459 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
10460 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
10464 if (uentry_isYield (ucurrent))
10466 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
10467 exprNode_checkSet (current, current->sref);
10471 if (uentry_isSefParam (ucurrent))
10473 sRefSet sets = current->sets;
10474 sRef ref = exprNode_getSref (current);
10476 if (sRef_isMacroParamRef (ref))
10478 uentry ue = sRef_getUentry (ref);
10480 if (!uentry_isSefParam (ue))
10485 ("Parameter %d to %s is declared sef, but "
10486 "the argument is a macro parameter declared "
10488 argno, exprNode_unparse (fcn),
10489 exprNode_unparse (current)),
10490 exprNode_loc (current));
10494 if (!sRefSet_isEmpty (sets))
10496 sRefSet reported = sRefSet_undefined;
10498 sRefSet_realElements (current->sets, el)
10500 if (sRefSet_isSameNameMember (reported, el))
10502 ; /* don't report again */
10506 if (sRef_isUnconstrained (el))
10511 ("Parameter %d to %s is declared sef, but "
10512 "the argument calls unconstrained function %s "
10513 "(no guarantee it will not modify something): %s",
10514 argno, exprNode_unparse (fcn),
10515 sRef_unconstrainedName (el),
10516 exprNode_unparse (current)),
10517 exprNode_loc (current));
10524 ("Parameter %d to %s is declared sef, but "
10525 "the argument may modify %q: %s",
10526 argno, exprNode_unparse (fcn),
10528 exprNode_unparse (current)),
10529 exprNode_loc (current));
10532 } end_sRefSet_realElements;
10536 transferChecks_passParam (current, ucurrent, isSpec, fcn, argno, totargs);
10537 exprNode_mergeUSs (fcn, current);
10542 checkAnyCall (/*@dependent@*/ exprNode fcn,
10543 /*@dependent@*/ cstring fname,
10546 bool hasMods, sRefSet mods,
10551 int nargs = exprNodeList_size (args);
10556 ** concat all args ud's to f, add each arg sref as a use unless
10557 ** it was specified as "out", in which case it is a def.
10560 uentryList_reset (pn);
10563 ** aliasing checks:
10565 ** if paramn is only or unique, no other arg may alias argn
10568 exprNodeList_elements (args, current)
10572 if (exprNode_isDefined (current))
10574 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
10576 uentry ucurrent = uentryList_current (pn);
10578 if (specialArgs == 0
10579 || (paramno < specialArgs))
10581 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
10583 if (context_maybeSet (FLG_ALIASUNIQUE))
10585 if (uentry_isOnly (ucurrent)
10586 || uentry_isUnique (ucurrent))
10588 checkUniqueParams (fcn, current, args,
10589 paramno, ucurrent);
10594 else /* uentry is undefined */
10596 if (specialArgs == 0)
10598 exprNode_checkUseParam (current);
10601 exprNode_mergeUSs (fcn, current);
10604 uentryList_advanceSafe (pn);
10605 } end_exprNodeList_elements;
10611 sRefSet_allElements (mods, s)
10614 sRef rb = sRef_getRootBase (s);
10616 if (sRef_isFileOrGlobalScope (rb))
10618 context_usedGlobal (rb);
10621 fb = sRef_fixBaseParam (s, args);
10623 if (!sRef_isMacroParamRef (fb))
10625 if (sRef_isNothing (fb))
10631 if (sRef_isValid (fb))
10633 uentry ue = sRef_getBaseUentry (s);
10635 if (uentry_isValid (ue))
10637 uentry_setLset (ue);
10641 fcn->sets = sRefSet_insert (fcn->sets, fb);
10644 sRef_clearDerivedComplete (s);
10645 } end_sRefSet_allElements;
10651 if (context_hasMods ())
10653 if (context_maybeSet (FLG_MODUNCON))
10657 message ("Undetected modification possible "
10658 "from call to unconstrained function %s: %s",
10660 exprNode_unparse (fcn)),
10661 exprNode_loc (fcn));
10666 if (context_maybeSet (FLG_MODUNCONNOMODS)
10667 && !(context_inIterDef () || context_inIterEnd ()))
10670 (FLG_MODUNCONNOMODS,
10671 message ("Undetected modification possible "
10672 "from call to unconstrained function %s: %s",
10674 exprNode_unparse (fcn)),
10675 exprNode_loc (fcn));
10679 exprNode_checkSetAny (fcn, fname);
10683 void exprNode_checkUseParam (exprNode current)
10685 if (exprNode_isDefined (current))
10687 exprNode_checkUse (current, current->sref, current->loc);
10692 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10693 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10698 if (!ctype_match (tr1, tr2))
10700 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10701 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10703 DPRINTF (("No error: [%s] %s / [%s] %s",
10704 exprNode_unparse (e1), ctype_unparse (tr1),
10705 exprNode_unparse (e2), ctype_unparse (tr2)));
10707 ret = ctype_biggerType (tr1, tr2);
10711 if (ctype_isNumAbstract (tr1)
10712 && exprNode_isNumLiteral (e2)
10713 && context_flagOn (FLG_NUMABSTRACTLIT, e1->loc))
10715 ret = tr1; /* No error */
10717 else if (ctype_isNumAbstract (tr2)
10718 && exprNode_isNumLiteral (e1)
10719 && context_flagOn (FLG_NUMABSTRACTLIT, e1->loc))
10727 message ("Incompatible types for %s (%s, %s): %s %s %s",
10728 lltok_unparse (op),
10729 ctype_unparse (te1),
10730 ctype_unparse (te2),
10731 exprNode_unparse (e1), lltok_unparse (op),
10732 exprNode_unparse (e2)),
10735 ret = ctype_unknown;
10739 ret = ctype_biggerType (tr1, tr2);
10746 if (ctype_isNumAbstract (tr1))
10750 else if (ctype_isForceRealNumeric (&tr1)
10751 && ctype_isForceRealNumeric (&tr2))
10753 ret = ctype_resolveNumerics (tr1, tr2);
10755 else if (!context_msgStrictOps ())
10757 if (ctype_isPointer (tr1))
10759 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10763 else if (ctype_isInt (tr2))
10769 ret = ctype_unknown;
10772 else if (ctype_isPointer (tr2))
10774 if (ctype_isPointer (tr1))
10778 else if (ctype_isInt (tr1))
10784 ret = ctype_unknown;
10789 ret = ctype_resolveNumerics (tr1, tr2);
10794 int opid = lltok_getTok (op);
10795 bool comparop = (opid == EQ_OP || opid == NE_OP
10796 || opid == TLT || opid == TGT
10797 || opid == LE_OP || opid == GE_OP);
10799 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10802 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10803 || (ctype_isBool (tr1) && ctype_isBool (tr2))
10804 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10810 if (ctype_sameName (te1, te2))
10814 message ("Operands of %s are non-numeric (%t): %s %s %s",
10815 lltok_unparse (op), te1,
10816 exprNode_unparse (e1), lltok_unparse (op),
10817 exprNode_unparse (e2)),
10824 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10825 lltok_unparse (op), te1, te2,
10826 exprNode_unparse (e1), lltok_unparse (op),
10827 exprNode_unparse (e2)),
10832 else if (!ctype_isNumeric (tr1))
10836 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10837 lltok_unparse (op), te1,
10838 exprNode_unparse (e1), lltok_unparse (op),
10839 exprNode_unparse (e2)),
10844 if (!ctype_isNumeric (tr2))
10848 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10849 lltok_unparse (op), te2,
10850 exprNode_unparse (e1), lltok_unparse (op),
10851 exprNode_unparse (e2)),
10856 ret = ctype_unknown;
10864 abstractOpError (ctype tr1, ctype tr2, lltok op,
10865 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10866 fileloc loc1, fileloc loc2)
10868 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10870 if (ctype_match (tr1, tr2))
10872 if (ctype_isRealNumAbstract (tr1))
10874 ; /* No warning for numabstract types */
10880 message ("Operands of %s are abstract type (%t): %s %s %s",
10881 lltok_unparse (op), tr1,
10882 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10888 if (ctype_isRealNumAbstract (tr1) && ctype_isRealNumAbstract (tr2))
10893 ("Operands of %s are different numabstract types (%t, %t): %s %s %s",
10894 lltok_unparse (op), tr1, tr2,
10895 exprNode_unparse (e1),
10896 lltok_unparse (op), exprNode_unparse (e2)),
10903 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10904 lltok_unparse (op), tr1, tr2,
10905 exprNode_unparse (e1), lltok_unparse (op),
10906 exprNode_unparse (e2)),
10911 else if (ctype_isRealAbstract (tr1) && !ctype_isRealNumAbstract (tr1))
10915 message ("Left operand of %s is abstract type (%t): %s %s %s",
10916 lltok_unparse (op), tr1,
10917 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10922 if (ctype_isRealAbstract (tr2) && !ctype_isRealNumAbstract (tr2))
10926 message ("Right operand of %s is abstract type (%t): %s %s %s",
10927 lltok_unparse (op), tr2,
10928 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10939 ** requies e1 and e2 and not error exprNode's.
10943 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10944 ** the rep of the abstract type is exposed.
10946 ** The order is very important:
10948 ** check rep expose (move into check transfer)
10954 ** This isn't really a sensible procedure, but the indententation
10955 ** was getting too deep.
10959 checkOneRepExpose (sRef ysr, sRef base,
10960 /*@notnull@*/ exprNode e1,
10961 /*@notnull@*/ exprNode e2, ctype ct,
10964 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
10965 || sRef_isOwned (ysr)
10966 || sRef_isExposed (ysr)))
10968 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10969 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10972 if (sRef_isIReference (ysr))
10974 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10979 ("Assignment of mutable component of parameter %q "
10980 "to component of abstract "
10981 "type %s exposes rep: %s = %s",
10982 sRef_unparse (base),
10983 ctype_unparse (ct),
10984 exprNode_unparse (e1), exprNode_unparse (e2)),
10992 ("Assignment of mutable component of parameter %q "
10993 "(through alias %q) to component of abstract "
10994 "type %s exposes rep: %s = %s",
10995 sRef_unparse (base),
10996 sRef_unparse (e2->sref),
10997 ctype_unparse (ct),
10998 exprNode_unparse (e1), exprNode_unparse (e2)),
11004 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
11008 message ("Assignment of mutable parameter %q "
11009 "to component of abstract type %s "
11010 "exposes rep: %s = %s",
11011 sRef_unparse (base),
11012 ctype_unparse (ct),
11013 exprNode_unparse (e1),
11014 exprNode_unparse (e2)),
11021 message ("Assignment of mutable parameter %q "
11022 "(through alias %q) to "
11023 "component of abstract type %s exposes "
11025 sRef_unparse (base),
11026 sRef_unparse (e2->sref),
11027 ctype_unparse (ct),
11028 exprNode_unparse (e1),
11029 exprNode_unparse (e2)),
11035 if (sRef_isFileOrGlobalScope (s2b))
11037 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
11041 message ("Assignment of global %q "
11043 "abstract type %s exposes rep: %s = %s",
11044 sRef_unparse (base),
11045 ctype_unparse (ct),
11046 exprNode_unparse (e1), exprNode_unparse (e2)),
11053 message ("Assignment of global %q (through alias %q) "
11055 "abstract type %s exposes rep: %s = %s",
11056 sRef_unparse (base),
11057 sRef_unparse (e2->sref),
11058 ctype_unparse (ct),
11059 exprNode_unparse (e1), exprNode_unparse (e2)),
11067 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
11069 DPRINTF (("Do assign: %s <- %s",
11070 exprNode_unparse (e1), exprNode_unparse (e2)));
11071 DPRINTF (("Ctype: %s", ctype_unparse (exprNode_getType (e1))));
11073 if (ctype_isRealFunction (exprNode_getType (e1))
11074 && !ctype_isRealPointer (exprNode_getType (e1)))
11078 message ("Invalid left-hand side of assignment (function type %s): %s",
11079 ctype_unparse (exprNode_getType (e1)),
11080 exprNode_unparse (e1)),
11084 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
11086 ctype t2 = exprNode_getType (e2);
11087 sRef sr = sRef_getRootBase (e1->sref);
11088 ctype ct = sRef_getType (sr);
11090 if (ctype_isAbstract (t2)
11091 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
11093 /* it is immutable, okay to reference */
11094 goto donerepexpose;
11097 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
11099 sRef s2b = sRef_getRootBase (e2->sref);
11100 sRef s1 = e1->sref;
11101 sRef s1b = sRef_getRootBase (s1);
11104 aliases = usymtab_canAlias (e2->sref);
11106 if (!sRef_similar (s2b, s1b)
11107 && !sRef_isExposed (s1)
11108 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
11110 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
11111 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
11112 && !sRef_isExposed (s2b))
11114 if (sRef_isIReference (e2->sref))
11119 ("Assignment of mutable component of parameter %q "
11120 "to component of abstract type %s exposes rep: %s = %s",
11121 sRef_unparse (s2b),
11122 ctype_unparse (ct),
11123 exprNode_unparse (e1), exprNode_unparse (e2)),
11130 message ("Assignment of mutable parameter %q to "
11131 "component of abstract type %s exposes rep: %s = %s",
11132 sRef_unparse (s2b),
11133 ctype_unparse (ct),
11134 exprNode_unparse (e1), exprNode_unparse (e2)),
11139 if (sRef_isFileOrGlobalScope (s2b))
11143 message ("Assignment of global %q to component of "
11144 "abstract type %s exposes rep: %s = %s",
11145 sRef_unparse (s2b),
11146 ctype_unparse (ct),
11147 exprNode_unparse (e1), exprNode_unparse (e2)),
11151 sRefSet_realElements (aliases, ysr)
11153 sRef base = sRef_getRootBase (ysr);
11155 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
11156 || sRef_sameName (base, s1b))
11158 ; /* error already reported or same sref */
11162 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
11164 } end_sRefSet_realElements;
11166 sRefSet_free (aliases);
11173 ** function variables don't really work...
11176 if (!ctype_isFunction (ctype_realType (e2->typ)))
11180 DPRINTF (("Check init: %s / %s",
11181 exprNode_unparse (e1), exprNode_unparse (e2)));
11182 transferChecks_initialization (e1, e2);
11186 transferChecks_assign (e1, e2);
11191 sRef fref = e2->sref;
11193 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
11194 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
11196 /* Need to typecheck the annotation on the parameters */
11198 if (ctype_isRealFunction (e1->typ)) {
11199 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
11200 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
11202 if (!uentryList_isMissingParams (e1p)
11203 && !uentryList_isMissingParams (e2p)
11204 && uentryList_size (e1p) > 0) {
11205 if (uentryList_size (e1p) == uentryList_size (e2p)) {
11208 uentryList_elements (e1p, el1) {
11211 el2 = uentryList_getN (e2p, n);
11213 uentry_checkMatchParam (el1, el2, n, e2);
11214 } end_uentryList_elements;
11220 if (exprNode_isStringLiteral (e2))
11222 exprNode_checkStringLiteralLength (exprNode_getType (e1), e2);
11225 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
11231 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
11232 updateAliases (e1, e2);
11237 checkMacroParen (exprNode e)
11239 if (exprNode_isError (e) || e->kind == XPR_CAST)
11245 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
11249 message ("Macro parameter used without parentheses: %s",
11250 exprNode_unparse (e)),
11257 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
11261 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
11265 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
11272 ** if e2 is a parameter or global derived location which
11273 ** can be modified (that is, e2 is a mutable abstract type,
11274 ** or a derived pointer), then e1 can alias e2.
11276 ** e1 can alias everything which e2 can alias.
11278 ** Also, if e1 is guarded, remove from guard sets!
11281 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
11283 if (!context_inProtectVars ())
11286 ** depends on types of e1 and e2
11289 sRef s1 = e1->sref;
11290 sRef s2 = e2->sref;
11291 ctype t1 = exprNode_getType (e1);
11293 /* handle pointer sRefs, record fields, arrays, etc... */
11295 if (!ctype_isRealSU (t1))
11297 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
11298 sRef_copyRealDerivedComplete (s1, s2);
11303 ** Fields should alias
11306 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
11309 if (ctype_isMutable (t1) && sRef_isKnown (s1))
11311 usymtab_clearAlias (s1);
11312 usymtab_addMustAlias (s1, s2);
11313 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
11317 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
11320 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
11322 usymtab_unguard (s1);
11327 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
11329 if (exprNode_isDefined (e))
11331 e->loc = fileloc_update (e->loc, loc);
11335 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
11341 static void checkUniqueParams (exprNode fcn,
11342 /*@notnull@*/ exprNode current,
11344 int paramno, uentry ucurrent)
11347 sRef thisref = exprNode_getSref (current);
11350 ** Check if any argument could match this argument.
11353 exprNodeList_elements (args, icurrent)
11357 if (iparamno != paramno)
11359 sRef sr = exprNode_getSref (icurrent);
11361 if (sRef_similarRelaxed (thisref, sr))
11363 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
11368 ("Parameter %d (%s) to function %s is declared %s but "
11369 "is aliased by parameter %d (%s)",
11371 exprNode_unparse (current),
11372 exprNode_unparse (fcn),
11373 alkind_unparse (uentry_getAliasKind (ucurrent)),
11374 iparamno, exprNode_unparse (icurrent)),
11380 sRefSet aliases = usymtab_canAlias (sr);
11382 sRefSet_allElements (aliases, asr)
11384 if (ctype_isUnknown (sRef_getType (thisref)))
11386 sRef_setType (thisref, uentry_getType (ucurrent));
11389 if (sRef_similarRelaxed (thisref, asr))
11391 if (sRef_isExternal (asr))
11393 if (sRef_isLocalState (thisref))
11399 sRef base = sRef_getRootBase (asr);
11401 if (!sRef_similar (sRef_getBase (asr), thisref))
11403 if (sRef_isUnique (base) || sRef_isOnly (base)
11404 || sRef_isKept (base)
11405 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
11406 || (sRef_isAddress (thisref)
11407 && sRef_isLocalVar (sRef_getRootBase (thisref))))
11409 ; /* okay, no error */
11414 (FLG_MAYALIASUNIQUE,
11416 ("Parameter %d (%s) to function %s is declared %s but "
11417 "may be aliased externally by parameter %d (%s)",
11419 exprNode_unparse (current),
11420 exprNode_unparse (fcn),
11421 alkind_unparse (uentry_getAliasKind (ucurrent)),
11422 iparamno, exprNode_unparse (icurrent)),
11433 ("Parameter %d (%s) to function %s is declared %s but "
11434 "is aliased externally by parameter %d (%s) through "
11437 exprNode_unparse (current),
11438 exprNode_unparse (fcn),
11439 alkind_unparse (uentry_getAliasKind (ucurrent)),
11440 iparamno, exprNode_unparse (icurrent),
11441 sRef_unparse (asr)),
11445 } end_sRefSet_allElements;
11446 sRefSet_free (aliases);
11449 } end_exprNodeList_elements;
11452 long exprNode_getLongValue (exprNode e) {
11455 if (exprNode_hasValue (e)
11456 && multiVal_isInt (exprNode_getValue (e)))
11458 value = multiVal_forceInt (exprNode_getValue (e));
11469 /*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
11471 if (exprNode_isDefined (p_e) )
11472 return ( p_e->loc );
11474 return fileloc_undefined;
11477 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
11480 ** Returns the location of the sequence point following e.
11482 ** Only works for statements (for now).
11485 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
11486 lltok t = exprData_getUopTok (e->edata);
11487 return fileloc_copy(lltok_getLoc (t));
11489 /* drl possible problem : warning fix
11490 llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
11492 return fileloc_undefined;
11496 exprNode exprNode_createNew(ctype c)
11500 ret = exprNode_createPlain (c);
11505 bool exprNode_isInitBlock (exprNode e)
11507 return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);