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 "cgrammar_tokens.h"
34 # include "exprChecks.h"
35 # include "transferChecks.h"
36 # include "exprNodeSList.h"
38 static bool exprNode_sameStorage (exprNode p_e1, exprNode p_e2) /*@*/ ;
39 static bool exprNode_isEmptyStatement (exprNode p_e);
40 static /*@exposed@*/ exprNode exprNode_firstStatement (/*@returned@*/ exprNode p_e);
41 static bool exprNode_isFalseConstant (exprNode p_e) /*@*/ ;
42 static bool exprNode_isBlock (exprNode p_e);
43 static void checkGlobUse (uentry p_glob, bool p_isCall, /*@notnull@*/ exprNode p_e);
44 static void exprNode_addUse (exprNode p_e, /*@exposed@*/ sRef p_s);
45 static bool exprNode_matchArgType (ctype p_ct, exprNode p_e);
46 static exprNode exprNode_fakeCopy (exprNode p_e) /*@*/ ;
47 static exprNode exprNode_statementError (/*@only@*/ exprNode p_e, /*@only@*/ lltok p_t);
48 static bool exprNode_matchTypes (exprNode p_e1, exprNode p_e2);
49 static void checkUniqueParams (exprNode p_fcn,
50 /*@notnull@*/ exprNode p_current, exprNodeList p_args,
51 int p_paramno, uentry p_ucurrent);
52 static void updateAliases (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2);
53 static void abstractOpError (ctype p_tr1, ctype p_tr2, lltok p_op,
54 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2,
55 fileloc p_loc1, fileloc p_loc2);
56 static ctype checkNumerics (ctype p_tr1, ctype p_tr2, ctype p_te1, ctype p_te2,
57 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, lltok p_op);
58 static void doAssign (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, bool p_isInit);
59 static void checkSafeUse (exprNode p_e, /*@exposed@*/ sRef p_s);
60 static void reflectNullTest (/*@notnull@*/ exprNode p_e, bool p_isnull);
61 static void checkMacroParen (exprNode p_e);
62 static exprNodeSList exprNode_flatten (/*@dependent@*/ exprNode p_e);
63 static void exprNode_checkSetAny (exprNode p_e, /*@dependent@*/ cstring p_name);
64 static void exprNode_checkUse (exprNode p_e, /*@exposed@*/ sRef p_s, fileloc p_loc);
65 static void exprNode_mergeUSs (exprNode p_res, exprNode p_other);
66 static void exprNode_mergeCondUSs (exprNode p_res, exprNode p_other1, exprNode p_other2);
67 static /*@only@*/ /*@notnull@*/ exprNode exprNode_fromIdentifierAux (/*@observer@*/ uentry p_c);
68 static void checkAnyCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn,
69 /*@dependent@*/ cstring p_fname,
70 uentryList p_pn, exprNodeList p_args,
71 bool p_hasMods, sRefSet p_mods, bool p_isSpec,
73 static void checkOneArg (uentry p_ucurrent, /*@notnull@*/ exprNode p_current,
74 /*@dependent@*/ exprNode p_fcn, bool p_isSpec, int p_argno, int p_totargs);
76 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn, uentryList p_params, exprNodeList p_args);
78 static /*@only@*/ exprNode exprNode_effect (exprNode p_e)
79 /*@globals internalState@*/ ;
80 static /*@only@*/ cstring exprNode_doUnparse (exprNode p_e);
81 static /*@observer@*/ cstring exprNode_rootVarName (exprNode p_e);
82 static /*@exposed@*/ exprNode
83 exprNode_lastStatement (/*@returned@*/ exprNode p_e);
85 static /*@null@*/ sRef defref = sRef_undefined;
86 static /*@only@*/ exprNode mustExitNode = exprNode_undefined;
88 static int checkArgsReal (uentry p_fcn, /*@dependent@*/ exprNode p_f,
90 exprNodeList p_args, bool p_isIter, exprNode p_ret);
92 static bool inEffect = FALSE;
93 static int nowalloc = 0;
94 static int totalloc = 0;
95 static int maxalloc = 0;
97 static /*@only@*/ uentry regArg;
98 static /*@only@*/ uentry outArg;
99 static /*@only@*/ uentry outStringArg;
100 static /*@exposed@*/ sRef stdinRef;
101 static /*@exposed@*/ sRef stdoutRef;
102 static /*@only@*/ uentry csArg;
103 static /*@only@*/ uentry csOnlyArg;
104 static ctype cstringType;
105 static ctype ctypeType;
106 static ctype filelocType;
107 static bool initMod = FALSE;
109 /*@function void exprNode_swap (sef exprNode, sef exprNode)@*/
111 # define exprNode_swap(e1,e2) do { exprNode m_tmp = (e1); (e1) = (e2); (e2) = m_tmp; } while (FALSE)
114 static void exprNode_defineConstraints(/*@sef@*/ /*@special@*/ /*@notnull@*/ exprNode e)
115 /*@defines e->requiresConstraints, e->ensuresConstraints,
116 e->trueEnsuresConstraints, e->falseEnsuresConstraints @*/
118 e->requiresConstraints = constraintList_makeNew ();
119 e->ensuresConstraints = constraintList_makeNew ();
120 e->trueEnsuresConstraints = constraintList_makeNew ();
121 e->falseEnsuresConstraints = constraintList_makeNew ();
125 ** must occur after library has been read
128 void exprNode_initMod (void)
129 /*@globals undef regArg, undef outArg, undef outStringArg,
130 undef csOnlyArg, undef csArg;
137 cstringType = ctype_unknown;
138 ctypeType = ctype_unknown;
139 filelocType = ctype_unknown;
141 defref = sRef_undefined;
143 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
145 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
148 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
150 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
153 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
155 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
158 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdin")))
160 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdin"));
162 else /* define stdin */
164 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdin"),
166 fileloc_getBuiltin (),
168 uentry_setHasNameError (ue);
169 ue = usymtab_supGlobalEntryReturn (ue);
172 stdinRef = sRef_makePointer (uentry_getSref (ue));
174 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdout")))
176 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdout"));
180 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdout"),
182 fileloc_getBuiltin (),
184 uentry_setHasNameError (ue);
185 ue = usymtab_supGlobalEntryReturn (ue);
188 stdoutRef = sRef_makePointer (uentry_getSref (ue));
190 tmp = idDecl_create (cstring_undefined, qtype_create (ctype_unknown));
192 regArg = uentry_makeParam (tmp, PARAMUNKNOWN);
195 qtype_addQual (qtype_create (ctype_makePointer (ctype_unknown)),
198 outArg = uentry_makeParam (tmp, PARAMUNKNOWN);
200 idDecl_setTyp (tmp, qtype_addQual (qtype_create (ctype_string),
203 outStringArg = uentry_makeParam (tmp, PARAMUNKNOWN);
205 idDecl_setTyp (tmp, qtype_addQual (qtype_addQual (qtype_create (cstringType),
207 qual_createNull ()));
209 csOnlyArg = uentry_makeParam (tmp, PARAMUNKNOWN);
211 idDecl_setTyp (tmp, qtype_addQual (qtype_create (cstringType), qual_createNull ()));
212 csArg = uentry_makeParam (tmp, PARAMUNKNOWN);
218 exprNode_destroyMod (void)
219 /*@globals killed regArg, killed outArg, killed outStringArg,
220 killed mustExitNode, initMod @*/
224 uentry_free (regArg);
225 uentry_free (outArg);
226 uentry_free (outStringArg);
228 exprNode_free (mustExitNode);
235 static void exprNode_resetSref (/*@notnull@*/ exprNode e)
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;
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 (mustExitNode))
464 mustExitNode = exprNode_createPlain (ctype_unknown);
465 mustExitNode->exitCode = XK_MUSTEXIT;
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;
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;
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;
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 int len = cstring_length (t);
820 if (context_getFlag (FLG_STRINGLITERALLEN))
822 if (len > 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 ();
863 exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
865 int len = cstring_length (t) - 2;
866 char *ts = cstring_toCharsSafe (t);
867 char *s = cstring_toCharsSafe (cstring_create (len + 1));
869 llassert (*ts == '\"' && *(ts + len + 1) == '\"');
870 strncpy (s, ts+1, size_fromInt (len));
873 return exprNode_rawStringLiteral (cstring_fromCharsO (s), loc);
876 exprNode exprNode_fromUIO (cstring c)
878 fileloc loc = context_getSaveLocation ();
879 exprNode e = exprNode_createPlain (ctype_unknown);
883 if (fileloc_isUndefined (loc))
885 loc = fileloc_copy (g_currentloc);
888 e->loc = loc; /* save loc was mangled */
891 if (usymtab_exists (c))
893 uentry ue = usymtab_lookupEither (c);
895 if (uentry_isDatatype (ue)
896 && uentry_isSpecified (ue))
899 (message ("%q: Specified datatype %s used in code, but not defined. "
900 "(Cannot continue reasonably from this error.)",
901 fileloc_unparse (e->loc), c));
909 llassertprint (!usymtab_exists (c), ("Entry exists: %s", c));
912 ** was supercedeGlobalEntry...is this better?
915 if (!context_inIterEnd ())
917 if (context_inMacro ())
919 if (context_getFlag (FLG_UNRECOG))
923 message ("Unrecognized identifier in macro definition: %s", c), e->loc);
927 flagcode_recordSuppressed (FLG_UNRECOG);
933 (FLG_UNRECOG, message ("Unrecognized identifier: %s", c), e->loc);
937 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
939 /* No alias errors for unrecognized identifiers */
940 sRef_setAliasKind (e->sref, AK_ERROR, loc);
945 exprNode exprNode_makeConstantString (cstring c, /*@only@*/ fileloc loc)
947 exprNode e = exprNode_createPlain (ctype_unknown);
950 e->sref = sRef_makeConst (ctype_string);
951 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
952 e->typ = ctype_string;
954 /* No alias errors for unrecognized identifiers */
955 sRef_setAliasKind (e->sref, AK_STATIC, loc);
956 sRef_setExKind (e->sref, XO_OBSERVER, loc);
961 exprNode exprNode_createId (/*@observer@*/ uentry c)
963 if (uentry_isValid (c))
965 exprNode e = exprNode_new ();
967 DPRINTF (("create id: %s", uentry_unparse (c)));
969 e->typ = uentry_getType (c);
971 if (uentry_isFunction (c)
972 && !sRef_isLocalVar (uentry_getSref (c)))
974 e->sref = sRef_undefined;
978 e->sref = uentry_getSref (c);
981 if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
983 sRef_setDefined (e->sref, fileloc_undefined);
987 ** yoikes! leaving this out was a heinous bug...that would have been
988 ** caught if i had splint working first. gag!
991 e->etext = cstring_undefined;
993 if (uentry_isEitherConstant (c))
996 e->val = multiVal_copy (uentry_getConstantValue (c));
1001 e->val = multiVal_unknown ();
1004 e->edata = exprData_makeId (c);
1005 e->loc = context_getSaveLocation ();
1007 if (fileloc_isUndefined (e->loc))
1009 fileloc_free (e->loc);
1010 e->loc = fileloc_copy (g_currentloc);
1013 e->guards = guardSet_new ();
1014 e->sets = sRefSet_new ();
1015 e->msets = sRefSet_new ();
1016 e->uses = sRefSet_new ();
1018 /*> missing fields, detected by splint <*/
1019 e->exitCode = XK_NEVERESCAPE;
1020 e->isJumpPoint = FALSE;
1021 e->canBreak = FALSE;
1022 e->mustBreak = FALSE;
1024 exprNode_defineConstraints(e);
1030 return exprNode_createUnknown ();
1034 /*@notnull@*/ exprNode
1035 exprNode_fromIdentifier (/*@observer@*/ uentry c)
1039 if (context_justPopped ()) /* watch out! c could be dead */
1041 uentry ce = usymtab_lookupSafe (LastIdentifier ());
1043 if (uentry_isValid (ce))
1049 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
1053 ret = exprNode_fromIdentifierAux (c);
1058 static void exprNode_checkStringLiteralLength (ctype t1, exprNode e2)
1060 multiVal mval = exprNode_getValue (e2);
1064 if (ctype_isFixedArray (t1))
1067 int nelements = long_toInt (ctype_getArraySize (t1));
1069 llassert (multiVal_isString (mval));
1070 slit = multiVal_forceString (mval);
1072 len = cstring_lengthExpandEscapes (slit);
1075 if (len == nelements)
1079 temp = cstring_expandEscapes(slit);
1081 if (temp[len-1] == '\0')
1084 (FLG_STRINGLITNOROOMFINALNULL,
1085 message ("String literal with %d character%& "
1086 "is assigned to %s (no room for final null terminator): %s",
1089 exprNode_unparse (e2)),
1097 (FLG_STRINGLITNOROOM,
1098 message ("String literal with %d character%& "
1099 "is assigned to %s (no room for null terminator): %s",
1102 exprNode_unparse (e2)),
1106 else if (len > nelements)
1109 (FLG_STRINGLITTOOLONG,
1110 message ("String literal with %d character%& (counting null terminator) "
1111 "is assigned to %s (insufficient storage available): %s",
1114 exprNode_unparse (e2)),
1117 else if (len < nelements - 1)
1120 (FLG_STRINGLITSMALLER,
1121 message ("String literal with %d character%& is assigned to %s (possible waste of storage): %s",
1124 exprNode_unparse (e2)),
1134 static /*@only@*/ /*@notnull@*/ exprNode
1135 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
1137 exprNode e = exprNode_createId (c);
1140 uentry_setUsed (c, e->loc);
1142 if (uentry_isVar (c) && sRef_isFileOrGlobalScope (sr))
1144 checkGlobUse (c, FALSE, e);
1151 exprNode_isZero (exprNode e)
1153 if (exprNode_isDefined (e))
1155 multiVal m = exprNode_getValue (e);
1157 if (multiVal_isInt (m))
1159 return (multiVal_forceInt (m) == 0);
1167 exprNode_isNonNegative (exprNode e)
1169 if (exprNode_isDefined (e))
1171 multiVal m = exprNode_getValue (e);
1173 if (multiVal_isInt (m))
1175 return (multiVal_forceInt (m) >= 0);
1179 ** This is not always true if programmer defines enum
1180 ** values, but then the constant should be known.
1183 if (ctype_isEnum (ctype_realType (e->typ)))
1193 ** a[x] - uses a but NOT a[]
1194 ** result sref = a[] (set/use in assignment)
1196 ** The syntax x[a] is also legal in C, and has the same
1197 ** semantics. If ind is an array, and arr is an int, flip
1202 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
1205 ** error in arr, error propagates (no new messages)
1206 ** error in ind, assume valid and continue
1209 DPRINTF (("Array fetch: %s / %s",
1210 exprNode_unparse (e1), exprNode_unparse (e2)));
1212 if (exprNode_isError (e1))
1215 return (exprNode_makeError ());
1221 ctype carr = exprNode_getType (e1);
1222 ctype crarr = ctype_realType (carr);
1225 ** this sets up funny aliasing, that leads to spurious
1226 ** splint errors. Hence, the i2 comments.
1229 /* evans 2001-09-09 added ctype_isKnown so there is no swap when e1 type is unknown */
1230 if (ctype_isKnown (crarr)
1231 && !ctype_isRealArray (crarr)
1232 && ctype_isRealNumeric (crarr)
1233 && !exprNode_isError (e2)
1234 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1239 carr = exprNode_getType (arr);
1240 crarr = ctype_realType (carr);
1248 DPRINTF (("arr: %s", exprNode_unparse (arr)));
1250 if (sRef_possiblyNull (arr->sref))
1252 if (!usymtab_isGuarded (arr->sref))
1254 if (optgenerror (FLG_NULLDEREF,
1255 message ("Index of %s pointer %q: %s",
1256 sRef_nullMessage (arr->sref),
1257 sRef_unparse (arr->sref),
1258 exprNode_unparse (arr)),
1261 DPRINTF (("ref: %s", sRef_unparseFull (arr->sref)));
1262 sRef_showNullInfo (arr->sref);
1264 /* suppress future messages */
1265 sRef_setNullError (arr->sref);
1270 if (exprNode_isError (ind))
1272 if ((ctype_isArrayPtr (crarr)
1273 && !ctype_isFunction (crarr))
1274 || ctype_isUnknown (carr))
1276 exprNode ret = exprNode_createPartialCopy (arr);
1278 if (ctype_isKnown (carr))
1280 ret->typ = ctype_baseArrayPtr (crarr);
1284 ret->typ = ctype_unknown;
1287 ret->sref = sRef_makeArrayFetch (arr->sref);
1289 ret->kind = XPR_FETCH;
1292 ** Because of funny aliasing (when arr and ind are
1293 ** flipped) spurious errors would be reported here.
1296 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1297 checkSafeUse (ret, arr->sref);
1302 voptgenerror (FLG_TYPE,
1303 message ("Array fetch from non-array (%t): %s[%s]", carr,
1304 exprNode_unparse (e1), exprNode_unparse (e2)),
1306 exprNode_free (arr);
1307 return (exprNode_makeError ());
1312 if (!ctype_isForceRealInt (&(ind->typ)))
1314 ctype rt = ctype_realType (ind->typ);
1316 if (ctype_isChar (rt))
1320 message ("Array fetch using non-integer, %t: %s[%s]",
1322 exprNode_unparse (e1), exprNode_unparse (e2)),
1325 else if (ctype_isEnum (rt))
1329 message ("Array fetch using non-integer, %t: %s[%s]",
1331 exprNode_unparse (e1), exprNode_unparse (e2)),
1338 message ("Array fetch using non-integer, %t: %s[%s]",
1340 exprNode_unparse (e1), exprNode_unparse (e2)),
1344 multiVal_free (ind->val);
1345 ind->val = multiVal_unknown ();
1348 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1350 exprNode ret = exprNode_createSemiCopy (arr);
1351 multiVal m = exprNode_getValue (ind);
1353 ret->typ = ctype_baseArrayPtr (crarr);
1354 ret->kind = XPR_FETCH;
1356 if (multiVal_isInt (m))
1358 int i = (int) multiVal_forceInt (m);
1360 if (sRef_isValid (arr->sref)) {
1361 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1363 ret->sref = sRef_undefined;
1368 ret->sref = sRef_makeArrayFetch (arr->sref);
1371 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1372 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1373 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1375 /* (see comment on spurious errors above) */
1376 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1378 exprNode_checkUse (ret, ind->sref, ind->loc);
1379 exprNode_checkUse (ret, arr->sref, arr->loc);
1385 if (ctype_isUnknown (carr))
1387 exprNode ret = exprNode_createPartialCopy (arr);
1389 ret->kind = XPR_FETCH;
1390 ret->typ = ctype_unknown;
1391 ret->sets = sRefSet_union (ret->sets, ind->sets);
1392 ret->msets = sRefSet_union (ret->msets, ind->msets);
1393 ret->uses = sRefSet_union (ret->uses, ind->uses);
1395 /* (see comment on spurious errors above) */
1396 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1398 exprNode_checkUse (ret, ind->sref, ind->loc);
1399 exprNode_checkUse (ret, arr->sref, arr->loc);
1406 message ("Array fetch from non-array (%t): %s[%s]", carr,
1407 exprNode_unparse (e1), exprNode_unparse (e2)),
1410 exprNode_free (arr);
1411 exprNode_free (ind);
1413 return (exprNode_makeError ());
1423 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1424 exprNodeList args, exprNode ret)
1426 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1430 ** checkPrintfArgs --- checks arguments for printf-like functions
1431 ** Arguments before ... have already been checked.
1432 ** The argument before the ... is a char *.
1433 ** argno is the format string argument.
1437 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1438 exprNodeList args, exprNode ret, int argno)
1441 ** the last argument before the elips is the format string
1446 int nargs = exprNodeList_size (args);
1447 uentryList params = uentry_getParams (fcn);
1451 ** These should be ensured by checkSpecialFunction
1454 llassert (uentryList_size (params) == argno + 1);
1455 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1457 a = exprNodeList_getN (args, argno - 1);
1458 formatloc = fileloc_copy (exprNode_loc (a));
1460 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1461 && exprNode_knownStringValue (a))
1463 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1464 char *code = format;
1467 nargs = exprNodeList_size (args);
1469 while ((code = strchr (code, '%')) != NULL)
1471 char *origcode = code;
1472 cstring codetext = cstring_newEmpty ();
1473 char key = *(++code);
1474 ctype modtype = ctype_int;
1475 bool modified = FALSE;
1477 fileloc_addColumn (formatloc, code - ocode);
1479 codetext = cstring_appendChar (codetext, key);
1482 while (isFlagKey (key))
1485 codetext = cstring_appendChar (codetext, key);
1486 fileloc_incColumn (formatloc);
1489 if (key == 'm') /* skipped in syslog */
1494 /* ignore field width */
1495 while (isdigit ((int) key) != 0)
1498 codetext = cstring_appendChar (codetext, key);
1499 fileloc_incColumn (formatloc);
1502 /* ignore precision */
1506 codetext = cstring_appendChar (codetext, key);
1507 fileloc_incColumn (formatloc);
1510 ** In printf, '*' means: read the next arg as an int for the
1511 ** field width. This seems to be missing from my copy of the
1512 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1513 ** later) but never does.
1518 ; /* don't do anything --- handle later */
1522 while (isdigit ((int) key) != 0)
1525 codetext = cstring_appendChar (codetext, key);
1526 fileloc_incColumn (formatloc);
1533 modtype = ctype_sint; /* short */
1535 codetext = cstring_appendChar (codetext, key);
1536 fileloc_incColumn (formatloc);
1538 else if (key == 'l' || key == 'L')
1540 modtype = ctype_lint; /* long */
1542 codetext = cstring_appendChar (codetext, key);
1543 fileloc_incColumn (formatloc);
1545 if (key == 'l' || key == 'L') {
1546 modtype = ctype_llint; /* long long */
1548 codetext = cstring_appendChar (codetext, key);
1549 fileloc_incColumn (formatloc);
1557 /* now, key = type of conversion to apply */
1559 fileloc_incColumn (formatloc);
1567 message ("No argument corresponding to %q format "
1568 "code %d (%%%s): \"%s\"",
1569 uentry_getName (fcn),
1571 cstring_fromChars (format)),
1574 if (fileloc_isDefined (formatloc)
1575 && context_getFlag (FLG_SHOWCOL))
1577 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1585 a = exprNodeList_getN (args, i);
1588 if (!exprNode_isError (a))
1594 case '*': /* int argument for fieldwidth */
1595 expecttype = ctype_int;
1596 *(--code) = '%'; /* convert it for next code */
1597 fileloc_subColumn (formatloc, 1);
1598 /*@switchbreak@*/ break;
1601 expecttype = ctype_combine (ctype_uint, modtype);
1602 /*@switchbreak@*/ break;
1604 case 'i': /* int argument */
1606 expecttype = ctype_combine (ctype_int, modtype);
1607 /*@switchbreak@*/ break;
1609 case 'x': /* unsigned int */
1611 expecttype = ctype_combine (ctype_uint, modtype);
1613 /*@switchbreak@*/ break;
1619 case 'f': /* double */
1620 expecttype = ctype_combine (ctype_double, modtype);
1621 /*@switchbreak@*/ break;
1623 case 'c': /* int converted to char (check its a char?) */
1624 expecttype = ctype_makeConj (ctype_int,
1625 ctype_makeConj (ctype_char,
1628 /* evans 2001-10-05 - changed to reflect correct ISO spec:
1629 int converted to char */
1631 /* expecttype = ctype_makeConj (ctype_char, ctype_uchar); */
1632 /*@switchbreak@*/ break;
1634 case 's': /* string */
1635 expecttype = ctype_string;
1636 /*@switchbreak@*/ break;
1639 while (((key = *(++code)) != ']')
1642 codetext = cstring_appendChar (codetext, key);
1643 fileloc_incColumn (formatloc);
1649 (message ("Bad character set format: %s",
1650 cstring_fromChars (origcode)));
1653 expecttype = ctype_string;
1654 /*@switchbreak@*/ break;
1656 case 'p': /* pointer */
1657 expecttype = ctype_makePointer (ctype_void);
1658 uentry_setDefState (regArg, SS_RELDEF); /* need not be defined */
1659 sRef_setPosNull (uentry_getSref (regArg), fileloc_undefined); /* could be null */
1660 /*@switchbreak@*/ break;
1662 case 'n': /* pointer to int, modified by call! */
1663 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1665 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1666 /*@switchbreak@*/ break;
1668 case 'm': /* in a syslog, it doesn't consume an argument */
1669 /* should check we're really doing syslog */
1671 /*@switchbreak@*/ break;
1675 expecttype = ctype_unknown;
1679 message ("Unrecognized format code: %s",
1680 cstring_fromChars (origcode)),
1681 fileloc_isDefined (formatloc)
1682 ? formatloc : g_currentloc);
1684 /*@switchbreak@*/ break;
1687 if (!(exprNode_matchArgType (expecttype, a)))
1689 if (ctype_isVoidPointer (expecttype)
1690 && ctype_isRealAbstract (a->typ)
1691 && (context_getFlag (FLG_ABSTVOIDP)))
1697 if (llgenformattypeerror
1698 (expecttype, exprNode_undefined,
1700 message ("Format argument %d to %q (%%%s) expects "
1703 uentry_getName (fcn),
1706 a->typ, exprNode_unparse (a)),
1709 if (fileloc_isDefined (formatloc)
1710 && context_getFlag (FLG_SHOWCOL))
1713 (cstring_makeLiteral
1714 ("Corresponding format code"),
1721 uentry_setType (regArg, expecttype);
1722 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1724 if (ctype_equal (expecttype, ctype_string))
1726 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1729 uentry_setType (regArg, ctype_unknown);
1730 uentry_fixupSref (regArg);
1734 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1745 cstring_free (codetext);
1750 voptgenerror (FLG_TYPE,
1751 message ("Format string for %q has %d arg%&, given %d",
1752 uentry_getName (fcn), i - argno, nargs - argno),
1758 /* no checking possible for compile-time unknown format strings */
1759 if (exprNode_isDefined (a))
1763 message ("Format string parameter to %s is not a compile-time constant: %s",
1764 exprNode_unparse (f),
1765 exprNode_unparse (a)),
1770 fileloc_free (formatloc);
1774 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1775 exprNodeList args, exprNode ret, int argno)
1779 int nargs = exprNodeList_size (args);
1780 uentryList params = uentry_getParams (fcn);
1784 ** These should be ensured by checkSpecialFunction
1787 llassert (uentryList_size (params) == argno + 1);
1788 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1790 a = exprNodeList_getN (args, argno - 1);
1791 formatloc = fileloc_copy (exprNode_loc (a));
1793 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1794 && exprNode_knownStringValue (a))
1796 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1797 char *code = format;
1800 nargs = exprNodeList_size (args);
1802 while ((code = strchr (code, '%')) != NULL)
1804 char *origcode = code;
1805 char key = *(++code);
1806 cstring codetext = cstring_newEmpty ();
1807 ctype modtype = ctype_int;
1808 char modifier = '\0';
1809 bool modified = TRUE;
1810 bool ignore = FALSE;
1812 codetext = cstring_appendChar (codetext, key);
1813 fileloc_addColumn (formatloc, code - ocode);
1816 ** this is based on ANSI standard library description of fscanf
1817 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1820 /* '*' suppresses assignment (does not need match argument) */
1825 codetext = cstring_appendChar (codetext, key);
1828 fileloc_incColumn (formatloc);
1831 /* ignore field width */
1832 while (isdigit ((int) key) != 0)
1835 codetext = cstring_appendChar (codetext, key);
1836 fileloc_incColumn (formatloc);
1841 modtype = ctype_sint; /* short */
1843 codetext = cstring_appendChar (codetext, key);
1844 fileloc_incColumn (formatloc);
1846 else if (key == 'l' || key == 'L')
1848 modtype = ctype_lint; /* long */
1852 codetext = cstring_appendChar (codetext, key);
1854 fileloc_incColumn (formatloc);
1856 if (key == 'l' || key == 'L') {
1857 modtype = ctype_llint; /* long long */
1859 codetext = cstring_appendChar (codetext, key);
1860 fileloc_incColumn (formatloc);
1868 /* now, key = type of conversion to apply */
1870 fileloc_incColumn (formatloc);
1884 message ("No argument corresponding to %q format "
1885 "code %d (%%%s): \"%s\"",
1886 uentry_getName (fcn),
1888 cstring_fromChars (format)),
1891 if (fileloc_isDefined (formatloc)
1892 && context_getFlag (FLG_SHOWCOL))
1895 (cstring_makeLiteral ("Corresponding format code"),
1903 a = exprNodeList_getN (args, i);
1906 if (!exprNode_isError (a))
1912 case '*': /* int argument for fieldwidth */
1913 expecttype = ctype_makePointer (ctype_int);
1914 *(--code) = '%'; /* convert it for next code */
1915 fileloc_subColumn (formatloc, 1);
1916 /*@switchbreak@*/ break;
1919 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1920 /*@switchbreak@*/ break;
1925 case 'X': /* unsigned int */
1926 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1927 /*@switchbreak@*/ break;
1934 /* printf is double, scanf is float! */
1936 if (modifier == 'l')
1938 expecttype = ctype_makePointer (ctype_double);
1940 else if (modifier == 'L')
1942 expecttype = ctype_makePointer (ctype_ldouble);
1946 llassert (modifier == '\0');
1947 expecttype = ctype_makePointer (ctype_float);
1949 /*@switchbreak@*/ break;
1951 case 'c': /* int converted to char (check its a char?) */
1952 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1953 /*@switchbreak@*/ break;
1955 case 's': /* string */
1956 expecttype = ctype_string;
1957 /*@switchbreak@*/ break;
1961 while (((key = *(++code)) != ']')
1964 codetext = cstring_appendChar (codetext, key);
1965 fileloc_incColumn (formatloc);
1971 (message ("Bad character set format: %s",
1972 cstring_fromChars (origcode)));
1975 expecttype = ctype_string;
1976 /*@switchbreak@*/ break;
1979 case 'p': /* pointer */
1982 message ("Format code should not be used in scanf: %s",
1983 cstring_fromChars (origcode)),
1984 fileloc_isDefined (formatloc)
1985 ? formatloc : g_currentloc);
1987 expecttype = ctype_unknown;
1988 /*@switchbreak@*/ break;
1990 case 'n': /* pointer to int, modified by call! */
1991 expecttype = ctype_makePointer (ctype_int);
1992 /*@switchbreak@*/ break;
1995 expecttype = ctype_unknown;
1999 message ("Unrecognized format code: %s",
2000 cstring_fromChars (origcode)),
2001 fileloc_isDefined (formatloc)
2002 ? formatloc : g_currentloc);
2004 /*@switchbreak@*/ break;
2007 if (!(exprNode_matchArgType (expecttype, a)))
2009 if (ctype_isVoidPointer (expecttype)
2010 && ctype_isRealAbstract (a->typ)
2011 && (context_getFlag (FLG_ABSTVOIDP)))
2017 if (llgenformattypeerror
2018 (expecttype, exprNode_undefined,
2020 message ("Format argument %d to %q (%%%s) expects "
2023 uentry_getName (fcn),
2024 codetext, expecttype,
2025 a->typ, exprNode_unparse (a)),
2028 if (fileloc_isDefined (formatloc)
2029 && context_getFlag (FLG_SHOWCOL))
2032 (cstring_makeLiteral
2033 ("Corresponding format code"),
2040 uentry_setType (outArg, expecttype);
2041 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
2042 uentry_setType (outArg, ctype_unknown);
2043 uentry_fixupSref (outArg);
2047 exprNode_checkCallModifyVal (a->sref, args, f, ret);
2052 /* a->sref = defref; */
2059 cstring_free (codetext);
2064 voptgenerror (FLG_TYPE,
2065 message ("Format string for %q has %d arg%&, given %d",
2066 uentry_getName (fcn), i - argno, nargs - argno),
2072 /* no checking possible for compile-time unknown format strings */
2075 fileloc_free (formatloc);
2079 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
2082 /*@unused@*/ int argno)
2085 ** the last argument before the elips is the format string
2088 int nargs = exprNodeList_size (args);
2093 a = exprNodeList_getN (args, argno - 1);
2094 formatloc = fileloc_copy (exprNode_loc (a));
2096 if (ctype_isUnknown (cstringType)) {
2097 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
2099 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
2103 if (ctype_isUnknown (ctypeType)) {
2104 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
2106 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
2110 if (ctype_isUnknown (filelocType)) {
2111 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
2113 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
2117 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
2118 && exprNode_knownStringValue (a))
2120 cstring format = multiVal_forceString (exprNode_getValue (a));
2121 char *code = cstring_toCharsSafe (format);
2124 nargs = exprNodeList_size (args);
2126 while ((code = strchr (code, '%')) != NULL)
2128 char *origcode = code;
2129 char key = *(++code);
2130 cstring codetext = cstring_newEmpty ();
2131 bool isOnly = FALSE;
2133 codetext = cstring_appendChar (codetext, key);
2135 fileloc_addColumn (formatloc, code - ocode);
2137 while (key >= '0' && key <= '9')
2140 codetext = cstring_appendChar (codetext, key);
2141 fileloc_incColumn (formatloc);
2145 fileloc_incColumn (formatloc);
2149 if (key == '&') /* plural marker */
2158 message ("Message missing format arg %d (%%%s): \"%s\"",
2159 i + 1, codetext, format),
2165 a = exprNodeList_getN (args, i);
2169 if (!exprNode_isError (a))
2173 /*@-loopswitchbreak@*/
2179 expecttype = ctype_char; break;
2181 expecttype = cstringType; break;
2183 expecttype = cstringType; isOnly = TRUE; break;
2185 expecttype = cstringType; isOnly = TRUE; break;
2186 case 'd': expecttype = ctype_int; break;
2187 case 'u': expecttype = ctype_uint; break;
2188 case 'w': expecttype = ctype_ulint; break;
2189 case 'f': expecttype = ctype_float; break;
2190 case 'b': expecttype = ctype_bool; break;
2191 case 't': expecttype = ctypeType; break;
2192 case 'l': expecttype = filelocType; break;
2193 case '&': /* a wee bit of a hack methinks */
2194 expecttype = ctype_int;
2196 case 'r': expecttype = ctype_bool; break;
2198 expecttype = ctype_unknown;
2201 message ("Unrecognized format code: %s",
2202 cstring_fromChars (origcode)),
2203 fileloc_isDefined (formatloc)
2204 ? formatloc : g_currentloc);
2207 /*@=loopswitchbreak@*/
2209 if (!(exprNode_matchArgType (expecttype, a)))
2211 if (ctype_isVoidPointer (expecttype)
2212 && ctype_isRealAbstract (a->typ)
2213 && (context_getFlag (FLG_ABSTVOIDP)))
2219 if (llgenformattypeerror
2220 (expecttype, exprNode_undefined,
2222 message ("Format argument %d to %q (%%%s) expects "
2225 uentry_getName (fcn),
2226 codetext, expecttype,
2227 a->typ, exprNode_unparse (a)),
2230 if (fileloc_isDefined (formatloc)
2231 && context_getFlag (FLG_SHOWCOL))
2234 (cstring_makeLiteral
2235 ("Corresponding format code"),
2242 if (ctype_equal (expecttype, cstringType))
2246 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2247 uentry_fixupSref (csOnlyArg);
2251 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2252 uentry_fixupSref (csArg);
2257 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2258 uentry_fixupSref (regArg);
2264 cstring_free (codetext);
2269 voptgenerror (FLG_TYPE,
2270 message ("Format string for %q has %d arg%&, given %d",
2271 uentry_getName (fcn), i - argno, nargs -argno),
2277 /* no checking possible for compile-time unknown format strings */
2280 fileloc_free (formatloc);
2284 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2285 /*@notnull@*/ exprNode e2,
2291 bool hadUncon = FALSE;
2293 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
2294 sRefSet_hasUnconstrained (sets2))
2297 (FLG_EVALORDERUNCON,
2299 ("Expression may have undefined behavior (%q used in right operand "
2300 "may set global variable %q used in left operand): %s %s %s",
2301 sRefSet_unparseUnconstrained (sets2),
2302 sRef_unparse (sRef_getRootBase (e1->sref)),
2303 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2307 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
2308 sRefSet_hasUnconstrained (sets1))
2311 (FLG_EVALORDERUNCON,
2313 ("Expression has undefined behavior (%q used in left operand "
2314 "may set global variable %q used in right operand): %s %s %s",
2315 sRefSet_unparseUnconstrained (sets1),
2316 sRef_unparse (e2->sref),
2317 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2321 sRefSet_realElements (e1->uses, sr)
2323 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2328 ("Expression has undefined behavior (left operand uses %q, "
2329 "modified by right operand): %s %s %s",
2331 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2334 } end_sRefSet_realElements;
2336 sRefSet_realElements (sets1, sr)
2338 if (sRef_isMeaningful (sr))
2340 if (sRef_same (sr, e2->sref))
2345 ("Expression has undefined behavior (value of right operand "
2346 "modified by left operand): %s %s %s",
2347 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2350 else if (sRefSet_member (e2->uses, sr))
2355 ("Expression has undefined behavior (left operand modifies %q, "
2356 "used by right operand): %s %s %s",
2358 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2363 if (sRefSet_member (sets2, sr))
2365 if (sRef_isUnconstrained (sr))
2373 hadUncon = optgenerror
2374 (FLG_EVALORDERUNCON,
2376 ("Expression may have undefined behavior. Left operand "
2377 "calls %q; right operand calls %q. The unconstrained "
2378 "functions may modify global state used by "
2379 "the other operand): %s %s %s",
2380 sRefSet_unparseUnconstrained (sets1),
2381 sRefSet_unparseUnconstrained (sets2),
2382 exprNode_unparse (e1), lltok_unparse (op),
2383 exprNode_unparse (e2)),
2392 ("Expression has undefined behavior (both "
2393 "operands modify %q): %s %s %s",
2395 exprNode_unparse (e1),
2396 lltok_unparse (op), exprNode_unparse (e2)),
2402 } end_sRefSet_realElements;
2405 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2407 bool hasError = FALSE;
2409 if (exprNode_isError (e1) || exprNode_isError (e2))
2414 if (sRefSet_member (e2->sets, e1->sref))
2416 if (e2->kind == XPR_CALL)
2422 hasError = optgenerror
2424 message ("Expression has undefined behavior "
2425 "(value of left operand %s is modified "
2426 "by right operand %s): %s %s %s",
2427 exprNode_unparse (e1),
2428 exprNode_unparse (e2),
2429 exprNode_unparse (e1), lltok_unparse (op),
2430 exprNode_unparse (e2)),
2435 if (context_getFlag (FLG_EVALORDERUNCON))
2437 if (sRefSet_member (e2->msets, e1->sref))
2439 if (e2->kind == XPR_CALL)
2445 hasError = optgenerror
2448 ("Expression has undefined behavior (value of left "
2449 "operand may be modified by right operand): %s %s %s",
2450 exprNode_unparse (e1), lltok_unparse (op),
2451 exprNode_unparse (e2)),
2459 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2461 if (context_maybeSet (FLG_EVALORDERUNCON))
2463 checkExpressionDefinedAux (e1, e2, e1->msets,
2464 e2->msets, op, FLG_EVALORDERUNCON);
2469 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2472 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2473 exprNodeList args, bool isIter, exprNode ret)
2477 if (!exprNode_isError (f))
2479 if (!uentryList_isMissingParams (cl))
2481 int nargs = exprNodeList_size (args);
2482 int expectargs = uentryList_size (cl);
2486 if (expectargs == 0)
2494 message ("Iter %q invoked with %d args, "
2496 uentry_getName (fcn),
2504 message ("Function %s called with %d args, "
2506 exprNode_unparse (f), nargs),
2513 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2515 exprNodeList_reset (args);
2517 uentryList_elements (cl, current)
2519 ctype ct = uentry_getType (current);
2522 if (ctype_isElips (ct))
2525 ** do special checking for printf/scanf library functions
2527 ** this is kludgey code, just for handling the special case
2531 if (uentry_isPrintfLike (fcn))
2533 checkPrintfArgs (f, fcn, args, ret, i);
2536 else if (uentry_isScanfLike (fcn))
2538 checkScanfArgs (f, fcn, args, ret, i);
2541 else if (uentry_isMessageLike (fcn))
2543 checkMessageArgs (f, fcn, args, i);
2548 llassert (!uentry_isSpecialFunction (fcn));
2551 nargs = expectargs; /* avoid errors */
2556 if (i >= nargs) break;
2558 a = exprNodeList_current (args);
2559 exprNodeList_advance (args);
2563 if (exprNode_isError (a))
2570 probably necessary? I'm not sure about this one
2571 checkMacroParen (a);
2574 f->guards = guardSet_union (f->guards, a->guards);
2576 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2578 if (!(exprNode_matchArgType (ct, a)))
2580 DPRINTF (("Args mismatch!"));
2582 if (ctype_isVoidPointer (ct)
2583 && (ctype_isPointer (a->typ)
2584 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2589 ("Pointer to abstract type (%t) used "
2591 "(arg %d to %q): %s",
2593 uentry_getName (fcn),
2594 exprNode_unparse (a)),
2602 (ct, exprNode_undefined,
2605 ("Iter %q expects arg %d to "
2606 "be %t gets %t: %s",
2607 uentry_getName (fcn),
2608 i, ct, a->typ, exprNode_unparse (a)),
2619 ("Function %q expects arg %d to be %t gets %t: %s",
2620 uentry_getName (fcn),
2621 i, ct, a->typ, exprNode_unparse (a)),
2624 DPRINTF (("Types: %s / %s",
2626 ctype_unparse (a->typ)));
2630 ** Clear null marker for abstract types.
2631 ** (It is not revealed, so suppress future messages.)
2634 if (ctype_isAbstract (a->typ))
2636 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2643 } end_uentryList_elements ;
2646 if (expectargs != nargs) /* note: not != since we may have ... */
2648 if (ctype_isElips (last))
2652 message ("Function %s called with %d args, expects at least %d",
2653 exprNode_unparse (f),
2654 nargs, expectargs - 1),
2663 message ("Iter %q invoked with %d args, expects %d",
2664 uentry_getName (fcn), nargs, expectargs),
2671 message ("Function %s called with %d args, expects %d",
2672 exprNode_unparse (f),
2685 ** Check for undefined code sequences in function arguments:
2687 ** one parameter sets something used by another parameter
2688 ** one parameter sets something set by another parameter
2692 checkSequencingOne (exprNode f, exprNodeList args,
2693 /*@notnull@*/ exprNode el, int argno)
2696 ** Do second loop, iff +undefunspec
2700 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2702 for (checkloop = 0; checkloop < numloops; checkloop++)
2708 thissets = el->sets;
2712 llassert (checkloop == 1);
2713 thissets = el->msets;
2716 sRefSet_realElements (thissets, thisset)
2720 /*@access exprNodeList@*/
2721 for (j = 0; j < args->nelements; j++)
2723 exprNode jl = args->elements[j];
2724 int thisargno = j + 1;
2726 if (thisargno != argno && exprNode_isDefined (jl))
2728 sRefSet otheruses = jl->uses;
2730 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
2731 sRefSet_hasUnconstrained (thissets))
2734 (FLG_EVALORDERUNCON,
2737 ("%q used in argument %d may set "
2738 "global variable %q used by argument %d: %s(%q)",
2739 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2742 sRef_unparse (sRef_getRootBase (jl->sref)),
2744 exprNode_unparse (f), exprNodeList_unparse (args)),
2748 if (sRefSet_member (otheruses, thisset))
2750 if (sRef_isUnconstrained (thisset))
2753 (FLG_EVALORDERUNCON,
2755 ("Unconstrained functions used in arguments %d (%q) "
2756 "and %d (%s) may modify "
2757 "or use global state in undefined way: %s(%q)",
2759 sRefSet_unparseUnconstrainedPlain (otheruses),
2761 sRef_unconstrainedName (thisset),
2762 exprNode_unparse (f),
2763 exprNodeList_unparse (args)),
2771 ("Argument %d modifies %q, used by argument %d "
2772 "(order of evaluation of actual parameters is "
2773 "undefined): %s(%q)",
2774 argno, sRef_unparse (thisset), thisargno,
2775 exprNode_unparse (f), exprNodeList_unparse (args)),
2781 sRefSet othersets = jl->sets;
2783 if (sRefSet_member (othersets, thisset))
2785 if (sRef_isUnconstrained (thisset))
2788 (FLG_EVALORDERUNCON,
2790 ("Unconstrained functions used in "
2791 "arguments %d (%q) and %d (%s) may modify "
2792 "or use global state in undefined way: %s(%q)",
2794 sRefSet_unparseUnconstrainedPlain (othersets),
2796 sRef_unconstrainedName (thisset),
2797 exprNode_unparse (f), exprNodeList_unparse (args)),
2805 ("Argument %d modifies %q, set by argument %d (order of"
2806 " evaluation of actual parameters is undefined): %s(%q)",
2807 argno, sRef_unparse (thisset), thisargno,
2808 exprNode_unparse (f), exprNodeList_unparse (args)),
2815 /*@noaccess exprNodeList@*/
2816 } end_sRefSet_realElements;
2821 checkSequencing (exprNode f, exprNodeList args)
2823 if (exprNodeList_size (args) > 1)
2828 /*@access exprNodeList*/
2830 for (i = 0; i < args->nelements; i++)
2832 el = args->elements[i];
2834 if (!exprNode_isError (el))
2836 checkSequencingOne (f, args, el, i + 1);
2839 /*@noaccess exprNodeList*/
2844 ** requires le = exprNode_getUentry (f)
2848 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2849 uentry le, exprNodeList args,
2850 /*@notnull@*/ exprNode ret, int specialArgs)
2852 bool isSpec = FALSE;
2853 bool hasMods = FALSE;
2855 globSet usesGlobs = globSet_undefined;
2856 sRefSet mods = sRefSet_undefined;
2857 bool freshMods = FALSE;
2858 uentryList params = uentryList_undefined;
2860 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2863 ** check globals and modifies
2868 if (!uentry_isValid (le))
2870 ctype fr = ctype_realType (f->typ);
2872 if (ctype_isFunction (fr))
2874 params = ctype_argsFunction (fr);
2878 params = uentryList_missingParams;
2881 if (!context_getFlag (FLG_MODNOMODS)
2882 && !context_getFlag (FLG_GLOBUNSPEC))
2884 checkUnspecCall (f, params, args);
2890 fname = uentry_rawName (le);
2894 if (uentry_isFunction (le))
2896 params = uentry_getParams (le);
2897 mods = uentry_getMods (le);
2898 hasMods = uentry_hasMods (le);
2899 usesGlobs = uentry_getGlobs (le);
2900 isSpec = uentry_isSpecified (le);
2902 else /* not a function */
2904 ctype ct = ctype_realType (uentry_getType (le));
2906 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2907 ("checkModGlobs: uentry not a function: %s",
2908 uentry_unparse (le)));
2910 params = ctype_argsFunction (ct);
2911 return; /*@32 ! remove this? */
2920 globSet_allElements (usesGlobs, el)
2922 if (sRef_isValid (el))
2924 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2926 context_usedGlobal (el);
2927 exprNode_checkUse (f, el, f->loc);
2929 if (context_checkInternalUse ())
2931 if (!context_globAccess (el))
2933 if (sRef_isSystemState (el)
2934 && !context_getFlag (FLG_MODFILESYSTEM))
2943 ("Called procedure %s may access %q, but "
2944 "globals list does not include globals %s",
2945 exprNode_unparse (f),
2947 cstring_makeLiteralTemp (sRef_isInternalState (el)
2955 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2961 uentry gle = sRef_getUentry (el);
2962 sRef sr = sRef_updateSref (el);
2964 if (sRef_isUndefGlob (el))
2966 sRef_setDefined (sr, f->loc);
2967 exprNode_checkSet (f, sr);
2975 if (sRef_isAllocated (el))
2977 exprNode_checkSet (f, sr);
2981 if (sRef_isStateUndefined (sr))
2986 ("%s %q used by function undefined before call: %s",
2987 sRef_getScopeName (sr),
2989 exprNode_unparse (f)),
2991 sRef_setDefined (sr, f->loc);
2993 exprNode_checkUse (f, sr, f->loc);
2996 checkGlobUse (gle, TRUE, f);
2999 if (sRef_isKilledGlob (el))
3001 sRef_kill (sr, f->loc);
3002 context_usedGlobal (sr);
3006 } end_globSet_allElements;
3012 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
3014 sRefSet smods = sRefSet_undefined;
3017 ** NEED to check for modifies anything
3021 ** check each sRef that called function modifies (ml), is
3027 sRefSet_allElements (mods, s) /* s is something which may be modified */
3029 DPRINTF (("Check modify: %s", sRef_unparse (s)));
3031 if (sRef_isKindSpecial (s))
3033 if (sRef_isSpecInternalState (s))
3035 if (context_getFlag (FLG_MODINTERNALSTRICT))
3037 exprNode_checkCallModifyVal (s, args, f, ret);
3041 sRefSet mmods = context_modList ();
3043 sRefSet_allElements (mmods, el)
3045 if (sRef_isInternalState (el))
3047 sRef_setModified (el);
3049 } end_sRefSet_allElements ;
3054 exprNode_checkCallModifyVal (s, args, f, ret);
3059 sRef rb = sRef_getRootBase (s);
3061 if (sRef_isFileOrGlobalScope (rb))
3063 context_usedGlobal (rb);
3066 if (sRef_isFileStatic (s)
3067 && !fileId_equal (fileloc_fileId (f->loc),
3068 fileloc_fileId (uentry_whereDefined (le))))
3070 smods = sRefSet_insert (smods, s);
3074 exprNode_checkCallModifyVal (s, args, f, ret);
3077 } end_sRefSet_allElements;
3082 ** Static elements in modifies set can have nasty consequences.
3083 ** (I think...have not been able to reproduce a possible bug.)
3086 if (!sRefSet_isDefined (smods))
3088 mods = sRefSet_newCopy (mods);
3091 sRefSet_allElements (smods, el)
3093 bool res = sRefSet_delete (mods, el);
3096 } end_sRefSet_allElements;
3098 sRefSet_free (smods);
3103 else if (sRefSet_isDefined (mods))
3104 { /* just check observers */
3107 sRefSet_allElements (mods, s) /* s is something which may be modified */
3109 sRef rb = sRef_getRootBase (s);
3113 if (sRef_isParam (rb))
3115 sRef b = sRef_fixBaseParam (s, args);
3117 if (sRef_isObserver (b))
3119 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
3123 message ("Function call may modify observer%q: %s",
3124 sRef_unparsePreOpt (b), exprNode_unparse (e)),
3127 sRef_showExpInfo (b);
3131 } end_sRefSet_allElements;
3135 if (!hasMods) /* no specified modifications */
3137 if (context_getFlag (FLG_MODOBSERVERUNCON))
3139 exprNodeList_elements (args, e)
3141 if (exprNode_isDefined (e))
3143 sRef s = exprNode_getSref (e);
3145 if (sRef_isObserver (s)
3146 && ctype_isMutable (sRef_getType (s)))
3149 (FLG_MODOBSERVERUNCON,
3151 ("Call to unconstrained function %s may modify observer%q: %s",
3152 exprNode_unparse (f),
3153 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3156 sRef_showExpInfo (s);
3160 } end_exprNodeList_elements;
3165 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3167 ret->uses = sRefSet_union (ret->uses, f->uses);
3168 ret->sets = sRefSet_union (ret->sets, f->sets);
3169 ret->msets = sRefSet_union (ret->msets, f->msets);
3174 ** Spurious errors reported, because splint can't tell
3175 ** mods must be fresh if freshMods is true.
3178 /*@i@*/ sRefSet_free (mods);
3184 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3186 if (uentry_isVar (glob))
3188 if (context_inFunctionLike ())
3190 sRef sr = uentry_getSref (glob);
3192 context_usedGlobal (sr);
3194 if (context_checkGlobUse (glob))
3196 if (!context_globAccess (sr))
3202 message ("Called procedure %s may access %s %q",
3203 exprNode_unparse (e),
3204 sRef_unparseScope (sr),
3205 uentry_getName (glob)),
3212 message ("Undocumented use of %s %s",
3213 sRef_unparseScope (sr),
3214 exprNode_unparse (e)),
3223 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3228 reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
3230 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3231 exprNode_unparse (f), exprNodeList_unparse (args),
3232 uentry_unparseFull (le),
3233 stateClauseList_unparse (uentry_getStateClauseList (le))));
3235 if (uentry_isValid (le) && uentry_isFunction (le))
3237 stateClauseList sclauses = uentry_getStateClauseList (le);
3239 if (stateClauseList_isDefined (sclauses))
3241 DPRINTF (("Reflect ensures: %s / %s / %s",
3242 uentry_unparse (le),
3243 exprNode_unparse (f), exprNodeList_unparse (args)));
3245 stateClauseList_elements (sclauses, cl)
3247 if (stateClause_hasEnsures (cl))
3249 /* Same in usymtab.c:1904 */
3250 if (stateClause_setsMetaState (cl))
3252 qual q = stateClause_getMetaQual (cl);
3253 annotationInfo ainfo = qual_getAnnotationInfo (q);
3254 metaStateInfo minfo = annotationInfo_getState (ainfo);
3255 cstring key = metaStateInfo_getName (minfo);
3256 int mvalue = annotationInfo_getValue (ainfo);
3258 sRefSet osrs = sRefSet_undefined;
3261 if (stateClause_isGlobal (cl))
3263 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3268 srs = stateClause_getRefs (cl);
3271 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3274 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3276 sRefSet_elements (srs, sel)
3280 if (sRef_isResult (sRef_getRootBase (sel)))
3282 s = exprNode_getSref (ret);
3286 s = sRef_fixBaseParam (sel, args);
3289 DPRINTF (("Reflecting state clause on: %s / %s",
3290 sRef_unparse (sel), sRef_unparse (s)));
3292 sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3293 } end_sRefSet_elements;
3295 sRefSet_free (osrs);
3299 sRefSet srs = stateClause_getRefs (cl);
3300 sRefModVal modf = stateClause_getEnsuresFunction (cl);
3301 int eparam = stateClause_getStateParameter (cl);
3303 DPRINTF (("Reflect after clause: %s / %s",
3304 stateClause_unparse (cl),
3305 sRefSet_unparse (srs)));
3307 sRefSet_elements (srs, sel)
3311 DPRINTF (("elements: %s", sRef_unparse (sel)));
3312 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3314 if (sRef_isResult (sRef_getRootBase (sel)))
3316 DPRINTF (("Fix base: %s / %s",
3317 sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
3318 s = sRef_fixBase (sel, exprNode_getSref (ret));
3319 DPRINTF (("==> %s", sRef_unparseFull (s)));
3323 s = sRef_fixBaseParam (sel, args);
3326 DPRINTF (("elements: %s", sRef_unparse (s)));
3327 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3329 DPRINTF (("Reflecting state clause on: %s / %s",
3330 sRef_unparseFull (sel), sRef_unparseFull (s)));
3332 /* evans 2001-08-24 - added aliasSetCompleteParam */
3333 sRef_aliasSetCompleteParam (modf, s, eparam, exprNode_loc (f));
3335 DPRINTF (("After reflecting state clause on: %s / %s",
3336 sRef_unparseFull (sel), sRef_unparseFull (s)));
3337 } end_sRefSet_elements;
3340 } end_stateClauseList_elements ;
3343 DPRINTF (("Here: %s / %s",
3344 uentry_unparseFull (le),
3345 bool_unparse (uentry_hasMetaStateEnsures (le))));
3347 if (uentry_hasMetaStateEnsures (le))
3349 fileloc loc = exprNode_loc (f);
3351 metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3353 metaStateConstraintList_elements (mscl, msc)
3355 metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3356 metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3357 metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
3358 cstring key = metaStateInfo_getName (msinfo);
3359 sRef mlsr = metaStateSpecifier_getSref (msspec);
3361 sRef lastref = sRef_undefined;
3362 stateValue sval = stateValue_undefined;
3364 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3365 metaStateConstraint_unparse (msc)));
3366 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3368 if (sRef_isResult (sRef_getRootBase (mlsr)))
3370 s = exprNode_getSref (ret);
3374 s = sRef_fixBaseParam (mlsr, args);
3377 DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3379 while (metaStateExpression_isDefined (msexpr))
3381 metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
3382 metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
3385 DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3387 if (metaStateExpression_isMerge (msexpr))
3389 msexpr = metaStateExpression_getRest (msexpr);
3393 msexpr = metaStateExpression_undefined;
3396 if (metaStateInfo_isDefined (msi))
3398 /* Must match lhs state */
3399 llassert (metaStateInfo_equal (msinfo, msi));
3402 if (metaStateSpecifier_isElipsis (ms))
3405 ** For elipsis, we need to merge all the relevant elipsis parameters
3409 uentryList params = uentry_getParams (le);
3410 int paramno = uentryList_size (params) - 1;
3412 if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
3416 message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3417 uentry_getName (le)),
3418 uentry_whereLast (le));
3419 /*@innerbreak@*/ break;
3422 while (paramno < exprNodeList_size (args))
3424 exprNode arg = exprNodeList_getN (args, paramno);
3425 fs = exprNode_getSref (arg);
3426 DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3428 /* cut and pasted... gack*/
3429 if (stateValue_isDefined (sval))
3431 /* Use combination table to merge old state value with new one: */
3432 stateValue tval = sRef_getMetaStateValue (fs, key);
3434 if (stateValue_isDefined (tval))
3436 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3437 cstring msg = cstring_undefined;
3438 int nval = stateCombinationTable_lookup (sctable,
3439 stateValue_getValue (sval),
3440 stateValue_getValue (tval),
3442 DPRINTF (("Combining: %s + %s -> %d",
3443 stateValue_unparseValue (sval, msinfo),
3444 stateValue_unparseValue (tval, msinfo),
3447 if (nval == stateValue_error)
3452 ("Attributes merged in ensures clause in states that "
3453 "cannot be combined (%q is %q, %q is %q)%q",
3454 sRef_unparse (lastref),
3455 stateValue_unparseValue (sval, msinfo),
3457 stateValue_unparseValue (tval, msinfo),
3458 cstring_isDefined (msg) ?
3459 message (": %s", msg) : cstring_undefined),
3462 sRef_showMetaStateInfo (fs, key);
3466 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3467 loc = exprNode_loc (arg);
3471 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3476 sval = sRef_getMetaStateValue (fs, key);
3481 if (stateValue_isError (sval))
3483 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3492 msr = metaStateSpecifier_getSref (ms);
3495 llassert (sRef_isParam (sRef_getRootBase (msr)));
3496 fs = sRef_fixBaseParam (msr, args);
3498 if (stateValue_isDefined (sval))
3500 /* Use combination table to merge old state value with new one: */
3501 stateValue tval = sRef_getMetaStateValue (fs, key);
3503 if (stateValue_isDefined (tval))
3505 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3506 cstring msg = cstring_undefined;
3507 int nval = stateCombinationTable_lookup (sctable,
3508 stateValue_getValue (sval),
3509 stateValue_getValue (tval),
3511 DPRINTF (("Combining: %s + %s -> %d",
3512 stateValue_unparseValue (sval, msinfo),
3513 stateValue_unparseValue (tval, msinfo),
3516 if (nval == stateValue_error)
3521 ("Attributes merged in ensures clause in states that "
3522 "cannot be combined (%q is %q, %q is %q)%q",
3523 sRef_unparse (lastref),
3524 stateValue_unparseValue (sval, msinfo),
3526 stateValue_unparseValue (tval, msinfo),
3527 cstring_isDefined (msg)
3528 ? message (": %s", msg) : cstring_undefined),
3531 sRef_showMetaStateInfo (fs, key);
3535 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3539 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3544 sval = sRef_getMetaStateValue (fs, key);
3549 if (stateValue_isError (sval))
3551 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3556 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3558 if (stateValue_isDefined (sval))
3560 sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
3564 DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
3566 } end_metaStateConstraintList_elements ;
3568 metaStateConstraintList_free (mscl);
3574 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3576 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3577 exprNode_unparse (f), exprNodeList_unparse (args),
3578 uentry_unparseFull (le),
3579 stateClauseList_unparse (uentry_getStateClauseList (le))));
3581 if (uentry_isValid (le) && uentry_isFunction (le))
3583 stateClauseList sclauses = uentry_getStateClauseList (le);
3585 if (stateClauseList_isDefined (sclauses))
3587 DPRINTF (("Check requires: %s / %s / %s",
3588 uentry_unparse (le),
3589 exprNode_unparse (f), exprNodeList_unparse (args)));
3591 stateClauseList_elements (sclauses, cl)
3593 DPRINTF (("Check clause: %s / %s",
3594 stateClause_unparse (cl),
3595 bool_unparse (stateClause_hasRequires (cl))));
3597 if (stateClause_hasRequires (cl))
3599 sRefSet osrs = sRefSet_undefined;
3602 if (stateClause_isGlobal (cl))
3604 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3609 srs = stateClause_getRefs (cl);
3612 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3614 if (stateClause_setsMetaState (cl))
3616 qual q = stateClause_getMetaQual (cl);
3617 annotationInfo ainfo = qual_getAnnotationInfo (q);
3618 metaStateInfo minfo = annotationInfo_getState (ainfo);
3619 cstring key = metaStateInfo_getName (minfo);
3620 int mvalue = annotationInfo_getValue (ainfo);
3622 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3624 sRefSet_elements (srs, sel)
3626 sRef s = sRef_fixBaseParam (sel, args);
3628 if (sRef_isResult (sRef_getRootBase (sel)))
3634 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3635 sRef_unparseFull (sel), sRef_unparseFull (s),
3638 if (!sRef_checkMetaStateValue (s, key, mvalue))
3640 DPRINTF (("HERE: %s", sRef_unparse (s)));
3644 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3645 uentry_getName (le),
3646 sRef_isGlobalMarker (s)
3648 : message (" by %q", sRef_unparse (s)),
3649 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3651 stateClause_unparse (cl)),
3654 sRef_showAliasInfo (s);
3658 DPRINTF (("Error supressed!"));
3659 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3660 DPRINTF (("Context supress: %s",
3661 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3665 } end_sRefSet_elements;
3669 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3670 int eparam = stateClause_getStateParameter (cl);
3672 DPRINTF (("Reflect after clause: %s / %s",
3673 stateClause_unparse (cl),
3674 sRefSet_unparse (srs)));
3676 sRefSet_elements (srs, sel)
3680 DPRINTF (("elements: %s", sRef_unparse (sel)));
3681 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3683 s = sRef_fixBaseParam (sel, args);
3685 DPRINTF (("elements: %s", sRef_unparse (s)));
3686 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3688 if (sRef_isResult (sRef_getRootBase (sel)))
3690 ; /*@i423 what do we do about results */
3694 DPRINTF (("Reflecting state clause on: %s / %s",
3695 sRef_unparse (sel), sRef_unparse (s)));
3697 modf (s, eparam, exprNode_loc (f));
3699 } end_sRefSet_elements;
3702 sRefSet_free (osrs);
3704 } end_stateClauseList_elements ;
3709 static /*@only@*/ exprNode
3710 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3711 ctype t, /*@keep@*/ exprNodeList args)
3713 /* requires f is a non-error exprNode, with type function */
3714 cstring fname = exprNode_unparse (f);
3715 uentry le = exprNode_getUentry (f);
3716 exprNode ret = exprNode_createPartialCopy (f);
3721 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3723 ret->typ = ctype_getReturnType (t);
3724 ret->kind = XPR_CALL;
3726 ret->edata = exprData_makeCall (f, args);
3729 ** Order of these steps is very important!
3731 ** Must check for argument dependencies before messing up uses and sets.
3734 if (context_getFlag (FLG_EVALORDER))
3736 exprNodeList_elements (args, current)
3738 if (exprNode_isDefined (current))
3740 exprNode_addUse (current, current->sref);
3742 } end_exprNodeList_elements;
3744 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3746 checkSequencing (f, args);
3749 exprNodeList_elements (args, current)
3751 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3753 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3755 } end_exprNodeList_elements ;
3758 special = checkArgs (le, f, t, args, ret);
3759 checkGlobMods (f, le, args, ret, special);
3760 checkRequiresClause (le, f, args);
3763 if (uentry_isValid (le)
3764 && (uentry_isFunction (le)
3765 || (uentry_isVariable (le)
3766 && ctype_isFunction (uentry_getType (le)))))
3768 exitkind exk = uentry_getExitCode (le);
3770 /* f->typ is already set to the return type */
3772 DPRINTF (("Function: %s", uentry_unparseFull (le)));
3773 ret->sref = uentry_returnedRef (le, args);
3774 DPRINTF (("Returned: %s / %s",
3775 uentry_unparseFull (le),
3776 sRef_unparseFull (ret->sref)));
3778 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3780 qual nullPred = uentry_nullPred (le);
3782 if (qual_isTrueNull (nullPred))
3784 exprNode arg = exprNodeList_head (args);
3786 if (exprNode_isDefined (arg))
3788 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3791 else if (qual_isFalseNull (nullPred))
3793 exprNode arg = exprNodeList_head (args);
3795 if (exprNode_isDefined (arg))
3797 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3802 llassert (qual_isUnknown (nullPred));
3806 if (exitkind_isConditionalExit (exk))
3810 ** if (arg0) then { exit! } else { ; }
3812 ** if (arg0) then { ; } else { exit! }
3817 llassert (!exprNodeList_isEmpty (args));
3818 firstArg = exprNodeList_head (args);
3820 if (exprNode_isDefined (firstArg)
3821 && !guardSet_isEmpty (firstArg->guards))
3823 usymtab_trueBranch (guardSet_undefined);
3824 usymtab_altBranch (guardSet_undefined);
3826 if (exitkind_isTrueExit (exk))
3828 usymtab_popBranches (firstArg,
3829 exprNode_makeMustExit (),
3831 TRUE, TRUEEXITCLAUSE);
3835 usymtab_popBranches (firstArg,
3837 exprNode_makeMustExit (),
3838 TRUE, FALSEEXITCLAUSE);
3842 ret->exitCode = XK_MAYEXIT;
3844 else if (exitkind_mustExit (exk))
3846 ret->exitCode = XK_MUSTEXIT;
3848 else if (exitkind_couldExit (exk))
3850 ret->exitCode = XK_MAYEXIT;
3857 if (cstring_equalLit (fname, "exit"))
3859 if (exprNodeList_size (args) == 1)
3861 exprNode arg = exprNodeList_head (args);
3863 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3865 long int val = multiVal_forceInt (exprNode_getValue (arg));
3872 ("Argument to exit has implementation defined behavior: %s",
3873 exprNode_unparse (arg)),
3874 exprNode_loc (arg));
3883 exprNode_checkSetAny (ret, uentry_rawName (le));
3886 DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3887 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3888 reflectEnsuresClause (ret, le, f, args);
3895 ** this is yucky! should keep the uentry as part of exprNode!
3898 uentry exprNode_getUentry (exprNode e)
3900 if (exprNode_isError (e))
3902 return uentry_undefined;
3906 cstring s = exprNode_rootVarName (e);
3907 uentry ue = usymtab_lookupSafe (s);
3914 ** Returns true iff e1 and e2 are both exactly the same storage
3918 static bool exprNode_sameStorage (exprNode e1, exprNode e2)
3920 sRef s1 = exprNode_getSref (e1);
3921 sRef s2 = exprNode_getSref (e2);
3923 return (sRef_realSame (s1, s2));
3927 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3929 exprNode ret = exprNode_createPlain (ctype_unknown);
3931 ret->kind = XPR_INITBLOCK;
3932 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3933 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3939 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3945 if (exprNode_isUndefined (f))
3948 exprNodeList_free (args);
3949 return exprNode_undefined;
3952 t = exprNode_getType (f);
3954 if (sRef_isLocalVar (f->sref))
3956 exprNode_checkUse (f, f->sref, f->loc);
3958 if (sRef_possiblyNull (f->sref))
3960 if (!usymtab_isGuarded (f->sref))
3962 if (optgenerror (FLG_NULLDEREF,
3963 message ("Function call using %s pointer %q",
3964 sRef_nullMessage (f->sref),
3965 sRef_unparse (f->sref)),
3968 sRef_showNullInfo (f->sref);
3969 sRef_setNullError (f->sref);
3977 if (ctype_isRealFunction (t))
3979 exprNode ret = functionCallSafe (f, t, args);
3983 else if (ctype_isUnknown (t))
3985 exprNode ret = exprNode_createPartialCopy (f);
3991 exprNodeList_elements (args, current)
3993 if (exprNode_isDefined (current))
3995 exprNode_checkUse (ret, current->sref, ret->loc);
3998 ** also, anything derivable from current->sref may be used
4001 exprNode_addUse (ret, sRef_makeDerived (current->sref));
4002 exprNode_mergeUSs (ret, current);
4004 } end_exprNodeList_elements;
4006 ret->edata = exprData_makeCall (f, args);
4007 ret->kind = XPR_CALL;
4009 tstring = cstring_copy (exprNode_unparse (f));
4011 cstring_markOwned (tstring);
4012 exprNode_checkSetAny (ret, tstring);
4018 voptgenerror (FLG_TYPE,
4019 message ("Call to non-function (type %t): %s", t,
4020 exprNode_unparse (f)),
4023 exprNodeList_free (args);
4025 return (exprNode_makeError ());
4030 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4031 /*@only@*/ cstring f)
4033 exprNode ret = exprNode_createPartialCopy (s);
4035 ret->kind = XPR_FACCESS;
4037 if (exprNode_isError (s))
4039 ret->edata = exprData_makeField (s, f);
4044 ctype t = exprNode_getType (s);
4045 ctype tr = ctype_realType (t);
4047 checkMacroParen (s);
4049 ret->edata = exprData_makeField (s, f);
4051 if (ctype_isStructorUnion (tr))
4053 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
4055 if (uentry_isUndefined (tf))
4057 voptgenerror (FLG_TYPE,
4058 message ("Access non-existent field %s of %t: %s", f, t,
4059 exprNode_unparse (ret)),
4061 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
4066 uentry_setUsed (tf, exprNode_loc (ret));
4068 ret->typ = uentry_getType (tf);
4069 checkSafeUse (ret, s->sref);
4071 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
4072 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
4076 else /* isStructorUnion */
4078 if (ctype_isRealAbstract (tr))
4082 message ("Access field of abstract type (%t): %s.%s",
4083 t, exprNode_unparse (s), f),
4085 ret->typ = ctype_unknown;
4089 if (ctype_isKnown (tr))
4094 ("Access field of non-struct or union (%t): %s.%s",
4095 t, exprNode_unparse (s), f),
4098 ret->typ = ctype_unknown;
4102 cstring sn = cstring_copy (f);
4104 checkSafeUse (ret, s->sref);
4105 cstring_markOwned (sn);
4106 ret->sref = sRef_makeField (s->sref, sn);
4118 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
4119 /*@only@*/ cstring f)
4121 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
4122 lltok_release (dot);
4127 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
4129 exprNode ret = exprNode_createPartialCopy (e);
4131 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
4132 ret->kind = XPR_PARENS;
4133 ret->edata = exprData_makeUop (e, lpar);
4135 if (!exprNode_isError (e))
4137 ret->exitCode = e->exitCode;
4138 ret->canBreak = e->canBreak;
4139 ret->mustBreak = e->mustBreak;
4140 ret->isJumpPoint = e->isJumpPoint;
4141 ret->sref = e->sref;
4148 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4149 /*@only@*/ cstring f)
4151 exprNode ret = exprNode_createPartialCopy (s);
4153 ret->edata = exprData_makeField (s, f);
4154 ret->kind = XPR_ARROW;
4156 if (exprNode_isError (s))
4162 ctype t = exprNode_getType (s);
4163 ctype tr = ctype_realType (t);
4165 checkMacroParen (s);
4167 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4169 if (ctype_isRealPointer (tr))
4171 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4173 if (ctype_isStructorUnion (b))
4175 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4177 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4179 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4183 message ("Arrow access from %s pointer%q: %s",
4184 sRef_nullMessage (s->sref),
4185 sRef_unparsePreOpt (s->sref),
4186 exprNode_unparse (ret)),
4189 sRef_showNullInfo (s->sref);
4190 sRef_setNullError (s->sref);
4195 if (uentry_isUndefined (fentry))
4199 message ("Access non-existent field %s of %t: %s",
4200 f, t, exprNode_unparse (ret)),
4202 ret->typ = ctype_unknown;
4208 ** was safeUse: shouldn't be safe!
4211 ** rec must be defined,
4212 ** *rec must be allocated
4213 ** rec->field need only be defined it if is an rvalue
4216 uentry_setUsed (fentry, exprNode_loc (ret));
4217 ret->typ = uentry_getType (fentry);
4219 exprNode_checkUse (ret, s->sref, s->loc);
4221 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4222 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4226 else /* Pointer to something that is not a struct or union*/
4228 if (ctype_isRealAbstract (tr))
4230 ctype xrt = ctype_forceRealType (tr);
4234 message ("Arrow access field of abstract type (%t): %s->%s",
4235 t, exprNode_unparse (s), f),
4239 ** Set the state correctly, as if the abstraction is broken.
4242 if (ctype_isRealPointer (xrt) &&
4243 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4244 ctype_isStructorUnion (b)))
4246 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4247 ret->typ = uentry_getType (fentry);
4248 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4252 ret->typ = ctype_unknown;
4253 ret->sref = sRef_undefined;
4256 else /* not a struct, union or abstract */
4258 if (ctype_isUnknown (tr)) {
4259 cstring sn = cstring_copy (f);
4261 DPRINTF (("Here: %s", exprNode_unparse (s)));
4263 exprNode_checkUse (ret, s->sref, s->loc);
4264 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4266 cstring_markOwned (sn);
4267 ret->sref = sRef_makeArrow (s->sref, sn);
4269 ret->kind = XPR_ARROW;
4274 message ("Arrow access field of non-struct or union "
4275 "pointer (%t): %s->%s",
4276 t, exprNode_unparse (s), f),
4279 ret->typ = ctype_unknown;
4280 ret->sref = sRef_undefined;
4285 else /* its not a pointer */
4287 if (!ctype_isUnknown (tr))
4291 message ("Arrow access of non-pointer (%t): %s->%s",
4292 t, exprNode_unparse (s), f),
4295 ret->typ = ctype_unknown;
4296 ret->sref = sRef_undefined;
4300 cstring sn = cstring_copy (f);
4302 DPRINTF (("Here: %s", exprNode_unparse (s)));
4304 exprNode_checkUse (ret, s->sref, s->loc);
4305 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4307 cstring_markOwned (sn);
4308 ret->sref = sRef_makeArrow (s->sref, sn);
4310 ret->kind = XPR_ARROW;
4321 exprNode_arrowAccess (/*@only@*/ exprNode s,
4322 /*@only@*/ lltok arrow,
4323 /*@only@*/ cstring f)
4325 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4326 lltok_release (arrow);
4331 ** only postOp's in C: i++ and i--
4335 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4337 /* check modification also */
4338 /* cstring opname = lltok_unparse (op);*/
4340 exprNode ret = exprNode_createPartialCopy (e);
4342 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4343 ret->kind = XPR_POSTOP;
4344 ret->edata = exprData_makeUop (e, op);
4346 if (!exprNode_isDefined (e))
4351 checkMacroParen (e);
4353 exprNode_checkUse (ret, e->sref, e->loc);
4354 exprNode_checkSet (ret, e->sref);
4356 t = exprNode_getType (e);
4358 if (sRef_isUnsafe (e->sref))
4360 voptgenerror (FLG_MACROPARAMS,
4361 message ("Operand of %s is macro parameter (non-functional): %s%s",
4362 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4364 sRef_makeSafe (e->sref);
4365 sRef_makeSafe (ret->sref);
4368 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4374 if (ctype_isRealAbstract (t))
4378 message ("Operand of %s is abstract type (%t): %s",
4379 lltok_unparse (op), t, exprNode_unparse (e)),
4386 message ("Operand of %s is non-numeric (%t): %s",
4387 lltok_unparse (op), t, exprNode_unparse (e)),
4390 ret->typ = ctype_unknown;
4393 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4395 exprNode_checkModify (e, ret);
4397 /* added 7/11/2000 D.L */
4399 /*DRL 6/8/01 I decided to disable all Splint warnings here since the code
4400 probably needs a rewrite any way */
4405 /* updateEnvironmentForPostOp (e); */
4407 /* start modifications */
4408 /* added by Seejo on 4/16/2000 */
4410 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4412 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4414 ret->sref = sRef_copy (e->sref);
4417 if (lltok_getTok (op) == INC_OP) {
4418 if (sRef_getSize(e->sref) > 0) {
4420 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4422 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4423 /* Assumption: there is only 1 \0 in the buffer */
4424 /* This will not be correct if there are 2 \0's in the buffer */
4425 sRef_setNotNullTerminatedState(ret->sref);
4426 sRef_resetLen(ret->sref);
4428 sRef_setNullTerminatedState(ret->sref);
4429 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4431 if (sRef_isNullTerminated (ret->sref))
4432 printf ("ret->sref is Null Terminated\n");
4433 else if (sRef_isPossiblyNullTerminated (ret->sref))
4434 printf ("ret->sref is Possibly Null Terminated\n");
4435 else if (sRef_isNotNullTerminated (ret->sref))
4436 printf ("ret->sref is Not Null Terminated\n");
4441 if (lltok_getTok (op) == DEC_OP) {
4442 if (sRef_getSize(e->sref) >= 0) {
4443 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4444 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4449 /* end modifications */
4455 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4457 bool checkMod = FALSE;
4459 int opid = lltok_getTok (op);
4460 exprNode ret = exprNode_createSemiCopy (e);
4462 exprNode_copySets (ret, e);
4464 multiVal_free (ret->val);
4465 ret->val = multiVal_undefined;
4466 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4467 ret->kind = XPR_PREOP;
4468 ret->edata = exprData_makeUop (e, op);
4470 if (exprNode_isError (e))
4475 checkMacroParen (e);
4477 te = exprNode_getType (e);
4478 tr = ctype_realType (te);
4480 if (opid != TAMPERSAND)
4482 exprNode_checkUse (ret, e->sref, e->loc);
4484 if (ctype_isRealAbstract (tr)
4485 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4487 if (optgenerror (FLG_ABSTRACT,
4488 message ("Operand of %s is abstract type (%t): %s",
4489 lltok_unparse (op), tr,
4490 exprNode_unparse (ret)),
4493 tr = te = ctype_unknown;
4494 ret->typ = ctype_unknown;
4495 sRef_setNullError (e->sref);
4503 case DEC_OP: /* should also check modification! */
4504 if (sRef_isMacroParamRef (e->sref))
4508 message ("Operand of %s is macro parameter (non-functional): %s",
4509 lltok_unparse (op), exprNode_unparse (ret)),
4514 exprNode_checkSet (ret, e->sref);
4517 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4522 if (context_msgStrictOps ())
4526 message ("Operand of %s is non-numeric (%t): %s",
4527 lltok_unparse (op), te, exprNode_unparse (ret)),
4530 ret->typ = ctype_int;
4533 /* start modifications */
4534 /* added by Seejo on 4/16/2000 */
4536 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4538 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4540 ret->sref = sRef_copy (e->sref);
4543 if (lltok_getTok (op) == INC_OP) {
4544 if (sRef_getSize(e->sref) > 0) {
4546 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4548 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4549 /* Assumption: there is only 1 \0 in the buffer */
4550 /* This will not be correct if there are 2 \0's in the buffer */
4551 sRef_setNotNullTerminatedState(ret->sref);
4552 sRef_resetLen (ret->sref);
4554 sRef_setNullTerminatedState(ret->sref);
4555 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4561 if (lltok_getTok (op) == DEC_OP) {
4562 if (sRef_getSize(e->sref) >= 0) {
4563 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4564 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4569 /* end modifications */
4576 if (ctype_isForceRealNumeric (&tr))
4580 ret->val = multiVal_invert (exprNode_getValue (e));
4584 ret->val = multiVal_copy (exprNode_getValue (e));
4589 if (context_msgStrictOps ())
4593 message ("Operand of %s is non-numeric (%t): %s",
4594 lltok_unparse (op), te, exprNode_unparse (ret)),
4598 ret->typ = ctype_int;
4602 case TEXCL: /* maybe this should be restricted */
4603 guardSet_flip (ret->guards);
4605 if (ctype_isRealBool (te) || ctype_isUnknown (te))
4611 if (ctype_isRealPointer (tr))
4613 if (sRef_isKnown (e->sref))
4615 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4619 (FLG_BOOLOPS, FLG_PTRNEGATE,
4620 message ("Operand of %s is non-boolean (%t): %s",
4621 lltok_unparse (op), te, exprNode_unparse (ret)),
4628 message ("Operand of %s is non-boolean (%t): %s",
4629 lltok_unparse (op), te, exprNode_unparse (ret)),
4633 ret->typ = ctype_bool;
4638 if (ctype_isForceRealInt (&tr))
4643 if (context_msgStrictOps ())
4647 message ("Operand of %s is non-integer (%t): %s",
4648 lltok_unparse (op), te, exprNode_unparse (ret)),
4652 if (ctype_isInt (e->typ))
4658 ret->typ = ctype_int;
4664 ret->typ = ctype_makePointer (e->typ);
4666 if (sRef_isKnown (e->sref))
4668 ret->sref = sRef_makeAddress (e->sref);
4675 if (ctype_isAP (tr))
4677 ret->typ = ctype_baseArrayPtr (e->typ);
4681 if (ctype_isKnown (te))
4683 if (ctype_isFunction (te))
4689 message ("Dereference of function type (%t): %s",
4690 te, exprNode_unparse (ret)),
4695 voptgenerror (FLG_TYPE,
4696 message ("Dereference of non-pointer (%t): %s",
4697 te, exprNode_unparse (ret)),
4699 ret->typ = ctype_unknown;
4704 ret->typ = ctype_unknown;
4709 if (sRef_isKnown (e->sref))
4711 DPRINTF (("Checking possibly null: %s", sRef_unparseFull (e->sref)));
4713 if (sRef_possiblyNull (e->sref))
4715 DPRINTF (("Checking possibly null: %s", sRef_unparse (e->sref)));
4716 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4720 message ("Dereference of %s pointer %q: %s",
4721 sRef_nullMessage (e->sref),
4722 sRef_unparse (e->sref),
4723 exprNode_unparse (ret)),
4726 sRef_showNullInfo (e->sref);
4727 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4732 ret->sref = sRef_makePointer (e->sref);
4737 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4742 exprNode_checkModify (e, ret);
4749 ** any reason to disallow sizeof (abstract type) ?
4753 ** used by both sizeof
4757 ctype sizeof_resultType (void)
4759 static ctype sizet = ctype_unknown;
4761 if (ctype_isUnknown (sizet))
4763 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4765 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4769 sizet = ctype_ulint;
4776 exprNode_sizeofType (/*@only@*/ qtype qt)
4778 exprNode ret = exprNode_create (sizeof_resultType ());
4779 ctype ct = qtype_getType (qt);
4781 ret->kind = XPR_SIZEOFT;
4782 ret->edata = exprData_makeSizeofType (qt);
4784 voptgenerror (FLG_SIZEOFTYPE,
4785 message ("Parameter to sizeof is type %s: %s",
4787 exprNode_unparse (ret)),
4794 exprNode_alignofType (/*@only@*/ qtype qt)
4796 exprNode ret = exprNode_create (sizeof_resultType ());
4797 ctype ct = qtype_getType (qt);
4799 ret->kind = XPR_ALIGNOFT;
4800 ret->edata = exprData_makeSizeofType (qt);
4802 voptgenerror (FLG_SIZEOFTYPE,
4803 message ("Parameter to alignof is type %s: %s",
4805 exprNode_unparse (ret)),
4811 exprNode exprNode_offsetof (qtype qt, cstringList s)
4813 exprNode ret = exprNode_create (sizeof_resultType ());
4814 ctype ct = qtype_getType (qt);
4816 ret->kind = XPR_OFFSETOF;
4817 ret->edata = exprData_makeOffsetof (qt, s);
4819 if (!ctype_isRealSU (ct))
4821 voptgenerror (FLG_TYPE,
4822 message ("First parameter to offsetof is not a "
4823 "struct or union type (type %s): %s",
4825 exprNode_unparse (ret)),
4832 cstringList_elements (s, el) {
4836 if (ctype_isUndefined (lt))
4840 else if (!ctype_isRealSU (lt))
4842 voptgenerror (FLG_TYPE,
4843 message ("Inner offsetof type is not a "
4844 "struct or union type (type %s before field %s): %s",
4845 ctype_unparse (lt), el,
4846 exprNode_unparse (ret)),
4852 fields = ctype_getFields (ctype_realType (lt));
4853 fld = uentryList_lookupField (fields, el);
4854 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4856 if (uentry_isUndefined (fld))
4858 if (ctype_equal (lt, ct)) {
4859 voptgenerror (FLG_TYPE,
4860 message ("Field %s in offsetof is not the "
4861 "name of a field of %s: %s",
4864 exprNode_unparse (ret)),
4867 voptgenerror (FLG_TYPE,
4868 message ("Deep field %s in offsetof is not the "
4869 "name of a field of %s: %s",
4872 exprNode_unparse (ret)),
4878 lt = uentry_getType (fld);
4881 } end_cstringList_elements;
4883 /* Should report error if its a bit field - behavior is undefined! */
4890 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4894 if (exprNode_isUndefined (e))
4896 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4897 ret->edata = exprData_makeSingle (e);
4898 ret->typ = sizeof_resultType ();
4899 ret->kind = XPR_SIZEOF;
4903 uentry u = exprNode_getUentry (e);
4905 ret = exprNode_createPartialCopy (e);
4906 ret->edata = exprData_makeSingle (e);
4908 ret->typ = sizeof_resultType ();
4909 ret->kind = XPR_SIZEOF;
4911 if (uentry_isValid (u)
4912 && uentry_isRefParam (u)
4913 && ctype_isRealArray (uentry_getType (u)))
4916 (FLG_SIZEOFFORMALARRAY,
4917 message ("Parameter to sizeof is an array-type function parameter: %s",
4918 exprNode_unparse (ret)),
4924 ** sizeof (x) doesn't "really" use x
4931 exprNode_alignofExpr (/*@only@*/ exprNode e)
4935 if (exprNode_isUndefined (e))
4937 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4941 ret = exprNode_createPartialCopy (e);
4944 ret->edata = exprData_makeSingle (e);
4945 ret->typ = sizeof_resultType ();
4946 ret->kind = XPR_ALIGNOF;
4949 ** sizeof (x) doesn't "really" use x
4956 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4962 if (exprNode_isError (e))
4965 lltok_release (tok);
4966 return exprNode_undefined;
4969 checkMacroParen (e);
4971 c = qtype_getType (q);
4972 t = exprNode_getType (e);
4974 ret = exprNode_createPartialCopy (e);
4976 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4978 ret->kind = XPR_CAST;
4979 ret->edata = exprData_makeCast (tok, e, q);
4981 if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
4984 ** This is a bit of a hack to avoid a problem
4985 ** when the code does,
4986 ** (some other struct) x
4991 ret->sref = sRef_copy (e->sref);
4992 usymtab_addForceMustAlias (ret->sref, e->sref);
4993 sRef_setTypeFull (ret->sref, c);
4994 DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
4995 sRef_unparseFull (ret->sref)));
4999 ret->sref = e->sref;
5000 sRef_setTypeFull (ret->sref, c);
5001 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
5008 ** void * <-> abstract * (if FLG_ABSTVOIDP)
5009 ** abstract * <-> void * (if FLG_ABSTVOIDP)
5012 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
5016 else if (ctype_isRealAP (c)) /* casting to array or pointer */
5018 ctype bc = ctype_getBaseType (c);
5019 ctype bt = ctype_getBaseType (t);
5020 ctype rt = ctype_realType (t);
5022 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
5023 && (ctype_isArrayPtr (rt)
5024 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5028 message ("Cast from function pointer type (%t) to "
5029 "non-function pointer (%t): %s",
5030 c, t, exprNode_unparse (ret)),
5034 if (!ctype_isFunction (ctype_baseArrayPtr (c))
5035 && (ctype_isArrayPtr (rt)
5036 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5040 message ("Cast from non-function pointer type (%t) to "
5041 "function pointer (%t): %s",
5042 c, t, exprNode_unparse (ret)),
5046 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
5047 !(ctype_isRealAbstract (bc)
5048 && context_hasAccess (ctype_typeId (bc))))
5050 ; /* okay to cast zero */
5054 if (ctype_isRealAbstract (bc)
5055 && !context_hasAccess (ctype_typeId (bc)))
5057 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
5061 message ("Cast to underlying abstract type %t: %s",
5062 c, exprNode_unparse (ret)),
5069 message ("Cast to underlying abstract type %t: %s",
5070 c, exprNode_unparse (ret)),
5075 if (ctype_isRealAbstract (bt)
5076 && !context_hasAccess (ctype_typeId (bt)))
5078 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
5082 message ("Cast from underlying abstract type %t: %s",
5083 t, exprNode_unparse (ret)),
5090 message ("Cast from underlying abstract type %t: %s",
5091 t, exprNode_unparse (ret)),
5099 ctype bt = ctype_realType (ctype_getBaseType (t));
5100 ctype bc = ctype_realType (ctype_getBaseType (c));
5102 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
5104 if (ctype_match (c, t))
5106 if (ctype_equal (c, t))
5110 message ("Redundant cast involving abstract type %t: %s",
5111 bt, exprNode_unparse (ret)),
5119 message ("Cast from abstract type %t: %s",
5120 bt, exprNode_unparse (ret)),
5125 if (ctype_isAbstract (bc)
5126 && !context_hasAccess (ctype_typeId (bc)))
5128 if (ctype_match (c, t))
5134 DPRINTF (("No access to: %s / %d",
5135 ctype_unparse (bc), ctype_typeId (bc)));
5136 DPRINTF (("Context %s %s",
5137 bool_unparse (context_inFunctionLike ()),
5138 context_unparse ()));
5141 message ("Cast to abstract type %t: %s", bc,
5142 exprNode_unparse (ret)),
5148 if (ctype_isAbstract (c))
5150 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
5152 /* okay, cast exposed to abstract */
5153 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
5157 if (ctype_isVisiblySharable (t)
5158 && sRef_isExternallyVisible (e->sref)
5159 && !(ctype_isAbstract (t)
5160 && context_hasAccess (ctype_typeId (t))))
5164 message ("Cast to abstract type from externally visible "
5165 "mutable storage exposes rep of %s: %s",
5167 exprNode_unparse (e)),
5177 evaluationOrderUndefined (lltok op)
5179 int opid = lltok_getTok (op);
5181 return (opid != AND_OP && opid != OR_OP);
5184 static bool checkIntegral (/*@notnull@*/ exprNode e1,
5185 /*@notnull@*/ exprNode e2,
5186 /*@notnull@*/ exprNode ret,
5191 ctype te1 = exprNode_getType (e1);
5192 ctype te2 = exprNode_getType (e2);
5194 ctype tr1 = ctype_realishType (te1);
5195 ctype tr2 = ctype_realishType (te2);
5197 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5203 if (context_msgStrictOps ())
5205 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5207 if (ctype_sameName (te1, te2))
5211 message ("Operands of %s are non-integer (%t): %s",
5212 lltok_unparse (op), te1,
5213 exprNode_unparse (ret)),
5220 message ("Operands of %s are non-integers (%t, %t): %s",
5221 lltok_unparse (op), te1, te2,
5222 exprNode_unparse (ret)),
5226 else if (!ctype_isInt (tr1))
5230 message ("Left operand of %s is non-integer (%t): %s",
5231 lltok_unparse (op), te1, exprNode_unparse (ret)),
5235 /* !ctype_isInt (te2) */
5239 message ("Right operand of %s is non-integer (%t): %s",
5240 lltok_unparse (op), te2, exprNode_unparse (ret)),
5250 ** returns exprNode representing e1 op e2
5252 ** uses msg if there are errors
5253 ** can be used for both assignment ops and regular ops
5258 static /*@only@*/ /*@notnull@*/ exprNode
5259 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
5260 /*@keep@*/ lltok op)
5262 ctype te1, te2, tr1, tr2, tret;
5263 int opid = lltok_getTok (op);
5264 bool hasError = FALSE;
5267 if (exprNode_isError (e1))
5269 ret = exprNode_createPartialNVCopy (e2);
5273 ret = exprNode_createPartialNVCopy (e1);
5276 ret->val = multiVal_undefined;
5279 ret->edata = exprData_makeOp (e1, e2, op);
5281 if (exprNode_isError (e1) || exprNode_isError (e2))
5283 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5284 || opid == EQ_OP || opid == NE_OP
5285 || opid == AND_OP || opid == OR_OP)
5287 ret->typ = ctype_bool;
5290 if (exprNode_isDefined (e1))
5292 exprNode_checkUse (ret, e1->sref, e1->loc);
5295 if (exprNode_isDefined (e2))
5297 exprNode_mergeUSs (ret, e2);
5298 exprNode_checkUse (ret, e2->sref, e2->loc);
5304 tret = ctype_unknown;
5305 te1 = exprNode_getType (e1);
5307 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5309 te2 = exprNode_getType (e2);
5311 tr1 = ctype_realishType (te1);
5312 tr2 = ctype_realishType (te2);
5316 ret->guards = guardSet_or (ret->guards, e2->guards);
5318 else if (opid == AND_OP)
5320 ret->guards = guardSet_and (ret->guards, e2->guards);
5327 if (opid == EQ_OP || opid == NE_OP)
5329 exprNode temp1 = e1, temp2 = e2;
5331 /* could do NULL == x */
5333 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5335 temp1 = e2; temp2 = e1;
5338 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5340 reflectNullTest (temp1, (opid == NE_OP));
5341 guardSet_free (ret->guards);
5342 ret->guards = guardSet_copy (temp1->guards);
5346 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5347 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5352 if (anyAbstract (tr1, tr2) &&
5353 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
5354 (opid == AND_OP || opid == OR_OP
5355 || opid == EQ_OP || opid == NE_OP))))
5357 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
5359 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5361 /* unknown types, no comparisons possible */
5367 case TMULT: /* multiplication and division: */
5369 case MUL_ASSIGN: /* numeric, numeric -> numeric */
5370 case DIV_ASSIGN: /* */
5372 if (opid == TMULT || opid == MUL_ASSIGN)
5374 ret->val = multiVal_multiply (exprNode_getValue (e1),
5375 exprNode_getValue (e2));
5379 ret->val = multiVal_divide (exprNode_getValue (e1),
5380 exprNode_getValue (e2));
5383 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5386 case TPLUS: /* addition and subtraction: */
5387 case TMINUS: /* pointer, int -> pointer */
5388 case SUB_ASSIGN: /* int, pointer -> pointer */
5389 case ADD_ASSIGN: /* numeric, numeric -> numeric */
5391 if (opid == TPLUS || opid == ADD_ASSIGN)
5393 ret->val = multiVal_add (exprNode_getValue (e1),
5394 exprNode_getValue (e2));
5398 ret->val = multiVal_subtract (exprNode_getValue (e1),
5399 exprNode_getValue (e2));
5402 tr1 = ctype_fixArrayPtr (tr1);
5404 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5405 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5409 if (context_msgPointerArith ())
5413 message ("Pointer arithmetic (%t, %t): %s",
5414 te1, te2, exprNode_unparse (ret)),
5419 ** Swap terms so e1 is always the pointer
5422 if (ctype_isRealPointer (tr1))
5428 exprNode_swap (e1, e2);
5432 if (sRef_possiblyNull (e1->sref)
5433 && !usymtab_isGuarded (e1->sref))
5436 (FLG_NULLPOINTERARITH,
5437 message ("Pointer arithmetic involving possibly "
5438 "null pointer %s: %s",
5439 exprNode_unparse (e1),
5440 exprNode_unparse (ret)),
5444 ret->sref = sRef_copy (e1->sref);
5446 /* start modifications */
5447 /* added by Seejo on 4/16/2000 */
5449 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5451 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5454 added ugly fixed to stop
5455 program from crashing on point + int +int
5456 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5458 if (!multiVal_isInt (e2->val) )
5462 val = (int) multiVal_forceInt (e2->val);
5464 /* Operator : + or += */
5465 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5466 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5467 val should not result in a
5468 size < 0 (size = 0 is ok !) */
5470 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5472 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5473 sRef_setNotNullTerminatedState(ret->sref);
5474 sRef_resetLen (ret->sref);
5476 sRef_setNullTerminatedState(ret->sref);
5477 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5482 /* Operator : - or -= */
5483 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5484 if (sRef_getSize(e1->sref) >= 0) {
5485 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5486 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5491 /* end modifications */
5493 sRef_setNullError (ret->sref);
5496 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5497 ** since is points to storage that should not be deallocated
5498 ** through this pointer.
5501 if (sRef_isOnly (ret->sref)
5502 || sRef_isFresh (ret->sref))
5504 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5509 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5510 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5512 if (context_msgPointerArith ())
5516 message ("Pointer arithmetic (%t, %t): %s",
5517 te1, te2, exprNode_unparse (ret)),
5521 if (sRef_possiblyNull (e1->sref)
5522 && !usymtab_isGuarded (e1->sref))
5525 (FLG_NULLPOINTERARITH,
5526 message ("Pointer arithmetic involving possibly "
5527 "null pointer %s: %s",
5528 exprNode_unparse (e2),
5529 exprNode_unparse (ret)),
5533 ret->sref = sRef_copy (e2->sref);
5535 /* start modifications */
5536 /* added by Seejo on 4/16/2000 */
5538 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5541 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5542 int val = (int) multiVal_forceInt (e1->val);
5544 /* Operator : + or += */
5545 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5546 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5547 val should not result in a
5548 size < 0 (size = 0 is ok !) */
5550 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5552 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5553 sRef_setNotNullTerminatedState(ret->sref);
5554 sRef_resetLen (ret->sref);
5556 sRef_setNullTerminatedState(ret->sref);
5557 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5562 /* Operator : - or -= */
5563 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5564 if (sRef_getSize(e2->sref) >= 0) {
5565 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5566 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5570 /* end modifications */
5572 sRef_setNullError (ret->sref);
5575 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5576 ** since is points to storage that should not be deallocated
5577 ** through this pointer.
5580 if (sRef_isOnly (ret->sref)
5581 || sRef_isFresh (ret->sref)) {
5582 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5586 ret->sref = e2->sref;
5590 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5599 case TAMPERSAND: /* bitwise & */
5601 case TCIRC: /* ^ (XOR) */
5606 bool reported = FALSE;
5612 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5613 || opid == RIGHT_OP || opid == RIGHT_ASSIGN)
5616 ** evans 2002-01-01: fixed this to follow ISO 6.5.7.
5619 if (!ctype_isUnsigned (tr2)
5620 && !exprNode_isNonNegative (e2))
5622 reported = optgenerror
5624 message ("Right operand of %s may be negative (%t): %s",
5625 lltok_unparse (op), te2,
5626 exprNode_unparse (ret)),
5630 if (!ctype_isUnsigned (tr1)
5631 && !exprNode_isNonNegative (e1))
5633 reported = optgenerror
5634 (FLG_SHIFTIMPLEMENTATION,
5635 message ("Left operand of %s may be negative (%t): %s",
5636 lltok_unparse (op), te1,
5637 exprNode_unparse (ret)),
5642 ** Should check size of right operand also...
5648 if (!ctype_isUnsigned (tr1))
5650 if (exprNode_isNonNegative (e1)) {
5653 reported = optgenerror
5655 message ("Left operand of %s is not unsigned value (%t): %s",
5656 lltok_unparse (op), te1,
5657 exprNode_unparse (ret)),
5667 if (!ctype_isUnsigned (tr2))
5669 if (!exprNode_isNonNegative (e2)) {
5670 reported = optgenerror
5672 message ("Right operand of %s is not unsigned value (%t): %s",
5673 lltok_unparse (op), te2,
5674 exprNode_unparse (ret)),
5683 if (!checkIntegral (e1, e2, ret, op)) {
5684 te1 = ctype_unknown;
5688 DPRINTF (("Set: %s", ctype_unparse (te1)));
5691 ** tret is the widest type of te1 and te2
5694 tret = ctype_widest (te1, te2);
5699 if (checkIntegral (e1, e2, ret, op)) {
5702 tret = ctype_unknown;
5707 case TLT: /* comparisons */
5708 case TGT: /* numeric, numeric -> bool */
5710 DPRINTF (("Here we go: %s / %s",
5711 ctype_unparse (tr1), ctype_unparse (tr2)));
5713 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5714 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5717 bool fepsilon = FALSE;
5719 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5724 if (opid == TLT || opid == TGT)
5726 uentry ue1 = exprNode_getUentry (e1);
5727 uentry ue2 = exprNode_getUentry (e2);
5730 ** FLT_EPSILON, etc. really is a variable, not
5734 if (uentry_isVariable (ue1))
5736 cstring uname = uentry_rawName (ue1);
5738 if (cstring_equalLit (uname, "FLT_EPSILON")
5739 || cstring_equalLit (uname, "DBL_EPSILON")
5740 || cstring_equalLit (uname, "LDBL_EPSILON"))
5746 if (uentry_isVariable (ue2))
5748 cstring uname = uentry_rawName (ue2);
5750 if (cstring_equalLit (uname, "FLT_EPSILON")
5751 || cstring_equalLit (uname, "DBL_EPSILON")
5752 || cstring_equalLit (uname, "LDBL_EPSILON"))
5761 ; /* Don't complain. */
5767 message ("Dangerous comparison involving %s types: %s",
5768 ctype_unparse (rtype),
5769 exprNode_unparse (ret)),
5778 ** Types should match.
5781 DPRINTF (("Match types: %s / %s", exprNode_unparse (e1),
5782 exprNode_unparse (e2)));
5784 if (!exprNode_matchTypes (e1, e2))
5786 hasError = gentypeerror
5788 message ("Operands of %s have incompatible types (%t, %t): %s",
5789 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5795 || (ctype_isForceRealNumeric (&tr1)
5796 && ctype_isForceRealNumeric (&tr2)) ||
5797 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5803 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5804 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5808 message ("Comparison of pointer and numeric (%t, %t): %s",
5809 te1, te2, exprNode_unparse (ret)),
5814 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5819 /* certain comparisons on unsigned's and zero look suspicious */
5821 if (opid == TLT || opid == LE_OP || opid == GE_OP)
5823 if ((ctype_isUnsigned (tr1) && exprNode_isZero (e2))
5824 || (ctype_isUnsigned (tr2) && exprNode_isZero (e1)))
5827 (FLG_UNSIGNEDCOMPARE,
5828 message ("Comparison of unsigned value involving zero: %s",
5829 exprNode_unparse (ret)),
5834 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5836 if ((opid == EQ_OP || opid == NE_OP) &&
5837 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5840 ** is one a variable?
5843 if (uentry_isVariable (exprNode_getUentry (e1))
5844 || uentry_isVariable (exprNode_getUentry (e2)))
5847 ** comparisons with FALSE are okay
5850 if (exprNode_isFalseConstant (e1)
5851 || exprNode_isFalseConstant (e2))
5860 ("Use of %q with %s variables (risks inconsistency because "
5861 "of multiple true values): %s",
5862 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5863 context_printBoolName (), exprNode_unparse (ret)),
5870 case AND_OP: /* bool, bool -> bool */
5873 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5879 if (context_maybeSet (FLG_BOOLOPS))
5881 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5883 if (ctype_sameName (te1, te2))
5887 message ("Operands of %s are non-boolean (%t): %s",
5888 lltok_unparse (op), te1,
5889 exprNode_unparse (ret)),
5897 ("Operands of %s are non-booleans (%t, %t): %s",
5898 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5902 else if (!ctype_isRealBool (te1))
5906 message ("Left operand of %s is non-boolean (%t): %s",
5907 lltok_unparse (op), te1, exprNode_unparse (ret)),
5910 else if (!ctype_isRealBool (te2))
5914 message ("Right operand of %s is non-boolean (%t): %s",
5915 lltok_unparse (op), te2, exprNode_unparse (ret)),
5928 (cstring_makeLiteral
5929 ("There has been a problem in the parser. This is believed to result "
5930 "from a problem with bison v. 1.25. Please try rebuidling Splint "
5931 "using the pre-compiled grammar files by commenting out the "
5932 "BISON= line in the top-level Makefile."));
5937 DPRINTF (("Return type: %s", ctype_unparse (tret)));
5940 exprNode_checkUse (ret, e1->sref, e1->loc);
5941 exprNode_mergeUSs (ret, e2);
5942 exprNode_checkUse (ret, e2->sref, e2->loc);
5948 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5949 /*@only@*/ lltok op)
5953 checkMacroParen (e1);
5954 checkMacroParen (e2);
5956 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5958 checkExpressionDefined (e1, e2, op);
5961 ret = exprNode_makeOp (e1, e2, op);
5966 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5969 ** This is somewhat bogus!
5971 ** Assigning to a nested observer in a non-observer datatype
5972 ** should not produce an error.
5975 sRef ref = exprNode_getSref (e1);
5977 DPRINTF (("Check assign mod: %s",
5978 sRef_unparseFull (ref)));
5980 if (sRef_isObserver (ref)
5981 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
5982 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5984 sRef base = sRef_getBase (ref);
5986 if (sRef_isValid (base) && sRef_isObserver (base))
5988 exprNode_checkModify (e1, ret);
5992 exprNode_checkModifyVal (e1, ret);
5997 exprNode_checkModify (e1, ret);
6002 exprNode_assign (/*@only@*/ exprNode e1,
6003 /*@only@*/ exprNode e2, /*@only@*/ lltok op)
6005 bool isalloc = FALSE;
6006 bool isjustalloc = FALSE;
6007 bool noalias = FALSE;
6010 DPRINTF (("%s [%s] <- %s [%s]",
6011 exprNode_unparse (e1),
6012 ctype_unparse (e1->typ),
6013 exprNode_unparse (e2),
6014 ctype_unparse (e2->typ)));
6016 if (lltok_getTok (op) != TASSIGN)
6018 ret = exprNode_makeOp (e1, e2, op);
6020 DPRINTF (("Here goes: %s %s",
6021 ctype_unparse (e1->typ),
6022 ctype_unparse (e2->typ)));
6024 if (ctype_isNumeric (e2->typ)
6025 || ctype_isNumeric (e1->typ))
6027 /* Its a pointer arithmetic expression like ptr += i */
6033 ret = exprNode_createPartialCopy (e1);
6034 ret->kind = XPR_ASSIGN;
6035 ret->edata = exprData_makeOp (e1, e2, op);
6037 if (!exprNode_isError (e2))
6039 ret->sets = sRefSet_union (ret->sets, e2->sets);
6040 ret->msets = sRefSet_union (ret->msets, e2->msets);
6041 ret->uses = sRefSet_union (ret->uses, e2->uses);
6045 checkExpressionDefined (e1, e2, op);
6047 if (exprNode_isError (e1))
6049 if (!exprNode_isError (e2))
6051 ret->loc = fileloc_update (ret->loc, e2->loc);
6055 ret->loc = fileloc_update (ret->loc, g_currentloc);
6059 if (!exprNode_isError (e2))
6061 checkMacroParen (e2);
6064 if (exprNode_isDefined (e1))
6066 if (sRef_isMacroParamRef (e1->sref))
6068 if (context_inIterDef ())
6070 uentry ue = sRef_getUentry (e1->sref);
6072 if (uentry_isYield (ue))
6078 if (fileloc_isDefined (e1->loc))
6082 message ("Assignment to non-yield iter parameter: %q",
6083 sRef_unparse (e1->sref)),
6090 message ("Assignment to non-yield iter parameter: %q",
6091 sRef_unparse (e1->sref)),
6098 if (fileloc_isDefined (e1->loc))
6102 message ("Assignment to macro parameter: %q",
6103 sRef_unparse (e1->sref)),
6110 message ("Assignment to macro parameter: %q",
6111 sRef_unparse (e1->sref)),
6115 exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
6120 exprNode_checkAssignMod (e1, ret);
6123 if (exprNode_isDefined (e2))
6125 if (lltok_getTok (op) == TASSIGN)
6127 ctype te1 = exprNode_getType (e1);
6128 ctype te2 = exprNode_getType (e2);
6130 if (!ctype_forceMatch (te1, te2))
6132 if (exprNode_matchLiteral (te1, e2))
6140 message ("Assignment of %t to %t: %s %s %s",
6141 te2, te1, exprNode_unparse (e1),
6143 exprNode_unparse (e2)),
6149 exprNode_mergeUSs (ret, e2);
6150 exprNode_checkUse (ret, e2->sref, e2->loc);
6152 DPRINTF (("Do assign! %s %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6159 doAssign (e1, e2, FALSE);
6162 ret->sref = e1->sref;
6166 if (exprNode_isDefined (e2))
6168 exprNode_mergeUSs (ret, e2);
6169 exprNode_checkUse (ret, e2->sref, e2->loc);
6173 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
6175 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
6178 isjustalloc = sRef_isJustAllocated (e1->sref);
6179 isalloc = sRef_isAllocated (e1->sref);
6181 if (sRef_isField (e1->sref))
6183 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
6185 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
6187 exprNode_checkUse (ret, root, e1->loc);
6193 ** be careful! this defines e1->sref.
6196 /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
6198 DPRINTF (("Setting: %s -> %s", exprNode_unparse (ret), sRef_unparse (e1->sref)));
6199 exprNode_checkSet (ret, e1->sref);
6203 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
6204 ? e2->loc : e1->loc);
6210 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
6219 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
6220 /*@keep@*/ exprNode elseclause)
6224 if (!exprNode_isError (pred))
6226 ret = exprNode_createPartialCopy (pred);
6227 checkMacroParen (pred);
6228 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
6230 if (!exprNode_isError (ifclause))
6232 checkMacroParen (ifclause); /* update macro counts! */
6234 if (!exprNode_isError (elseclause))
6236 checkMacroParen (elseclause);
6238 if (!exprNode_matchTypes (ifclause, elseclause))
6241 (exprNode_getType (ifclause),
6243 exprNode_getType (elseclause),
6245 message ("Conditional clauses are not of same type: "
6247 exprNode_unparse (ifclause),
6248 exprNode_getType (ifclause),
6249 exprNode_unparse (elseclause),
6250 exprNode_getType (elseclause)),
6253 ret->sref = sRef_undefined;
6254 ret->typ = ctype_unknown;
6259 /* for now...should merge the states */
6260 ret->sref = ifclause->sref;
6261 ret->typ = ifclause->typ;
6263 if (exprNode_isNullValue (ifclause))
6265 ret->typ = elseclause->typ;
6269 exprNode_checkUse (ret, pred->sref, pred->loc);
6270 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6271 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6273 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6278 ret->typ = ifclause->typ;
6280 exprNode_checkUse (pred, pred->sref, pred->loc);
6281 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6283 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6288 if (!exprNode_isError (elseclause))
6290 ret->typ = elseclause->typ;
6292 exprNode_checkUse (pred, pred->sref, pred->loc);
6293 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6295 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6299 else /* pred is error */
6301 if (!exprNode_isError (ifclause))
6303 ret = exprNode_createSemiCopy (ifclause);
6305 checkMacroParen (ifclause); /* update macro counts! */
6307 if (!exprNode_isError (elseclause))
6309 checkMacroParen (elseclause);
6311 ret->typ = ifclause->typ;
6313 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6316 (exprNode_getType (ifclause),
6318 exprNode_getType (elseclause),
6320 message ("Conditional clauses are not of same type: "
6322 exprNode_unparse (ifclause),
6323 exprNode_getType (ifclause),
6324 exprNode_unparse (elseclause),
6325 exprNode_getType (elseclause)),
6328 ret->typ = ctype_unknown;
6332 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6333 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6335 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6338 else if (!exprNode_isError (elseclause)) /* pred, if errors */
6340 ret = exprNode_createSemiCopy (ifclause);
6342 ret->typ = elseclause->typ;
6343 checkMacroParen (elseclause);
6345 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6346 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6348 else /* all errors! */
6350 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6354 ret->kind = XPR_COND;
6355 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
6357 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6359 exprNode_combineControl (ret, ifclause, elseclause);
6366 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6368 ctype totype = qtype_getType (qt);
6370 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6374 ** check use of va_arg : <valist>, type -> type
6377 if (exprNode_isError (arg))
6382 targ = exprNode_getType (arg);
6385 ** arg should have be a pointer
6388 if (!ctype_isUA (targ) ||
6389 (!usymId_equal (ctype_typeId (targ),
6390 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6394 message ("First argument to va_arg is not a va_list (type %t): %s",
6395 targ, exprNode_unparse (arg)),
6399 exprNode_checkSet (ret, arg->sref);
6403 ** return type is totype
6407 ret->kind = XPR_VAARG;
6408 ret->edata = exprData_makeCast (tok, arg, qt);
6413 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6415 exprNode ret = exprNode_createPlain (ctype_undefined);
6416 ret->kind = XPR_LABEL;
6417 ret->edata = exprData_makeLiteral (label);
6418 ret->isJumpPoint = TRUE;
6420 return (ret); /* for now, ignore label */
6423 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6425 if (exprNode_isDefined (stmt))
6427 stmt->isJumpPoint = TRUE;
6429 /* This prevent stray no return path errors, etc. */
6430 stmt->exitCode = XK_MUSTEXIT;
6436 bool exprNode_isDefaultMarker (exprNode e)
6438 if (exprNode_isDefined (e))
6440 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6446 bool exprNode_isCaseMarker (exprNode e)
6448 if (exprNode_isDefined (e))
6450 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6456 bool exprNode_isLabelMarker (exprNode e)
6458 if (exprNode_isDefined (e))
6460 return (e->kind == XPR_LABEL);
6466 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6468 exprNode ret = exprNode_createPartialCopy (test);
6470 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6472 if (exprNode_isError (test)) {
6476 exprNode_checkUse (ret, test->sref, test->loc);
6478 usymtab_setExitCode (ret->exitCode);
6482 usymtab_setMustBreak ();
6485 ret->edata = exprData_makeSingle (test);
6486 ret->isJumpPoint = TRUE;
6492 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6494 exprNode ret = exprNode_createPartialCopy (test);
6496 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6497 ret->edata = exprData_makePair (test, stmt);
6498 ret->isJumpPoint = TRUE;
6500 if (exprNode_isError (test))
6505 exprNode_checkUse (ret, test->sref, test->loc);
6507 if (exprNode_isError (stmt))
6512 exprNode_mergeUSs (ret, stmt);
6514 ret->exitCode = stmt->exitCode;
6515 ret->mustBreak = stmt->mustBreak;
6516 ret->canBreak = stmt->canBreak;
6518 usymtab_setExitCode (ret->exitCode);
6522 usymtab_setMustBreak ();
6529 /*@notnull@*/ /*@only@*/ exprNode
6530 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6532 exprNode ret = exprNode_createTok (def);
6534 ret->isJumpPoint = TRUE;
6535 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6540 exprNode_mayEscape (exprNode e)
6542 if (exprNode_isDefined (e))
6544 return exitkind_couldEscape (e->exitCode);
6550 exprNode_mustBreak (exprNode e)
6552 if (exprNode_isDefined (e))
6554 return e->mustBreak;
6561 exprNode_mustEscape (exprNode e)
6563 if (exprNode_isDefined (e))
6565 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6572 exprNode_errorEscape (exprNode e)
6574 if (exprNode_isDefined (e))
6576 return exitkind_isError (e->exitCode);
6582 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6584 exprNode ret = exprNode_createPartialCopy (e1);
6586 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6588 ret->edata = exprData_makePair (e1, e2);
6589 ret->kind = XPR_STMTLIST;
6591 if (exprNode_isDefined (e1))
6593 ret->isJumpPoint = e1->isJumpPoint;
6594 ret->canBreak = e1->canBreak;
6598 if (exprNode_isDefined (e2))
6600 ret->loc = fileloc_update (ret->loc, e2->loc);
6604 if (exprNode_isDefined (e2))
6606 ret->exitCode = e2->exitCode;
6607 ret->mustBreak = e2->mustBreak;
6608 if (e2->canBreak) ret->canBreak = TRUE;
6612 ** if e1 must return, then e2 is unreachable!
6615 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6617 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6618 && !(e2->isJumpPoint))
6620 if (context_getFlag (FLG_UNREACHABLE))
6624 if (e2->kind == XPR_STMT)
6626 nr = exprData_getUopNode (e2->edata);
6629 if ((nr->kind == XPR_TOK
6630 && lltok_isSemi (exprData_getTok (nr->edata))))
6632 /* okay to have unreachable ";" */
6633 ret->exitCode = XK_MUSTEXIT;
6634 ret->canBreak = TRUE;
6638 if (optgenerror (FLG_UNREACHABLE,
6639 message ("Unreachable code: %s",
6640 exprNode_unparseFirst (nr)),
6643 ret->isJumpPoint = TRUE;
6644 ret->mustBreak = FALSE;
6645 ret->exitCode = XK_ERROR;
6646 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6650 ret->exitCode = XK_MUSTEXIT;
6651 ret->canBreak = TRUE;
6659 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6662 ** We want a warning anytime we have:
6664 ** yyy; <<<- no break or return
6668 exprNode lastStmt = exprNode_lastStatement (e1);
6670 if (exprNode_isDefined (lastStmt)
6671 && !exprNode_mustEscape (lastStmt)
6672 && !exprNode_mustBreak (lastStmt)
6673 && !exprNode_isCaseMarker (lastStmt)
6674 && !exprNode_isDefaultMarker (lastStmt)
6675 && !exprNode_isLabelMarker (lastStmt))
6677 voptgenerror (FLG_CASEBREAK,
6679 ("Fall through case (no preceding break)"),
6686 exprNode_mergeUSs (ret, e2);
6688 usymtab_setExitCode (ret->exitCode);
6692 usymtab_setMustBreak ();
6698 exprNode exprNode_createTok (/*@only@*/ lltok t)
6700 exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6701 ret = exprNode_create (ctype_unknown);
6702 ret->kind = XPR_TOK;
6703 ret->edata = exprData_makeTok (t);
6707 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6709 if (!exprNode_isError (e))
6711 exprNode_checkStatement(e);
6714 return (exprNode_statementError (e, t));
6717 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6719 exprNode ret = exprNode_createPartialCopy (e);
6721 if (!exprNode_isError (e))
6723 if (e->kind != XPR_ASSIGN)
6725 exprNode_checkUse (ret, e->sref, e->loc);
6728 ret->exitCode = e->exitCode;
6729 ret->canBreak = e->canBreak;
6730 ret->mustBreak = e->mustBreak;
6733 ret->edata = exprData_makeUop (e, t);
6734 ret->kind = XPR_STMT;
6739 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6741 if (!exprNode_isError (e))
6743 if (e->kind != XPR_ASSIGN)
6745 exprNode_checkUse (e, e->sref, e->loc);
6752 void exprNode_produceGuards (exprNode pred)
6754 if (!exprNode_isError (pred))
6756 if (ctype_isRealPointer (pred->typ))
6758 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6761 exprNode_checkUse (pred, pred->sref, pred->loc);
6762 exprNode_resetSref (pred);
6766 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6768 exprNode ret = exprNode_createPartialCopy (e);
6770 if (!exprNode_isError (e))
6772 ret->exitCode = e->exitCode;
6773 ret->canBreak = e->canBreak;
6774 ret->mustBreak = e->mustBreak;
6777 ret->edata = exprData_makeSingle (e);
6778 ret->kind = XPR_BLOCK;
6782 bool exprNode_isBlock (exprNode e)
6784 return (exprNode_isDefined (e)
6785 && ((e)->kind == XPR_BLOCK));
6788 bool exprNode_isAssign (exprNode e)
6790 if (exprNode_isDefined (e))
6792 return (e->kind == XPR_ASSIGN);
6798 bool exprNode_isEmptyStatement (exprNode e)
6800 return (exprNode_isDefined (e)
6801 && (e->kind == XPR_TOK)
6802 && (lltok_isSemi (exprData_getTok (e->edata))));
6805 void exprNode_checkIfPred (exprNode pred)
6807 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6810 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6813 bool emptyErr = FALSE;
6815 if (context_maybeSet (FLG_IFEMPTY))
6817 if (exprNode_isEmptyStatement (tclause))
6819 emptyErr = optgenerror (FLG_IFEMPTY,
6821 ("Body of if statement is empty"),
6822 exprNode_loc (tclause));
6826 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6828 if (exprNode_isDefined (tclause)
6829 && !exprNode_isBlock (tclause))
6831 voptgenerror (FLG_IFBLOCK,
6833 ("Body of if statement is not a block: %s",
6834 exprNode_unparse (tclause)),
6835 exprNode_loc (tclause));
6839 if (exprNode_isError (pred))
6841 if (exprNode_isError (tclause))
6843 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6847 ret = exprNode_createPartialCopy (tclause);
6852 if (exprNode_mustEscape (pred))
6856 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6857 exprNode_loc (pred));
6860 /*! exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred); */ /*@i523@*/
6861 exprNode_checkUse (pred, pred->sref, pred->loc);
6863 if (!exprNode_isError (tclause))
6865 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
6868 ret = exprNode_createPartialCopy (pred);
6872 ret->edata = exprData_makePair (pred, tclause);
6874 ret->exitCode = XK_UNKNOWN;
6876 if (exprNode_isDefined (tclause))
6878 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
6879 ret->canBreak = tclause->canBreak;
6880 ret->sets = sRefSet_union (ret->sets, tclause->sets);
6881 ret->msets = sRefSet_union (ret->msets, tclause->msets);
6882 ret->uses = sRefSet_union (ret->uses, tclause->uses);
6885 ret->mustBreak = FALSE;
6890 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
6891 /*@only@*/ exprNode tclause,
6892 /*@only@*/ exprNode eclause)
6895 bool tEmptyErr = FALSE;
6896 bool eEmptyErr = FALSE;
6898 if (context_maybeSet (FLG_IFEMPTY))
6900 if (exprNode_isEmptyStatement (tclause))
6902 tEmptyErr = optgenerror
6905 ("Body of if clause of if statement is empty"),
6906 exprNode_loc (tclause));
6909 if (exprNode_isEmptyStatement (eclause))
6911 eEmptyErr = optgenerror
6914 ("Body of else clause of if statement is empty"),
6915 exprNode_loc (eclause));
6919 if (context_maybeSet (FLG_IFBLOCK))
6922 && exprNode_isDefined (tclause)
6923 && !exprNode_isBlock (tclause))
6925 voptgenerror (FLG_IFBLOCK,
6927 ("Body of if clause of if statement is not a block: %s",
6928 exprNode_unparse (tclause)),
6929 exprNode_loc (tclause));
6933 && exprNode_isDefined (eclause)
6934 && !exprNode_isBlock (eclause)
6935 && !(eclause->kind == XPR_IF)
6936 && !(eclause->kind == XPR_IFELSE))
6941 ("Body of else clause of if statement is not a block: %s",
6942 exprNode_unparse (eclause)),
6943 exprNode_loc (eclause));
6947 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
6949 if (exprNode_isDefined (eclause)
6950 && (eclause->kind == XPR_IF))
6952 voptgenerror (FLG_ELSEIFCOMPLETE,
6953 message ("Incomplete else if logic (no final else): %s",
6954 exprNode_unparse (eclause)),
6955 exprNode_loc (eclause));
6959 if (exprNode_isError (pred))
6961 if (exprNode_isError (tclause))
6963 if (exprNode_isError (eclause))
6965 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6969 ret = exprNode_createPartialCopy (eclause);
6974 ret = exprNode_createPartialCopy (tclause);
6977 else /* pred is okay */
6979 ret = exprNode_createPartialCopy (pred);
6981 if (exprNode_mustEscape (pred))
6985 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6986 exprNode_loc (pred));
6989 /*@i3423 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);*/
6990 exprNode_checkUse (ret, pred->sref, pred->loc);
6992 exprNode_mergeCondUSs (ret, tclause, eclause);
6995 ret->kind = XPR_IFELSE;
6996 ret->edata = exprData_makeCond (pred, tclause, eclause);
6998 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
7000 exprNode_combineControl (ret, tclause, eclause);
7001 ret->loc = fileloc_update (ret->loc, eclause->loc);
7008 ** *allpaths <- TRUE iff all executions paths must go through the switch
7012 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
7014 exprNodeSList el = exprNode_flatten (e);
7015 bool mustReturn = TRUE; /* find a branch that doesn't */
7016 bool thisReturn = FALSE;
7017 bool hasDefault = FALSE;
7018 bool hasAllMembers = FALSE;
7019 bool inSwitch = FALSE;
7020 bool isEnumSwitch = FALSE;
7021 bool canBreak = FALSE;
7022 bool fallThrough = FALSE;
7023 ctype ct = ctype_unknown;
7024 enumNameSList usedEnums;
7027 if (exprNode_isDefined (test))
7032 ttype = ctype_realType (ct);
7034 if (ctype_isEnum (ttype))
7036 isEnumSwitch = TRUE;
7037 enums = ctype_elist (ttype);
7038 usedEnums = enumNameSList_new ();
7042 exprNodeSList_elements (el, current)
7045 DPRINTF ((message("checkSwitchExpr current = %s ", exprNode_unparse(current) ) ));
7047 if (exprNode_isDefined (current))
7049 switch (current->kind)
7056 (FLG_DUPLICATECASES,
7057 message ("Duplicate default cases in switch"),
7058 exprNode_loc (current));
7063 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
7071 exprNode st = exprData_getSingle (current->edata);
7072 uentry ue = exprNode_getUentry (st);
7074 if (uentry_isValid (ue))
7076 cstring cname = uentry_rawName (ue);
7078 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
7080 if (enumNameSList_member
7081 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
7084 (FLG_DUPLICATECASES,
7085 message ("Duplicate case in switch: %s",
7091 enumNameSList_addh (usedEnums, cname);
7098 message ("Case in switch not %s member: %s",
7099 ctype_unparse (ct), cname),
7106 if (inSwitch && !fallThrough)
7108 if (!thisReturn || canBreak)
7118 /*@switchbreak@*/ break;
7120 thisReturn = thisReturn || exprNode_mustEscape (current);
7121 canBreak = canBreak || current->canBreak;
7122 if (canBreak) fallThrough = FALSE;
7125 } end_exprNodeSList_elements;
7127 if (inSwitch) /* check the last one! */
7129 if (!thisReturn || canBreak)
7138 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
7139 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
7141 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
7143 voptgenerror (FLG_MISSCASE,
7144 message ("Missing case%s in switch: %q",
7145 cstring_makeLiteralTemp
7146 ((enumNameSList_size (unused) > 1) ? "s" : ""),
7147 enumNameSList_unparse (unused)),
7150 enumNameSList_free (unused);
7151 *allpaths = FALSE; /* evans 2002-01-01 */
7155 hasAllMembers = TRUE;
7159 enumNameSList_free (usedEnums);
7163 *allpaths = hasDefault;
7166 exprNodeSList_free (el);
7167 return ((hasDefault || hasAllMembers) && mustReturn);
7170 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
7172 exprNode ret = exprNode_createPartialCopy (e);
7175 DPRINTF (("Switch: %s", exprNode_unparse (s)));
7177 ret->kind = XPR_SWITCH;
7178 ret->edata = exprData_makePair (e, s);
7180 if (!exprNode_isError (s))
7182 exprNode fs = exprNode_firstStatement (s);
7183 ret->loc = fileloc_update (ret->loc, s->loc);
7185 if (exprNode_isUndefined (fs)
7186 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
7187 || exprNode_isDefaultMarker (fs)) {
7190 voptgenerror (FLG_FIRSTCASE,
7192 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
7197 if (!exprNode_isError (e))
7199 if (checkSwitchExpr (e, s, &allpaths))
7201 ret->exitCode = XK_MUSTRETURN;
7205 ret->exitCode = e->exitCode;
7208 ret->canBreak = e->canBreak;
7209 ret->mustBreak = e->mustBreak;
7213 ** exprNode.c:3883,32: Variable allpaths used before definition
7220 DPRINTF (("Context exit switch!"));
7221 context_exitSwitch (ret, allpaths);
7222 DPRINTF (("Context exit switch done!"));
7227 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
7228 /*@notnull@*/ exprNode body)
7230 sRefSet tuses = test->uses;
7232 if (!sRefSet_isEmpty (test->uses))
7234 sRefSet sets = sRefSet_newCopy (body->sets);
7235 bool hasError = TRUE;
7236 bool innerState = FALSE;
7237 sRefSet tuncon = sRefSet_undefined;
7239 sets = sRefSet_union (sets, test->sets);
7240 sets = sRefSet_union (sets, body->msets);
7241 sets = sRefSet_union (sets, test->msets);
7243 sRefSet_allElements (tuses, el)
7245 if (sRef_isUnconstrained (el))
7247 tuncon = sRefSet_insert (tuncon, el);
7251 if (sRefSet_member (sets, el))
7258 if (sRef_isInternalState (el)
7259 || sRef_isFileStatic (sRef_getRootBase (el)))
7263 } end_sRefSet_allElements ;
7267 sRefSet suncon = sRefSet_undefined;
7268 bool sinner = FALSE;
7270 sRefSet_allElements (sets, el)
7272 if (sRef_isUnconstrained (el))
7274 suncon = sRefSet_insert (suncon, el);
7276 else if (sRef_isInternalState (el))
7284 } end_sRefSet_allElements ;
7286 if (sinner && innerState)
7290 else if (sRefSet_isEmpty (tuncon)
7291 && sRefSet_isEmpty (suncon))
7296 ("Suspected infinite loop. No value used in loop test (%q) "
7297 "is modified by test or loop body.",
7298 sRefSet_unparsePlain (tuses)),
7303 if (sRefSet_isEmpty (tuncon))
7307 message ("Suspected infinite loop. No condition values "
7308 "modified. Modification possible through "
7309 "unconstrained calls: %q",
7310 sRefSet_unparsePlain (suncon)),
7317 message ("Suspected infinite loop. No condition values "
7318 "modified. Possible undetected dependency through "
7319 "unconstrained calls in loop test: %q",
7320 sRefSet_unparsePlain (tuncon)),
7326 sRefSet_free (sets);
7330 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7333 bool emptyErr = FALSE;
7335 if (context_maybeSet (FLG_WHILEEMPTY))
7337 if (exprNode_isEmptyStatement (b))
7339 emptyErr = optgenerror
7342 ("Body of while statement is empty"),
7347 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7349 if (exprNode_isDefined (b)
7350 && !exprNode_isBlock (b))
7352 if (context_inIterDef ()
7353 && (b->kind == XPR_STMTLIST
7354 || b->kind == XPR_TOK))
7360 voptgenerror (FLG_WHILEBLOCK,
7362 ("Body of while statement is not a block: %s",
7363 exprNode_unparse (b)),
7369 if (exprNode_isError (t))
7371 if (exprNode_isError (b))
7373 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7377 ret = exprNode_createPartialCopy (b);
7384 ret = exprNode_createPartialCopy (t);
7386 llassert (t->kind == XPR_WHILEPRED);
7388 test = exprData_getSingle (t->edata);
7390 if (!exprNode_isError (b) && exprNode_isDefined (test))
7392 if (context_maybeSet (FLG_INFLOOPS)
7393 || context_maybeSet (FLG_INFLOOPSUNCON))
7396 ** check that some variable in the predicate is set by the body
7397 ** if the predicate uses any variables
7400 checkInfiniteLoop (test, b);
7403 exprNode_mergeUSs (ret, b);
7405 if (exprNode_isDefined (b))
7407 ret->exitCode = exitkind_makeConditional (b->exitCode);
7412 ret->edata = exprData_makePair (t, b);
7413 ret->kind = XPR_WHILE;
7415 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7419 message ("Predicate always exits: %s", exprNode_unparse (t)),
7423 ret->exitCode = XK_NEVERESCAPE;
7426 ** If loop is infinite, and there is no break inside,
7427 ** exit code is never reach.
7430 if (exprNode_knownIntValue (t))
7432 if (!exprNode_isZero (t))
7434 if (exprNode_isDefined (b))
7438 /* Really, it means never reached. */
7439 ret->exitCode = XK_MUSTEXIT;
7449 ret->canBreak = FALSE;
7450 ret->mustBreak = FALSE;
7456 ** do { b } while (t);
7458 ** note: body passed as first argument
7461 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7465 DPRINTF (("Do while: %s / %s",
7466 exprNode_unparse (b), exprNode_unparse (t)));
7468 if (exprNode_isError (t))
7470 if (exprNode_isError (b))
7472 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7476 ret = exprNode_createPartialCopy (b);
7478 ret->exitCode = exitkind_makeConditional (b->exitCode);
7479 exprNode_checkUse (ret, b->sref, b->loc);
7480 ret->exitCode = b->exitCode;
7481 ret->canBreak = b->canBreak;
7482 ret->mustBreak = FALSE;
7487 DPRINTF (("Do while: %s / %s",
7488 exitkind_unparse (t->exitCode),
7489 exitkind_unparse (b->exitCode)));
7491 ret = exprNode_createPartialCopy (t);
7492 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7494 if (!exprNode_isError (b))
7497 ** forgot the copy's --- why wasn't this detected??
7500 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7501 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7502 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
7504 /* left this out --- causes and aliasing bug (infinite loop)
7505 should be detected?? */
7507 exprNode_checkUse (ret, b->sref, b->loc);
7508 exprNode_mergeUSs (ret, t);
7509 exprNode_checkUse (ret, t->sref, t->loc);
7511 /* evans 2001-10-05: while loop can break */
7512 ret->exitCode = exitkind_makeConditional (b->exitCode);
7514 DPRINTF (("Do while: %s",
7515 exitkind_unparse (ret->exitCode)));
7517 ret->canBreak = b->canBreak;
7519 /* Always FALSE for doWhile loops - break's when test is false */
7520 ret->mustBreak = FALSE; /* b->mustBreak; */
7524 context_exitDoWhileClause (t);
7526 ret->kind = XPR_DOWHILE;
7527 ret->edata = exprData_makePair (t, b);
7531 bool exprNode_loopMustExec (exprNode forPred)
7534 ** Returns true if it is obvious that the loop always executes at least once
7536 ** For now, we only identify the most obvious cases. Should be true anytime
7537 ** we can prove init => !test.
7540 if (exprNode_isDefined (forPred))
7542 exprNode init, test, inc;
7545 llassert (forPred->kind == XPR_FORPRED);
7547 edata = forPred->edata;
7548 init = exprData_getTripleInit (edata);
7549 test = exprData_getTripleTest (edata);
7550 inc = exprData_getTripleInc (edata);
7552 if (exprNode_isAssign (init))
7554 exprNode loopVar = exprData_getOpA (init->edata);
7555 exprNode loopInit = exprData_getOpB (init->edata);
7557 if (exprNode_isDefined (test) && test->kind == XPR_OP)
7559 exprNode testVar = exprData_getOpA (test->edata);
7560 exprNode testVal = exprData_getOpB (test->edata);
7561 lltok comp = exprData_getOpTok (test->edata);
7562 int opid = lltok_getTok (comp);
7564 DPRINTF (("Same storage: %s / %s", exprNode_unparse (loopVar),
7565 exprNode_unparse (testVar)));
7567 if (exprNode_sameStorage (loopVar, testVar))
7569 multiVal valinit = exprNode_getValue (loopInit);
7570 multiVal valtest = exprNode_getValue (testVal);
7572 DPRINTF (("Values: %s / %s", multiVal_unparse (valinit),
7573 multiVal_unparse (valtest)));
7575 if (multiVal_isInt (valinit) && multiVal_isInt (valtest))
7577 long v1 = multiVal_forceInt (valinit);
7578 long v2 = multiVal_forceInt (valtest);
7580 DPRINTF (("Here: %ld %ld", v1, v2));
7582 if ((opid == EQ_OP && v1 < v2)
7583 || (opid == NE_OP && v1 != v2)
7584 || (opid == TLT && v1 <= v2)
7585 || (opid == TGT && v1 >= v2)
7586 || (opid == LE_OP && v1 < v2)
7587 || (opid == GE_OP && v1 > v2))
7589 DPRINTF (("mustexec if inc"));
7598 DPRINTF (("loop must exec: FALSE"));
7602 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7605 bool emptyErr = FALSE;
7607 if (context_maybeSet (FLG_FOREMPTY))
7609 if (exprNode_isEmptyStatement (body))
7611 emptyErr = optgenerror
7614 ("Body of for statement is empty"),
7615 exprNode_loc (body));
7619 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7621 if (exprNode_isDefined (body)
7622 && !exprNode_isBlock (body))
7624 if (context_inIterDef ()
7625 && (body->kind == XPR_STMTLIST
7626 || body->kind == XPR_TOK))
7632 voptgenerror (FLG_FORBLOCK,
7634 ("Body of for statement is not a block: %s",
7635 exprNode_unparse (body)),
7636 exprNode_loc (body));
7642 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7645 if (exprNode_isError (body))
7647 ret = exprNode_createPartialCopy (inc);
7651 ret = exprNode_createPartialCopy (body);
7653 ret->exitCode = exitkind_makeConditional (body->exitCode);
7655 exprNode_mergeUSs (inc, body);
7657 if (exprNode_isDefined (inc))
7661 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7663 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7664 exprNode_freeShallow (tmp);
7666 context_clearMessageAnnote ();
7667 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7669 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7670 exprNode_freeShallow (tmp);
7672 context_clearMessageAnnote ();
7674 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7675 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7676 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7680 ret->kind = XPR_FOR;
7681 ret->edata = exprData_makePair (inc, body);
7683 if (exprNode_isDefined (inc)) {
7684 exprNode test = exprData_getTripleTest (inc->edata);
7686 if (exprNode_isUndefined (test)) {
7687 if (exprNode_isDefined (body)) {
7688 if (!body->canBreak) {
7689 /* Really, it means never reached. */
7690 ret->exitCode = XK_MUSTEXIT;
7700 ** for (init; test; inc)
7703 ** while (test) { body; inc; }
7705 ** Now: check use of init (may set vars for test)
7706 ** check use of test
7710 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7714 if (exprNode_isError (pred)) return guardSet_undefined;
7716 llassert (pred->kind == XPR_FORPRED);
7718 test = exprData_getTripleTest (pred->edata);
7720 if (!exprNode_isError (test))
7722 return (test->guards);
7725 return guardSet_undefined;
7728 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7730 exprNode ret = exprNode_createSemiCopy (test);
7732 if (exprNode_isDefined (test))
7734 exprNode_copySets (ret, test);
7735 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7736 exprNode_checkUse (ret, test->sref, test->loc);
7738 exprNode_produceGuards (test);
7740 ret->guards = guardSet_copy (test->guards);
7743 ret->edata = exprData_makeSingle (test);
7744 ret->kind = XPR_WHILEPRED;
7748 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7749 /*@only@*/ exprNode inc)
7754 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7757 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7759 if (!exprNode_isError (inc))
7761 ret = exprNode_createPartialCopy (inc);
7765 if (!exprNode_isError (init))
7767 ret = exprNode_createPartialCopy (init);
7769 else if (!exprNode_isError (test))
7771 ret = exprNode_createPartialCopy (test);
7775 ret = exprNode_createUnknown ();
7779 exprNode_mergeUSs (ret, init);
7781 if (exprNode_isDefined (init))
7783 exprNode_checkUse (ret, init->sref, init->loc);
7786 exprNode_mergeUSs (ret, test);
7788 if (exprNode_isDefined (test))
7790 exprNode_checkUse (ret, test->sref, test->loc);
7793 ret->kind = XPR_FORPRED;
7794 ret->edata = exprData_makeFor (init, test, inc);
7798 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7800 exprNode ret = exprNode_createUnknown ();
7802 if (context_inMacro ())
7804 voptgenerror (FLG_MACROSTMT,
7805 message ("Macro %s uses goto (not functional)",
7806 context_inFunctionName ()),
7810 ret->kind = XPR_GOTO;
7811 ret->edata = exprData_makeLiteral (label);
7812 ret->mustBreak = TRUE;
7813 ret->exitCode = XK_GOTO;
7814 ret->canBreak = TRUE;
7818 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7820 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7822 ret->kind = XPR_CONTINUE;
7823 ret->edata = exprData_makeTok (l);
7824 ret->canBreak = TRUE;
7825 ret->mustBreak = TRUE;
7827 if (qcontinue == QSAFEBREAK)
7831 else if (qcontinue == QINNERCONTINUE)
7833 if (!context_inDeepLoop ())
7836 (FLG_LOOPLOOPCONTINUE,
7837 cstring_makeLiteral ("Continue statement marked with innercontinue "
7838 "is not inside a nested loop"),
7839 exprNode_loc (ret));
7842 else if (qcontinue == BADTOK)
7844 if (context_inDeepLoop ())
7847 (FLG_LOOPLOOPCONTINUE,
7848 cstring_makeLiteral ("Continue statement in nested loop"),
7849 exprNode_loc (ret));
7854 llbuglit ("exprNode_continue: bad qcontinue");
7860 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
7862 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7863 clause breakClause = context_breakClause ();
7865 ret->kind = XPR_BREAK;
7866 ret->edata = exprData_makeTok (l);
7867 ret->canBreak = TRUE;
7868 ret->mustBreak = TRUE;
7870 if (breakClause == NOCLAUSE)
7874 cstring_makeLiteral ("Break not inside while, for or switch statement"),
7875 exprNode_loc (ret));
7879 if (bqual != BADTOK)
7886 if (breakClause == SWITCHCLAUSE)
7888 if (!context_inDeepSwitch ())
7890 voptgenerror (FLG_SYNTAX,
7892 ("Break preceded by innerbreak is not in a deep switch"),
7893 exprNode_loc (ret));
7898 if (!context_inDeepLoop ())
7900 voptgenerror (FLG_SYNTAX,
7902 ("Break preceded by innerbreak is not in a deep loop"),
7903 exprNode_loc (ret));
7908 if (breakClause == SWITCHCLAUSE)
7910 voptgenerror (FLG_SYNTAX,
7912 ("Break preceded by loopbreak is breaking a switch"),
7913 exprNode_loc (ret));
7917 if (breakClause != SWITCHCLAUSE)
7921 message ("Break preceded by switchbreak is breaking %s",
7922 cstring_makeLiteralTemp
7923 ((breakClause == WHILECLAUSE
7924 || breakClause == DOWHILECLAUSE) ? "a while loop"
7925 : (breakClause == FORCLAUSE) ? "a for loop"
7926 : (breakClause == ITERCLAUSE) ? "an iterator"
7928 exprNode_loc (ret));
7936 if (breakClause == SWITCHCLAUSE)
7938 clause nextBreakClause = context_nextBreakClause ();
7940 switch (nextBreakClause)
7942 case NOCLAUSE: break;
7948 (FLG_LOOPSWITCHBREAK,
7949 cstring_makeLiteral ("Break statement in switch inside loop"),
7950 exprNode_loc (ret));
7954 (FLG_SWITCHSWITCHBREAK,
7955 cstring_makeLiteral ("Break statement in switch inside switch"),
7956 exprNode_loc (ret));
7963 if (context_inDeepLoop ())
7967 cstring_makeLiteral ("Break statement in nested loop"),
7968 exprNode_loc (ret));
7972 if (context_inDeepLoopSwitch ())
7975 (FLG_SWITCHLOOPBREAK,
7976 cstring_makeLiteral ("Break statement in loop inside switch"),
7977 exprNode_loc (ret));
7987 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
7989 fileloc loc = lltok_getLoc (t);
7990 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
7992 context_returnFunction ();
7993 exprChecks_checkNullReturn (loc);
7995 ret->kind = XPR_NULLRETURN;
7996 ret->edata = exprData_makeTok (t);
7997 ret->exitCode = XK_MUSTRETURN;
8001 exprNode exprNode_return (/*@only@*/ exprNode e)
8005 if (exprNode_isError (e))
8007 ret = exprNode_createUnknown ();
8011 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
8013 exprNode_checkUse (ret, e->sref, e->loc);
8014 exprNode_checkReturn (e);
8017 context_returnFunction ();
8018 ret->kind = XPR_RETURN;
8019 ret->edata = exprData_makeSingle (e);
8020 ret->exitCode = XK_MUSTRETURN;
8025 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
8029 if (exprNode_isError (e1))
8031 if (exprNode_isError (e2))
8033 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
8037 ret = exprNode_createPartialCopy (e2);
8038 exprNode_checkUse (ret, e2->sref, e2->loc);
8039 ret->sref = e2->sref;
8044 ret = exprNode_createPartialCopy (e1);
8046 exprNode_checkUse (ret, e1->sref, e1->loc);
8048 if (!exprNode_isError (e2))
8050 exprNode_mergeUSs (ret, e2);
8051 exprNode_checkUse (ret, e2->sref, e2->loc);
8052 ret->sref = e2->sref;
8056 ret->kind = XPR_COMMA;
8057 ret->edata = exprData_makePair (e1, e2);
8059 if (exprNode_isDefined (e1))
8061 if (exprNode_isDefined (e2))
8065 if (exprNode_mustEscape (e1) || e1->mustBreak)
8069 message ("Second clause of comma expression is unreachable: %s",
8070 exprNode_unparse (e2)),
8074 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
8075 ret->mustBreak = e1->mustBreak || e2->mustBreak;
8076 ret->canBreak = e1->canBreak || e2->canBreak;
8080 if (exprNode_mustEscape (e1) || e1->mustBreak)
8084 message ("Second clause of comma expression is unreachable: %s",
8085 exprNode_unparse (e2)),
8089 ret->exitCode = e1->exitCode;
8090 ret->canBreak = e1->canBreak;
8095 if (exprNode_isDefined (e2))
8097 ret->exitCode = e2->exitCode;
8098 ret->mustBreak = e2->mustBreak;
8099 ret->canBreak = e2->canBreak;
8106 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
8108 ctype t1 = exprNode_getType (el);
8109 ctype t2 = exprNode_getType (val);
8110 bool hasError = FALSE;
8112 DPRINTF (("Check one init: %s / %s",
8113 exprNode_unparse (el),
8114 exprNode_unparse (val)));
8116 if (ctype_isUnknown (t1))
8118 voptgenerror (FLG_IMPTYPE,
8119 message ("Variable has unknown (implicitly int) type: %s",
8120 exprNode_unparse (el)),
8124 el->typ = ctype_int;
8127 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
8129 exprNodeList vals = exprData_getArgs (val->edata);
8131 DPRINTF (("Check one init: %s", exprNodeList_unparse (vals)));
8132 DPRINTF (("Type: %s", ctype_unparse (t1)));
8134 if (ctype_isRealAP (t1))
8139 if (ctype_isFixedArray (t1))
8141 int nelements = long_toInt (ctype_getArraySize (t1));
8143 DPRINTF (("Checked array: %s / %d",
8144 ctype_unparse (t1), nelements));
8146 if (exprNode_isStringLiteral (val))
8148 exprNode_checkStringLiteralLength (t1, val);
8152 if (exprNodeList_size (vals) != nelements)
8154 hasError = optgenerror
8155 (exprNodeList_size (vals) > nelements ? FLG_INITSIZE : FLG_INITALLELEMENTS,
8156 message ("Initializer block for "
8157 "%s has %d element%&, but declared as %s: %q",
8158 exprNode_unparse (el),
8159 exprNodeList_size (vals),
8161 exprNodeList_unparse (vals)),
8167 exprNodeList_elements (vals, oneval)
8169 cstring istring = message ("%d", i);
8172 (exprNode_fakeCopy (el),
8173 exprNode_numLiteral (ctype_int, istring,
8174 fileloc_copy (el->loc), i));
8176 if (exprNode_isDefined (newel))
8178 if (exprNodeList_size (vals) == 1
8179 && ctype_isString (exprNode_getType (oneval))
8180 && ctype_isChar (exprNode_getType (newel)))
8182 exprNode_freeIniter (newel);
8186 if (exprNode_checkOneInit (newel, oneval))
8191 if (nerrors > 3 && exprNodeList_size (vals) > 6)
8194 (message ("Additional initialization errors "
8195 "for %s not reported",
8196 exprNode_unparse (el)),
8198 exprNode_freeIniter (newel);
8203 exprNode_freeIniter (newel);
8208 exprNode_freeIniter (newel);
8213 cstring_free (istring);
8216 } end_exprNodeList_elements;
8219 else if (ctype_isStruct (ctype_realType (t1)))
8221 uentryList fields = ctype_getFields (t1);
8224 if (uentryList_size (fields) != exprNodeList_size (vals))
8226 if (uentryList_size (fields) > exprNodeList_size (vals))
8228 hasError = optgenerror
8230 message ("Initializer block for "
8231 "%s has %d field%&, but %s has %d field%&: %q",
8232 exprNode_unparse (el),
8233 exprNodeList_size (vals),
8235 uentryList_size (fields),
8236 exprNodeList_unparse (vals)),
8241 hasError = optgenerror
8243 message ("Initializer block for "
8244 "%s has %d field%&, but %s has %d field%&: %q",
8245 exprNode_unparse (el),
8246 exprNodeList_size (vals),
8248 uentryList_size (fields),
8249 exprNodeList_unparse (vals)),
8255 exprNodeList_elements (vals, oneval)
8257 uentry thisfield = uentryList_getN (fields, i);
8259 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8261 uentry_getName (thisfield));
8263 if (exprNode_isDefined (newel))
8265 if (exprNode_checkOneInit (newel, oneval))
8270 exprNode_freeIniter (newel);
8274 } end_exprNodeList_elements;
8277 /* evans 2001-12-30: added to fix bug reported by Jim Zelenka */
8278 else if (ctype_isUnion (ctype_realType (t1)))
8280 uentryList fields = ctype_getFields (t1);
8284 ** Union initializers set the first member always.
8287 DPRINTF (("Union initializer: %s / %s",
8288 exprNode_unparse (el), ctype_unparse (ctype_realType (t1))));
8290 if (exprNodeList_size (vals) != 1)
8292 hasError = optgenerror
8294 message ("Initializer block for union "
8295 "%s has %d elements, union initializers should have one element: %q",
8296 exprNode_unparse (el),
8297 exprNodeList_size (vals),
8298 exprNodeList_unparse (vals)),
8303 exprNode oneval = exprNodeList_head (vals);
8304 uentry thisfield = uentryList_getN (fields, i);
8306 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8308 uentry_getName (thisfield));
8310 if (exprNode_isDefined (newel))
8312 if (exprNode_checkOneInit (newel, oneval))
8317 exprNode_freeIniter (newel);
8323 hasError = optgenerror
8325 message ("Initializer block used for "
8326 "%s where %t is expected: %s",
8327 exprNode_unparse (el), t1, exprNode_unparse (val)),
8333 if (exprNode_isDefined (val))
8335 doAssign (el, val, TRUE);
8337 if (!exprNode_matchType (t1, val))
8339 hasError = gentypeerror
8341 message ("Initial value of %s is type %t, "
8343 exprNode_unparse (el),
8344 t2, t1, exprNode_unparse (val)),
8354 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
8358 DPRINTF (("Initialization: %s", idDecl_unparse (t)));
8360 if (usymtab_exists (idDecl_observeId (t)))
8362 uentry ue = usymtab_lookup (idDecl_observeId (t));
8363 ret = exprNode_createId (ue);
8365 /*@i723 don't do this...but why? */
8367 ct = ctype_realishType (ret->typ);
8369 DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
8371 if (ctype_isUnknown (ct))
8373 if (uentry_isAnyTag (ue))
8377 message ("%s used but not previously declared: %s",
8378 uentry_ekindName (ue),
8379 idDecl_getName (t)),
8387 message ("Variable has unknown (implicitly int) type: %s",
8388 idDecl_getName (t)),
8400 DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
8402 ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
8403 /*!! fileloc_copy (g_currentloc)); */
8404 /*@i32!!! should get error without this */
8406 ret = exprNode_fromIdentifierAux (ue);
8409 ** No error - this happens in old style declarations:
8413 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8420 exprData_free (ret->edata, ret->kind);
8421 ret->edata = exprData_undefined;
8423 ret->exitCode = XK_NEVERESCAPE;
8424 ret->mustBreak = FALSE;
8425 ret->kind = XPR_INIT;
8429 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8431 exprNode ret = exprNode_makeInitializationAux (t);
8432 llassert (ret->edata == exprData_undefined);
8433 ret->edata = exprData_makeInit (t, exprNode_undefined);
8437 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8438 /*@only@*/ exprNode e)
8440 uentry ue = usymtab_lookup (idDecl_observeId (t));
8441 exprNode ret = exprNode_makeInitializationAux (t);
8442 fileloc loc = exprNode_loc (e);
8444 if (exprNode_isError (e))
8446 e = exprNode_createUnknown ();
8449 /* error: assume initializer is defined */
8450 sRef_setDefined (ret->sref, g_currentloc);
8454 ctype ct = ctype_realishType (ret->typ);
8459 ** was addSafeUse --- what's the problem?
8461 ** int x = 3, y = x ?
8464 exprData_free (ret->edata, ret->kind);
8465 ret->edata = exprData_makeInit (t, e);
8467 exprNode_checkUse (ret, e->sref, e->loc);
8469 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8471 exprNode lhs = exprNode_createId (ue);
8474 ** static storage should be undefined before initializing
8477 if (uentry_isStatic (ue))
8479 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8482 (void) exprNode_checkOneInit (lhs, e);
8484 if (uentry_isStatic (ue))
8486 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8489 exprNode_free (lhs);
8493 if (!exprNode_matchType (ct, e))
8495 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
8502 (exprNode_getType (e), e, exprNode_getType (ret), ret,
8504 ("Variable %q initialized to type %t, expects %t: %s",
8505 uentry_getName (ue), exprNode_getType (e),
8506 exprNode_getType (ret),
8507 exprNode_unparse (e)),
8513 if (uentry_isStatic (ue))
8515 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8518 doAssign (ret, e, TRUE);
8520 if (uentry_isStatic (ue))
8522 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8526 if (context_inIterDef ())
8528 /* should check if it is yield */
8529 uentry_setUsed (ue, loc);
8536 exprNode_mergeUSs (ret, e);
8540 exprNode exprNode_iter (/*@observer@*/ uentry name,
8541 /*@only@*/ exprNodeList alist,
8542 /*@only@*/ exprNode body,
8543 /*@observer@*/ uentry end)
8548 llassert (uentry_isValid (name));
8550 uentry_setUsed (name, exprNode_loc (body));
8552 ret = exprNode_createPartialCopy (body);
8553 iname = uentry_getName (name);
8555 if (uentry_isInvalid (end))
8557 llerror (FLG_ITERBALANCE,
8558 message ("Iter %s not balanced with end_%s", iname, iname));
8562 cstring ename = uentry_getName (end);
8564 if (!cstring_equalPrefixLit (ename, "end_"))
8566 llerror (FLG_ITERBALANCE, message ("Iter %s not balanced with end_%s: %s",
8567 iname, iname, ename));
8571 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8573 llerror (FLG_ITERBALANCE,
8574 message ("Iter %s not balanced with end_%s: %s",
8575 iname, iname, ename));
8579 cstring_free (ename);
8582 context_exitIterClause (body);
8584 ret->kind = XPR_ITER;
8585 ret->edata = exprData_makeIter (name, alist, body, end);
8587 if (uentry_isIter (name))
8589 (void) checkArgsReal (name, body,
8590 uentry_getParams (name), alist, TRUE, ret);
8593 cstring_free (iname);
8599 exprNode_iterNewId (/*@only@*/ cstring s)
8601 exprNode e = exprNode_new ();
8602 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8604 llassert (processingIterVars ());
8606 e->loc = context_getSaveLocation ();
8608 if (fileloc_isUndefined (e->loc))
8610 fileloc_free (e->loc);
8611 e->loc = fileloc_copy (g_currentloc);
8614 e->uses = sRefSet_new ();
8615 e->sets = sRefSet_new ();
8616 e->msets = sRefSet_new ();
8618 e->val = multiVal_unknown ();
8619 e->guards = guardSet_new ();
8621 e->isJumpPoint = FALSE;
8622 e->exitCode = XK_NEVERESCAPE;
8624 /*> missing fields, detected by splint <*/
8625 e->canBreak = FALSE;
8626 e->mustBreak = FALSE;
8627 e->etext = cstring_undefined;
8629 if (uentry_isYield (ue))
8631 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8632 fileloc_copy (e->loc),
8636 uue = usymtab_supEntrySrefReturn (uue);
8638 sr = uentry_getSref (uue);
8639 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8640 sr = uentry_getSref (uue);
8641 sRef_setDefined (sr, e->loc);
8643 e->typ = uentry_getType (uue);
8645 e->edata = exprData_makeId (uue);
8646 uentry_setUsed (uue, g_currentloc);
8652 sRef_setGlobalScope ();
8653 uue = uentry_makeVariableLoc (s, ctype_unknown);
8655 e->typ = ctype_unknown;
8656 e->edata = exprData_makeId (uue);
8658 uentry_setUsed (uue, e->loc);
8659 uentry_setHasNameError (uue);
8661 if (context_getFlag (FLG_REPEATUNRECOG))
8663 uentry_markOwned (uue);
8667 usymtab_supGlobalEntry (uue);
8670 sRef_clearGlobalScope ();
8672 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8679 exprNode_defineConstraints(e);
8684 exprNode_iterExpr (/*@returned@*/ exprNode e)
8686 if (!processingIterVars ())
8688 llcontbuglit ("checkIterParam: not in iter");
8692 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8695 if (exprNode_isDefined (e))
8697 if (fileloc_isDefined (e->loc))
8701 message ("Yield parameter is not simple identifier: %s",
8702 exprNode_unparse (e)),
8709 message ("Yield parameter is not simple identifier: %s",
8710 exprNode_unparse (e)),
8720 exprNode_iterId (/*@observer@*/ uentry c)
8724 llassert (processingIterVars ());
8726 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8729 if (uentry_isYield (ue))
8731 ctype ct = uentry_getType (ue);
8732 exprNode e = exprNode_createPlain (ct);
8733 cstring name = uentry_getName (c);
8734 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8736 uentry_setUsed (ue, g_currentloc);
8737 uentry_setHasNameError (ue);
8739 cstring_free (name);
8742 e->edata = exprData_makeId (le);
8743 e->loc = context_getSaveLocation ();
8744 e->sref = uentry_getSref (le);
8746 usymtab_supEntrySref (le);
8748 if (!context_inHeader ())
8752 message ("Yield parameter shadows local declaration: %q",
8753 uentry_getName (c)),
8754 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8756 uentry_showWhereDeclared (c);
8763 return (exprNode_fromIdentifierAux (c));
8766 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8768 exprNode ret = exprNode_create (ctype_unknown);
8770 ret->kind = XPR_ITERCALL;
8771 ret->edata = exprData_makeIterCall (name, alist);
8773 if (uentry_isIter (name))
8775 uentryList params = uentry_getParams (name);
8777 if (context_inIterDef ()
8778 && uentryList_size (params) == exprNodeList_size (alist))
8782 exprNodeList_elements (alist, arg)
8784 uentry parg = uentryList_getN (params, i);
8786 if (uentry_isYield (parg))
8788 uentry ue = exprNode_getUentry (arg);
8790 if (uentry_isValid (ue))
8797 } end_exprNodeList_elements;
8800 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8801 checkUnspecCall (ret, params, alist);
8807 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8809 if (exprNode_isDefined (e))
8812 if (e->sref == defref) /*@noaccess sRef@*/
8815 e->sref = sRef_makeUnknown ();
8816 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8827 return sRef_undefined;
8831 /*@observer@*/ cstring
8832 exprNode_unparseFirst (exprNode e)
8834 if (exprNode_isDefined (e))
8838 if (e->kind == XPR_STMTLIST
8839 || e->kind == XPR_COMMA || e->kind == XPR_COND)
8841 exprNode first = exprData_getPairA (e->edata);
8843 if (exprNode_isDefined (first))
8845 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8849 return (cstring_makeLiteralTemp ("..."));
8853 ret = cstring_elide (exprNode_unparse (e), 20);
8854 cstring_markOwned (ret);
8860 return cstring_makeLiteralTemp ("<error>");
8864 /*@observer@*/ cstring
8865 exprNode_unparse (/*@temp@*/ exprNode e)
8867 if (exprNode_isError (e))
8869 return cstring_makeLiteralTemp ("<error>");
8872 if (cstring_isDefined (e->etext))
8878 cstring ret = exprNode_doUnparse (e);
8880 /*@-modifies@*/ /* benevolent */
8887 /*@observer@*/ fileloc
8888 exprNode_loc (exprNode e)
8890 if (exprNode_isError (e))
8892 return (g_currentloc);
8901 ** executes exprNode e
8902 ** recursively rexecutes as though in original parse using
8903 ** information in e->edata
8906 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
8908 exprNodeList ret = exprNodeList_new ();
8910 exprNodeList_elements (e, current)
8912 exprNodeList_addh (ret, exprNode_effect (current));
8913 } end_exprNodeList_elements;
8918 static /*@only@*/ exprNode exprNode_effect (exprNode e)
8919 /*@globals internalState@*/
8921 bool innerEffect = inEffect;
8927 context_clearJustPopped ();
8929 if (exprNode_isError (e))
8931 ret = exprNode_undefined;
8936 ** Turn off expose and dependent transfer checking.
8937 ** Need to pass exposed internal nodes,
8938 ** [ copying would be a waste! ]
8939 ** [ Actually, I think I wasted a lot more time than its worth ]
8940 ** [ trying to do this. ]
8944 /*@-observertrans@*/
8945 /*@-dependenttrans@*/
8952 ret = exprNode_addParens (exprData_getUopTok (data),
8953 exprNode_effect (exprData_getUopNode (data)));
8956 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
8957 exprNode_effect (exprData_getOpB (data)),
8958 exprData_getOpTok (data));
8961 ret = exprNode_undefined;
8964 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
8965 exprNodeList_effect (exprData_getArgs (data)));
8978 cstring id = exprData_getId (data);
8979 uentry ue = usymtab_lookupSafe (id);
8981 ret = exprNode_fromIdentifierAux (ue);
8982 ret->loc = fileloc_update (ret->loc, e->loc);
8989 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
8990 exprNode_effect (exprData_getPairB (data)));
8993 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
8994 exprNode_effect (exprData_getOpB (data)),
8995 exprData_getOpTok (data));
8999 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
9000 exprData_getUopTok (data));
9003 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
9004 exprData_getUopTok (data));
9016 ret = exprNode_vaArg (exprData_getCastTok (data),
9017 exprNode_effect (exprData_getCastNode (data)),
9018 exprData_getCastType (data));
9022 ret = exprNode_cast (exprData_getCastTok (data),
9023 exprNode_effect (exprData_getCastNode (data)),
9024 exprData_getCastType (data));
9027 ret = exprNode_iterStart (exprData_getIterCallIter (data),
9029 (exprData_getIterCallArgs (data)));
9033 ret = exprNode_iter (exprData_getIterSname (data),
9034 exprNodeList_effect (exprData_getIterAlist (data)),
9035 exprNode_effect (exprData_getIterBody (data)),
9036 exprData_getIterEname (data));
9040 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
9041 exprNode_effect (exprData_getPairB (data)));
9045 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
9046 exprNode_effect (exprData_getTripleTest (data)),
9047 exprNode_effect (exprData_getTripleInc (data)));
9051 ret = exprNode_createTok (exprData_getTok (data));
9055 ret = exprNode_goto (exprData_getLiteral (data));
9056 ret->loc = fileloc_update (ret->loc, e->loc);
9060 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
9064 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
9068 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
9071 case XPR_NULLRETURN:
9072 ret = exprNode_nullReturn (exprData_getTok (data));
9076 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
9077 exprNode_effect (exprData_getPairB (data)));
9081 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
9082 exprNode_effect (exprData_getTripleTrue (data)),
9083 exprNode_effect (exprData_getTripleFalse (data)));
9086 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
9087 exprNode_effect (exprData_getPairB (data)));
9091 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
9092 exprNode_effect (exprData_getTripleTrue (data)),
9093 exprNode_effect (exprData_getTripleFalse (data)));
9096 ret = exprNode_whilePred (exprData_getSingle (data));
9100 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
9101 exprNode_effect (exprData_getPairB (data)));
9105 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
9106 exprNode_effect (exprData_getPairB (data)));
9110 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
9114 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
9115 exprData_getUopTok (data));
9119 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
9120 exprNode_effect (exprData_getPairB (data)));
9125 ret = exprNode_caseMarker
9126 (exprNode_effect (exprData_getSingle (data)),
9132 ret = exprNode_createTok (exprData_getTok (data));
9136 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
9137 exprNode_effect (exprData_getPairB (data)));
9141 ret = exprNode_makeInitialization
9142 (exprData_getInitId (data),
9143 exprNode_effect (exprData_getInitNode (data)));
9147 ret = exprNode_fieldAccessAux
9148 (exprNode_effect (exprData_getFieldNode (data)),
9149 exprNode_loc (exprData_getFieldNode (data)),
9150 cstring_copy (exprData_getFieldName (data)));
9154 ret = exprNode_arrowAccessAux
9155 (exprNode_effect (exprData_getFieldNode (data)),
9156 exprNode_loc (exprData_getFieldNode (data)),
9157 cstring_copy (exprData_getFieldName (data)));
9160 case XPR_STRINGLITERAL:
9174 /*@=observertrans@*/
9176 /*@=dependenttrans@*/
9187 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
9192 if (exprNode_isError (e))
9194 return cstring_undefined;
9202 ret = exprNode_rootVarName (exprData_getUopNode (data));
9205 ret = exprNode_rootVarName (exprData_getOpA (data));
9209 ret = exprData_getId (data);
9212 ret = idDecl_getName (exprData_getInitId (data));
9237 case XPR_NULLRETURN:
9259 case XPR_STRINGLITERAL:
9260 ret = cstring_undefined;
9267 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
9272 if (exprNode_isError (e))
9274 static /*@only@*/ cstring error = cstring_undefined;
9276 if (!cstring_isDefined (error))
9278 error = cstring_makeLiteral ("<error>");
9289 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
9292 ret = message ("%s %s %s",
9293 exprNode_unparse (exprData_getOpA (data)),
9294 lltok_unparse (exprData_getOpTok (data)),
9295 exprNode_unparse (exprData_getOpB (data)));
9298 ret = message ("%s(%q)",
9299 exprNode_unparse (exprData_getFcn (data)),
9300 exprNodeList_unparse (exprData_getArgs (data)));
9303 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
9306 ret = cstring_undefined;
9309 ret = message ("%s:", exprData_getId (data));
9313 ret = cstring_copy (exprData_getId (data));
9316 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
9317 exprNode_unparse (exprData_getPairB (data)));
9320 ret = message ("<body>");
9323 ret = message ("%s %s %s",
9324 exprNode_unparse (exprData_getOpA (data)),
9325 lltok_unparse (exprData_getOpTok (data)),
9326 exprNode_unparse (exprData_getOpB (data)));
9330 ret = message ("%s%s",
9331 lltok_unparse (exprData_getUopTok (data)),
9332 exprNode_unparse (exprData_getUopNode (data)));
9336 ret = message ("%s%s",
9337 exprNode_unparse (exprData_getUopNode (data)),
9338 lltok_unparse (exprData_getUopTok (data)));
9342 ret = message ("offsetof(%s,%q)",
9343 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
9344 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
9348 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9352 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
9356 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9360 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
9364 ret = message ("va_arg(%s, %q)",
9365 exprNode_unparse (exprData_getCastNode (data)),
9366 qtype_unparse (exprData_getCastType (data)));
9370 ret = message ("%q(%q)",
9371 uentry_getName (exprData_getIterCallIter (data)),
9372 exprNodeList_unparse (exprData_getIterCallArgs (data)));
9375 ret = message ("%q(%q) %s %q",
9376 uentry_getName (exprData_getIterSname (data)),
9377 exprNodeList_unparse (exprData_getIterAlist (data)),
9378 exprNode_unparse (exprData_getIterBody (data)),
9379 uentry_getName (exprData_getIterEname (data)));
9382 ret = message ("(%q)%s",
9383 qtype_unparse (exprData_getCastType (data)),
9384 exprNode_unparse (exprData_getCastNode (data)));
9388 ret = message ("%s %s",
9389 exprNode_unparse (exprData_getPairA (data)),
9390 exprNode_unparse (exprData_getPairB (data)));
9394 ret = message ("for (%s; %s; %s)",
9395 exprNode_unparse (exprData_getTripleInit (data)),
9396 exprNode_unparse (exprData_getTripleTest (data)),
9397 exprNode_unparse (exprData_getTripleInc (data)));
9401 ret = message ("goto %s", exprData_getLiteral (data));
9405 ret = cstring_makeLiteral ("continue");
9409 ret = cstring_makeLiteral ("break");
9413 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
9416 case XPR_NULLRETURN:
9417 ret = cstring_makeLiteral ("return");
9421 ret = message ("%s, %s",
9422 exprNode_unparse (exprData_getPairA (data)),
9423 exprNode_unparse (exprData_getPairB (data)));
9427 ret = message ("%s ? %s : %s",
9428 exprNode_unparse (exprData_getTriplePred (data)),
9429 exprNode_unparse (exprData_getTripleTrue (data)),
9430 exprNode_unparse (exprData_getTripleFalse (data)));
9433 ret = message ("if (%s) %s",
9434 exprNode_unparse (exprData_getPairA (data)),
9435 exprNode_unparse (exprData_getPairB (data)));
9439 ret = message ("if (%s) %s else %s",
9440 exprNode_unparse (exprData_getTriplePred (data)),
9441 exprNode_unparse (exprData_getTripleTrue (data)),
9442 exprNode_unparse (exprData_getTripleFalse (data)));
9445 ret = message ("while (%s) %s",
9446 exprNode_unparse (exprData_getPairA (data)),
9447 exprNode_unparse (exprData_getPairB (data)));
9451 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9455 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9459 ret = message ("do { %s } while (%s)",
9460 exprNode_unparse (exprData_getPairB (data)),
9461 exprNode_unparse (exprData_getPairA (data)));
9465 ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
9469 ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
9473 ret = message ("%s; %s",
9474 exprNode_unparse (exprData_getPairA (data)),
9475 exprNode_unparse (exprData_getPairB (data)));
9480 ret = cstring_makeLiteral ("default:");
9484 ret = message ("switch (%s) %s",
9485 exprNode_unparse (exprData_getPairA (data)),
9486 exprNode_unparse (exprData_getPairB (data)));
9491 ret = message ("case %s:",
9492 exprNode_unparse (exprData_getSingle (data)));
9496 if (exprNode_isError (exprData_getInitNode (data)))
9498 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9502 ret = message ("%q = %s",
9503 idDecl_unparseC (exprData_getInitId (data)),
9504 exprNode_unparse (exprData_getInitNode (data)));
9509 ret = message ("%s.%s",
9510 exprNode_unparse (exprData_getFieldNode (data)),
9511 exprData_getFieldName (data));
9515 ret = message ("%s->%s",
9516 exprNode_unparse (exprData_getFieldNode (data)),
9517 exprData_getFieldName (data));
9520 case XPR_STRINGLITERAL:
9521 if (ctype_isWideString (e->typ))
9523 ret = message ("L\"%s\"", exprData_getLiteral (data));
9527 ret = message ("\"%s\"", exprData_getLiteral (data));
9532 ret = cstring_copy (exprData_getLiteral (data));
9536 ret = cstring_makeLiteral ("<node>");
9544 exprNode_isInitializer (exprNode e)
9546 return (exprNode_isDefined (e)
9547 && e->kind == XPR_INIT);
9551 exprNode_isCharLit (exprNode e)
9553 if (exprNode_isDefined (e))
9555 return (multiVal_isChar (exprNode_getValue (e)));
9564 exprNode_isNumLit (exprNode e)
9566 if (exprNode_isDefined (e))
9568 return (multiVal_isInt (exprNode_getValue (e)));
9577 exprNode_isFalseConstant (exprNode e)
9579 if (exprNode_isDefined (e))
9581 cstring s = exprNode_rootVarName (e);
9583 if (cstring_equal (s, context_getFalseName ()))
9593 exprNode_matchLiteral (ctype expected, exprNode e)
9595 if (exprNode_isDefined (e))
9597 multiVal m = exprNode_getValue (e);
9599 if (multiVal_isDefined (m))
9601 if (multiVal_isInt (m))
9603 long int val = multiVal_forceInt (m);
9605 if (ctype_isDirectBool (ctype_realishType (expected)))
9609 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9617 if (ctype_isRealInt (expected))
9620 ** unsigned <- [ constant >= 0 is okay ]
9623 if (ctype_isUnsigned (expected))
9632 ** No checks on sizes of integers...maybe add
9636 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9637 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9638 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9640 if (context_getFlag (FLG_NUMLITERAL)
9641 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9647 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9651 else if (ctype_isChar (expected))
9655 else if (ctype_isArrayPtr (expected))
9658 ** evans 2001-10-14: We allow 0 to match any pointer, but only if the type matches or is void *.
9663 if (ctype_match (exprNode_getType (e), expected)
9664 || ctype_isVoidPointer (exprNode_getType (e)))
9674 else if (ctype_isAnyFloat (expected))
9676 return (context_getFlag (FLG_NUMLITERAL));
9683 else if (multiVal_isDouble (m))
9685 if (ctype_isAnyFloat (expected))
9690 else if (multiVal_isChar (m))
9692 char val = multiVal_forceChar (m);
9694 if (ctype_isChar (expected))
9696 if (ctype_isUnsigned (expected) && ((int)val) < 0)
9717 exprNode_matchType (ctype expected, exprNode e)
9721 if (!exprNode_isDefined (e)) return TRUE;
9723 actual = ctype_realishType (exprNode_getType (e));
9725 if (ctype_match (ctype_realishType (expected), actual))
9730 llassert (!exprNode_isError (e));
9731 return (exprNode_matchLiteral (expected, e));
9735 exprNode_matchTypes (exprNode e1, exprNode e2)
9740 if (!exprNode_isDefined (e1)) return TRUE;
9741 if (!exprNode_isDefined (e2)) return TRUE;
9744 ** realish type --- keep bools, bools
9747 t1 = ctype_realishType (exprNode_getType (e1));
9748 t2 = ctype_realishType (exprNode_getType (e2));
9750 if (ctype_match (t1, t2))
9755 DPRINTF (("Matching literal! %s %s %s %s",
9756 ctype_unparse (t1), exprNode_unparse (e2),
9757 ctype_unparse (t2), exprNode_unparse (e1)));
9759 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9767 exprNode_matchArgType (ctype ct, exprNode e)
9771 if (!exprNode_isDefined (e))
9776 et = ctype_realType (exprNode_getType (e));
9778 if (ctype_matchArg (ct, et)) return TRUE;
9780 llassert (!exprNode_isError (e));
9781 return (exprNode_matchLiteral (ct, e));
9784 static /*@only@*/ exprNodeSList
9785 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9787 if (exprNode_isDefined (e))
9789 if (e->kind == XPR_STMTLIST)
9791 return (exprNodeSList_append
9792 (exprNode_flatten (exprData_getPairA (e->edata)),
9793 exprNode_flatten (exprData_getPairB (e->edata))));
9795 else if (e->kind == XPR_BLOCK)
9797 return (exprNode_flatten (exprData_getSingle (e->edata)));
9801 return (exprNodeSList_singleton (e));
9805 return exprNodeSList_new ();
9808 static /*@exposed@*/ exprNode
9809 exprNode_lastStatement (/*@returned@*/ exprNode e)
9811 if (exprNode_isDefined (e))
9813 if (e->kind == XPR_STMTLIST)
9815 exprNode b = exprData_getPairB (e->edata);
9817 if (exprNode_isDefined (b))
9819 return exprNode_lastStatement (b);
9823 return exprNode_lastStatement (exprData_getPairA (e->edata));
9826 else if (e->kind == XPR_BLOCK)
9828 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
9836 return exprNode_undefined;
9839 static /*@exposed@*/ exprNode
9840 exprNode_firstStatement (/*@returned@*/ exprNode e)
9842 if (exprNode_isDefined (e))
9844 if (e->kind == XPR_STMTLIST)
9846 exprNode b = exprData_getPairA (e->edata);
9848 if (exprNode_isDefined (b))
9850 return exprNode_firstStatement (b);
9854 return exprNode_firstStatement (exprData_getPairB (e->edata));
9857 else if (e->kind == XPR_BLOCK)
9859 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
9867 return exprNode_undefined;
9871 exprNode_mergeUSs (exprNode res, exprNode other)
9873 if (exprNode_isDefined (res) && exprNode_isDefined (other))
9875 res->msets = sRefSet_union (res->msets, other->msets);
9876 res->sets = sRefSet_union (res->sets, other->sets);
9877 res->uses = sRefSet_union (res->uses, other->uses);
9882 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
9884 if (exprNode_isDefined (res))
9886 if (exprNode_isDefined (other1))
9888 res->sets = sRefSet_union (res->sets, other1->sets);
9889 res->msets = sRefSet_union (res->msets, other1->msets);
9890 res->uses = sRefSet_union (res->uses, other1->uses);
9892 if (exprNode_isDefined (other2))
9894 res->sets = sRefSet_union (res->sets, other2->sets);
9895 res->msets = sRefSet_union (res->msets, other2->msets);
9896 res->uses = sRefSet_union (res->uses, other2->uses);
9904 ** Reports errors is s is not defined.
9908 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
9910 if (exprNode_isDefined (e))
9912 e->uses = sRefSet_insert (e->uses, s);
9917 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
9919 if (sRef_isKnown (s) && !sRef_isConst (s))
9922 ** need to check all outer types are useable
9925 DPRINTF (("Check use: %s / %s",
9926 exprNode_unparse (e), sRef_unparse (s)));
9928 exprNode_addUse (e, s);
9930 if (!context_inProtectVars ())
9933 ** only report the deepest error
9936 sRef errorRef = sRef_undefined;
9937 sRef lastRef = sRef_undefined;
9938 bool deadRef = FALSE;
9939 bool unuseable = FALSE;
9940 bool errorMaybe = FALSE;
9942 while (sRef_isValid (s) && sRef_isKnown (s))
9944 ynm readable = sRef_isValidLvalue (s);
9946 DPRINTF (("Readable: %s / %s",
9947 sRef_unparseFull (s), ynm_unparse (readable)));
9949 if (!(ynm_toBoolStrict (readable)))
9951 if (ynm_isMaybe (readable))
9955 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
9956 deadRef = sRef_isPossiblyDead (errorRef);
9957 unuseable = sRef_isUnuseable (errorRef);
9964 deadRef = sRef_isDead (errorRef);
9965 unuseable = sRef_isUnuseable (errorRef);
9969 if (!sRef_isPartial (s))
9971 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
9972 sRef_setDefined (s, fileloc_undefined);
9976 s = sRef_getBaseSafe (s);
9979 if (sRef_isValid (errorRef))
9981 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
9982 && sRef_isPointer (errorRef))
9989 if (sRef_isThroughArrayFetch (errorRef))
9992 (FLG_STRICTUSERELEASED,
9993 message ("%q %q may be used after being released",
9994 sRef_unparseKindNamePlain (errorRef),
9995 sRef_unparse (errorRef)),
9998 sRef_showRefKilled (errorRef);
10000 if (sRef_isKept (errorRef))
10002 sRef_clearAliasState (errorRef, loc);
10008 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
10012 message ("%q %q %qused after being released",
10013 sRef_unparseKindNamePlain (errorRef),
10014 sRef_unparse (errorRef),
10015 cstring_makeLiteral (errorMaybe
10016 ? "may be " : "")),
10019 sRef_showRefKilled (errorRef);
10021 if (sRef_isKept (errorRef))
10023 sRef_clearAliasState (errorRef, loc);
10028 else if (unuseable)
10032 message ("%q %q%qused in inconsistent state",
10033 sRef_unparseKindName (errorRef),
10034 sRef_unparseOpt (errorRef),
10035 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10038 sRef_showStateInconsistent (errorRef);
10043 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
10047 message ("%q %q%qused before definition",
10048 sRef_unparseKindName (errorRef),
10049 sRef_unparseOpt (errorRef),
10050 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10053 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
10056 sRef_setDefined (errorRef, loc);
10058 if (sRef_isAddress (errorRef))
10060 sRef_setDefined (sRef_getRootBase (errorRef), loc);
10062 } /* end is error */
10070 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
10072 if (exprNode_isDefined (e) && sRef_isKnown (s))
10074 e->uses = sRefSet_insert (e->uses, s);
10079 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
10081 if (exprNode_isDefined (e))
10083 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
10088 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
10090 sRef defines = sRef_undefined;
10092 if (sRef_isValid (s) && !sRef_isNothing (s))
10094 uentry ue = sRef_getBaseUentry (s);
10096 if (uentry_isValid (ue))
10098 uentry_setLset (ue);
10101 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10103 voptgenerror (FLG_USEDEF,
10104 message ("Attempt to set unuseable storage: %q",
10109 if (sRef_isMeaningful (s))
10111 if (sRef_isDead (s))
10113 sRef base = sRef_getBaseSafe (s);
10115 if (sRef_isValid (base)
10116 && sRef_isDead (base))
10118 sRef_setPartial (s, exprNode_loc (e));
10121 defines = s; /* okay - modifies for only param */
10123 else if (sRef_isPartial (s))
10125 sRef eref = exprNode_getSref (e);
10127 if (!sRef_isPartial (eref))
10130 ** should do something different here???
10133 sRef_setDefinedComplete (eref, exprNode_loc (e));
10137 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
10140 if (sRef_isMeaningful (eref))
10149 else if (sRef_isAllocated (s))
10151 sRef eref = exprNode_getSref (e);
10154 if (!sRef_isAllocated (eref))
10156 sRef_setDefinedComplete (eref, exprNode_loc (e));
10160 sRef base = sRef_getBaseSafe (eref);
10162 if (sRef_isValid (base))
10164 sRef_setPdefined (base, exprNode_loc (e));
10172 sRef_setDefinedNCComplete (s, exprNode_loc (e));
10177 else /* not meaningful...but still need to insert it */
10183 if (exprNode_isDefined (e) && sRef_isValid (defines))
10185 e->sets = sRefSet_insert (e->sets, defines);
10190 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
10192 if (sRef_isValid (s) && !sRef_isNothing (s))
10194 uentry ue = sRef_getBaseUentry (s);
10196 if (uentry_isValid (ue))
10198 uentry_setLset (ue);
10201 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10203 voptgenerror (FLG_USEDEF,
10204 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
10208 if (sRef_isMeaningful (s))
10210 sRef_setDefinedComplete (s, exprNode_loc (e));
10213 if (exprNode_isDefined (e))
10215 e->msets = sRefSet_insert (e->msets, s);
10221 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
10223 checkAnyCall (fcn, cstring_undefined, params, args,
10224 FALSE, sRefSet_undefined, FALSE, 0);
10228 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
10229 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
10233 if (uentry_isYield (ucurrent))
10235 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
10236 exprNode_checkSet (current, current->sref);
10240 if (uentry_isSefParam (ucurrent))
10242 sRefSet sets = current->sets;
10243 sRef ref = exprNode_getSref (current);
10245 if (sRef_isMacroParamRef (ref))
10247 uentry ue = sRef_getUentry (ref);
10249 if (!uentry_isSefParam (ue))
10254 ("Parameter %d to %s is declared sef, but "
10255 "the argument is a macro parameter declared "
10257 argno, exprNode_unparse (fcn),
10258 exprNode_unparse (current)),
10259 exprNode_loc (current));
10263 if (!sRefSet_isEmpty (sets))
10265 sRefSet reported = sRefSet_undefined;
10267 sRefSet_realElements (current->sets, el)
10269 if (sRefSet_isSameNameMember (reported, el))
10271 ; /* don't report again */
10275 if (sRef_isUnconstrained (el))
10280 ("Parameter %d to %s is declared sef, but "
10281 "the argument calls unconstrained function %s "
10282 "(no guarantee it will not modify something): %s",
10283 argno, exprNode_unparse (fcn),
10284 sRef_unconstrainedName (el),
10285 exprNode_unparse (current)),
10286 exprNode_loc (current));
10293 ("Parameter %d to %s is declared sef, but "
10294 "the argument may modify %q: %s",
10295 argno, exprNode_unparse (fcn),
10297 exprNode_unparse (current)),
10298 exprNode_loc (current));
10301 } end_sRefSet_realElements;
10305 transferChecks_passParam (current, ucurrent, isSpec, fcn, argno, totargs);
10306 exprNode_mergeUSs (fcn, current);
10311 checkAnyCall (/*@dependent@*/ exprNode fcn,
10312 /*@dependent@*/ cstring fname,
10315 bool hasMods, sRefSet mods,
10320 int nargs = exprNodeList_size (args);
10325 ** concat all args ud's to f, add each arg sref as a use unless
10326 ** it was specified as "out", in which case it is a def.
10329 uentryList_reset (pn);
10332 ** aliasing checks:
10334 ** if paramn is only or unique, no other arg may alias argn
10337 exprNodeList_elements (args, current)
10341 if (exprNode_isDefined (current))
10343 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
10345 uentry ucurrent = uentryList_current (pn);
10347 if (specialArgs == 0
10348 || (paramno < specialArgs))
10350 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
10352 if (context_maybeSet (FLG_ALIASUNIQUE))
10354 if (uentry_isOnly (ucurrent)
10355 || uentry_isUnique (ucurrent))
10357 checkUniqueParams (fcn, current, args,
10358 paramno, ucurrent);
10363 else /* uentry is undefined */
10365 if (specialArgs == 0)
10367 exprNode_checkUseParam (current);
10370 exprNode_mergeUSs (fcn, current);
10373 uentryList_advanceSafe (pn);
10374 } end_exprNodeList_elements;
10380 sRefSet_allElements (mods, s)
10383 sRef rb = sRef_getRootBase (s);
10385 if (sRef_isFileOrGlobalScope (rb))
10387 context_usedGlobal (rb);
10390 fb = sRef_fixBaseParam (s, args);
10392 if (!sRef_isMacroParamRef (fb))
10394 if (sRef_isNothing (fb))
10400 if (sRef_isValid (fb))
10402 uentry ue = sRef_getBaseUentry (s);
10404 if (uentry_isValid (ue))
10406 uentry_setLset (ue);
10410 fcn->sets = sRefSet_insert (fcn->sets, fb);
10413 sRef_clearDerivedComplete (s);
10414 } end_sRefSet_allElements;
10420 if (context_hasMods ())
10422 if (context_maybeSet (FLG_MODUNCON))
10426 message ("Undetected modification possible "
10427 "from call to unconstrained function %s: %s",
10429 exprNode_unparse (fcn)),
10430 exprNode_loc (fcn));
10435 if (context_maybeSet (FLG_MODUNCONNOMODS)
10436 && !(context_inIterDef () || context_inIterEnd ()))
10439 (FLG_MODUNCONNOMODS,
10440 message ("Undetected modification possible "
10441 "from call to unconstrained function %s: %s",
10443 exprNode_unparse (fcn)),
10444 exprNode_loc (fcn));
10448 exprNode_checkSetAny (fcn, fname);
10452 void exprNode_checkUseParam (exprNode current)
10454 if (exprNode_isDefined (current))
10456 exprNode_checkUse (current, current->sref, current->loc);
10461 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10462 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10467 if (!ctype_match (tr1, tr2))
10469 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10470 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10472 DPRINTF (("No error: [%s] %s / [%s] %s",
10473 exprNode_unparse (e1), ctype_unparse (tr1),
10474 exprNode_unparse (e2), ctype_unparse (tr2)));
10478 (void) gentypeerror
10480 message ("Incompatible types for %s (%s, %s): %s %s %s",
10481 lltok_unparse (op),
10482 ctype_unparse (te1),
10483 ctype_unparse (te2),
10484 exprNode_unparse (e1), lltok_unparse (op),
10485 exprNode_unparse (e2)),
10488 ret = ctype_unknown;
10492 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
10494 ret = ctype_resolveNumerics (tr1, tr2);
10496 else if (!context_msgStrictOps ())
10498 if (ctype_isPointer (tr1))
10500 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10504 else if (ctype_isInt (tr2))
10510 ret = ctype_unknown;
10513 else if (ctype_isPointer (tr2))
10515 if (ctype_isPointer (tr1))
10519 else if (ctype_isInt (tr1))
10525 ret = ctype_unknown;
10530 ret = ctype_resolveNumerics (tr1, tr2);
10535 int opid = lltok_getTok (op);
10536 bool comparop = (opid == EQ_OP || opid == NE_OP
10537 || opid == TLT || opid == TGT
10538 || opid == LE_OP || opid == GE_OP);
10540 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10543 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10544 || (ctype_isBool (tr1) && ctype_isBool (tr2))
10545 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10551 if (ctype_sameName (te1, te2))
10555 message ("Operands of %s are non-numeric (%t): %s %s %s",
10556 lltok_unparse (op), te1,
10557 exprNode_unparse (e1), lltok_unparse (op),
10558 exprNode_unparse (e2)),
10565 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10566 lltok_unparse (op), te1, te2,
10567 exprNode_unparse (e1), lltok_unparse (op),
10568 exprNode_unparse (e2)),
10573 else if (!ctype_isNumeric (tr1))
10577 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10578 lltok_unparse (op), te1,
10579 exprNode_unparse (e1), lltok_unparse (op),
10580 exprNode_unparse (e2)),
10585 if (!ctype_isNumeric (tr2))
10589 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10590 lltok_unparse (op), te2,
10591 exprNode_unparse (e1), lltok_unparse (op),
10592 exprNode_unparse (e2)),
10597 ret = ctype_unknown;
10605 abstractOpError (ctype tr1, ctype tr2, lltok op,
10606 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10607 fileloc loc1, fileloc loc2)
10609 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10611 if (ctype_match (tr1, tr2))
10615 message ("Operands of %s are abstract type (%t): %s %s %s",
10616 lltok_unparse (op), tr1,
10617 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10624 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10625 lltok_unparse (op), tr1, tr2,
10626 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10630 else if (ctype_isRealAbstract (tr1))
10634 message ("Left operand of %s is abstract type (%t): %s %s %s",
10635 lltok_unparse (op), tr1,
10636 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10641 if (ctype_isRealAbstract (tr2))
10645 message ("Right operand of %s is abstract type (%t): %s %s %s",
10646 lltok_unparse (op), tr2,
10647 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10656 ** requies e1 and e2 and not error exprNode's.
10660 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10661 ** the rep of the abstract type is exposed.
10663 ** The order is very important:
10665 ** check rep expose (move into check transfer)
10671 ** This isn't really a sensible procedure, but the indententation
10672 ** was getting too deep.
10676 checkOneRepExpose (sRef ysr, sRef base,
10677 /*@notnull@*/ exprNode e1,
10678 /*@notnull@*/ exprNode e2, ctype ct,
10681 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
10682 || sRef_isOwned (ysr)
10683 || sRef_isExposed (ysr)))
10685 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10686 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10689 if (sRef_isIReference (ysr))
10691 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10696 ("Assignment of mutable component of parameter %q "
10697 "to component of abstract "
10698 "type %s exposes rep: %s = %s",
10699 sRef_unparse (base),
10700 ctype_unparse (ct),
10701 exprNode_unparse (e1), exprNode_unparse (e2)),
10709 ("Assignment of mutable component of parameter %q "
10710 "(through alias %q) to component of abstract "
10711 "type %s exposes rep: %s = %s",
10712 sRef_unparse (base),
10713 sRef_unparse (e2->sref),
10714 ctype_unparse (ct),
10715 exprNode_unparse (e1), exprNode_unparse (e2)),
10721 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10725 message ("Assignment of mutable parameter %q "
10726 "to component of abstract type %s "
10727 "exposes rep: %s = %s",
10728 sRef_unparse (base),
10729 ctype_unparse (ct),
10730 exprNode_unparse (e1),
10731 exprNode_unparse (e2)),
10738 message ("Assignment of mutable parameter %q "
10739 "(through alias %q) to "
10740 "component of abstract type %s exposes "
10742 sRef_unparse (base),
10743 sRef_unparse (e2->sref),
10744 ctype_unparse (ct),
10745 exprNode_unparse (e1),
10746 exprNode_unparse (e2)),
10752 if (sRef_isFileOrGlobalScope (s2b))
10754 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10758 message ("Assignment of global %q "
10760 "abstract type %s exposes rep: %s = %s",
10761 sRef_unparse (base),
10762 ctype_unparse (ct),
10763 exprNode_unparse (e1), exprNode_unparse (e2)),
10770 message ("Assignment of global %q (through alias %q) "
10772 "abstract type %s exposes rep: %s = %s",
10773 sRef_unparse (base),
10774 sRef_unparse (e2->sref),
10775 ctype_unparse (ct),
10776 exprNode_unparse (e1), exprNode_unparse (e2)),
10784 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
10786 DPRINTF (("Do assign: %s <- %s",
10787 exprNode_unparse (e1), exprNode_unparse (e2)));
10788 DPRINTF (("Ctype: %s", ctype_unparse (exprNode_getType (e1))));
10790 if (ctype_isRealFunction (exprNode_getType (e1))
10791 && !ctype_isRealPointer (exprNode_getType (e1)))
10795 message ("Invalid left-hand side of assignment (function type %s): %s",
10796 ctype_unparse (exprNode_getType (e1)),
10797 exprNode_unparse (e1)),
10801 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
10803 ctype t2 = exprNode_getType (e2);
10804 sRef sr = sRef_getRootBase (e1->sref);
10805 ctype ct = sRef_getType (sr);
10807 if (ctype_isAbstract (t2)
10808 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
10810 /* it is immutable, okay to reference */
10811 goto donerepexpose;
10814 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
10816 sRef s2b = sRef_getRootBase (e2->sref);
10817 sRef s1 = e1->sref;
10818 sRef s1b = sRef_getRootBase (s1);
10821 aliases = usymtab_canAlias (e2->sref);
10823 if (!sRef_similar (s2b, s1b)
10824 && !sRef_isExposed (s1)
10825 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
10827 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
10828 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
10829 && !sRef_isExposed (s2b))
10831 if (sRef_isIReference (e2->sref))
10836 ("Assignment of mutable component of parameter %q "
10837 "to component of abstract type %s exposes rep: %s = %s",
10838 sRef_unparse (s2b),
10839 ctype_unparse (ct),
10840 exprNode_unparse (e1), exprNode_unparse (e2)),
10847 message ("Assignment of mutable parameter %q to "
10848 "component of abstract type %s exposes rep: %s = %s",
10849 sRef_unparse (s2b),
10850 ctype_unparse (ct),
10851 exprNode_unparse (e1), exprNode_unparse (e2)),
10856 if (sRef_isFileOrGlobalScope (s2b))
10860 message ("Assignment of global %q to component of "
10861 "abstract type %s exposes rep: %s = %s",
10862 sRef_unparse (s2b),
10863 ctype_unparse (ct),
10864 exprNode_unparse (e1), exprNode_unparse (e2)),
10868 sRefSet_realElements (aliases, ysr)
10870 sRef base = sRef_getRootBase (ysr);
10872 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
10873 || sRef_sameName (base, s1b))
10875 ; /* error already reported or same sref */
10879 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
10881 } end_sRefSet_realElements;
10883 sRefSet_free (aliases);
10890 ** function variables don't really work...
10893 if (!ctype_isFunction (ctype_realType (e2->typ)))
10897 DPRINTF (("Check init: %s / %s",
10898 exprNode_unparse (e1), exprNode_unparse (e2)));
10899 transferChecks_initialization (e1, e2);
10903 transferChecks_assign (e1, e2);
10908 sRef fref = e2->sref;
10910 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
10911 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
10913 /* Need to typecheck the annotation on the parameters */
10915 if (ctype_isRealFunction (e1->typ)) {
10916 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
10917 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
10919 if (!uentryList_isMissingParams (e1p)
10920 && !uentryList_isMissingParams (e2p)
10921 && uentryList_size (e1p) > 0) {
10922 if (uentryList_size (e1p) == uentryList_size (e2p)) {
10925 uentryList_elements (e1p, el1) {
10928 el2 = uentryList_getN (e2p, n);
10930 uentry_checkMatchParam (el1, el2, n, e2);
10931 } end_uentryList_elements;
10937 if (exprNode_isStringLiteral (e2))
10939 exprNode_checkStringLiteralLength (exprNode_getType (e1), e2);
10942 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
10948 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
10949 updateAliases (e1, e2);
10954 checkMacroParen (exprNode e)
10956 if (exprNode_isError (e) || e->kind == XPR_CAST)
10962 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
10966 message ("Macro parameter used without parentheses: %s",
10967 exprNode_unparse (e)),
10974 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
10978 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
10982 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
10989 ** if e2 is a parameter or global derived location which
10990 ** can be modified (that is, e2 is a mutable abstract type,
10991 ** or a derived pointer), then e1 can alias e2.
10993 ** e1 can alias everything which e2 can alias.
10995 ** Also, if e1 is guarded, remove from guard sets!
10998 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
11000 if (!context_inProtectVars ())
11003 ** depends on types of e1 and e2
11006 sRef s1 = e1->sref;
11007 sRef s2 = e2->sref;
11008 ctype t1 = exprNode_getType (e1);
11010 /* handle pointer sRefs, record fields, arrays, etc... */
11012 if (!ctype_isRealSU (t1))
11014 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
11015 sRef_copyRealDerivedComplete (s1, s2);
11020 ** Fields should alias
11023 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
11026 if (ctype_isMutable (t1) && sRef_isKnown (s1))
11028 usymtab_clearAlias (s1);
11029 usymtab_addMustAlias (s1, s2);
11030 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
11034 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
11037 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
11039 usymtab_unguard (s1);
11044 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
11046 if (exprNode_isDefined (e))
11048 e->loc = fileloc_update (e->loc, loc);
11052 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
11058 static void checkUniqueParams (exprNode fcn,
11059 /*@notnull@*/ exprNode current,
11061 int paramno, uentry ucurrent)
11064 sRef thisref = exprNode_getSref (current);
11067 ** Check if any argument could match this argument.
11070 exprNodeList_elements (args, icurrent)
11074 if (iparamno != paramno)
11076 sRef sr = exprNode_getSref (icurrent);
11078 if (sRef_similarRelaxed (thisref, sr))
11080 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
11085 ("Parameter %d (%s) to function %s is declared %s but "
11086 "is aliased by parameter %d (%s)",
11088 exprNode_unparse (current),
11089 exprNode_unparse (fcn),
11090 alkind_unparse (uentry_getAliasKind (ucurrent)),
11091 iparamno, exprNode_unparse (icurrent)),
11097 sRefSet aliases = usymtab_canAlias (sr);
11099 sRefSet_allElements (aliases, asr)
11101 if (ctype_isUnknown (sRef_getType (thisref)))
11103 sRef_setType (thisref, uentry_getType (ucurrent));
11106 if (sRef_similarRelaxed (thisref, asr))
11108 if (sRef_isExternal (asr))
11110 if (sRef_isLocalState (thisref))
11116 sRef base = sRef_getRootBase (asr);
11118 if (!sRef_similar (sRef_getBase (asr), thisref))
11120 if (sRef_isUnique (base) || sRef_isOnly (base)
11121 || sRef_isKept (base)
11122 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
11123 || (sRef_isAddress (thisref)
11124 && sRef_isLocalVar (sRef_getRootBase (thisref))))
11126 ; /* okay, no error */
11131 (FLG_MAYALIASUNIQUE,
11133 ("Parameter %d (%s) to function %s is declared %s but "
11134 "may be aliased externally by parameter %d (%s)",
11136 exprNode_unparse (current),
11137 exprNode_unparse (fcn),
11138 alkind_unparse (uentry_getAliasKind (ucurrent)),
11139 iparamno, exprNode_unparse (icurrent)),
11150 ("Parameter %d (%s) to function %s is declared %s but "
11151 "is aliased externally by parameter %d (%s) through "
11154 exprNode_unparse (current),
11155 exprNode_unparse (fcn),
11156 alkind_unparse (uentry_getAliasKind (ucurrent)),
11157 iparamno, exprNode_unparse (icurrent),
11158 sRef_unparse (asr)),
11162 } end_sRefSet_allElements;
11163 sRefSet_free (aliases);
11166 } end_exprNodeList_elements;
11169 long exprNode_getLongValue (exprNode e) {
11172 if (exprNode_hasValue (e)
11173 && multiVal_isInt (exprNode_getValue (e)))
11175 value = multiVal_forceInt (exprNode_getValue (e));
11186 /*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
11188 if (exprNode_isDefined (p_e) )
11189 return ( p_e->loc );
11191 return fileloc_undefined;
11194 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
11197 ** Returns the location of the sequence point following e.
11199 ** Only works for statements (for now).
11202 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
11203 lltok t = exprData_getUopTok (e->edata);
11204 return fileloc_copy(lltok_getLoc (t));
11206 /* drl possible problem : warning fix
11207 llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
11209 return fileloc_undefined;
11213 exprNode exprNode_createNew(ctype c)
11217 ret = exprNode_createPlain (c);
11222 bool exprNode_isInitBlock (exprNode e)
11224 return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);