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_isStatement (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 size_t len = cstring_length (t);
820 if (context_getFlag (FLG_STRINGLITERALLEN))
822 if (len > size_fromInt (context_getValue (FLG_STRINGLITERALLEN)))
824 voptgenerror (FLG_STRINGLITERALLEN,
826 ("String literal length (%d) exceeds maximum "
827 "length (%d): \"%s\"",
829 context_getValue (FLG_STRINGLITERALLEN),
835 e->kind = XPR_STRINGLITERAL;
836 e->val = multiVal_makeString (cstring_copy (t));
837 e->edata = exprData_makeLiteral (t);
838 e->sref = sRef_makeConst (ctype_string);
840 if (context_getFlag (FLG_READONLYSTRINGS))
842 sRef_setAliasKind (e->sref, AK_STATIC, fileloc_undefined);
843 sRef_setExKind (e->sref, XO_OBSERVER, loc);
847 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
850 return (e); /* s released */
854 exprNode_wideStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
856 exprNode res = exprNode_stringLiteral (t, loc);
857 res->typ = ctype_makeWideString ();
862 exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
864 size_t len = size_fromInt (cstring_length (t) - 2);
865 char *ts = cstring_toCharsSafe (t);
866 char *s = cstring_toCharsSafe (cstring_create (len + 1));
868 llassert (*ts == '\"' && *(ts + len + 1) == '\"');
869 strncpy (s, ts+1, len);
872 return exprNode_rawStringLiteral (cstring_fromCharsO (s), loc);
875 exprNode exprNode_fromUIO (cstring c)
877 fileloc loc = context_getSaveLocation ();
878 exprNode e = exprNode_createPlain (ctype_unknown);
882 if (fileloc_isUndefined (loc))
884 loc = fileloc_copy (g_currentloc);
887 e->loc = loc; /* save loc was mangled */
890 if (usymtab_exists (c))
892 uentry ue = usymtab_lookupEither (c);
894 if (uentry_isDatatype (ue)
895 && uentry_isSpecified (ue))
898 (message ("%q: Specified datatype %s used in code, but not defined. "
899 "(Cannot continue reasonably from this error.)",
900 fileloc_unparse (e->loc), c));
908 llassertprint (!usymtab_exists (c), ("Entry exists: %s", c));
911 ** was supercedeGlobalEntry...is this better?
914 if (!context_inIterEnd ())
916 if (context_inMacro ())
918 if (context_getFlag (FLG_UNRECOG))
922 message ("Unrecognized identifier in macro definition: %s", c), e->loc);
926 flagcode_recordSuppressed (FLG_UNRECOG);
932 (FLG_UNRECOG, message ("Unrecognized identifier: %s", c), e->loc);
936 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
938 /* No alias errors for unrecognized identifiers */
939 sRef_setAliasKind (e->sref, AK_ERROR, loc);
944 exprNode exprNode_makeConstantString (cstring c, /*@only@*/ fileloc loc)
946 exprNode e = exprNode_createPlain (ctype_unknown);
949 e->sref = sRef_makeConst (ctype_string);
950 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
951 e->typ = ctype_string;
953 /* No alias errors for unrecognized identifiers */
954 sRef_setAliasKind (e->sref, AK_STATIC, loc);
955 sRef_setExKind (e->sref, XO_OBSERVER, loc);
960 exprNode exprNode_createId (/*@observer@*/ uentry c)
962 if (uentry_isValid (c))
964 exprNode e = exprNode_new ();
966 DPRINTF (("create id: %s", uentry_unparse (c)));
968 e->typ = uentry_getType (c);
970 if (uentry_isFunction (c)
971 && !sRef_isLocalVar (uentry_getSref (c)))
973 e->sref = sRef_undefined;
977 e->sref = uentry_getSref (c);
980 if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
982 sRef_setDefined (e->sref, fileloc_undefined);
986 ** yoikes! leaving this out was a heinous bug...that would have been
987 ** caught if i had splint working first. gag!
990 e->etext = cstring_undefined;
992 if (uentry_isEitherConstant (c))
995 e->val = multiVal_copy (uentry_getConstantValue (c));
1000 e->val = multiVal_unknown ();
1003 e->edata = exprData_makeId (c);
1004 e->loc = context_getSaveLocation ();
1006 if (fileloc_isUndefined (e->loc))
1008 fileloc_free (e->loc);
1009 e->loc = fileloc_copy (g_currentloc);
1012 e->guards = guardSet_new ();
1013 e->sets = sRefSet_new ();
1014 e->msets = sRefSet_new ();
1015 e->uses = sRefSet_new ();
1017 /*> missing fields, detected by splint <*/
1018 e->exitCode = XK_NEVERESCAPE;
1019 e->isJumpPoint = FALSE;
1020 e->canBreak = FALSE;
1021 e->mustBreak = FALSE;
1023 exprNode_defineConstraints(e);
1029 return exprNode_createUnknown ();
1033 /*@notnull@*/ exprNode
1034 exprNode_fromIdentifier (/*@observer@*/ uentry c)
1038 if (context_justPopped ()) /* watch out! c could be dead */
1040 uentry ce = usymtab_lookupSafe (LastIdentifier ());
1042 if (uentry_isValid (ce))
1048 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
1052 ret = exprNode_fromIdentifierAux (c);
1057 static void exprNode_checkStringLiteralLength (ctype t1, exprNode e2)
1059 multiVal mval = exprNode_getValue (e2);
1063 if (ctype_isFixedArray (t1))
1065 int nelements = long_toInt (ctype_getArraySize (t1));
1067 llassert (multiVal_isString (mval));
1068 slit = multiVal_forceString (mval);
1070 len = cstring_lengthExpandEscapes (slit);
1072 llassert (exprNode_isDefined (e2));
1074 if (len == nelements)
1078 temp = cstring_expandEscapes (slit);
1080 if (temp[len-1] == '\0')
1083 (FLG_STRINGLITNOROOMFINALNULL,
1084 message ("String literal with %d character%& "
1085 "is assigned to %s (no room for final null terminator): %s",
1088 exprNode_unparse (e2)),
1094 (FLG_STRINGLITNOROOM,
1095 message ("String literal with %d character%& "
1096 "is assigned to %s (no room for null terminator): %s",
1099 exprNode_unparse (e2)),
1103 else if (len > nelements)
1106 (FLG_STRINGLITTOOLONG,
1107 message ("String literal with %d character%& (counting null terminator) "
1108 "is assigned to %s (insufficient storage available): %s",
1111 exprNode_unparse (e2)),
1114 else if (len < nelements - 1)
1117 (FLG_STRINGLITSMALLER,
1118 message ("String literal with %d character%& is assigned to %s (possible waste of storage): %s",
1121 exprNode_unparse (e2)),
1131 static /*@only@*/ /*@notnull@*/ exprNode
1132 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
1134 exprNode e = exprNode_createId (c);
1137 uentry_setUsed (c, e->loc);
1139 if (uentry_isVar (c) && sRef_isFileOrGlobalScope (sr))
1141 checkGlobUse (c, FALSE, e);
1148 exprNode_isZero (exprNode e)
1150 if (exprNode_isDefined (e))
1152 multiVal m = exprNode_getValue (e);
1154 if (multiVal_isInt (m))
1156 return (multiVal_forceInt (m) == 0);
1164 exprNode_isNonNegative (exprNode e)
1166 if (exprNode_isDefined (e))
1168 multiVal m = exprNode_getValue (e);
1170 if (multiVal_isInt (m))
1172 return (multiVal_forceInt (m) >= 0);
1176 ** This is not always true if programmer defines enum
1177 ** values, but then the constant should be known.
1180 if (ctype_isEnum (ctype_realType (e->typ)))
1190 ** a[x] - uses a but NOT a[]
1191 ** result sref = a[] (set/use in assignment)
1193 ** The syntax x[a] is also legal in C, and has the same
1194 ** semantics. If ind is an array, and arr is an int, flip
1199 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
1202 ** error in arr, error propagates (no new messages)
1203 ** error in ind, assume valid and continue
1206 DPRINTF (("Array fetch: %s / %s",
1207 exprNode_unparse (e1), exprNode_unparse (e2)));
1209 if (exprNode_isError (e1))
1212 return (exprNode_makeError ());
1218 ctype carr = exprNode_getType (e1);
1219 ctype crarr = ctype_realType (carr);
1222 ** this sets up funny aliasing, that leads to spurious
1223 ** splint errors. Hence, the i2 comments.
1226 /* evans 2001-09-09 added ctype_isKnown so there is no swap when e1 type is unknown */
1227 if (ctype_isKnown (crarr)
1228 && !ctype_isRealArray (crarr)
1229 && ctype_isRealNumeric (crarr)
1230 && !exprNode_isError (e2)
1231 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1236 carr = exprNode_getType (arr);
1237 crarr = ctype_realType (carr);
1245 DPRINTF (("arr: %s", exprNode_unparse (arr)));
1247 if (sRef_possiblyNull (arr->sref))
1249 if (!usymtab_isGuarded (arr->sref))
1251 if (optgenerror (FLG_NULLDEREF,
1252 message ("Index of %s pointer %q: %s",
1253 sRef_nullMessage (arr->sref),
1254 sRef_unparse (arr->sref),
1255 exprNode_unparse (arr)),
1258 DPRINTF (("ref: %s", sRef_unparseFull (arr->sref)));
1259 sRef_showNullInfo (arr->sref);
1261 /* suppress future messages */
1262 sRef_setNullError (arr->sref);
1267 if (exprNode_isError (ind))
1269 if ((ctype_isArrayPtr (crarr)
1270 && !ctype_isFunction (crarr))
1271 || ctype_isUnknown (carr))
1273 exprNode ret = exprNode_createPartialCopy (arr);
1275 if (ctype_isKnown (carr))
1277 ret->typ = ctype_baseArrayPtr (crarr);
1281 ret->typ = ctype_unknown;
1284 ret->sref = sRef_makeArrayFetch (arr->sref);
1286 ret->kind = XPR_FETCH;
1289 ** Because of funny aliasing (when arr and ind are
1290 ** flipped) spurious errors would be reported here.
1293 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1294 checkSafeUse (ret, arr->sref);
1299 voptgenerror (FLG_TYPE,
1300 message ("Array fetch from non-array (%t): %s[%s]", carr,
1301 exprNode_unparse (e1), exprNode_unparse (e2)),
1303 exprNode_free (arr);
1304 return (exprNode_makeError ());
1309 if (!ctype_isForceRealInt (&(ind->typ)))
1311 ctype rt = ctype_realType (ind->typ);
1313 if (ctype_isChar (rt))
1317 message ("Array fetch using non-integer, %t: %s[%s]",
1319 exprNode_unparse (e1), exprNode_unparse (e2)),
1322 else if (ctype_isEnum (rt))
1326 message ("Array fetch using non-integer, %t: %s[%s]",
1328 exprNode_unparse (e1), exprNode_unparse (e2)),
1335 message ("Array fetch using non-integer, %t: %s[%s]",
1337 exprNode_unparse (e1), exprNode_unparse (e2)),
1341 multiVal_free (ind->val);
1342 ind->val = multiVal_unknown ();
1345 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1347 exprNode ret = exprNode_createSemiCopy (arr);
1348 multiVal m = exprNode_getValue (ind);
1350 ret->typ = ctype_baseArrayPtr (crarr);
1351 ret->kind = XPR_FETCH;
1353 if (multiVal_isInt (m))
1355 int i = (int) multiVal_forceInt (m);
1357 if (sRef_isValid (arr->sref)) {
1358 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1360 ret->sref = sRef_undefined;
1365 ret->sref = sRef_makeArrayFetch (arr->sref);
1368 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1369 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1370 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1372 /* (see comment on spurious errors above) */
1373 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1375 exprNode_checkUse (ret, ind->sref, ind->loc);
1376 exprNode_checkUse (ret, arr->sref, arr->loc);
1382 if (ctype_isUnknown (carr))
1384 exprNode ret = exprNode_createPartialCopy (arr);
1386 ret->kind = XPR_FETCH;
1387 ret->typ = ctype_unknown;
1388 ret->sets = sRefSet_union (ret->sets, ind->sets);
1389 ret->msets = sRefSet_union (ret->msets, ind->msets);
1390 ret->uses = sRefSet_union (ret->uses, ind->uses);
1392 /* (see comment on spurious errors above) */
1393 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1395 exprNode_checkUse (ret, ind->sref, ind->loc);
1396 exprNode_checkUse (ret, arr->sref, arr->loc);
1403 message ("Array fetch from non-array (%t): %s[%s]", carr,
1404 exprNode_unparse (e1), exprNode_unparse (e2)),
1407 exprNode_free (arr);
1408 exprNode_free (ind);
1410 return (exprNode_makeError ());
1420 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1421 exprNodeList args, exprNode ret)
1423 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1427 ** checkPrintfArgs --- checks arguments for printf-like functions
1428 ** Arguments before ... have already been checked.
1429 ** The argument before the ... is a char *.
1430 ** argno is the format string argument.
1434 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1435 exprNodeList args, exprNode ret, int argno)
1438 ** the last argument before the elips is the format string
1443 int nargs = exprNodeList_size (args);
1444 uentryList params = uentry_getParams (fcn);
1448 ** These should be ensured by checkSpecialFunction
1451 llassert (uentryList_size (params) == argno + 1);
1452 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1454 a = exprNodeList_getN (args, argno - 1);
1455 formatloc = fileloc_copy (exprNode_loc (a));
1457 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1458 && exprNode_knownStringValue (a))
1460 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1461 char *code = format;
1464 nargs = exprNodeList_size (args);
1466 while ((code = strchr (code, '%')) != NULL)
1468 char *origcode = code;
1469 cstring codetext = cstring_newEmpty ();
1470 char key = *(++code);
1471 ctype modtype = ctype_int;
1472 bool modified = FALSE;
1474 fileloc_addColumn (formatloc, code - ocode);
1476 codetext = cstring_appendChar (codetext, key);
1479 while (isFlagKey (key))
1482 codetext = cstring_appendChar (codetext, key);
1483 fileloc_incColumn (formatloc);
1486 if (key == 'm') /* skipped in syslog */
1491 /* ignore field width */
1492 while (isdigit ((int) key) != 0)
1495 codetext = cstring_appendChar (codetext, key);
1496 fileloc_incColumn (formatloc);
1499 /* ignore precision */
1503 codetext = cstring_appendChar (codetext, key);
1504 fileloc_incColumn (formatloc);
1507 ** In printf, '*' means: read the next arg as an int for the
1508 ** field width. This seems to be missing from my copy of the
1509 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1510 ** later) but never does.
1515 ; /* don't do anything --- handle later */
1519 while (isdigit ((int) key) != 0)
1522 codetext = cstring_appendChar (codetext, key);
1523 fileloc_incColumn (formatloc);
1530 modtype = ctype_sint; /* short */
1532 codetext = cstring_appendChar (codetext, key);
1533 fileloc_incColumn (formatloc);
1535 else if (key == 'l' || key == 'L')
1537 modtype = ctype_lint; /* long */
1539 codetext = cstring_appendChar (codetext, key);
1540 fileloc_incColumn (formatloc);
1542 if (key == 'l' || key == 'L') {
1543 modtype = ctype_llint; /* long long */
1545 codetext = cstring_appendChar (codetext, key);
1546 fileloc_incColumn (formatloc);
1554 /* now, key = type of conversion to apply */
1556 fileloc_incColumn (formatloc);
1564 message ("No argument corresponding to %q format "
1565 "code %d (%%%s): \"%s\"",
1566 uentry_getName (fcn),
1568 cstring_fromChars (format)),
1571 if (fileloc_isDefined (formatloc)
1572 && context_getFlag (FLG_SHOWCOL))
1574 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1582 a = exprNodeList_getN (args, i);
1585 if (!exprNode_isError (a))
1591 case '*': /* int argument for fieldwidth */
1592 expecttype = ctype_int;
1593 *(--code) = '%'; /* convert it for next code */
1594 fileloc_subColumn (formatloc, 1);
1595 /*@switchbreak@*/ break;
1598 expecttype = ctype_combine (ctype_uint, modtype);
1599 /*@switchbreak@*/ break;
1601 case 'i': /* int argument */
1603 expecttype = ctype_combine (ctype_int, modtype);
1604 /*@switchbreak@*/ break;
1606 case 'x': /* unsigned int */
1608 expecttype = ctype_combine (ctype_uint, modtype);
1610 /*@switchbreak@*/ break;
1616 case 'f': /* double */
1617 expecttype = ctype_combine (ctype_double, modtype);
1618 /*@switchbreak@*/ break;
1620 case 'c': /* int converted to char (check its a char?) */
1621 expecttype = ctype_makeConj (ctype_int,
1622 ctype_makeConj (ctype_char,
1625 /* evans 2001-10-05 - changed to reflect correct ISO spec:
1626 int converted to char */
1628 /* expecttype = ctype_makeConj (ctype_char, ctype_uchar); */
1629 /*@switchbreak@*/ break;
1631 case 's': /* string */
1632 expecttype = ctype_string;
1633 /*@switchbreak@*/ break;
1636 while (((key = *(++code)) != ']')
1639 codetext = cstring_appendChar (codetext, key);
1640 fileloc_incColumn (formatloc);
1646 (message ("Bad character set format: %s",
1647 cstring_fromChars (origcode)));
1650 expecttype = ctype_string;
1651 /*@switchbreak@*/ break;
1653 case 'p': /* pointer */
1654 expecttype = ctype_makePointer (ctype_void);
1655 /* need not be defined */
1656 uentry_setDefState (regArg, SS_RELDEF);
1657 sRef_setPosNull (uentry_getSref (regArg),
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;
2193 expecttype = ctype_makePointer (ctype_void);
2194 /* need not be defined */
2195 uentry_setDefState (regArg, SS_RELDEF);
2196 sRef_setPosNull (uentry_getSref (regArg),
2199 /*@switchbreak@*/ break;
2200 case 'l': expecttype = filelocType; break;
2201 case '&': /* a wee bit of a hack methinks */
2202 expecttype = ctype_int;
2204 case 'r': expecttype = ctype_bool; break;
2206 expecttype = ctype_unknown;
2209 message ("Unrecognized format code: %s",
2210 cstring_fromChars (origcode)),
2211 fileloc_isDefined (formatloc)
2212 ? formatloc : g_currentloc);
2215 /*@=loopswitchbreak@*/
2217 if (!(exprNode_matchArgType (expecttype, a)))
2219 if (ctype_isVoidPointer (expecttype)
2220 && ctype_isRealAbstract (a->typ)
2221 && (context_getFlag (FLG_ABSTVOIDP)))
2227 if (llgenformattypeerror
2228 (expecttype, exprNode_undefined,
2230 message ("Format argument %d to %q (%%%s) expects "
2233 uentry_getName (fcn),
2234 codetext, expecttype,
2235 a->typ, exprNode_unparse (a)),
2238 if (fileloc_isDefined (formatloc)
2239 && context_getFlag (FLG_SHOWCOL))
2242 (cstring_makeLiteral
2243 ("Corresponding format code"),
2250 if (ctype_equal (expecttype, cstringType))
2254 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2255 uentry_fixupSref (csOnlyArg);
2259 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2260 uentry_fixupSref (csArg);
2265 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2266 uentry_fixupSref (regArg);
2272 cstring_free (codetext);
2277 voptgenerror (FLG_TYPE,
2278 message ("Format string for %q has %d arg%&, given %d",
2279 uentry_getName (fcn), i - argno, nargs -argno),
2285 /* no checking possible for compile-time unknown format strings */
2288 fileloc_free (formatloc);
2292 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2293 /*@notnull@*/ exprNode e2,
2299 bool hadUncon = FALSE;
2301 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
2302 sRefSet_hasUnconstrained (sets2))
2305 (FLG_EVALORDERUNCON,
2307 ("Expression may have undefined behavior (%q used in right operand "
2308 "may set global variable %q used in left operand): %s %s %s",
2309 sRefSet_unparseUnconstrained (sets2),
2310 sRef_unparse (sRef_getRootBase (e1->sref)),
2311 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2315 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
2316 sRefSet_hasUnconstrained (sets1))
2319 (FLG_EVALORDERUNCON,
2321 ("Expression has undefined behavior (%q used in left operand "
2322 "may set global variable %q used in right operand): %s %s %s",
2323 sRefSet_unparseUnconstrained (sets1),
2324 sRef_unparse (e2->sref),
2325 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2329 sRefSet_realElements (e1->uses, sr)
2331 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2336 ("Expression has undefined behavior (left operand uses %q, "
2337 "modified by right operand): %s %s %s",
2339 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2342 } end_sRefSet_realElements;
2344 sRefSet_realElements (sets1, sr)
2346 if (sRef_isMeaningful (sr))
2348 if (sRef_same (sr, e2->sref))
2353 ("Expression has undefined behavior (value of right operand "
2354 "modified by left operand): %s %s %s",
2355 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2358 else if (sRefSet_member (e2->uses, sr))
2363 ("Expression has undefined behavior (left operand modifies %q, "
2364 "used by right operand): %s %s %s",
2366 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2371 if (sRefSet_member (sets2, sr))
2373 if (sRef_isUnconstrained (sr))
2381 hadUncon = optgenerror
2382 (FLG_EVALORDERUNCON,
2384 ("Expression may have undefined behavior. Left operand "
2385 "calls %q; right operand calls %q. The unconstrained "
2386 "functions may modify global state used by "
2387 "the other operand): %s %s %s",
2388 sRefSet_unparseUnconstrained (sets1),
2389 sRefSet_unparseUnconstrained (sets2),
2390 exprNode_unparse (e1), lltok_unparse (op),
2391 exprNode_unparse (e2)),
2400 ("Expression has undefined behavior (both "
2401 "operands modify %q): %s %s %s",
2403 exprNode_unparse (e1),
2404 lltok_unparse (op), exprNode_unparse (e2)),
2410 } end_sRefSet_realElements;
2413 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2415 bool hasError = FALSE;
2417 if (exprNode_isError (e1) || exprNode_isError (e2))
2422 if (sRefSet_member (e2->sets, e1->sref))
2424 if (e2->kind == XPR_CALL)
2430 hasError = optgenerror
2432 message ("Expression has undefined behavior "
2433 "(value of left operand %s is modified "
2434 "by right operand %s): %s %s %s",
2435 exprNode_unparse (e1),
2436 exprNode_unparse (e2),
2437 exprNode_unparse (e1), lltok_unparse (op),
2438 exprNode_unparse (e2)),
2443 if (context_getFlag (FLG_EVALORDERUNCON))
2445 if (sRefSet_member (e2->msets, e1->sref))
2447 if (e2->kind == XPR_CALL)
2453 hasError = optgenerror
2456 ("Expression has undefined behavior (value of left "
2457 "operand may be modified by right operand): %s %s %s",
2458 exprNode_unparse (e1), lltok_unparse (op),
2459 exprNode_unparse (e2)),
2467 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2469 if (context_maybeSet (FLG_EVALORDERUNCON))
2471 checkExpressionDefinedAux (e1, e2, e1->msets,
2472 e2->msets, op, FLG_EVALORDERUNCON);
2477 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2480 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2481 exprNodeList args, bool isIter, exprNode ret)
2485 if (!exprNode_isError (f))
2487 if (!uentryList_isMissingParams (cl))
2489 int nargs = exprNodeList_size (args);
2490 int expectargs = uentryList_size (cl);
2494 if (expectargs == 0)
2502 message ("Iter %q invoked with %d args, "
2504 uentry_getName (fcn),
2512 message ("Function %s called with %d args, "
2514 exprNode_unparse (f), nargs),
2521 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2523 exprNodeList_reset (args);
2525 uentryList_elements (cl, current)
2527 ctype ct = uentry_getType (current);
2530 if (ctype_isElips (ct))
2533 ** do special checking for printf/scanf library functions
2535 ** this is kludgey code, just for handling the special case
2539 if (uentry_isPrintfLike (fcn))
2541 checkPrintfArgs (f, fcn, args, ret, i);
2544 else if (uentry_isScanfLike (fcn))
2546 checkScanfArgs (f, fcn, args, ret, i);
2549 else if (uentry_isMessageLike (fcn))
2551 checkMessageArgs (f, fcn, args, i);
2556 llassert (!uentry_isSpecialFunction (fcn));
2559 nargs = expectargs; /* avoid errors */
2564 if (i >= nargs) break;
2566 a = exprNodeList_current (args);
2567 exprNodeList_advance (args);
2571 if (exprNode_isError (a))
2578 probably necessary? I'm not sure about this one
2579 checkMacroParen (a);
2582 f->guards = guardSet_union (f->guards, a->guards);
2584 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2586 if (!(exprNode_matchArgType (ct, a)))
2588 DPRINTF (("Args mismatch!"));
2590 if (ctype_isVoidPointer (ct)
2591 && (ctype_isPointer (a->typ)
2592 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2597 ("Pointer to abstract type (%t) used "
2599 "(arg %d to %q): %s",
2601 uentry_getName (fcn),
2602 exprNode_unparse (a)),
2610 (ct, exprNode_undefined,
2613 ("Iter %q expects arg %d to "
2614 "be %t gets %t: %s",
2615 uentry_getName (fcn),
2616 i, ct, a->typ, exprNode_unparse (a)),
2627 ("Function %q expects arg %d to be %t gets %t: %s",
2628 uentry_getName (fcn),
2629 i, ct, a->typ, exprNode_unparse (a)),
2632 DPRINTF (("Types: %s / %s",
2634 ctype_unparse (a->typ)));
2638 ** Clear null marker for abstract types.
2639 ** (It is not revealed, so suppress future messages.)
2642 if (ctype_isAbstract (a->typ))
2644 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2651 } end_uentryList_elements ;
2654 if (expectargs != nargs) /* note: not != since we may have ... */
2656 if (ctype_isElips (last))
2660 message ("Function %s called with %d args, expects at least %d",
2661 exprNode_unparse (f),
2662 nargs, expectargs - 1),
2671 message ("Iter %q invoked with %d args, expects %d",
2672 uentry_getName (fcn), nargs, expectargs),
2679 message ("Function %s called with %d args, expects %d",
2680 exprNode_unparse (f),
2693 ** Check for undefined code sequences in function arguments:
2695 ** one parameter sets something used by another parameter
2696 ** one parameter sets something set by another parameter
2700 checkSequencingOne (exprNode f, exprNodeList args,
2701 /*@notnull@*/ exprNode el, int argno)
2704 ** Do second loop, iff +undefunspec
2708 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2710 for (checkloop = 0; checkloop < numloops; checkloop++)
2716 thissets = el->sets;
2720 llassert (checkloop == 1);
2721 thissets = el->msets;
2724 sRefSet_realElements (thissets, thisset)
2728 /*@access exprNodeList@*/
2729 for (j = 0; j < args->nelements; j++)
2731 exprNode jl = args->elements[j];
2732 int thisargno = j + 1;
2734 if (thisargno != argno && exprNode_isDefined (jl))
2736 sRefSet otheruses = jl->uses;
2738 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
2739 sRefSet_hasUnconstrained (thissets))
2742 (FLG_EVALORDERUNCON,
2745 ("%q used in argument %d may set "
2746 "global variable %q used by argument %d: %s(%q)",
2747 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2750 sRef_unparse (sRef_getRootBase (jl->sref)),
2752 exprNode_unparse (f), exprNodeList_unparse (args)),
2756 if (sRefSet_member (otheruses, thisset))
2758 if (sRef_isUnconstrained (thisset))
2761 (FLG_EVALORDERUNCON,
2763 ("Unconstrained functions used in arguments %d (%q) "
2764 "and %d (%s) may modify "
2765 "or use global state in undefined way: %s(%q)",
2767 sRefSet_unparseUnconstrainedPlain (otheruses),
2769 sRef_unconstrainedName (thisset),
2770 exprNode_unparse (f),
2771 exprNodeList_unparse (args)),
2779 ("Argument %d modifies %q, used by argument %d "
2780 "(order of evaluation of actual parameters is "
2781 "undefined): %s(%q)",
2782 argno, sRef_unparse (thisset), thisargno,
2783 exprNode_unparse (f), exprNodeList_unparse (args)),
2789 sRefSet othersets = jl->sets;
2791 if (sRefSet_member (othersets, thisset))
2793 if (sRef_isUnconstrained (thisset))
2796 (FLG_EVALORDERUNCON,
2798 ("Unconstrained functions used in "
2799 "arguments %d (%q) and %d (%s) may modify "
2800 "or use global state in undefined way: %s(%q)",
2802 sRefSet_unparseUnconstrainedPlain (othersets),
2804 sRef_unconstrainedName (thisset),
2805 exprNode_unparse (f), exprNodeList_unparse (args)),
2813 ("Argument %d modifies %q, set by argument %d (order of"
2814 " evaluation of actual parameters is undefined): %s(%q)",
2815 argno, sRef_unparse (thisset), thisargno,
2816 exprNode_unparse (f), exprNodeList_unparse (args)),
2823 /*@noaccess exprNodeList@*/
2824 } end_sRefSet_realElements;
2829 checkSequencing (exprNode f, exprNodeList args)
2831 if (exprNodeList_size (args) > 1)
2836 /*@access exprNodeList*/
2838 for (i = 0; i < args->nelements; i++)
2840 el = args->elements[i];
2842 if (!exprNode_isError (el))
2844 checkSequencingOne (f, args, el, i + 1);
2847 /*@noaccess exprNodeList*/
2852 ** requires le = exprNode_getUentry (f)
2856 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2857 uentry le, exprNodeList args,
2858 /*@notnull@*/ exprNode ret, int specialArgs)
2860 bool isSpec = FALSE;
2861 bool hasMods = FALSE;
2863 globSet usesGlobs = globSet_undefined;
2864 sRefSet mods = sRefSet_undefined;
2865 bool freshMods = FALSE;
2866 uentryList params = uentryList_undefined;
2868 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2871 ** check globals and modifies
2876 if (!uentry_isValid (le))
2878 ctype fr = ctype_realType (f->typ);
2880 if (ctype_isFunction (fr))
2882 params = ctype_argsFunction (fr);
2886 params = uentryList_missingParams;
2889 if (!context_getFlag (FLG_MODNOMODS)
2890 && !context_getFlag (FLG_GLOBUNSPEC))
2892 checkUnspecCall (f, params, args);
2898 fname = uentry_rawName (le);
2902 if (uentry_isFunction (le))
2904 params = uentry_getParams (le);
2905 mods = uentry_getMods (le);
2906 hasMods = uentry_hasMods (le);
2907 usesGlobs = uentry_getGlobs (le);
2908 isSpec = uentry_isSpecified (le);
2910 else /* not a function */
2912 ctype ct = ctype_realType (uentry_getType (le));
2914 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2915 ("checkModGlobs: uentry not a function: %s",
2916 uentry_unparse (le)));
2918 params = ctype_argsFunction (ct);
2919 return; /*@32 ! remove this? */
2928 globSet_allElements (usesGlobs, el)
2930 if (sRef_isValid (el))
2932 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2934 context_usedGlobal (el);
2935 exprNode_checkUse (f, el, f->loc);
2937 if (context_checkInternalUse ())
2939 if (!context_globAccess (el))
2941 if (sRef_isSystemState (el)
2942 && !context_getFlag (FLG_MODFILESYSTEM))
2951 ("Called procedure %s may access %q, but "
2952 "globals list does not include globals %s",
2953 exprNode_unparse (f),
2955 cstring_makeLiteralTemp (sRef_isInternalState (el)
2963 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2969 uentry gle = sRef_getUentry (el);
2970 sRef sr = sRef_updateSref (el);
2972 if (sRef_isUndefGlob (el))
2974 sRef_setDefined (sr, f->loc);
2975 exprNode_checkSet (f, sr);
2983 if (sRef_isAllocated (el))
2985 exprNode_checkSet (f, sr);
2989 if (sRef_isStateUndefined (sr))
2994 ("%s %q used by function undefined before call: %s",
2995 sRef_getScopeName (sr),
2997 exprNode_unparse (f)),
2999 sRef_setDefined (sr, f->loc);
3001 exprNode_checkUse (f, sr, f->loc);
3004 checkGlobUse (gle, TRUE, f);
3007 if (sRef_isKilledGlob (el))
3009 sRef_kill (sr, f->loc);
3010 context_usedGlobal (sr);
3014 } end_globSet_allElements;
3020 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
3022 sRefSet smods = sRefSet_undefined;
3025 ** NEED to check for modifies anything
3029 ** check each sRef that called function modifies (ml), is
3035 sRefSet_allElements (mods, s) /* s is something which may be modified */
3037 DPRINTF (("Check modify: %s", sRef_unparse (s)));
3039 if (sRef_isKindSpecial (s))
3041 if (sRef_isSpecInternalState (s))
3043 if (context_getFlag (FLG_MODINTERNALSTRICT))
3045 exprNode_checkCallModifyVal (s, args, f, ret);
3049 sRefSet mmods = context_modList ();
3051 sRefSet_allElements (mmods, el)
3053 if (sRef_isInternalState (el))
3055 sRef_setModified (el);
3057 } end_sRefSet_allElements ;
3062 exprNode_checkCallModifyVal (s, args, f, ret);
3067 sRef rb = sRef_getRootBase (s);
3069 if (sRef_isFileOrGlobalScope (rb))
3071 context_usedGlobal (rb);
3074 if (sRef_isFileStatic (s)
3075 && !fileId_equal (fileloc_fileId (f->loc),
3076 fileloc_fileId (uentry_whereDefined (le))))
3078 smods = sRefSet_insert (smods, s);
3082 exprNode_checkCallModifyVal (s, args, f, ret);
3085 } end_sRefSet_allElements;
3090 ** Static elements in modifies set can have nasty consequences.
3091 ** (I think...have not been able to reproduce a possible bug.)
3094 if (!sRefSet_isDefined (smods))
3096 mods = sRefSet_newCopy (mods);
3099 sRefSet_allElements (smods, el)
3101 bool res = sRefSet_delete (mods, el);
3104 } end_sRefSet_allElements;
3106 sRefSet_free (smods);
3111 else if (sRefSet_isDefined (mods))
3112 { /* just check observers */
3115 sRefSet_allElements (mods, s) /* s is something which may be modified */
3117 sRef rb = sRef_getRootBase (s);
3121 if (sRef_isParam (rb))
3123 sRef b = sRef_fixBaseParam (s, args);
3125 if (sRef_isObserver (b))
3127 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
3131 message ("Function call may modify observer%q: %s",
3132 sRef_unparsePreOpt (b), exprNode_unparse (e)),
3135 sRef_showExpInfo (b);
3139 } end_sRefSet_allElements;
3143 if (!hasMods) /* no specified modifications */
3145 if (context_getFlag (FLG_MODOBSERVERUNCON))
3147 exprNodeList_elements (args, e)
3149 if (exprNode_isDefined (e))
3151 sRef s = exprNode_getSref (e);
3153 if (sRef_isObserver (s)
3154 && ctype_isMutable (sRef_getType (s)))
3157 (FLG_MODOBSERVERUNCON,
3159 ("Call to unconstrained function %s may modify observer%q: %s",
3160 exprNode_unparse (f),
3161 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3164 sRef_showExpInfo (s);
3168 } end_exprNodeList_elements;
3173 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3175 ret->uses = sRefSet_union (ret->uses, f->uses);
3176 ret->sets = sRefSet_union (ret->sets, f->sets);
3177 ret->msets = sRefSet_union (ret->msets, f->msets);
3182 ** Spurious errors reported, because splint can't tell
3183 ** mods must be fresh if freshMods is true.
3186 /*@i@*/ sRefSet_free (mods);
3192 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3194 if (uentry_isVar (glob))
3196 if (context_inFunctionLike ())
3198 sRef sr = uentry_getSref (glob);
3200 context_usedGlobal (sr);
3202 if (context_checkGlobUse (glob))
3204 if (!context_globAccess (sr))
3210 message ("Called procedure %s may access %s %q",
3211 exprNode_unparse (e),
3212 sRef_unparseScope (sr),
3213 uentry_getName (glob)),
3220 message ("Undocumented use of %s %s",
3221 sRef_unparseScope (sr),
3222 exprNode_unparse (e)),
3231 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3236 reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
3238 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3239 exprNode_unparse (f), exprNodeList_unparse (args),
3240 uentry_unparseFull (le),
3241 stateClauseList_unparse (uentry_getStateClauseList (le))));
3243 if (uentry_isValid (le) && uentry_isFunction (le))
3245 stateClauseList sclauses = uentry_getStateClauseList (le);
3247 if (stateClauseList_isDefined (sclauses))
3249 DPRINTF (("Reflect ensures: %s / %s / %s",
3250 uentry_unparse (le),
3251 exprNode_unparse (f), exprNodeList_unparse (args)));
3253 stateClauseList_elements (sclauses, cl)
3255 if (stateClause_hasEnsures (cl))
3257 /* Same in usymtab.c:1904 */
3258 if (stateClause_setsMetaState (cl))
3260 qual q = stateClause_getMetaQual (cl);
3261 annotationInfo ainfo = qual_getAnnotationInfo (q);
3262 metaStateInfo minfo = annotationInfo_getState (ainfo);
3263 cstring key = metaStateInfo_getName (minfo);
3264 int mvalue = annotationInfo_getValue (ainfo);
3266 sRefSet osrs = sRefSet_undefined;
3269 if (stateClause_isGlobal (cl))
3271 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3276 srs = stateClause_getRefs (cl);
3279 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3282 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3284 sRefSet_elements (srs, sel)
3288 if (sRef_isResult (sRef_getRootBase (sel)))
3290 s = exprNode_getSref (ret);
3294 s = sRef_fixBaseParam (sel, args);
3297 DPRINTF (("Reflecting state clause on: %s / %s",
3298 sRef_unparse (sel), sRef_unparse (s)));
3300 sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3301 } end_sRefSet_elements;
3303 sRefSet_free (osrs);
3307 sRefSet srs = stateClause_getRefs (cl);
3308 sRefModVal modf = stateClause_getEnsuresFunction (cl);
3309 int eparam = stateClause_getStateParameter (cl);
3311 llassert (modf != NULL);
3313 DPRINTF (("Reflect after clause: %s / %s",
3314 stateClause_unparse (cl),
3315 sRefSet_unparse (srs)));
3317 sRefSet_elements (srs, sel)
3321 DPRINTF (("elements: %s", sRef_unparse (sel)));
3322 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3324 if (sRef_isResult (sRef_getRootBase (sel)))
3326 DPRINTF (("Fix base: %s / %s",
3327 sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
3328 s = sRef_fixBase (sel, exprNode_getSref (ret));
3329 DPRINTF (("==> %s", sRef_unparseFull (s)));
3333 s = sRef_fixBaseParam (sel, args);
3336 DPRINTF (("elements: %s", sRef_unparse (s)));
3337 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3339 DPRINTF (("Reflecting state clause on: %s / %s",
3340 sRef_unparseFull (sel), sRef_unparseFull (s)));
3342 /* evans 2001-08-24 - added aliasSetCompleteParam */
3343 sRef_aliasSetCompleteParam (modf, s, eparam, exprNode_loc (f));
3345 DPRINTF (("After reflecting state clause on: %s / %s",
3346 sRef_unparseFull (sel), sRef_unparseFull (s)));
3347 } end_sRefSet_elements;
3350 } end_stateClauseList_elements ;
3353 DPRINTF (("Here: %s / %s",
3354 uentry_unparseFull (le),
3355 bool_unparse (uentry_hasMetaStateEnsures (le))));
3357 if (uentry_hasMetaStateEnsures (le))
3359 fileloc loc = exprNode_loc (f);
3361 metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3363 metaStateConstraintList_elements (mscl, msc)
3365 metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3366 metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3367 metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
3368 cstring key = metaStateInfo_getName (msinfo);
3369 sRef mlsr = metaStateSpecifier_getSref (msspec);
3371 sRef lastref = sRef_undefined;
3372 stateValue sval = stateValue_undefined;
3374 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3375 metaStateConstraint_unparse (msc)));
3376 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3378 if (sRef_isResult (sRef_getRootBase (mlsr)))
3380 s = exprNode_getSref (ret);
3384 s = sRef_fixBaseParam (mlsr, args);
3387 DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3389 while (metaStateExpression_isDefined (msexpr))
3391 metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
3392 metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
3395 DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3397 if (metaStateExpression_isMerge (msexpr))
3399 msexpr = metaStateExpression_getRest (msexpr);
3403 msexpr = metaStateExpression_undefined;
3406 if (metaStateInfo_isDefined (msi))
3408 /* Must match lhs state */
3409 llassert (metaStateInfo_equal (msinfo, msi));
3412 if (metaStateSpecifier_isElipsis (ms))
3415 ** For elipsis, we need to merge all the relevant elipsis parameters
3419 uentryList params = uentry_getParams (le);
3420 int paramno = uentryList_size (params) - 1;
3422 if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
3426 message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3427 uentry_getName (le)),
3428 uentry_whereLast (le));
3429 /*@innerbreak@*/ break;
3432 while (paramno < exprNodeList_size (args))
3434 exprNode arg = exprNodeList_getN (args, paramno);
3435 fs = exprNode_getSref (arg);
3436 DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3438 /* cut and pasted... gack*/
3439 if (stateValue_isDefined (sval))
3441 /* Use combination table to merge old state value with new one: */
3442 stateValue tval = sRef_getMetaStateValue (fs, key);
3444 if (stateValue_isDefined (tval))
3446 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3447 cstring msg = cstring_undefined;
3448 int nval = stateCombinationTable_lookup (sctable,
3449 stateValue_getValue (sval),
3450 stateValue_getValue (tval),
3452 DPRINTF (("Combining: %s + %s -> %d",
3453 stateValue_unparseValue (sval, msinfo),
3454 stateValue_unparseValue (tval, msinfo),
3457 if (nval == stateValue_error)
3462 ("Attributes merged in ensures clause in states that "
3463 "cannot be combined (%q is %q, %q is %q)%q",
3464 sRef_unparse (lastref),
3465 stateValue_unparseValue (sval, msinfo),
3467 stateValue_unparseValue (tval, msinfo),
3468 cstring_isDefined (msg) ?
3469 message (": %s", msg) : cstring_undefined),
3472 sRef_showMetaStateInfo (fs, key);
3476 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3477 loc = exprNode_loc (arg);
3481 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3486 sval = sRef_getMetaStateValue (fs, key);
3491 if (stateValue_isError (sval))
3493 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3502 msr = metaStateSpecifier_getSref (ms);
3505 llassert (sRef_isParam (sRef_getRootBase (msr)));
3506 fs = sRef_fixBaseParam (msr, args);
3508 if (stateValue_isDefined (sval))
3510 /* Use combination table to merge old state value with new one: */
3511 stateValue tval = sRef_getMetaStateValue (fs, key);
3513 if (stateValue_isDefined (tval))
3515 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3516 cstring msg = cstring_undefined;
3517 int nval = stateCombinationTable_lookup (sctable,
3518 stateValue_getValue (sval),
3519 stateValue_getValue (tval),
3521 DPRINTF (("Combining: %s + %s -> %d",
3522 stateValue_unparseValue (sval, msinfo),
3523 stateValue_unparseValue (tval, msinfo),
3526 if (nval == stateValue_error)
3531 ("Attributes merged in ensures clause in states that "
3532 "cannot be combined (%q is %q, %q is %q)%q",
3533 sRef_unparse (lastref),
3534 stateValue_unparseValue (sval, msinfo),
3536 stateValue_unparseValue (tval, msinfo),
3537 cstring_isDefined (msg)
3538 ? message (": %s", msg) : cstring_undefined),
3541 sRef_showMetaStateInfo (fs, key);
3545 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3549 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3554 sval = sRef_getMetaStateValue (fs, key);
3559 if (stateValue_isError (sval))
3561 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3566 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3568 if (stateValue_isDefined (sval))
3570 sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
3574 DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
3576 } end_metaStateConstraintList_elements ;
3578 metaStateConstraintList_free (mscl);
3584 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3586 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3587 exprNode_unparse (f), exprNodeList_unparse (args),
3588 uentry_unparseFull (le),
3589 stateClauseList_unparse (uentry_getStateClauseList (le))));
3591 if (uentry_isValid (le) && uentry_isFunction (le))
3593 stateClauseList sclauses = uentry_getStateClauseList (le);
3595 if (stateClauseList_isDefined (sclauses))
3597 DPRINTF (("Check requires: %s / %s / %s",
3598 uentry_unparse (le),
3599 exprNode_unparse (f), exprNodeList_unparse (args)));
3601 stateClauseList_elements (sclauses, cl)
3603 DPRINTF (("Check clause: %s / %s",
3604 stateClause_unparse (cl),
3605 bool_unparse (stateClause_hasRequires (cl))));
3607 if (stateClause_hasRequires (cl))
3609 sRefSet osrs = sRefSet_undefined;
3612 if (stateClause_isGlobal (cl))
3614 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3619 srs = stateClause_getRefs (cl);
3622 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3624 if (stateClause_setsMetaState (cl))
3626 qual q = stateClause_getMetaQual (cl);
3627 annotationInfo ainfo = qual_getAnnotationInfo (q);
3628 metaStateInfo minfo = annotationInfo_getState (ainfo);
3629 cstring key = metaStateInfo_getName (minfo);
3630 int mvalue = annotationInfo_getValue (ainfo);
3632 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3634 sRefSet_elements (srs, sel)
3636 sRef s = sRef_fixBaseParam (sel, args);
3638 if (sRef_isResult (sRef_getRootBase (sel)))
3644 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3645 sRef_unparseFull (sel), sRef_unparseFull (s),
3648 if (!sRef_checkMetaStateValue (s, key, mvalue))
3650 DPRINTF (("HERE: %s", sRef_unparse (s)));
3654 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3655 uentry_getName (le),
3656 sRef_isGlobalMarker (s)
3658 : message (" by %q", sRef_unparse (s)),
3659 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3661 stateClause_unparse (cl)),
3664 sRef_showAliasInfo (s);
3668 DPRINTF (("Error supressed!"));
3669 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3670 DPRINTF (("Context supress: %s",
3671 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3675 } end_sRefSet_elements;
3679 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3680 int eparam = stateClause_getStateParameter (cl);
3682 DPRINTF (("Reflect after clause: %s / %s",
3683 stateClause_unparse (cl),
3684 sRefSet_unparse (srs)));
3686 llassert (modf != NULL);
3688 sRefSet_elements (srs, sel)
3692 DPRINTF (("elements: %s", sRef_unparse (sel)));
3693 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3695 s = sRef_fixBaseParam (sel, args);
3697 DPRINTF (("elements: %s", sRef_unparse (s)));
3698 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3700 if (sRef_isResult (sRef_getRootBase (sel)))
3702 ; /*@i423 what do we do about results */
3706 DPRINTF (("Reflecting state clause on: %s / %s",
3707 sRef_unparse (sel), sRef_unparse (s)));
3709 modf (s, eparam, exprNode_loc (f));
3711 } end_sRefSet_elements;
3714 sRefSet_free (osrs);
3716 } end_stateClauseList_elements ;
3721 static /*@only@*/ exprNode
3722 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3723 ctype t, /*@keep@*/ exprNodeList args)
3725 /* requires f is a non-error exprNode, with type function */
3726 cstring fname = exprNode_unparse (f);
3727 uentry le = exprNode_getUentry (f);
3728 exprNode ret = exprNode_createPartialCopy (f);
3733 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3735 ret->typ = ctype_getReturnType (t);
3736 ret->kind = XPR_CALL;
3738 ret->edata = exprData_makeCall (f, args);
3741 ** Order of these steps is very important!
3743 ** Must check for argument dependencies before messing up uses and sets.
3746 if (context_getFlag (FLG_EVALORDER))
3748 exprNodeList_elements (args, current)
3750 if (exprNode_isDefined (current))
3752 exprNode_addUse (current, current->sref);
3754 } end_exprNodeList_elements;
3756 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3758 checkSequencing (f, args);
3761 exprNodeList_elements (args, current)
3763 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3765 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3767 } end_exprNodeList_elements ;
3770 special = checkArgs (le, f, t, args, ret);
3771 checkGlobMods (f, le, args, ret, special);
3772 checkRequiresClause (le, f, args);
3775 if (uentry_isValid (le)
3776 && (uentry_isFunction (le)
3777 || (uentry_isVariable (le)
3778 && ctype_isFunction (uentry_getType (le)))))
3780 exitkind exk = uentry_getExitCode (le);
3782 /* f->typ is already set to the return type */
3784 DPRINTF (("Function: %s", uentry_unparseFull (le)));
3785 ret->sref = uentry_returnedRef (le, args);
3786 DPRINTF (("Returned: %s / %s",
3787 uentry_unparseFull (le),
3788 sRef_unparseFull (ret->sref)));
3790 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3792 qual nullPred = uentry_nullPred (le);
3794 if (qual_isTrueNull (nullPred))
3796 exprNode arg = exprNodeList_head (args);
3798 if (exprNode_isDefined (arg))
3800 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3803 else if (qual_isFalseNull (nullPred))
3805 exprNode arg = exprNodeList_head (args);
3807 if (exprNode_isDefined (arg))
3809 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3814 llassert (qual_isUnknown (nullPred));
3818 if (exitkind_isConditionalExit (exk))
3822 ** if (arg0) then { exit! } else { ; }
3824 ** if (arg0) then { ; } else { exit! }
3829 llassert (!exprNodeList_isEmpty (args));
3830 firstArg = exprNodeList_head (args);
3832 if (exprNode_isDefined (firstArg)
3833 && !guardSet_isEmpty (firstArg->guards))
3835 usymtab_trueBranch (guardSet_undefined);
3836 usymtab_altBranch (guardSet_undefined);
3838 if (exitkind_isTrueExit (exk))
3840 usymtab_popBranches (firstArg,
3841 exprNode_makeMustExit (),
3843 TRUE, TRUEEXITCLAUSE);
3847 usymtab_popBranches (firstArg,
3849 exprNode_makeMustExit (),
3850 TRUE, FALSEEXITCLAUSE);
3854 ret->exitCode = XK_MAYEXIT;
3856 else if (exitkind_mustExit (exk))
3858 ret->exitCode = XK_MUSTEXIT;
3860 else if (exitkind_couldExit (exk))
3862 ret->exitCode = XK_MAYEXIT;
3869 if (cstring_equalLit (fname, "exit"))
3871 if (exprNodeList_size (args) == 1)
3873 exprNode arg = exprNodeList_head (args);
3875 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3877 long int val = multiVal_forceInt (exprNode_getValue (arg));
3884 ("Argument to exit has implementation defined behavior: %s",
3885 exprNode_unparse (arg)),
3886 exprNode_loc (arg));
3895 exprNode_checkSetAny (ret, uentry_rawName (le));
3898 DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3899 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3900 reflectEnsuresClause (ret, le, f, args);
3907 ** this is yucky! should keep the uentry as part of exprNode!
3910 uentry exprNode_getUentry (exprNode e)
3912 if (exprNode_isError (e))
3914 return uentry_undefined;
3918 cstring s = exprNode_rootVarName (e);
3919 uentry ue = usymtab_lookupSafe (s);
3926 ** Returns true iff e1 and e2 are both exactly the same storage
3930 static bool exprNode_sameStorage (exprNode e1, exprNode e2)
3932 sRef s1 = exprNode_getSref (e1);
3933 sRef s2 = exprNode_getSref (e2);
3935 return (sRef_realSame (s1, s2));
3939 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3941 exprNode ret = exprNode_createPlain (ctype_unknown);
3943 ret->kind = XPR_INITBLOCK;
3944 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3945 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3951 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3957 if (exprNode_isUndefined (f))
3960 exprNodeList_free (args);
3961 return exprNode_undefined;
3964 t = exprNode_getType (f);
3966 if (sRef_isLocalVar (f->sref))
3968 exprNode_checkUse (f, f->sref, f->loc);
3970 if (sRef_possiblyNull (f->sref))
3972 if (!usymtab_isGuarded (f->sref))
3974 if (optgenerror (FLG_NULLDEREF,
3975 message ("Function call using %s pointer %q",
3976 sRef_nullMessage (f->sref),
3977 sRef_unparse (f->sref)),
3980 sRef_showNullInfo (f->sref);
3981 sRef_setNullError (f->sref);
3989 if (ctype_isRealFunction (t))
3991 exprNode ret = functionCallSafe (f, t, args);
3995 else if (ctype_isUnknown (t))
3997 exprNode ret = exprNode_createPartialCopy (f);
4003 exprNodeList_elements (args, current)
4005 if (exprNode_isDefined (current))
4007 exprNode_checkUse (ret, current->sref, ret->loc);
4010 ** also, anything derivable from current->sref may be used
4013 exprNode_addUse (ret, sRef_makeDerived (current->sref));
4014 exprNode_mergeUSs (ret, current);
4016 } end_exprNodeList_elements;
4018 ret->edata = exprData_makeCall (f, args);
4019 ret->kind = XPR_CALL;
4021 tstring = cstring_copy (exprNode_unparse (f));
4023 cstring_markOwned (tstring);
4024 exprNode_checkSetAny (ret, tstring);
4030 voptgenerror (FLG_TYPE,
4031 message ("Call to non-function (type %t): %s", t,
4032 exprNode_unparse (f)),
4035 exprNodeList_free (args);
4037 return (exprNode_makeError ());
4042 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4043 /*@only@*/ cstring f)
4045 exprNode ret = exprNode_createPartialCopy (s);
4047 ret->kind = XPR_FACCESS;
4049 if (exprNode_isError (s))
4051 ret->edata = exprData_makeField (s, f);
4056 ctype t = exprNode_getType (s);
4057 ctype tr = ctype_realType (t);
4059 checkMacroParen (s);
4061 ret->edata = exprData_makeField (s, f);
4063 if (ctype_isStructorUnion (tr))
4065 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
4067 if (uentry_isUndefined (tf))
4069 voptgenerror (FLG_TYPE,
4070 message ("Access non-existent field %s of %t: %s", f, t,
4071 exprNode_unparse (ret)),
4073 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
4078 uentry_setUsed (tf, exprNode_loc (ret));
4080 ret->typ = uentry_getType (tf);
4081 checkSafeUse (ret, s->sref);
4083 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
4084 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
4088 else /* isStructorUnion */
4090 if (ctype_isRealAbstract (tr))
4094 message ("Access field of abstract type (%t): %s.%s",
4095 t, exprNode_unparse (s), f),
4097 ret->typ = ctype_unknown;
4101 if (ctype_isKnown (tr))
4106 ("Access field of non-struct or union (%t): %s.%s",
4107 t, exprNode_unparse (s), f),
4110 ret->typ = ctype_unknown;
4114 cstring sn = cstring_copy (f);
4116 checkSafeUse (ret, s->sref);
4117 cstring_markOwned (sn);
4118 ret->sref = sRef_makeField (s->sref, sn);
4130 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
4131 /*@only@*/ cstring f)
4133 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
4139 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
4141 exprNode ret = exprNode_createPartialCopy (e);
4143 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
4144 ret->kind = XPR_PARENS;
4145 ret->edata = exprData_makeUop (e, lpar);
4147 if (!exprNode_isError (e))
4149 ret->exitCode = e->exitCode;
4150 ret->canBreak = e->canBreak;
4151 ret->mustBreak = e->mustBreak;
4152 ret->isJumpPoint = e->isJumpPoint;
4153 ret->sref = e->sref;
4160 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4161 /*@only@*/ cstring f)
4163 exprNode ret = exprNode_createPartialCopy (s);
4165 ret->edata = exprData_makeField (s, f);
4166 ret->kind = XPR_ARROW;
4168 if (exprNode_isError (s))
4174 ctype t = exprNode_getType (s);
4175 ctype tr = ctype_realType (t);
4177 checkMacroParen (s);
4179 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4181 if (ctype_isRealPointer (tr))
4183 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4185 if (ctype_isStructorUnion (b))
4187 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4189 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4191 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4195 message ("Arrow access from %s pointer%q: %s",
4196 sRef_nullMessage (s->sref),
4197 sRef_unparsePreOpt (s->sref),
4198 exprNode_unparse (ret)),
4201 sRef_showNullInfo (s->sref);
4202 sRef_setNullError (s->sref);
4207 if (uentry_isUndefined (fentry))
4211 message ("Access non-existent field %s of %t: %s",
4212 f, t, exprNode_unparse (ret)),
4214 ret->typ = ctype_unknown;
4220 ** was safeUse: shouldn't be safe!
4223 ** rec must be defined,
4224 ** *rec must be allocated
4225 ** rec->field need only be defined it if is an rvalue
4228 uentry_setUsed (fentry, exprNode_loc (ret));
4229 ret->typ = uentry_getType (fentry);
4231 exprNode_checkUse (ret, s->sref, s->loc);
4233 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4234 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4238 else /* Pointer to something that is not a struct or union*/
4240 if (ctype_isRealAbstract (tr))
4242 ctype xrt = ctype_forceRealType (tr);
4246 message ("Arrow access field of abstract type (%t): %s->%s",
4247 t, exprNode_unparse (s), f),
4251 ** Set the state correctly, as if the abstraction is broken.
4254 if (ctype_isRealPointer (xrt) &&
4255 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4256 ctype_isStructorUnion (b)))
4258 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4259 ret->typ = uentry_getType (fentry);
4260 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4264 ret->typ = ctype_unknown;
4265 ret->sref = sRef_undefined;
4268 else /* not a struct, union or abstract */
4270 if (ctype_isUnknown (tr)) {
4271 cstring sn = cstring_copy (f);
4273 DPRINTF (("Here: %s", exprNode_unparse (s)));
4275 exprNode_checkUse (ret, s->sref, s->loc);
4276 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4278 cstring_markOwned (sn);
4279 ret->sref = sRef_makeArrow (s->sref, sn);
4281 ret->kind = XPR_ARROW;
4286 message ("Arrow access field of non-struct or union "
4287 "pointer (%t): %s->%s",
4288 t, exprNode_unparse (s), f),
4291 ret->typ = ctype_unknown;
4292 ret->sref = sRef_undefined;
4297 else /* its not a pointer */
4299 if (!ctype_isUnknown (tr))
4303 message ("Arrow access of non-pointer (%t): %s->%s",
4304 t, exprNode_unparse (s), f),
4307 ret->typ = ctype_unknown;
4308 ret->sref = sRef_undefined;
4312 cstring sn = cstring_copy (f);
4314 DPRINTF (("Here: %s", exprNode_unparse (s)));
4316 exprNode_checkUse (ret, s->sref, s->loc);
4317 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4319 cstring_markOwned (sn);
4320 ret->sref = sRef_makeArrow (s->sref, sn);
4322 ret->kind = XPR_ARROW;
4333 exprNode_arrowAccess (/*@only@*/ exprNode s,
4334 /*@only@*/ lltok arrow,
4335 /*@only@*/ cstring f)
4337 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4343 ** only postOp's in C: i++ and i--
4347 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4349 /* check modification also */
4350 /* cstring opname = lltok_unparse (op);*/
4352 exprNode ret = exprNode_createPartialCopy (e);
4354 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4355 ret->kind = XPR_POSTOP;
4356 ret->edata = exprData_makeUop (e, op);
4358 if (!exprNode_isDefined (e))
4363 checkMacroParen (e);
4365 exprNode_checkUse (ret, e->sref, e->loc);
4366 exprNode_checkSet (ret, e->sref);
4368 t = exprNode_getType (e);
4370 if (sRef_isUnsafe (e->sref))
4372 voptgenerror (FLG_MACROPARAMS,
4373 message ("Operand of %s is macro parameter (non-functional): %s%s",
4374 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4376 sRef_makeSafe (e->sref);
4377 sRef_makeSafe (ret->sref);
4380 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4386 if (ctype_isRealAbstract (t))
4390 message ("Operand of %s is abstract type (%t): %s",
4391 lltok_unparse (op), t, exprNode_unparse (e)),
4398 message ("Operand of %s is non-numeric (%t): %s",
4399 lltok_unparse (op), t, exprNode_unparse (e)),
4402 ret->typ = ctype_unknown;
4405 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4407 exprNode_checkModify (e, ret);
4409 /* added 7/11/2000 D.L */
4411 /*DRL 6/8/01 I decided to disable all Splint warnings here since the code
4412 probably needs a rewrite any way */
4417 /* updateEnvironmentForPostOp (e); */
4419 /* start modifications */
4420 /* added by Seejo on 4/16/2000 */
4422 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4424 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4426 ret->sref = sRef_copy (e->sref);
4429 if (lltok_getTok (op) == INC_OP) {
4430 if (sRef_getSize(e->sref) > 0) {
4432 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4434 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4435 /* Assumption: there is only 1 \0 in the buffer */
4436 /* This will not be correct if there are 2 \0's in the buffer */
4437 sRef_setNotNullTerminatedState(ret->sref);
4438 sRef_resetLen(ret->sref);
4440 sRef_setNullTerminatedState(ret->sref);
4441 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4443 if (sRef_isNullTerminated (ret->sref))
4444 printf ("ret->sref is Null Terminated\n");
4445 else if (sRef_isPossiblyNullTerminated (ret->sref))
4446 printf ("ret->sref is Possibly Null Terminated\n");
4447 else if (sRef_isNotNullTerminated (ret->sref))
4448 printf ("ret->sref is Not Null Terminated\n");
4453 if (lltok_getTok (op) == DEC_OP) {
4454 if (sRef_getSize(e->sref) >= 0) {
4455 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4456 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4461 /* end modifications */
4467 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4469 bool checkMod = FALSE;
4471 int opid = lltok_getTok (op);
4472 exprNode ret = exprNode_createSemiCopy (e);
4474 exprNode_copySets (ret, e);
4476 multiVal_free (ret->val);
4477 ret->val = multiVal_undefined;
4478 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4479 ret->kind = XPR_PREOP;
4480 ret->edata = exprData_makeUop (e, op);
4482 if (exprNode_isError (e))
4487 checkMacroParen (e);
4489 te = exprNode_getType (e);
4490 tr = ctype_realType (te);
4492 if (opid != TAMPERSAND)
4494 exprNode_checkUse (ret, e->sref, e->loc);
4496 if (ctype_isRealAbstract (tr)
4497 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4499 if (optgenerror (FLG_ABSTRACT,
4500 message ("Operand of %s is abstract type (%t): %s",
4501 lltok_unparse (op), tr,
4502 exprNode_unparse (ret)),
4505 tr = te = ctype_unknown;
4506 ret->typ = ctype_unknown;
4507 sRef_setNullError (e->sref);
4515 case DEC_OP: /* should also check modification! */
4516 if (sRef_isMacroParamRef (e->sref))
4520 message ("Operand of %s is macro parameter (non-functional): %s",
4521 lltok_unparse (op), exprNode_unparse (ret)),
4526 exprNode_checkSet (ret, e->sref);
4529 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4534 if (context_msgStrictOps ())
4538 message ("Operand of %s is non-numeric (%t): %s",
4539 lltok_unparse (op), te, exprNode_unparse (ret)),
4542 ret->typ = ctype_int;
4545 /* start modifications */
4546 /* added by Seejo on 4/16/2000 */
4548 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4550 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4552 ret->sref = sRef_copy (e->sref);
4555 if (lltok_getTok (op) == INC_OP) {
4556 if (sRef_getSize(e->sref) > 0) {
4558 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4560 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4561 /* Assumption: there is only 1 \0 in the buffer */
4562 /* This will not be correct if there are 2 \0's in the buffer */
4563 sRef_setNotNullTerminatedState(ret->sref);
4564 sRef_resetLen (ret->sref);
4566 sRef_setNullTerminatedState(ret->sref);
4567 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4573 if (lltok_getTok (op) == DEC_OP) {
4574 if (sRef_getSize(e->sref) >= 0) {
4575 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4576 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4581 /* end modifications */
4588 if (ctype_isForceRealNumeric (&tr))
4592 ret->val = multiVal_invert (exprNode_getValue (e));
4596 ret->val = multiVal_copy (exprNode_getValue (e));
4601 if (context_msgStrictOps ())
4605 message ("Operand of %s is non-numeric (%t): %s",
4606 lltok_unparse (op), te, exprNode_unparse (ret)),
4610 ret->typ = ctype_int;
4614 case TEXCL: /* maybe this should be restricted */
4615 guardSet_flip (ret->guards);
4617 if (ctype_isRealBool (te) || ctype_isUnknown (te))
4623 if (ctype_isRealPointer (tr))
4625 if (sRef_isKnown (e->sref))
4627 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4631 (FLG_BOOLOPS, FLG_PTRNEGATE,
4632 message ("Operand of %s is non-boolean (%t): %s",
4633 lltok_unparse (op), te, exprNode_unparse (ret)),
4640 message ("Operand of %s is non-boolean (%t): %s",
4641 lltok_unparse (op), te, exprNode_unparse (ret)),
4645 ret->typ = ctype_bool;
4650 if (ctype_isForceRealInt (&tr))
4655 if (context_msgStrictOps ())
4659 message ("Operand of %s is non-integer (%t): %s",
4660 lltok_unparse (op), te, exprNode_unparse (ret)),
4664 if (ctype_isInt (e->typ))
4670 ret->typ = ctype_int;
4676 ret->typ = ctype_makePointer (e->typ);
4678 if (sRef_isKnown (e->sref))
4680 ret->sref = sRef_makeAddress (e->sref);
4687 if (ctype_isAP (tr))
4689 ret->typ = ctype_baseArrayPtr (e->typ);
4693 if (ctype_isKnown (te))
4695 if (ctype_isFunction (te))
4701 message ("Dereference of function type (%t): %s",
4702 te, exprNode_unparse (ret)),
4707 voptgenerror (FLG_TYPE,
4708 message ("Dereference of non-pointer (%t): %s",
4709 te, exprNode_unparse (ret)),
4711 ret->typ = ctype_unknown;
4716 ret->typ = ctype_unknown;
4721 if (sRef_isKnown (e->sref))
4723 DPRINTF (("Checking possibly null: %s", sRef_unparseFull (e->sref)));
4725 if (sRef_possiblyNull (e->sref))
4727 DPRINTF (("Checking possibly null: %s", sRef_unparse (e->sref)));
4728 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4732 message ("Dereference of %s pointer %q: %s",
4733 sRef_nullMessage (e->sref),
4734 sRef_unparse (e->sref),
4735 exprNode_unparse (ret)),
4738 sRef_showNullInfo (e->sref);
4739 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4744 ret->sref = sRef_makePointer (e->sref);
4749 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4754 exprNode_checkModify (e, ret);
4761 ** any reason to disallow sizeof (abstract type) ?
4765 ** used by both sizeof
4769 ctype sizeof_resultType (void)
4771 static ctype sizet = ctype_unknown;
4773 if (ctype_isUnknown (sizet))
4775 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4777 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4781 sizet = ctype_ulint;
4788 exprNode_sizeofType (/*@only@*/ qtype qt)
4790 exprNode ret = exprNode_create (sizeof_resultType ());
4791 ctype ct = qtype_getType (qt);
4793 ret->kind = XPR_SIZEOFT;
4794 ret->edata = exprData_makeSizeofType (qt);
4796 voptgenerror (FLG_SIZEOFTYPE,
4797 message ("Parameter to sizeof is type %s: %s",
4799 exprNode_unparse (ret)),
4806 exprNode_alignofType (/*@only@*/ qtype qt)
4808 exprNode ret = exprNode_create (sizeof_resultType ());
4809 ctype ct = qtype_getType (qt);
4811 ret->kind = XPR_ALIGNOFT;
4812 ret->edata = exprData_makeSizeofType (qt);
4814 voptgenerror (FLG_SIZEOFTYPE,
4815 message ("Parameter to alignof is type %s: %s",
4817 exprNode_unparse (ret)),
4823 exprNode exprNode_offsetof (qtype qt, cstringList s)
4825 exprNode ret = exprNode_create (sizeof_resultType ());
4826 ctype ct = qtype_getType (qt);
4828 ret->kind = XPR_OFFSETOF;
4829 ret->edata = exprData_makeOffsetof (qt, s);
4831 if (!ctype_isRealSU (ct))
4833 voptgenerror (FLG_TYPE,
4834 message ("First parameter to offsetof is not a "
4835 "struct or union type (type %s): %s",
4837 exprNode_unparse (ret)),
4844 cstringList_elements (s, el) {
4848 if (ctype_isUndefined (lt))
4852 else if (!ctype_isRealSU (lt))
4854 voptgenerror (FLG_TYPE,
4855 message ("Inner offsetof type is not a "
4856 "struct or union type (type %s before field %s): %s",
4857 ctype_unparse (lt), el,
4858 exprNode_unparse (ret)),
4864 fields = ctype_getFields (ctype_realType (lt));
4865 fld = uentryList_lookupField (fields, el);
4866 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4868 if (uentry_isUndefined (fld))
4870 if (ctype_equal (lt, ct)) {
4871 voptgenerror (FLG_TYPE,
4872 message ("Field %s in offsetof is not the "
4873 "name of a field of %s: %s",
4876 exprNode_unparse (ret)),
4879 voptgenerror (FLG_TYPE,
4880 message ("Deep field %s in offsetof is not the "
4881 "name of a field of %s: %s",
4884 exprNode_unparse (ret)),
4890 lt = uentry_getType (fld);
4893 } end_cstringList_elements;
4895 /* Should report error if its a bit field - behavior is undefined! */
4902 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4906 if (exprNode_isUndefined (e))
4908 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4909 ret->edata = exprData_makeSingle (e);
4910 ret->typ = sizeof_resultType ();
4911 ret->kind = XPR_SIZEOF;
4915 uentry u = exprNode_getUentry (e);
4917 ret = exprNode_createPartialCopy (e);
4918 ret->edata = exprData_makeSingle (e);
4920 ret->typ = sizeof_resultType ();
4921 ret->kind = XPR_SIZEOF;
4923 if (uentry_isValid (u)
4924 && uentry_isRefParam (u)
4925 && ctype_isRealArray (uentry_getType (u)))
4928 (FLG_SIZEOFFORMALARRAY,
4929 message ("Parameter to sizeof is an array-type function parameter: %s",
4930 exprNode_unparse (ret)),
4936 ** sizeof (x) doesn't "really" use x
4943 exprNode_alignofExpr (/*@only@*/ exprNode e)
4947 if (exprNode_isUndefined (e))
4949 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4953 ret = exprNode_createPartialCopy (e);
4956 ret->edata = exprData_makeSingle (e);
4957 ret->typ = sizeof_resultType ();
4958 ret->kind = XPR_ALIGNOF;
4961 ** sizeof (x) doesn't "really" use x
4968 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4974 if (exprNode_isError (e))
4978 return exprNode_undefined;
4981 checkMacroParen (e);
4983 c = qtype_getType (q);
4984 t = exprNode_getType (e);
4986 ret = exprNode_createPartialCopy (e);
4988 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4990 ret->kind = XPR_CAST;
4991 ret->edata = exprData_makeCast (tok, e, q);
4993 if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
4996 ** This is a bit of a hack to avoid a problem
4997 ** when the code does,
4998 ** (some other struct) x
5003 ret->sref = sRef_copy (e->sref);
5004 usymtab_addForceMustAlias (ret->sref, e->sref);
5005 sRef_setTypeFull (ret->sref, c);
5006 DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
5007 sRef_unparseFull (ret->sref)));
5011 ret->sref = e->sref;
5012 sRef_setTypeFull (ret->sref, c);
5013 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
5020 ** void * <-> abstract * (if FLG_ABSTVOIDP)
5021 ** abstract * <-> void * (if FLG_ABSTVOIDP)
5024 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
5028 else if (ctype_isRealAP (c)) /* casting to array or pointer */
5030 ctype bc = ctype_getBaseType (c);
5031 ctype bt = ctype_getBaseType (t);
5032 ctype rt = ctype_realType (t);
5034 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
5035 && (ctype_isArrayPtr (rt)
5036 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5040 message ("Cast from function pointer type (%t) to "
5041 "non-function pointer (%t): %s",
5042 c, t, exprNode_unparse (ret)),
5046 if (!ctype_isFunction (ctype_baseArrayPtr (c))
5047 && (ctype_isArrayPtr (rt)
5048 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5052 message ("Cast from non-function pointer type (%t) to "
5053 "function pointer (%t): %s",
5054 c, t, exprNode_unparse (ret)),
5058 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
5059 !(ctype_isRealAbstract (bc)
5060 && context_hasAccess (ctype_typeId (bc))))
5062 ; /* okay to cast zero */
5066 if (ctype_isRealAbstract (bc)
5067 && !context_hasAccess (ctype_typeId (bc)))
5069 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
5073 message ("Cast to underlying abstract type %t: %s",
5074 c, exprNode_unparse (ret)),
5081 message ("Cast to underlying abstract type %t: %s",
5082 c, exprNode_unparse (ret)),
5087 if (ctype_isRealAbstract (bt)
5088 && !context_hasAccess (ctype_typeId (bt)))
5090 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
5094 message ("Cast from underlying abstract type %t: %s",
5095 t, exprNode_unparse (ret)),
5102 message ("Cast from underlying abstract type %t: %s",
5103 t, exprNode_unparse (ret)),
5111 ctype bt = ctype_realType (ctype_getBaseType (t));
5112 ctype bc = ctype_realType (ctype_getBaseType (c));
5114 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
5116 if (ctype_match (c, t))
5118 if (ctype_equal (c, t))
5122 message ("Redundant cast involving abstract type %t: %s",
5123 bt, exprNode_unparse (ret)),
5131 message ("Cast from abstract type %t: %s",
5132 bt, exprNode_unparse (ret)),
5137 if (ctype_isAbstract (bc)
5138 && !context_hasAccess (ctype_typeId (bc)))
5140 if (ctype_match (c, t))
5146 DPRINTF (("No access to: %s / %d",
5147 ctype_unparse (bc), ctype_typeId (bc)));
5148 DPRINTF (("Context %s %s",
5149 bool_unparse (context_inFunctionLike ()),
5150 context_unparse ()));
5153 message ("Cast to abstract type %t: %s", bc,
5154 exprNode_unparse (ret)),
5160 if (ctype_isAbstract (c))
5162 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
5164 /* okay, cast exposed to abstract */
5165 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
5169 if (ctype_isVisiblySharable (t)
5170 && sRef_isExternallyVisible (e->sref)
5171 && !(ctype_isAbstract (t)
5172 && context_hasAccess (ctype_typeId (t))))
5176 message ("Cast to abstract type from externally visible "
5177 "mutable storage exposes rep of %s: %s",
5179 exprNode_unparse (e)),
5189 evaluationOrderUndefined (lltok op)
5191 int opid = lltok_getTok (op);
5193 return (opid != AND_OP && opid != OR_OP);
5196 static bool checkIntegral (/*@notnull@*/ exprNode e1,
5197 /*@notnull@*/ exprNode e2,
5198 /*@notnull@*/ exprNode ret,
5203 ctype te1 = exprNode_getType (e1);
5204 ctype te2 = exprNode_getType (e2);
5206 ctype tr1 = ctype_realishType (te1);
5207 ctype tr2 = ctype_realishType (te2);
5209 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5215 if (context_msgStrictOps ())
5217 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5219 if (ctype_sameName (te1, te2))
5223 message ("Operands of %s are non-integer (%t): %s",
5224 lltok_unparse (op), te1,
5225 exprNode_unparse (ret)),
5232 message ("Operands of %s are non-integers (%t, %t): %s",
5233 lltok_unparse (op), te1, te2,
5234 exprNode_unparse (ret)),
5238 else if (!ctype_isInt (tr1))
5242 message ("Left operand of %s is non-integer (%t): %s",
5243 lltok_unparse (op), te1, exprNode_unparse (ret)),
5247 /* !ctype_isInt (te2) */
5251 message ("Right operand of %s is non-integer (%t): %s",
5252 lltok_unparse (op), te2, exprNode_unparse (ret)),
5262 ** returns exprNode representing e1 op e2
5264 ** uses msg if there are errors
5265 ** can be used for both assignment ops and regular ops
5270 static /*@only@*/ /*@notnull@*/ exprNode
5271 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
5272 /*@keep@*/ lltok op)
5274 ctype te1, te2, tr1, tr2, tret;
5275 int opid = lltok_getTok (op);
5276 bool hasError = FALSE;
5279 if (exprNode_isError (e1))
5281 ret = exprNode_createPartialNVCopy (e2);
5285 ret = exprNode_createPartialNVCopy (e1);
5288 ret->val = multiVal_undefined;
5291 ret->edata = exprData_makeOp (e1, e2, op);
5293 if (exprNode_isError (e1) || exprNode_isError (e2))
5295 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5296 || opid == EQ_OP || opid == NE_OP
5297 || opid == AND_OP || opid == OR_OP)
5299 ret->typ = ctype_bool;
5302 if (exprNode_isDefined (e1))
5304 exprNode_checkUse (ret, e1->sref, e1->loc);
5307 if (exprNode_isDefined (e2))
5309 exprNode_mergeUSs (ret, e2);
5310 exprNode_checkUse (ret, e2->sref, e2->loc);
5316 tret = ctype_unknown;
5317 te1 = exprNode_getType (e1);
5319 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5321 te2 = exprNode_getType (e2);
5323 tr1 = ctype_realishType (te1);
5324 tr2 = ctype_realishType (te2);
5328 ret->guards = guardSet_or (ret->guards, e2->guards);
5330 else if (opid == AND_OP)
5332 ret->guards = guardSet_and (ret->guards, e2->guards);
5339 if (opid == EQ_OP || opid == NE_OP)
5341 exprNode temp1 = e1, temp2 = e2;
5343 /* could do NULL == x */
5345 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5347 temp1 = e2; temp2 = e1;
5350 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5352 reflectNullTest (temp1, (opid == NE_OP));
5353 guardSet_free (ret->guards);
5354 ret->guards = guardSet_copy (temp1->guards);
5358 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5359 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5364 if (anyAbstract (tr1, tr2) &&
5365 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
5366 (opid == AND_OP || opid == OR_OP
5367 || opid == EQ_OP || opid == NE_OP))))
5369 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
5371 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5373 /* unknown types, no comparisons possible */
5379 case TMULT: /* multiplication and division: */
5381 case MUL_ASSIGN: /* numeric, numeric -> numeric */
5382 case DIV_ASSIGN: /* */
5384 if (opid == TMULT || opid == MUL_ASSIGN)
5386 ret->val = multiVal_multiply (exprNode_getValue (e1),
5387 exprNode_getValue (e2));
5391 ret->val = multiVal_divide (exprNode_getValue (e1),
5392 exprNode_getValue (e2));
5395 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5398 case TPLUS: /* addition and subtraction: */
5399 case TMINUS: /* pointer, int -> pointer */
5400 case SUB_ASSIGN: /* int, pointer -> pointer */
5401 case ADD_ASSIGN: /* numeric, numeric -> numeric */
5403 if (opid == TPLUS || opid == ADD_ASSIGN)
5405 ret->val = multiVal_add (exprNode_getValue (e1),
5406 exprNode_getValue (e2));
5410 ret->val = multiVal_subtract (exprNode_getValue (e1),
5411 exprNode_getValue (e2));
5414 tr1 = ctype_fixArrayPtr (tr1);
5416 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5417 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5421 if (context_msgPointerArith ())
5425 message ("Pointer arithmetic (%t, %t): %s",
5426 te1, te2, exprNode_unparse (ret)),
5431 ** Swap terms so e1 is always the pointer
5434 if (ctype_isRealPointer (tr1))
5440 exprNode_swap (e1, e2);
5444 if (sRef_possiblyNull (e1->sref)
5445 && !usymtab_isGuarded (e1->sref))
5448 (FLG_NULLPOINTERARITH,
5449 message ("Pointer arithmetic involving possibly "
5450 "null pointer %s: %s",
5451 exprNode_unparse (e1),
5452 exprNode_unparse (ret)),
5456 ret->sref = sRef_copy (e1->sref);
5458 /* start modifications */
5459 /* added by Seejo on 4/16/2000 */
5461 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5463 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5466 added ugly fixed to stop
5467 program from crashing on point + int +int
5468 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5470 if (!multiVal_isInt (e2->val) )
5474 val = (int) multiVal_forceInt (e2->val);
5476 /* Operator : + or += */
5477 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5478 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5479 val should not result in a
5480 size < 0 (size = 0 is ok !) */
5482 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5484 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5485 sRef_setNotNullTerminatedState(ret->sref);
5486 sRef_resetLen (ret->sref);
5488 sRef_setNullTerminatedState(ret->sref);
5489 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5494 /* Operator : - or -= */
5495 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5496 if (sRef_getSize(e1->sref) >= 0) {
5497 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5498 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5503 /* end modifications */
5505 sRef_setNullError (ret->sref);
5508 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5509 ** since is points to storage that should not be deallocated
5510 ** through this pointer.
5513 if (sRef_isOnly (ret->sref)
5514 || sRef_isFresh (ret->sref))
5516 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5521 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5522 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5524 if (context_msgPointerArith ())
5528 message ("Pointer arithmetic (%t, %t): %s",
5529 te1, te2, exprNode_unparse (ret)),
5533 if (sRef_possiblyNull (e1->sref)
5534 && !usymtab_isGuarded (e1->sref))
5537 (FLG_NULLPOINTERARITH,
5538 message ("Pointer arithmetic involving possibly "
5539 "null pointer %s: %s",
5540 exprNode_unparse (e2),
5541 exprNode_unparse (ret)),
5545 ret->sref = sRef_copy (e2->sref);
5547 /* start modifications */
5548 /* added by Seejo on 4/16/2000 */
5550 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5553 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5554 int val = (int) multiVal_forceInt (e1->val);
5556 /* Operator : + or += */
5557 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5558 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5559 val should not result in a
5560 size < 0 (size = 0 is ok !) */
5562 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5564 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5565 sRef_setNotNullTerminatedState(ret->sref);
5566 sRef_resetLen (ret->sref);
5568 sRef_setNullTerminatedState(ret->sref);
5569 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5574 /* Operator : - or -= */
5575 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5576 if (sRef_getSize(e2->sref) >= 0) {
5577 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5578 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5582 /* end modifications */
5584 sRef_setNullError (ret->sref);
5587 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5588 ** since is points to storage that should not be deallocated
5589 ** through this pointer.
5592 if (sRef_isOnly (ret->sref)
5593 || sRef_isFresh (ret->sref)) {
5594 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5598 ret->sref = e2->sref;
5602 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5611 case TAMPERSAND: /* bitwise & */
5613 case TCIRC: /* ^ (XOR) */
5618 bool reported = FALSE;
5624 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5625 || opid == RIGHT_OP || opid == RIGHT_ASSIGN)
5628 ** evans 2002-01-01: fixed this to follow ISO 6.5.7.
5631 if (!ctype_isUnsigned (tr2)
5632 && !exprNode_isNonNegative (e2))
5634 reported = optgenerror
5636 message ("Right operand of %s may be negative (%t): %s",
5637 lltok_unparse (op), te2,
5638 exprNode_unparse (ret)),
5642 if (!ctype_isUnsigned (tr1)
5643 && !exprNode_isNonNegative (e1))
5645 reported = optgenerror
5646 (FLG_SHIFTIMPLEMENTATION,
5647 message ("Left operand of %s may be negative (%t): %s",
5648 lltok_unparse (op), te1,
5649 exprNode_unparse (ret)),
5654 ** Should check size of right operand also...
5660 if (!ctype_isUnsigned (tr1))
5662 if (exprNode_isNonNegative (e1)) {
5665 reported = optgenerror
5667 message ("Left operand of %s is not unsigned value (%t): %s",
5668 lltok_unparse (op), te1,
5669 exprNode_unparse (ret)),
5679 if (!ctype_isUnsigned (tr2))
5681 if (!exprNode_isNonNegative (e2)) {
5682 reported = optgenerror
5684 message ("Right operand of %s is not unsigned value (%t): %s",
5685 lltok_unparse (op), te2,
5686 exprNode_unparse (ret)),
5695 if (!checkIntegral (e1, e2, ret, op)) {
5696 te1 = ctype_unknown;
5700 DPRINTF (("Set: %s", ctype_unparse (te1)));
5703 ** tret is the widest type of te1 and te2
5706 tret = ctype_widest (te1, te2);
5711 if (checkIntegral (e1, e2, ret, op)) {
5714 tret = ctype_unknown;
5719 case TLT: /* comparisons */
5720 case TGT: /* numeric, numeric -> bool */
5722 DPRINTF (("Here we go: %s / %s",
5723 ctype_unparse (tr1), ctype_unparse (tr2)));
5725 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5726 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5729 bool fepsilon = FALSE;
5731 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5736 if (opid == TLT || opid == TGT)
5738 uentry ue1 = exprNode_getUentry (e1);
5739 uentry ue2 = exprNode_getUentry (e2);
5742 ** FLT_EPSILON, etc. really is a variable, not
5746 if (uentry_isVariable (ue1))
5748 cstring uname = uentry_rawName (ue1);
5750 if (cstring_equalLit (uname, "FLT_EPSILON")
5751 || cstring_equalLit (uname, "DBL_EPSILON")
5752 || cstring_equalLit (uname, "LDBL_EPSILON"))
5758 if (uentry_isVariable (ue2))
5760 cstring uname = uentry_rawName (ue2);
5762 if (cstring_equalLit (uname, "FLT_EPSILON")
5763 || cstring_equalLit (uname, "DBL_EPSILON")
5764 || cstring_equalLit (uname, "LDBL_EPSILON"))
5773 ; /* Don't complain. */
5779 message ("Dangerous comparison involving %s types: %s",
5780 ctype_unparse (rtype),
5781 exprNode_unparse (ret)),
5790 ** Types should match.
5793 DPRINTF (("Match types: %s / %s", exprNode_unparse (e1),
5794 exprNode_unparse (e2)));
5796 if (!exprNode_matchTypes (e1, e2))
5798 hasError = gentypeerror
5800 message ("Operands of %s have incompatible types (%t, %t): %s",
5801 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5807 || (ctype_isForceRealNumeric (&tr1)
5808 && ctype_isForceRealNumeric (&tr2)) ||
5809 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5815 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5816 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5820 message ("Comparison of pointer and numeric (%t, %t): %s",
5821 te1, te2, exprNode_unparse (ret)),
5826 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5831 /* certain comparisons on unsigned's and zero look suspicious */
5833 if (opid == TLT || opid == LE_OP || opid == GE_OP)
5835 if ((ctype_isUnsigned (tr1) && exprNode_isZero (e2))
5836 || (ctype_isUnsigned (tr2) && exprNode_isZero (e1)))
5839 (FLG_UNSIGNEDCOMPARE,
5840 message ("Comparison of unsigned value involving zero: %s",
5841 exprNode_unparse (ret)),
5846 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5848 if ((opid == EQ_OP || opid == NE_OP) &&
5849 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5852 ** is one a variable?
5855 if (uentry_isVariable (exprNode_getUentry (e1))
5856 || uentry_isVariable (exprNode_getUentry (e2)))
5859 ** comparisons with FALSE are okay
5862 if (exprNode_isFalseConstant (e1)
5863 || exprNode_isFalseConstant (e2))
5872 ("Use of %q with %s variables (risks inconsistency because "
5873 "of multiple true values): %s",
5874 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5875 context_printBoolName (), exprNode_unparse (ret)),
5882 case AND_OP: /* bool, bool -> bool */
5885 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5891 if (context_maybeSet (FLG_BOOLOPS))
5893 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5895 if (ctype_sameName (te1, te2))
5899 message ("Operands of %s are non-boolean (%t): %s",
5900 lltok_unparse (op), te1,
5901 exprNode_unparse (ret)),
5909 ("Operands of %s are non-booleans (%t, %t): %s",
5910 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5914 else if (!ctype_isRealBool (te1))
5918 message ("Left operand of %s is non-boolean (%t): %s",
5919 lltok_unparse (op), te1, exprNode_unparse (ret)),
5922 else if (!ctype_isRealBool (te2))
5926 message ("Right operand of %s is non-boolean (%t): %s",
5927 lltok_unparse (op), te2, exprNode_unparse (ret)),
5940 (cstring_makeLiteral
5941 ("There has been a problem in the parser. This is believed to result "
5942 "from a problem with bison v. 1.25. Please try rebuidling Splint "
5943 "using the pre-compiled grammar files by commenting out the "
5944 "BISON= line in the top-level Makefile."));
5949 DPRINTF (("Return type: %s", ctype_unparse (tret)));
5952 exprNode_checkUse (ret, e1->sref, e1->loc);
5953 exprNode_mergeUSs (ret, e2);
5954 exprNode_checkUse (ret, e2->sref, e2->loc);
5960 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5961 /*@only@*/ lltok op)
5965 checkMacroParen (e1);
5966 checkMacroParen (e2);
5968 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5970 checkExpressionDefined (e1, e2, op);
5973 ret = exprNode_makeOp (e1, e2, op);
5978 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5981 ** This is somewhat bogus!
5983 ** Assigning to a nested observer in a non-observer datatype
5984 ** should not produce an error.
5987 sRef ref = exprNode_getSref (e1);
5989 DPRINTF (("Check assign mod: %s",
5990 sRef_unparseFull (ref)));
5992 if (sRef_isObserver (ref)
5993 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
5994 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5996 sRef base = sRef_getBase (ref);
5998 if (sRef_isValid (base) && sRef_isObserver (base))
6000 exprNode_checkModify (e1, ret);
6004 exprNode_checkModifyVal (e1, ret);
6009 exprNode_checkModify (e1, ret);
6014 exprNode_assign (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2, /*@only@*/ lltok op)
6016 bool isalloc = FALSE;
6017 bool isjustalloc = FALSE;
6018 bool noalias = FALSE;
6021 DPRINTF (("%s [%s] <- %s [%s]",
6022 exprNode_unparse (e1),
6023 ctype_unparse (e1->typ),
6024 exprNode_unparse (e2),
6025 ctype_unparse (e2->typ)));
6027 if (lltok_getTok (op) != TASSIGN)
6029 ret = exprNode_makeOp (e1, e2, op);
6031 DPRINTF (("Here goes: %s %s",
6032 ctype_unparse (e1->typ),
6033 ctype_unparse (e2->typ)));
6035 if (exprNode_isDefined (e1)
6036 && exprNode_isDefined (e2))
6038 if (ctype_isNumeric (e2->typ)
6039 || ctype_isNumeric (e1->typ))
6041 /* Its a pointer arithmetic expression like ptr += i */
6048 ret = exprNode_createPartialCopy (e1);
6049 ret->kind = XPR_ASSIGN;
6050 ret->edata = exprData_makeOp (e1, e2, op);
6052 if (!exprNode_isError (e2))
6054 ret->sets = sRefSet_union (ret->sets, e2->sets);
6055 ret->msets = sRefSet_union (ret->msets, e2->msets);
6056 ret->uses = sRefSet_union (ret->uses, e2->uses);
6060 checkExpressionDefined (e1, e2, op);
6062 if (exprNode_isError (e1))
6064 if (!exprNode_isError (e2))
6066 ret->loc = fileloc_update (ret->loc, e2->loc);
6070 ret->loc = fileloc_update (ret->loc, g_currentloc);
6074 if (!exprNode_isError (e2))
6076 checkMacroParen (e2);
6079 if (exprNode_isDefined (e1))
6081 if (sRef_isMacroParamRef (e1->sref))
6083 if (context_inIterDef ())
6085 uentry ue = sRef_getUentry (e1->sref);
6087 if (uentry_isYield (ue))
6093 if (fileloc_isDefined (e1->loc))
6097 message ("Assignment to non-yield iter parameter: %q",
6098 sRef_unparse (e1->sref)),
6105 message ("Assignment to non-yield iter parameter: %q",
6106 sRef_unparse (e1->sref)),
6113 if (fileloc_isDefined (e1->loc))
6117 message ("Assignment to macro parameter: %q",
6118 sRef_unparse (e1->sref)),
6125 message ("Assignment to macro parameter: %q",
6126 sRef_unparse (e1->sref)),
6130 exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
6135 exprNode_checkAssignMod (e1, ret);
6138 if (exprNode_isDefined (e2))
6140 if (lltok_getTok (op) == TASSIGN)
6142 ctype te1 = exprNode_getType (e1);
6143 ctype te2 = exprNode_getType (e2);
6145 if (ctype_isVoid (te2))
6149 message ("Assignment of void value to %t: %s %s %s",
6150 te1, exprNode_unparse (e1),
6152 exprNode_unparse (e2)),
6155 else if (!ctype_forceMatch (te1, te2))
6157 if (exprNode_matchLiteral (te1, e2))
6165 message ("Assignment of %t to %t: %s %s %s",
6166 te2, te1, exprNode_unparse (e1),
6168 exprNode_unparse (e2)),
6174 /* Type checks okay */
6178 exprNode_mergeUSs (ret, e2);
6179 exprNode_checkUse (ret, e2->sref, e2->loc);
6181 DPRINTF (("Do assign! %s %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6188 doAssign (e1, e2, FALSE);
6191 ret->sref = e1->sref;
6195 if (exprNode_isDefined (e2))
6197 exprNode_mergeUSs (ret, e2);
6198 exprNode_checkUse (ret, e2->sref, e2->loc);
6202 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
6204 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
6207 isjustalloc = sRef_isJustAllocated (e1->sref);
6208 isalloc = sRef_isAllocated (e1->sref);
6210 if (sRef_isField (e1->sref))
6212 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
6214 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
6216 exprNode_checkUse (ret, root, e1->loc);
6222 ** be careful! this defines e1->sref.
6225 /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
6227 DPRINTF (("Setting: %s -> %s", exprNode_unparse (ret), sRef_unparse (e1->sref)));
6228 exprNode_checkSet (ret, e1->sref);
6232 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
6233 ? e2->loc : e1->loc);
6239 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
6248 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
6249 /*@keep@*/ exprNode elseclause)
6253 if (!exprNode_isError (pred))
6255 ret = exprNode_createPartialCopy (pred);
6256 checkMacroParen (pred);
6257 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
6259 if (!exprNode_isError (ifclause))
6261 checkMacroParen (ifclause); /* update macro counts! */
6263 if (!exprNode_isError (elseclause))
6265 checkMacroParen (elseclause);
6267 if (!exprNode_matchTypes (ifclause, elseclause))
6270 (exprNode_getType (ifclause),
6272 exprNode_getType (elseclause),
6274 message ("Conditional clauses are not of same type: "
6276 exprNode_unparse (ifclause),
6277 exprNode_getType (ifclause),
6278 exprNode_unparse (elseclause),
6279 exprNode_getType (elseclause)),
6282 ret->sref = sRef_undefined;
6283 ret->typ = ctype_unknown;
6288 /* for now...should merge the states */
6289 ret->sref = ifclause->sref;
6290 ret->typ = ifclause->typ;
6292 if (exprNode_isNullValue (ifclause))
6294 ret->typ = elseclause->typ;
6298 exprNode_checkUse (ret, pred->sref, pred->loc);
6299 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6300 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6302 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6307 ret->typ = ifclause->typ;
6309 exprNode_checkUse (pred, pred->sref, pred->loc);
6310 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6312 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6317 if (!exprNode_isError (elseclause))
6319 ret->typ = elseclause->typ;
6321 exprNode_checkUse (pred, pred->sref, pred->loc);
6322 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6324 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6328 else /* pred is error */
6330 if (!exprNode_isError (ifclause))
6332 ret = exprNode_createSemiCopy (ifclause);
6334 checkMacroParen (ifclause); /* update macro counts! */
6336 if (!exprNode_isError (elseclause))
6338 checkMacroParen (elseclause);
6340 ret->typ = ifclause->typ;
6342 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6345 (exprNode_getType (ifclause),
6347 exprNode_getType (elseclause),
6349 message ("Conditional clauses are not of same type: "
6351 exprNode_unparse (ifclause),
6352 exprNode_getType (ifclause),
6353 exprNode_unparse (elseclause),
6354 exprNode_getType (elseclause)),
6357 ret->typ = ctype_unknown;
6361 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6362 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6364 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6367 else if (!exprNode_isError (elseclause)) /* pred, if errors */
6369 ret = exprNode_createSemiCopy (ifclause);
6371 ret->typ = elseclause->typ;
6372 checkMacroParen (elseclause);
6374 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6375 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6377 else /* all errors! */
6379 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6383 ret->kind = XPR_COND;
6384 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
6386 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6388 exprNode_combineControl (ret, ifclause, elseclause);
6395 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6397 ctype totype = qtype_getType (qt);
6399 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6403 ** check use of va_arg : <valist>, type -> type
6406 if (exprNode_isError (arg))
6411 targ = exprNode_getType (arg);
6414 ** arg should have be a pointer
6417 if (!ctype_isUA (targ) ||
6418 (!usymId_equal (ctype_typeId (targ),
6419 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6423 message ("First argument to va_arg is not a va_list (type %t): %s",
6424 targ, exprNode_unparse (arg)),
6428 exprNode_checkSet (ret, arg->sref);
6432 ** return type is totype
6436 ret->kind = XPR_VAARG;
6437 ret->edata = exprData_makeCast (tok, arg, qt);
6442 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6444 exprNode ret = exprNode_createPlain (ctype_undefined);
6445 ret->kind = XPR_LABEL;
6446 ret->edata = exprData_makeLiteral (label);
6447 ret->isJumpPoint = TRUE;
6449 return (ret); /* for now, ignore label */
6452 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6454 if (exprNode_isDefined (stmt))
6456 stmt->isJumpPoint = TRUE;
6458 /* This prevent stray no return path errors, etc. */
6459 stmt->exitCode = XK_MUSTEXIT;
6465 bool exprNode_isDefaultMarker (exprNode e)
6467 if (exprNode_isDefined (e))
6469 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6475 bool exprNode_isCaseMarker (exprNode e)
6477 if (exprNode_isDefined (e))
6479 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6485 bool exprNode_isLabelMarker (exprNode e)
6487 if (exprNode_isDefined (e))
6489 return (e->kind == XPR_LABEL);
6495 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6497 exprNode ret = exprNode_createPartialCopy (test);
6499 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6501 if (exprNode_isError (test)) {
6505 exprNode_checkUse (ret, test->sref, test->loc);
6507 usymtab_setExitCode (ret->exitCode);
6511 usymtab_setMustBreak ();
6514 ret->edata = exprData_makeSingle (test);
6515 ret->isJumpPoint = TRUE;
6521 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6523 exprNode ret = exprNode_createPartialCopy (test);
6525 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6526 ret->edata = exprData_makePair (test, stmt);
6527 ret->isJumpPoint = TRUE;
6529 if (exprNode_isError (test))
6534 exprNode_checkUse (ret, test->sref, test->loc);
6536 if (exprNode_isError (stmt))
6541 exprNode_mergeUSs (ret, stmt);
6543 ret->exitCode = stmt->exitCode;
6544 ret->mustBreak = stmt->mustBreak;
6545 ret->canBreak = stmt->canBreak;
6547 usymtab_setExitCode (ret->exitCode);
6551 usymtab_setMustBreak ();
6558 /*@notnull@*/ /*@only@*/ exprNode
6559 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6561 exprNode ret = exprNode_createTok (def);
6563 ret->isJumpPoint = TRUE;
6564 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6569 exprNode_mayEscape (exprNode e)
6571 if (exprNode_isDefined (e))
6573 return exitkind_couldEscape (e->exitCode);
6579 exprNode_mustBreak (exprNode e)
6581 if (exprNode_isDefined (e))
6583 return e->mustBreak;
6590 exprNode_mustEscape (exprNode e)
6592 if (exprNode_isDefined (e))
6594 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6601 exprNode_errorEscape (exprNode e)
6603 if (exprNode_isDefined (e))
6605 return exitkind_isError (e->exitCode);
6611 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6613 exprNode ret = exprNode_createPartialCopy (e1);
6615 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6617 ret->edata = exprData_makePair (e1, e2);
6618 ret->kind = XPR_STMTLIST;
6620 if (exprNode_isDefined (e1))
6622 ret->isJumpPoint = e1->isJumpPoint;
6623 ret->canBreak = e1->canBreak;
6627 if (exprNode_isDefined (e2))
6629 ret->loc = fileloc_update (ret->loc, e2->loc);
6633 if (exprNode_isDefined (e2))
6635 ret->exitCode = e2->exitCode;
6636 ret->mustBreak = e2->mustBreak;
6637 if (e2->canBreak) ret->canBreak = TRUE;
6641 ** if e1 must return, then e2 is unreachable!
6644 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6646 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6647 && !(e2->isJumpPoint))
6649 if (context_getFlag (FLG_UNREACHABLE))
6653 if (e2->kind == XPR_STMT)
6655 nr = exprData_getUopNode (e2->edata);
6658 if ((nr->kind == XPR_TOK
6659 && lltok_isSemi (exprData_getTok (nr->edata))))
6661 /* okay to have unreachable ";" */
6662 ret->exitCode = XK_MUSTEXIT;
6663 ret->canBreak = TRUE;
6667 if (optgenerror (FLG_UNREACHABLE,
6668 message ("Unreachable code: %s",
6669 exprNode_unparseFirst (nr)),
6672 ret->isJumpPoint = TRUE;
6673 ret->mustBreak = FALSE;
6674 ret->exitCode = XK_ERROR;
6675 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6679 ret->exitCode = XK_MUSTEXIT;
6680 ret->canBreak = TRUE;
6688 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6691 ** We want a warning anytime we have:
6693 ** yyy; <<<- no break or return
6697 exprNode lastStmt = exprNode_lastStatement (e1);
6699 if (exprNode_isDefined (lastStmt)
6700 && !exprNode_mustEscape (lastStmt)
6701 && !exprNode_mustBreak (lastStmt)
6702 && !exprNode_isCaseMarker (lastStmt)
6703 && !exprNode_isDefaultMarker (lastStmt)
6704 && !exprNode_isLabelMarker (lastStmt))
6706 voptgenerror (FLG_CASEBREAK,
6708 ("Fall through case (no preceding break)"),
6715 exprNode_mergeUSs (ret, e2);
6717 usymtab_setExitCode (ret->exitCode);
6721 usymtab_setMustBreak ();
6724 DPRINTF (("==> %s", exprNode_unparse (ret)));
6728 exprNode exprNode_createTok (/*@only@*/ lltok t)
6730 exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6731 ret = exprNode_create (ctype_unknown);
6732 ret->kind = XPR_TOK;
6733 ret->edata = exprData_makeTok (t);
6737 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6739 if (!exprNode_isError (e))
6741 exprChecks_checkStatementEffect(e);
6744 return (exprNode_statementError (e, t));
6747 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6749 exprNode ret = exprNode_createPartialCopy (e);
6751 if (!exprNode_isError (e))
6753 if (e->kind != XPR_ASSIGN)
6755 exprNode_checkUse (ret, e->sref, e->loc);
6758 ret->exitCode = e->exitCode;
6759 ret->canBreak = e->canBreak;
6760 ret->mustBreak = e->mustBreak;
6763 ret->edata = exprData_makeUop (e, t);
6764 ret->kind = XPR_STMT;
6769 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6771 if (!exprNode_isError (e))
6773 if (e->kind != XPR_ASSIGN)
6775 exprNode_checkUse (e, e->sref, e->loc);
6782 void exprNode_produceGuards (exprNode pred)
6784 if (!exprNode_isError (pred))
6786 if (ctype_isRealPointer (pred->typ))
6788 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6791 exprNode_checkUse (pred, pred->sref, pred->loc);
6792 exprNode_resetSref (pred);
6796 exprNode exprNode_compoundStatementExpression (/*@only@*/ lltok tlparen, /*@only@*/ exprNode e)
6800 DPRINTF (("Compound: %s", exprNode_unparse (e)));
6802 if (!context_flagOn (FLG_GNUEXTENSIONS, exprNode_loc (e)))
6804 (void) llgenhinterror
6806 message ("Compound statement expressions is not supported by ISO C99"),
6807 message ("Use +gnuextensions to allow compound statement expressions (and other GNU language extensions) "
6808 "without this warning"),
6813 ** The type of a compoundStatementExpression is the type of the last statement
6816 llassert (exprNode_isBlock (e));
6817 laststmt = exprNode_lastStatement (e);
6819 DPRINTF (("Last statement: %s / %s", exprNode_unparse (laststmt), ctype_unparse (exprNode_getType (laststmt))));
6820 DPRINTF (("e: %s", exprNode_unparse (e)));
6821 e->typ = exprNode_getType (laststmt);
6822 return exprNode_addParens (tlparen, e);
6826 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6828 exprNode ret = exprNode_createPartialCopy (e);
6830 if (!exprNode_isError (e))
6832 ret->exitCode = e->exitCode;
6833 ret->canBreak = e->canBreak;
6834 ret->mustBreak = e->mustBreak;
6837 DPRINTF (("Block e: %s", exprNode_unparse (e)));
6838 ret->edata = exprData_makeSingle (e);
6839 ret->kind = XPR_BLOCK;
6840 DPRINTF (("Block: %s", exprNode_unparse (ret)));
6844 bool exprNode_isBlock (exprNode e)
6846 return (exprNode_isDefined (e)
6847 && ((e)->kind == XPR_BLOCK));
6850 bool exprNode_isStatement (exprNode e)
6852 return (exprNode_isDefined (e)
6853 && ((e)->kind == XPR_STMT));
6856 bool exprNode_isAssign (exprNode e)
6858 if (exprNode_isDefined (e))
6860 return (e->kind == XPR_ASSIGN);
6866 bool exprNode_isEmptyStatement (exprNode e)
6868 return (exprNode_isDefined (e)
6869 && (e->kind == XPR_TOK)
6870 && (lltok_isSemi (exprData_getTok (e->edata))));
6873 bool exprNode_isMultiStatement (exprNode e)
6875 return (exprNode_isDefined (e)
6876 && ((e->kind == XPR_FOR)
6877 || (e->kind == XPR_FORPRED)
6878 || (e->kind == XPR_IF)
6879 || (e->kind == XPR_IFELSE)
6880 || (e->kind == XPR_WHILE)
6881 || (e->kind == XPR_WHILEPRED)
6882 || (e->kind == XPR_DOWHILE)
6883 || (e->kind == XPR_BLOCK)
6884 || (e->kind == XPR_STMT)
6885 || (e->kind == XPR_STMTLIST)
6886 || (e->kind == XPR_SWITCH)));
6889 void exprNode_checkIfPred (exprNode pred)
6891 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6894 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6897 bool emptyErr = FALSE;
6899 if (context_maybeSet (FLG_IFEMPTY))
6901 if (exprNode_isEmptyStatement (tclause))
6903 emptyErr = optgenerror (FLG_IFEMPTY,
6905 ("Body of if statement is empty"),
6906 exprNode_loc (tclause));
6910 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6912 if (exprNode_isDefined (tclause)
6913 && !exprNode_isBlock (tclause))
6915 voptgenerror (FLG_IFBLOCK,
6917 ("Body of if statement is not a block: %s",
6918 exprNode_unparse (tclause)),
6919 exprNode_loc (tclause));
6923 if (exprNode_isError (pred))
6925 if (exprNode_isError (tclause))
6927 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6931 ret = exprNode_createPartialCopy (tclause);
6936 if (exprNode_mustEscape (pred))
6940 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6941 exprNode_loc (pred));
6944 /*! exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred); */ /*@i523@*/
6945 exprNode_checkUse (pred, pred->sref, pred->loc);
6947 if (!exprNode_isError (tclause))
6949 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
6952 ret = exprNode_createPartialCopy (pred);
6956 ret->edata = exprData_makePair (pred, tclause);
6958 ret->exitCode = XK_UNKNOWN;
6960 if (exprNode_isDefined (tclause))
6962 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
6963 ret->canBreak = tclause->canBreak;
6964 ret->sets = sRefSet_union (ret->sets, tclause->sets);
6965 ret->msets = sRefSet_union (ret->msets, tclause->msets);
6966 ret->uses = sRefSet_union (ret->uses, tclause->uses);
6969 ret->mustBreak = FALSE;
6974 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
6975 /*@only@*/ exprNode tclause,
6976 /*@only@*/ exprNode eclause)
6979 bool tEmptyErr = FALSE;
6980 bool eEmptyErr = FALSE;
6982 if (context_maybeSet (FLG_IFEMPTY))
6984 if (exprNode_isEmptyStatement (tclause))
6986 tEmptyErr = optgenerror
6989 ("Body of if clause of if statement is empty"),
6990 exprNode_loc (tclause));
6993 if (exprNode_isEmptyStatement (eclause))
6995 eEmptyErr = optgenerror
6998 ("Body of else clause of if statement is empty"),
6999 exprNode_loc (eclause));
7003 if (context_maybeSet (FLG_IFBLOCK))
7006 && exprNode_isDefined (tclause)
7007 && !exprNode_isBlock (tclause))
7009 voptgenerror (FLG_IFBLOCK,
7011 ("Body of if clause of if statement is not a block: %s",
7012 exprNode_unparse (tclause)),
7013 exprNode_loc (tclause));
7017 && exprNode_isDefined (eclause)
7018 && !exprNode_isBlock (eclause)
7019 && !(eclause->kind == XPR_IF)
7020 && !(eclause->kind == XPR_IFELSE))
7025 ("Body of else clause of if statement is not a block: %s",
7026 exprNode_unparse (eclause)),
7027 exprNode_loc (eclause));
7031 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
7033 if (exprNode_isDefined (eclause)
7034 && (eclause->kind == XPR_IF))
7036 voptgenerror (FLG_ELSEIFCOMPLETE,
7037 message ("Incomplete else if logic (no final else): %s",
7038 exprNode_unparse (eclause)),
7039 exprNode_loc (eclause));
7043 if (exprNode_isError (pred))
7045 if (exprNode_isError (tclause))
7047 if (exprNode_isError (eclause))
7049 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7053 ret = exprNode_createPartialCopy (eclause);
7058 ret = exprNode_createPartialCopy (tclause);
7061 else /* pred is okay */
7063 ret = exprNode_createPartialCopy (pred);
7065 if (exprNode_mustEscape (pred))
7069 message ("Predicate always exits: %s", exprNode_unparse (pred)),
7070 exprNode_loc (pred));
7073 /*@i3423 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);*/
7074 exprNode_checkUse (ret, pred->sref, pred->loc);
7076 exprNode_mergeCondUSs (ret, tclause, eclause);
7079 ret->kind = XPR_IFELSE;
7080 ret->edata = exprData_makeCond (pred, tclause, eclause);
7082 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
7084 exprNode_combineControl (ret, tclause, eclause);
7085 ret->loc = fileloc_update (ret->loc, eclause->loc);
7092 ** *allpaths <- TRUE iff all executions paths must go through the switch
7096 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
7098 exprNodeSList el = exprNode_flatten (e);
7099 bool mustReturn = TRUE; /* find a branch that doesn't */
7100 bool thisReturn = FALSE;
7101 bool hasDefault = FALSE;
7102 bool hasAllMembers = FALSE;
7103 bool inSwitch = FALSE;
7104 bool isEnumSwitch = FALSE;
7105 bool canBreak = FALSE;
7106 bool fallThrough = FALSE;
7107 ctype ct = ctype_unknown;
7108 enumNameSList usedEnums;
7111 if (exprNode_isDefined (test))
7116 ttype = ctype_realType (ct);
7118 if (ctype_isEnum (ttype))
7120 isEnumSwitch = TRUE;
7121 enums = ctype_elist (ttype);
7122 usedEnums = enumNameSList_new ();
7126 exprNodeSList_elements (el, current)
7129 DPRINTF ((message("checkSwitchExpr current = %s ", exprNode_unparse(current) ) ));
7131 if (exprNode_isDefined (current))
7133 switch (current->kind)
7140 (FLG_DUPLICATECASES,
7141 message ("Duplicate default cases in switch"),
7142 exprNode_loc (current));
7147 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
7155 exprNode st = exprData_getSingle (current->edata);
7156 uentry ue = exprNode_getUentry (st);
7158 if (uentry_isValid (ue))
7160 cstring cname = uentry_rawName (ue);
7162 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
7164 if (enumNameSList_member
7165 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
7168 (FLG_DUPLICATECASES,
7169 message ("Duplicate case in switch: %s",
7175 enumNameSList_addh (usedEnums, cname);
7182 message ("Case in switch not %s member: %s",
7183 ctype_unparse (ct), cname),
7190 if (inSwitch && !fallThrough)
7192 if (!thisReturn || canBreak)
7202 /*@switchbreak@*/ break;
7204 thisReturn = thisReturn || exprNode_mustEscape (current);
7205 canBreak = canBreak || current->canBreak;
7206 if (canBreak) fallThrough = FALSE;
7209 } end_exprNodeSList_elements;
7211 if (inSwitch) /* check the last one! */
7213 if (!thisReturn || canBreak)
7222 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
7223 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
7225 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
7227 voptgenerror (FLG_MISSCASE,
7228 message ("Missing case%s in switch: %q",
7229 cstring_makeLiteralTemp
7230 ((enumNameSList_size (unused) > 1) ? "s" : ""),
7231 enumNameSList_unparse (unused)),
7234 enumNameSList_free (unused);
7235 *allpaths = FALSE; /* evans 2002-01-01 */
7239 hasAllMembers = TRUE;
7243 enumNameSList_free (usedEnums);
7247 *allpaths = hasDefault;
7250 exprNodeSList_free (el);
7251 return ((hasDefault || hasAllMembers) && mustReturn);
7254 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
7256 exprNode ret = exprNode_createPartialCopy (e);
7259 DPRINTF (("Switch: %s", exprNode_unparse (s)));
7261 ret->kind = XPR_SWITCH;
7262 ret->edata = exprData_makePair (e, s);
7264 if (!exprNode_isError (s))
7266 exprNode fs = exprNode_firstStatement (s);
7267 ret->loc = fileloc_update (ret->loc, s->loc);
7269 if (exprNode_isUndefined (fs)
7270 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
7271 || exprNode_isDefaultMarker (fs)) {
7274 voptgenerror (FLG_FIRSTCASE,
7276 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
7281 if (!exprNode_isError (e))
7283 if (checkSwitchExpr (e, s, &allpaths))
7285 ret->exitCode = XK_MUSTRETURN;
7289 ret->exitCode = e->exitCode;
7292 ret->canBreak = e->canBreak;
7293 ret->mustBreak = e->mustBreak;
7297 ** exprNode.c:3883,32: Variable allpaths used before definition
7304 DPRINTF (("Context exit switch!"));
7305 context_exitSwitch (ret, allpaths);
7306 DPRINTF (("Context exit switch done!"));
7311 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
7312 /*@notnull@*/ exprNode body)
7314 sRefSet tuses = test->uses;
7316 if (!sRefSet_isEmpty (test->uses))
7318 sRefSet sets = sRefSet_newCopy (body->sets);
7319 bool hasError = TRUE;
7320 bool innerState = FALSE;
7321 sRefSet tuncon = sRefSet_undefined;
7323 sets = sRefSet_union (sets, test->sets);
7324 sets = sRefSet_union (sets, body->msets);
7325 sets = sRefSet_union (sets, test->msets);
7327 sRefSet_allElements (tuses, el)
7329 if (sRef_isUnconstrained (el))
7331 tuncon = sRefSet_insert (tuncon, el);
7335 if (sRefSet_member (sets, el))
7342 if (sRef_isInternalState (el)
7343 || sRef_isFileStatic (sRef_getRootBase (el)))
7347 } end_sRefSet_allElements ;
7351 sRefSet suncon = sRefSet_undefined;
7352 bool sinner = FALSE;
7354 sRefSet_allElements (sets, el)
7356 if (sRef_isUnconstrained (el))
7358 suncon = sRefSet_insert (suncon, el);
7360 else if (sRef_isInternalState (el))
7368 } end_sRefSet_allElements ;
7370 if (sinner && innerState)
7374 else if (sRefSet_isEmpty (tuncon)
7375 && sRefSet_isEmpty (suncon))
7380 ("Suspected infinite loop. No value used in loop test (%q) "
7381 "is modified by test or loop body.",
7382 sRefSet_unparsePlain (tuses)),
7387 if (sRefSet_isEmpty (tuncon))
7391 message ("Suspected infinite loop. No condition values "
7392 "modified. Modification possible through "
7393 "unconstrained calls: %q",
7394 sRefSet_unparsePlain (suncon)),
7401 message ("Suspected infinite loop. No condition values "
7402 "modified. Possible undetected dependency through "
7403 "unconstrained calls in loop test: %q",
7404 sRefSet_unparsePlain (tuncon)),
7410 sRefSet_free (sets);
7414 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7417 bool emptyErr = FALSE;
7419 if (context_maybeSet (FLG_WHILEEMPTY))
7421 if (exprNode_isEmptyStatement (b))
7423 emptyErr = optgenerror
7426 ("Body of while statement is empty"),
7431 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7433 if (exprNode_isDefined (b)
7434 && !exprNode_isBlock (b))
7436 if (context_inIterDef ()
7437 && (b->kind == XPR_STMTLIST
7438 || b->kind == XPR_TOK))
7444 voptgenerror (FLG_WHILEBLOCK,
7446 ("Body of while statement is not a block: %s",
7447 exprNode_unparse (b)),
7453 if (exprNode_isError (t))
7455 if (exprNode_isError (b))
7457 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7461 ret = exprNode_createPartialCopy (b);
7468 ret = exprNode_createPartialCopy (t);
7470 llassert (t->kind == XPR_WHILEPRED);
7472 test = exprData_getSingle (t->edata);
7474 if (!exprNode_isError (b) && exprNode_isDefined (test))
7476 if (context_maybeSet (FLG_INFLOOPS)
7477 || context_maybeSet (FLG_INFLOOPSUNCON))
7480 ** check that some variable in the predicate is set by the body
7481 ** if the predicate uses any variables
7484 checkInfiniteLoop (test, b);
7487 exprNode_mergeUSs (ret, b);
7489 if (exprNode_isDefined (b))
7491 ret->exitCode = exitkind_makeConditional (b->exitCode);
7496 ret->edata = exprData_makePair (t, b);
7497 ret->kind = XPR_WHILE;
7499 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7503 message ("Predicate always exits: %s", exprNode_unparse (t)),
7507 ret->exitCode = XK_NEVERESCAPE;
7510 ** If loop is infinite, and there is no break inside,
7511 ** exit code is never reach.
7514 if (exprNode_knownIntValue (t))
7516 if (!exprNode_isZero (t))
7518 if (exprNode_isDefined (b))
7522 /* Really, it means never reached. */
7523 ret->exitCode = XK_MUSTEXIT;
7533 ret->canBreak = FALSE;
7534 ret->mustBreak = FALSE;
7540 ** do { b } while (t);
7542 ** note: body passed as first argument
7545 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7549 DPRINTF (("Do while: %s / %s",
7550 exprNode_unparse (b), exprNode_unparse (t)));
7552 if (exprNode_isError (t))
7554 if (exprNode_isError (b))
7556 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7560 ret = exprNode_createPartialCopy (b);
7562 ret->exitCode = exitkind_makeConditional (b->exitCode);
7563 exprNode_checkUse (ret, b->sref, b->loc);
7564 ret->exitCode = b->exitCode;
7565 ret->canBreak = b->canBreak;
7566 ret->mustBreak = FALSE;
7571 DPRINTF (("Do while: %s / %s",
7572 exitkind_unparse (t->exitCode),
7573 exitkind_unparse (b->exitCode)));
7575 ret = exprNode_createPartialCopy (t);
7576 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7578 if (!exprNode_isError (b))
7581 ** forgot the copy's --- why wasn't this detected??
7584 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7585 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7586 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
7588 /* left this out --- causes and aliasing bug (infinite loop)
7589 should be detected?? */
7591 exprNode_checkUse (ret, b->sref, b->loc);
7592 exprNode_mergeUSs (ret, t);
7593 exprNode_checkUse (ret, t->sref, t->loc);
7595 /* evans 2001-10-05: while loop can break */
7596 ret->exitCode = exitkind_makeConditional (b->exitCode);
7598 DPRINTF (("Do while: %s",
7599 exitkind_unparse (ret->exitCode)));
7601 ret->canBreak = b->canBreak;
7603 /* Always FALSE for doWhile loops - break's when test is false */
7604 ret->mustBreak = FALSE; /* b->mustBreak; */
7608 context_exitDoWhileClause (t);
7610 ret->kind = XPR_DOWHILE;
7611 ret->edata = exprData_makePair (t, b);
7615 bool exprNode_loopMustExec (exprNode forPred)
7618 ** Returns true if it is obvious that the loop always executes at least once
7620 ** For now, we only identify the most obvious cases. Should be true anytime
7621 ** we can prove init => !test.
7624 if (exprNode_isDefined (forPred))
7626 exprNode init, test, inc;
7629 llassert (forPred->kind == XPR_FORPRED);
7631 edata = forPred->edata;
7632 init = exprData_getTripleInit (edata);
7633 test = exprData_getTripleTest (edata);
7634 inc = exprData_getTripleInc (edata);
7636 if (exprNode_isAssign (init))
7638 exprNode loopVar = exprData_getOpA (init->edata);
7639 exprNode loopInit = exprData_getOpB (init->edata);
7641 if (exprNode_isDefined (test) && test->kind == XPR_OP)
7643 exprNode testVar = exprData_getOpA (test->edata);
7644 exprNode testVal = exprData_getOpB (test->edata);
7645 lltok comp = exprData_getOpTok (test->edata);
7646 int opid = lltok_getTok (comp);
7648 DPRINTF (("Same storage: %s / %s", exprNode_unparse (loopVar),
7649 exprNode_unparse (testVar)));
7651 if (exprNode_sameStorage (loopVar, testVar))
7653 multiVal valinit = exprNode_getValue (loopInit);
7654 multiVal valtest = exprNode_getValue (testVal);
7656 DPRINTF (("Values: %s / %s", multiVal_unparse (valinit),
7657 multiVal_unparse (valtest)));
7659 if (multiVal_isInt (valinit) && multiVal_isInt (valtest))
7661 long v1 = multiVal_forceInt (valinit);
7662 long v2 = multiVal_forceInt (valtest);
7664 DPRINTF (("Here: %ld %ld", v1, v2));
7666 if ((opid == EQ_OP && v1 < v2)
7667 || (opid == NE_OP && v1 != v2)
7668 || (opid == TLT && v1 <= v2)
7669 || (opid == TGT && v1 >= v2)
7670 || (opid == LE_OP && v1 < v2)
7671 || (opid == GE_OP && v1 > v2))
7673 DPRINTF (("mustexec if inc"));
7682 DPRINTF (("loop must exec: FALSE"));
7686 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7689 bool emptyErr = FALSE;
7691 if (context_maybeSet (FLG_FOREMPTY))
7693 if (exprNode_isEmptyStatement (body))
7695 emptyErr = optgenerror
7698 ("Body of for statement is empty"),
7699 exprNode_loc (body));
7703 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7705 if (exprNode_isDefined (body)
7706 && !exprNode_isBlock (body))
7708 if (context_inIterDef ()
7709 && (body->kind == XPR_STMTLIST
7710 || body->kind == XPR_TOK))
7716 voptgenerror (FLG_FORBLOCK,
7718 ("Body of for statement is not a block: %s",
7719 exprNode_unparse (body)),
7720 exprNode_loc (body));
7726 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7729 if (exprNode_isError (body))
7731 ret = exprNode_createPartialCopy (inc);
7735 ret = exprNode_createPartialCopy (body);
7737 ret->exitCode = exitkind_makeConditional (body->exitCode);
7739 exprNode_mergeUSs (inc, body);
7741 if (exprNode_isDefined (inc))
7745 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7747 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7748 exprNode_freeShallow (tmp);
7750 context_clearMessageAnnote ();
7751 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7753 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7754 exprNode_freeShallow (tmp);
7756 context_clearMessageAnnote ();
7758 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7759 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7760 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7764 ret->kind = XPR_FOR;
7765 ret->edata = exprData_makePair (inc, body);
7767 if (exprNode_isDefined (inc)) {
7768 exprNode test = exprData_getTripleTest (inc->edata);
7770 if (exprNode_isUndefined (test)) {
7771 if (exprNode_isDefined (body)) {
7772 if (!body->canBreak) {
7773 /* Really, it means never reached. */
7774 ret->exitCode = XK_MUSTEXIT;
7784 ** for (init; test; inc)
7787 ** while (test) { body; inc; }
7789 ** Now: check use of init (may set vars for test)
7790 ** check use of test
7794 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7798 if (exprNode_isError (pred)) return guardSet_undefined;
7800 llassert (pred->kind == XPR_FORPRED);
7802 test = exprData_getTripleTest (pred->edata);
7804 if (!exprNode_isError (test))
7806 return (test->guards);
7809 return guardSet_undefined;
7812 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7814 exprNode ret = exprNode_createSemiCopy (test);
7816 if (exprNode_isDefined (test))
7818 exprNode_copySets (ret, test);
7819 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7820 exprNode_checkUse (ret, test->sref, test->loc);
7822 exprNode_produceGuards (test);
7824 ret->guards = guardSet_copy (test->guards);
7827 ret->edata = exprData_makeSingle (test);
7828 ret->kind = XPR_WHILEPRED;
7832 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7833 /*@only@*/ exprNode inc)
7838 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7841 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7843 if (!exprNode_isError (inc))
7845 ret = exprNode_createPartialCopy (inc);
7849 if (!exprNode_isError (init))
7851 ret = exprNode_createPartialCopy (init);
7853 else if (!exprNode_isError (test))
7855 ret = exprNode_createPartialCopy (test);
7859 ret = exprNode_createUnknown ();
7863 exprNode_mergeUSs (ret, init);
7865 if (exprNode_isDefined (init))
7867 exprNode_checkUse (ret, init->sref, init->loc);
7870 exprNode_mergeUSs (ret, test);
7872 if (exprNode_isDefined (test))
7874 exprNode_checkUse (ret, test->sref, test->loc);
7877 ret->kind = XPR_FORPRED;
7878 ret->edata = exprData_makeFor (init, test, inc);
7882 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7884 exprNode ret = exprNode_createUnknown ();
7886 if (context_inMacro ())
7888 voptgenerror (FLG_MACROSTMT,
7889 message ("Macro %s uses goto (not functional)",
7890 context_inFunctionName ()),
7894 ret->kind = XPR_GOTO;
7895 ret->edata = exprData_makeLiteral (label);
7896 ret->mustBreak = TRUE;
7897 ret->exitCode = XK_GOTO;
7898 ret->canBreak = TRUE;
7902 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7904 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7906 ret->kind = XPR_CONTINUE;
7907 ret->edata = exprData_makeTok (l);
7908 ret->canBreak = TRUE;
7909 ret->mustBreak = TRUE;
7911 if (qcontinue == QSAFEBREAK)
7915 else if (qcontinue == QINNERCONTINUE)
7917 if (!context_inDeepLoop ())
7920 (FLG_LOOPLOOPCONTINUE,
7921 cstring_makeLiteral ("Continue statement marked with innercontinue "
7922 "is not inside a nested loop"),
7923 exprNode_loc (ret));
7926 else if (qcontinue == BADTOK)
7928 if (context_inDeepLoop ())
7931 (FLG_LOOPLOOPCONTINUE,
7932 cstring_makeLiteral ("Continue statement in nested loop"),
7933 exprNode_loc (ret));
7938 llbuglit ("exprNode_continue: bad qcontinue");
7944 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
7946 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7947 clause breakClause = context_breakClause ();
7949 ret->kind = XPR_BREAK;
7950 ret->edata = exprData_makeTok (l);
7951 ret->canBreak = TRUE;
7952 ret->mustBreak = TRUE;
7954 if (breakClause == NOCLAUSE)
7958 cstring_makeLiteral ("Break not inside while, for or switch statement"),
7959 exprNode_loc (ret));
7963 if (bqual != BADTOK)
7970 if (breakClause == SWITCHCLAUSE)
7972 if (!context_inDeepSwitch ())
7974 voptgenerror (FLG_SYNTAX,
7976 ("Break preceded by innerbreak is not in a deep switch"),
7977 exprNode_loc (ret));
7982 if (!context_inDeepLoop ())
7984 voptgenerror (FLG_SYNTAX,
7986 ("Break preceded by innerbreak is not in a deep loop"),
7987 exprNode_loc (ret));
7992 if (breakClause == SWITCHCLAUSE)
7994 voptgenerror (FLG_SYNTAX,
7996 ("Break preceded by loopbreak is breaking a switch"),
7997 exprNode_loc (ret));
8001 if (breakClause != SWITCHCLAUSE)
8005 message ("Break preceded by switchbreak is breaking %s",
8006 cstring_makeLiteralTemp
8007 ((breakClause == WHILECLAUSE
8008 || breakClause == DOWHILECLAUSE) ? "a while loop"
8009 : (breakClause == FORCLAUSE) ? "a for loop"
8010 : (breakClause == ITERCLAUSE) ? "an iterator"
8012 exprNode_loc (ret));
8020 if (breakClause == SWITCHCLAUSE)
8022 clause nextBreakClause = context_nextBreakClause ();
8024 switch (nextBreakClause)
8026 case NOCLAUSE: break;
8032 (FLG_LOOPSWITCHBREAK,
8033 cstring_makeLiteral ("Break statement in switch inside loop"),
8034 exprNode_loc (ret));
8038 (FLG_SWITCHSWITCHBREAK,
8039 cstring_makeLiteral ("Break statement in switch inside switch"),
8040 exprNode_loc (ret));
8047 if (context_inDeepLoop ())
8051 cstring_makeLiteral ("Break statement in nested loop"),
8052 exprNode_loc (ret));
8056 if (context_inDeepLoopSwitch ())
8059 (FLG_SWITCHLOOPBREAK,
8060 cstring_makeLiteral ("Break statement in loop inside switch"),
8061 exprNode_loc (ret));
8071 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
8073 fileloc loc = lltok_getLoc (t);
8074 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
8076 context_returnFunction ();
8077 exprChecks_checkNullReturn (loc);
8079 ret->kind = XPR_NULLRETURN;
8080 ret->edata = exprData_makeTok (t);
8081 ret->exitCode = XK_MUSTRETURN;
8085 exprNode exprNode_return (/*@only@*/ exprNode e)
8089 if (exprNode_isError (e))
8091 ret = exprNode_createUnknown ();
8095 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
8097 exprNode_checkUse (ret, e->sref, e->loc);
8098 exprNode_checkReturn (e);
8101 context_returnFunction ();
8102 ret->kind = XPR_RETURN;
8103 ret->edata = exprData_makeSingle (e);
8104 ret->exitCode = XK_MUSTRETURN;
8109 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
8113 if (exprNode_isError (e1))
8115 if (exprNode_isError (e2))
8117 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
8121 ret = exprNode_createPartialCopy (e2);
8122 exprNode_checkUse (ret, e2->sref, e2->loc);
8123 ret->sref = e2->sref;
8128 ret = exprNode_createPartialCopy (e1);
8130 exprNode_checkUse (ret, e1->sref, e1->loc);
8132 if (!exprNode_isError (e2))
8134 exprNode_mergeUSs (ret, e2);
8135 exprNode_checkUse (ret, e2->sref, e2->loc);
8136 ret->sref = e2->sref;
8140 ret->kind = XPR_COMMA;
8141 ret->edata = exprData_makePair (e1, e2);
8143 if (exprNode_isDefined (e1))
8145 if (exprNode_isDefined (e2))
8149 if (exprNode_mustEscape (e1) || e1->mustBreak)
8153 message ("Second clause of comma expression is unreachable: %s",
8154 exprNode_unparse (e2)),
8158 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
8159 ret->mustBreak = e1->mustBreak || e2->mustBreak;
8160 ret->canBreak = e1->canBreak || e2->canBreak;
8164 if (exprNode_mustEscape (e1) || e1->mustBreak)
8168 message ("Second clause of comma expression is unreachable: %s",
8169 exprNode_unparse (e2)),
8173 ret->exitCode = e1->exitCode;
8174 ret->canBreak = e1->canBreak;
8179 if (exprNode_isDefined (e2))
8181 ret->exitCode = e2->exitCode;
8182 ret->mustBreak = e2->mustBreak;
8183 ret->canBreak = e2->canBreak;
8190 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
8192 ctype t1 = exprNode_getType (el);
8193 ctype t2 = exprNode_getType (val);
8194 bool hasError = FALSE;
8196 DPRINTF (("Check one init: %s / %s",
8197 exprNode_unparse (el),
8198 exprNode_unparse (val)));
8200 if (ctype_isUnknown (t1))
8202 voptgenerror (FLG_IMPTYPE,
8203 message ("Variable has unknown (implicitly int) type: %s",
8204 exprNode_unparse (el)),
8208 el->typ = ctype_int;
8211 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
8213 exprNodeList vals = exprData_getArgs (val->edata);
8215 DPRINTF (("Check one init: %s", exprNodeList_unparse (vals)));
8216 DPRINTF (("Type: %s", ctype_unparse (t1)));
8218 if (ctype_isRealAP (t1))
8223 if (ctype_isFixedArray (t1))
8225 int nelements = long_toInt (ctype_getArraySize (t1));
8227 DPRINTF (("Checked array: %s / %d",
8228 ctype_unparse (t1), nelements));
8230 if (exprNode_isStringLiteral (val))
8232 exprNode_checkStringLiteralLength (t1, val);
8236 if (exprNodeList_size (vals) != nelements)
8238 hasError = optgenerror
8239 (exprNodeList_size (vals) > nelements ? FLG_INITSIZE : FLG_INITALLELEMENTS,
8240 message ("Initializer block for "
8241 "%s has %d element%&, but declared as %s: %q",
8242 exprNode_unparse (el),
8243 exprNodeList_size (vals),
8245 exprNodeList_unparse (vals)),
8251 exprNodeList_elements (vals, oneval)
8253 cstring istring = message ("%d", i);
8256 (exprNode_fakeCopy (el),
8257 exprNode_numLiteral (ctype_int, istring,
8258 fileloc_copy (el->loc), i));
8260 if (exprNode_isDefined (newel))
8262 if (exprNodeList_size (vals) == 1
8263 && ctype_isString (exprNode_getType (oneval))
8264 && ctype_isChar (exprNode_getType (newel)))
8266 exprNode_freeIniter (newel);
8270 if (exprNode_checkOneInit (newel, oneval))
8275 if (nerrors > 3 && exprNodeList_size (vals) > 6)
8278 (message ("Additional initialization errors "
8279 "for %s not reported",
8280 exprNode_unparse (el)),
8282 exprNode_freeIniter (newel);
8287 exprNode_freeIniter (newel);
8292 exprNode_freeIniter (newel);
8297 cstring_free (istring);
8300 } end_exprNodeList_elements;
8303 else if (ctype_isStruct (ctype_realType (t1)))
8305 uentryList fields = ctype_getFields (t1);
8308 if (uentryList_size (fields) != exprNodeList_size (vals))
8310 if (uentryList_size (fields) > exprNodeList_size (vals))
8312 hasError = optgenerror
8314 message ("Initializer block for "
8315 "%s has %d field%&, but %s has %d field%&: %q",
8316 exprNode_unparse (el),
8317 exprNodeList_size (vals),
8319 uentryList_size (fields),
8320 exprNodeList_unparse (vals)),
8325 hasError = optgenerror
8327 message ("Initializer block for "
8328 "%s has %d field%&, but %s has %d field%&: %q",
8329 exprNode_unparse (el),
8330 exprNodeList_size (vals),
8332 uentryList_size (fields),
8333 exprNodeList_unparse (vals)),
8339 exprNodeList_elements (vals, oneval)
8341 uentry thisfield = uentryList_getN (fields, i);
8343 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8345 uentry_getName (thisfield));
8347 if (exprNode_isDefined (newel))
8349 if (exprNode_checkOneInit (newel, oneval))
8354 exprNode_freeIniter (newel);
8358 } end_exprNodeList_elements;
8361 /* evans 2001-12-30: added to fix bug reported by Jim Zelenka */
8362 else if (ctype_isUnion (ctype_realType (t1)))
8364 uentryList fields = ctype_getFields (t1);
8368 ** Union initializers set the first member always.
8371 DPRINTF (("Union initializer: %s / %s",
8372 exprNode_unparse (el), ctype_unparse (ctype_realType (t1))));
8374 if (exprNodeList_size (vals) != 1)
8376 hasError = optgenerror
8378 message ("Initializer block for union "
8379 "%s has %d elements, union initializers should have one element: %q",
8380 exprNode_unparse (el),
8381 exprNodeList_size (vals),
8382 exprNodeList_unparse (vals)),
8387 exprNode oneval = exprNodeList_head (vals);
8388 uentry thisfield = uentryList_getN (fields, i);
8390 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8392 uentry_getName (thisfield));
8394 if (exprNode_isDefined (newel))
8396 if (exprNode_checkOneInit (newel, oneval))
8401 exprNode_freeIniter (newel);
8407 hasError = optgenerror
8409 message ("Initializer block used for "
8410 "%s where %t is expected: %s",
8411 exprNode_unparse (el), t1, exprNode_unparse (val)),
8417 if (exprNode_isDefined (val))
8419 doAssign (el, val, TRUE);
8421 if (!exprNode_matchType (t1, val))
8423 hasError = gentypeerror
8425 message ("Initial value of %s is type %t, "
8427 exprNode_unparse (el),
8428 t2, t1, exprNode_unparse (val)),
8437 static /*@notnull@*/ exprNode
8438 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
8442 DPRINTF (("Initialization: %s", idDecl_unparse (t)));
8444 if (usymtab_exists (idDecl_observeId (t)))
8446 uentry ue = usymtab_lookup (idDecl_observeId (t));
8447 ret = exprNode_createId (ue);
8449 /*@i723 don't do this...but why? */
8451 ct = ctype_realishType (ret->typ);
8453 DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
8455 if (ctype_isUnknown (ct))
8457 if (uentry_isAnyTag (ue))
8461 message ("%s used but not previously declared: %s",
8462 uentry_ekindName (ue),
8463 idDecl_getName (t)),
8471 message ("Variable has unknown (implicitly int) type: %s",
8472 idDecl_getName (t)),
8484 DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
8486 ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
8487 /*!! fileloc_copy (g_currentloc)); */
8488 /*@i32!!! should get error without this */
8490 ret = exprNode_fromIdentifierAux (ue);
8493 ** No error - this happens in old style declarations:
8497 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8504 exprData_free (ret->edata, ret->kind);
8505 ret->edata = exprData_undefined;
8507 ret->exitCode = XK_NEVERESCAPE;
8508 ret->mustBreak = FALSE;
8509 ret->kind = XPR_INIT;
8513 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8515 exprNode ret = exprNode_makeInitializationAux (t);
8516 llassert (ret->edata == exprData_undefined);
8517 ret->edata = exprData_makeInit (t, exprNode_undefined);
8521 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8522 /*@only@*/ exprNode e)
8524 uentry ue = usymtab_lookup (idDecl_observeId (t));
8525 exprNode ret = exprNode_makeInitializationAux (t);
8526 fileloc loc = exprNode_loc (e);
8528 if (exprNode_isError (e))
8530 e = exprNode_createUnknown ();
8533 /* error: assume initializer is defined */
8534 sRef_setDefined (ret->sref, g_currentloc);
8538 ctype ct = ctype_realishType (ret->typ);
8543 ** was addSafeUse --- what's the problem?
8545 ** int x = 3, y = x ?
8548 exprData_free (ret->edata, ret->kind);
8549 ret->edata = exprData_makeInit (t, e);
8551 exprNode_checkUse (ret, e->sref, e->loc);
8553 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8555 exprNode lhs = exprNode_createId (ue);
8558 ** static storage should be undefined before initializing
8561 if (uentry_isStatic (ue))
8563 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8566 (void) exprNode_checkOneInit (lhs, e);
8568 if (uentry_isStatic (ue))
8570 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8573 exprNode_free (lhs);
8577 if (!exprNode_matchType (ct, e))
8579 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
8586 (exprNode_getType (e), e, exprNode_getType (ret), ret,
8588 ("Variable %q initialized to type %t, expects %t: %s",
8589 uentry_getName (ue), exprNode_getType (e),
8590 exprNode_getType (ret),
8591 exprNode_unparse (e)),
8597 if (uentry_isStatic (ue))
8599 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8602 doAssign (ret, e, TRUE);
8604 if (uentry_isStatic (ue))
8606 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8610 if (context_inIterDef ())
8612 /* should check if it is yield */
8613 uentry_setUsed (ue, loc);
8620 exprNode_mergeUSs (ret, e);
8624 exprNode exprNode_iter (/*@observer@*/ uentry name,
8625 /*@only@*/ exprNodeList alist,
8626 /*@only@*/ exprNode body,
8627 /*@observer@*/ uentry end)
8632 llassert (uentry_isValid (name));
8634 uentry_setUsed (name, exprNode_loc (body));
8636 ret = exprNode_createPartialCopy (body);
8637 iname = uentry_getName (name);
8639 if (uentry_isInvalid (end))
8641 llerror (FLG_ITERBALANCE,
8642 message ("Iter %s not balanced with end_%s", iname, iname));
8646 cstring ename = uentry_getName (end);
8648 if (!cstring_equalPrefixLit (ename, "end_"))
8650 llerror (FLG_ITERBALANCE, message ("Iter %s not balanced with end_%s: %s",
8651 iname, iname, ename));
8655 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8657 llerror (FLG_ITERBALANCE,
8658 message ("Iter %s not balanced with end_%s: %s",
8659 iname, iname, ename));
8663 cstring_free (ename);
8666 context_exitIterClause (body);
8668 ret->kind = XPR_ITER;
8669 ret->edata = exprData_makeIter (name, alist, body, end);
8671 if (uentry_isIter (name))
8673 (void) checkArgsReal (name, body,
8674 uentry_getParams (name), alist, TRUE, ret);
8677 cstring_free (iname);
8683 exprNode_iterNewId (/*@only@*/ cstring s)
8685 exprNode e = exprNode_new ();
8686 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8688 llassert (processingIterVars ());
8690 e->loc = context_getSaveLocation ();
8692 if (fileloc_isUndefined (e->loc))
8694 fileloc_free (e->loc);
8695 e->loc = fileloc_copy (g_currentloc);
8698 e->uses = sRefSet_new ();
8699 e->sets = sRefSet_new ();
8700 e->msets = sRefSet_new ();
8702 e->val = multiVal_unknown ();
8703 e->guards = guardSet_new ();
8705 e->isJumpPoint = FALSE;
8706 e->exitCode = XK_NEVERESCAPE;
8708 /*> missing fields, detected by splint <*/
8709 e->canBreak = FALSE;
8710 e->mustBreak = FALSE;
8711 e->etext = cstring_undefined;
8713 if (uentry_isYield (ue))
8715 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8716 fileloc_copy (e->loc),
8720 uue = usymtab_supEntrySrefReturn (uue);
8722 sr = uentry_getSref (uue);
8723 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8724 sr = uentry_getSref (uue);
8725 sRef_setDefined (sr, e->loc);
8727 e->typ = uentry_getType (uue);
8729 e->edata = exprData_makeId (uue);
8730 uentry_setUsed (uue, g_currentloc);
8736 sRef_setGlobalScope ();
8737 uue = uentry_makeVariableLoc (s, ctype_unknown);
8739 e->typ = ctype_unknown;
8740 e->edata = exprData_makeId (uue);
8742 uentry_setUsed (uue, e->loc);
8743 uentry_setHasNameError (uue);
8745 if (context_getFlag (FLG_REPEATUNRECOG))
8747 uentry_markOwned (uue);
8751 usymtab_supGlobalEntry (uue);
8754 sRef_clearGlobalScope ();
8756 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8763 exprNode_defineConstraints(e);
8768 exprNode_iterExpr (/*@returned@*/ exprNode e)
8770 if (!processingIterVars ())
8772 llcontbuglit ("checkIterParam: not in iter");
8776 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8779 if (exprNode_isDefined (e))
8781 if (fileloc_isDefined (e->loc))
8785 message ("Yield parameter is not simple identifier: %s",
8786 exprNode_unparse (e)),
8793 message ("Yield parameter is not simple identifier: %s",
8794 exprNode_unparse (e)),
8804 exprNode_iterId (/*@observer@*/ uentry c)
8808 llassert (processingIterVars ());
8810 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8813 if (uentry_isYield (ue))
8815 ctype ct = uentry_getType (ue);
8816 exprNode e = exprNode_createPlain (ct);
8817 cstring name = uentry_getName (c);
8818 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8820 uentry_setUsed (ue, g_currentloc);
8821 uentry_setHasNameError (ue);
8823 cstring_free (name);
8826 e->edata = exprData_makeId (le);
8827 e->loc = context_getSaveLocation ();
8828 e->sref = uentry_getSref (le);
8830 usymtab_supEntrySref (le);
8832 if (!context_inHeader ())
8836 message ("Yield parameter shadows local declaration: %q",
8837 uentry_getName (c)),
8838 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8840 uentry_showWhereDeclared (c);
8847 return (exprNode_fromIdentifierAux (c));
8850 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8852 exprNode ret = exprNode_create (ctype_unknown);
8854 ret->kind = XPR_ITERCALL;
8855 ret->edata = exprData_makeIterCall (name, alist);
8857 if (uentry_isIter (name))
8859 uentryList params = uentry_getParams (name);
8861 if (context_inIterDef ()
8862 && uentryList_size (params) == exprNodeList_size (alist))
8866 exprNodeList_elements (alist, arg)
8868 uentry parg = uentryList_getN (params, i);
8870 if (uentry_isYield (parg))
8872 uentry ue = exprNode_getUentry (arg);
8874 if (uentry_isValid (ue))
8881 } end_exprNodeList_elements;
8884 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8885 checkUnspecCall (ret, params, alist);
8891 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8893 if (exprNode_isDefined (e))
8896 if (e->sref == defref) /*@noaccess sRef@*/
8899 e->sref = sRef_makeUnknown ();
8900 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8911 return sRef_undefined;
8915 /*@observer@*/ cstring
8916 exprNode_unparseFirst (exprNode e)
8918 if (exprNode_isDefined (e))
8922 if (e->kind == XPR_STMTLIST
8923 || e->kind == XPR_COMMA || e->kind == XPR_COND)
8925 exprNode first = exprData_getPairA (e->edata);
8927 if (exprNode_isDefined (first))
8929 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8933 return (cstring_makeLiteralTemp ("..."));
8937 ret = cstring_elide (exprNode_unparse (e), 20);
8938 cstring_markOwned (ret);
8944 return cstring_makeLiteralTemp ("<error>");
8948 /*@observer@*/ cstring
8949 exprNode_unparse (/*@temp@*/ exprNode e)
8951 if (exprNode_isError (e))
8953 return cstring_makeLiteralTemp ("<error>");
8956 if (cstring_isDefined (e->etext))
8962 cstring ret = exprNode_doUnparse (e);
8964 /*@-modifies@*/ /* benevolent */
8971 /*@observer@*/ fileloc
8972 exprNode_loc (exprNode e)
8974 if (exprNode_isError (e))
8976 return (g_currentloc);
8985 ** executes exprNode e
8986 ** recursively rexecutes as though in original parse using
8987 ** information in e->edata
8990 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
8992 exprNodeList ret = exprNodeList_new ();
8994 exprNodeList_elements (e, current)
8996 exprNodeList_addh (ret, exprNode_effect (current));
8997 } end_exprNodeList_elements;
9002 static /*@only@*/ exprNode exprNode_effect (exprNode e)
9003 /*@globals internalState@*/
9005 bool innerEffect = inEffect;
9011 context_clearJustPopped ();
9013 if (exprNode_isError (e))
9015 ret = exprNode_undefined;
9020 ** Turn off expose and dependent transfer checking.
9021 ** Need to pass exposed internal nodes,
9022 ** [ copying would be a waste! ]
9023 ** [ Actually, I think I wasted a lot more time than its worth ]
9024 ** [ trying to do this. ]
9028 /*@-observertrans@*/
9029 /*@-dependenttrans@*/
9036 ret = exprNode_addParens (exprData_getUopTok (data),
9037 exprNode_effect (exprData_getUopNode (data)));
9040 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
9041 exprNode_effect (exprData_getOpB (data)),
9042 exprData_getOpTok (data));
9045 ret = exprNode_undefined;
9048 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
9049 exprNodeList_effect (exprData_getArgs (data)));
9062 cstring id = exprData_getId (data);
9063 uentry ue = usymtab_lookupSafe (id);
9065 ret = exprNode_fromIdentifierAux (ue);
9066 ret->loc = fileloc_update (ret->loc, e->loc);
9073 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
9074 exprNode_effect (exprData_getPairB (data)));
9077 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
9078 exprNode_effect (exprData_getOpB (data)),
9079 exprData_getOpTok (data));
9083 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
9084 exprData_getUopTok (data));
9087 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
9088 exprData_getUopTok (data));
9100 ret = exprNode_vaArg (exprData_getCastTok (data),
9101 exprNode_effect (exprData_getCastNode (data)),
9102 exprData_getCastType (data));
9106 ret = exprNode_cast (exprData_getCastTok (data),
9107 exprNode_effect (exprData_getCastNode (data)),
9108 exprData_getCastType (data));
9111 ret = exprNode_iterStart (exprData_getIterCallIter (data),
9113 (exprData_getIterCallArgs (data)));
9117 ret = exprNode_iter (exprData_getIterSname (data),
9118 exprNodeList_effect (exprData_getIterAlist (data)),
9119 exprNode_effect (exprData_getIterBody (data)),
9120 exprData_getIterEname (data));
9124 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
9125 exprNode_effect (exprData_getPairB (data)));
9129 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
9130 exprNode_effect (exprData_getTripleTest (data)),
9131 exprNode_effect (exprData_getTripleInc (data)));
9135 ret = exprNode_createTok (exprData_getTok (data));
9139 ret = exprNode_goto (exprData_getLiteral (data));
9140 ret->loc = fileloc_update (ret->loc, e->loc);
9144 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
9148 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
9152 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
9155 case XPR_NULLRETURN:
9156 ret = exprNode_nullReturn (exprData_getTok (data));
9160 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
9161 exprNode_effect (exprData_getPairB (data)));
9165 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
9166 exprNode_effect (exprData_getTripleTrue (data)),
9167 exprNode_effect (exprData_getTripleFalse (data)));
9170 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
9171 exprNode_effect (exprData_getPairB (data)));
9175 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
9176 exprNode_effect (exprData_getTripleTrue (data)),
9177 exprNode_effect (exprData_getTripleFalse (data)));
9180 ret = exprNode_whilePred (exprData_getSingle (data));
9184 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
9185 exprNode_effect (exprData_getPairB (data)));
9189 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
9190 exprNode_effect (exprData_getPairB (data)));
9194 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
9198 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
9199 exprData_getUopTok (data));
9203 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
9204 exprNode_effect (exprData_getPairB (data)));
9209 ret = exprNode_caseMarker
9210 (exprNode_effect (exprData_getSingle (data)),
9216 ret = exprNode_createTok (exprData_getTok (data));
9220 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
9221 exprNode_effect (exprData_getPairB (data)));
9225 ret = exprNode_makeInitialization
9226 (exprData_getInitId (data),
9227 exprNode_effect (exprData_getInitNode (data)));
9231 ret = exprNode_fieldAccessAux
9232 (exprNode_effect (exprData_getFieldNode (data)),
9233 exprNode_loc (exprData_getFieldNode (data)),
9234 cstring_copy (exprData_getFieldName (data)));
9238 ret = exprNode_arrowAccessAux
9239 (exprNode_effect (exprData_getFieldNode (data)),
9240 exprNode_loc (exprData_getFieldNode (data)),
9241 cstring_copy (exprData_getFieldName (data)));
9244 case XPR_STRINGLITERAL:
9258 /*@=observertrans@*/
9260 /*@=dependenttrans@*/
9271 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
9276 if (exprNode_isError (e))
9278 return cstring_undefined;
9286 ret = exprNode_rootVarName (exprData_getUopNode (data));
9289 ret = exprNode_rootVarName (exprData_getOpA (data));
9293 ret = exprData_getId (data);
9296 ret = idDecl_getName (exprData_getInitId (data));
9321 case XPR_NULLRETURN:
9343 case XPR_STRINGLITERAL:
9344 ret = cstring_undefined;
9351 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
9356 if (exprNode_isError (e))
9358 static /*@only@*/ cstring error = cstring_undefined;
9360 if (!cstring_isDefined (error))
9362 error = cstring_makeLiteral ("<error>");
9373 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
9376 ret = message ("%s %s %s",
9377 exprNode_unparse (exprData_getOpA (data)),
9378 lltok_unparse (exprData_getOpTok (data)),
9379 exprNode_unparse (exprData_getOpB (data)));
9382 ret = message ("%s(%q)",
9383 exprNode_unparse (exprData_getFcn (data)),
9384 exprNodeList_unparse (exprData_getArgs (data)));
9387 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
9390 ret = cstring_undefined;
9393 ret = message ("%s:", exprData_getId (data));
9397 ret = cstring_copy (exprData_getId (data));
9400 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
9401 exprNode_unparse (exprData_getPairB (data)));
9404 ret = message ("<body>");
9407 ret = message ("%s %s %s",
9408 exprNode_unparse (exprData_getOpA (data)),
9409 lltok_unparse (exprData_getOpTok (data)),
9410 exprNode_unparse (exprData_getOpB (data)));
9414 ret = message ("%s%s",
9415 lltok_unparse (exprData_getUopTok (data)),
9416 exprNode_unparse (exprData_getUopNode (data)));
9420 ret = message ("%s%s",
9421 exprNode_unparse (exprData_getUopNode (data)),
9422 lltok_unparse (exprData_getUopTok (data)));
9426 ret = message ("offsetof(%s,%q)",
9427 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
9428 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
9432 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9436 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
9440 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9444 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
9448 ret = message ("va_arg(%s, %q)",
9449 exprNode_unparse (exprData_getCastNode (data)),
9450 qtype_unparse (exprData_getCastType (data)));
9454 ret = message ("%q(%q)",
9455 uentry_getName (exprData_getIterCallIter (data)),
9456 exprNodeList_unparse (exprData_getIterCallArgs (data)));
9459 ret = message ("%q(%q) %s %q",
9460 uentry_getName (exprData_getIterSname (data)),
9461 exprNodeList_unparse (exprData_getIterAlist (data)),
9462 exprNode_unparse (exprData_getIterBody (data)),
9463 uentry_getName (exprData_getIterEname (data)));
9466 ret = message ("(%q)%s",
9467 qtype_unparse (exprData_getCastType (data)),
9468 exprNode_unparse (exprData_getCastNode (data)));
9472 ret = message ("%s %s",
9473 exprNode_unparse (exprData_getPairA (data)),
9474 exprNode_unparse (exprData_getPairB (data)));
9478 ret = message ("for (%s; %s; %s)",
9479 exprNode_unparse (exprData_getTripleInit (data)),
9480 exprNode_unparse (exprData_getTripleTest (data)),
9481 exprNode_unparse (exprData_getTripleInc (data)));
9485 ret = message ("goto %s", exprData_getLiteral (data));
9489 ret = cstring_makeLiteral ("continue");
9493 ret = cstring_makeLiteral ("break");
9497 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
9500 case XPR_NULLRETURN:
9501 ret = cstring_makeLiteral ("return");
9505 ret = message ("%s, %s",
9506 exprNode_unparse (exprData_getPairA (data)),
9507 exprNode_unparse (exprData_getPairB (data)));
9511 ret = message ("%s ? %s : %s",
9512 exprNode_unparse (exprData_getTriplePred (data)),
9513 exprNode_unparse (exprData_getTripleTrue (data)),
9514 exprNode_unparse (exprData_getTripleFalse (data)));
9517 ret = message ("if (%s) %s",
9518 exprNode_unparse (exprData_getPairA (data)),
9519 exprNode_unparse (exprData_getPairB (data)));
9523 ret = message ("if (%s) %s else %s",
9524 exprNode_unparse (exprData_getTriplePred (data)),
9525 exprNode_unparse (exprData_getTripleTrue (data)),
9526 exprNode_unparse (exprData_getTripleFalse (data)));
9529 ret = message ("while (%s) %s",
9530 exprNode_unparse (exprData_getPairA (data)),
9531 exprNode_unparse (exprData_getPairB (data)));
9535 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9539 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9543 ret = message ("do { %s } while (%s)",
9544 exprNode_unparse (exprData_getPairB (data)),
9545 exprNode_unparse (exprData_getPairA (data)));
9549 ret = message ("{ %s }", exprNode_unparse (exprData_getSingle (data)));
9550 /* evans 2002-02-20 was unparseFirst! */
9554 ret = message ("%s;", exprNode_unparse (exprData_getUopNode (data)));
9558 if (exprNode_isStatement (exprData_getPairA (data)))
9561 ** statement expressions already print the ;
9564 ret = message ("%s %s",
9565 exprNode_unparse (exprData_getPairA (data)),
9566 exprNode_unparse (exprData_getPairB (data)));
9570 ret = message ("%s; %s",
9571 exprNode_unparse (exprData_getPairA (data)),
9572 exprNode_unparse (exprData_getPairB (data)));
9578 ret = cstring_makeLiteral ("default:");
9582 ret = message ("switch (%s) %s",
9583 exprNode_unparse (exprData_getPairA (data)),
9584 exprNode_unparse (exprData_getPairB (data)));
9589 ret = message ("case %s:",
9590 exprNode_unparse (exprData_getSingle (data)));
9594 if (exprNode_isError (exprData_getInitNode (data)))
9596 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9600 ret = message ("%q = %s",
9601 idDecl_unparseC (exprData_getInitId (data)),
9602 exprNode_unparse (exprData_getInitNode (data)));
9607 ret = message ("%s.%s",
9608 exprNode_unparse (exprData_getFieldNode (data)),
9609 exprData_getFieldName (data));
9613 ret = message ("%s->%s",
9614 exprNode_unparse (exprData_getFieldNode (data)),
9615 exprData_getFieldName (data));
9618 case XPR_STRINGLITERAL:
9619 if (ctype_isWideString (e->typ))
9621 ret = message ("L\"%s\"", exprData_getLiteral (data));
9625 ret = message ("\"%s\"", exprData_getLiteral (data));
9630 ret = cstring_copy (exprData_getLiteral (data));
9634 ret = cstring_makeLiteral ("<node>");
9642 exprNode_isInitializer (exprNode e)
9644 return (exprNode_isDefined (e)
9645 && e->kind == XPR_INIT);
9649 exprNode_isCharLit (exprNode e)
9651 if (exprNode_isDefined (e))
9653 return (multiVal_isChar (exprNode_getValue (e)));
9662 exprNode_isNumLit (exprNode e)
9664 if (exprNode_isDefined (e))
9666 return (multiVal_isInt (exprNode_getValue (e)));
9675 exprNode_isFalseConstant (exprNode e)
9677 if (exprNode_isDefined (e))
9679 cstring s = exprNode_rootVarName (e);
9681 if (cstring_equal (s, context_getFalseName ()))
9691 exprNode_matchLiteral (ctype expected, exprNode e)
9693 if (exprNode_isDefined (e))
9695 multiVal m = exprNode_getValue (e);
9697 if (multiVal_isDefined (m))
9699 if (multiVal_isInt (m))
9701 long int val = multiVal_forceInt (m);
9703 if (ctype_isDirectBool (ctype_realishType (expected)))
9707 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9715 if (ctype_isRealInt (expected))
9718 ** unsigned <- [ constant >= 0 is okay ]
9721 if (ctype_isUnsigned (expected))
9730 ** No checks on sizes of integers...maybe add
9734 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9735 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9736 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9738 if (context_getFlag (FLG_NUMLITERAL)
9739 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9745 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9749 else if (ctype_isChar (expected))
9753 else if (ctype_isArrayPtr (expected))
9756 ** evans 2001-10-14: We allow 0 to match any pointer, but only if the type matches or is void *.
9761 if (ctype_match (exprNode_getType (e), expected)
9762 || ctype_isVoidPointer (exprNode_getType (e)))
9772 else if (ctype_isAnyFloat (expected))
9774 return (context_getFlag (FLG_NUMLITERAL));
9781 else if (multiVal_isDouble (m))
9783 if (ctype_isAnyFloat (expected))
9788 else if (multiVal_isChar (m))
9790 char val = multiVal_forceChar (m);
9792 if (ctype_isChar (expected))
9794 if (ctype_isUnsigned (expected) && ((int)val) < 0)
9815 exprNode_matchType (ctype expected, exprNode e)
9819 if (!exprNode_isDefined (e)) return TRUE;
9821 actual = ctype_realishType (exprNode_getType (e));
9823 if (ctype_match (ctype_realishType (expected), actual))
9828 llassert (!exprNode_isError (e));
9829 return (exprNode_matchLiteral (expected, e));
9833 exprNode_matchTypes (exprNode e1, exprNode e2)
9838 if (!exprNode_isDefined (e1)) return TRUE;
9839 if (!exprNode_isDefined (e2)) return TRUE;
9842 ** realish type --- keep bools, bools
9845 t1 = ctype_realishType (exprNode_getType (e1));
9846 t2 = ctype_realishType (exprNode_getType (e2));
9848 if (ctype_match (t1, t2))
9853 DPRINTF (("Matching literal! %s %s %s %s",
9854 ctype_unparse (t1), exprNode_unparse (e2),
9855 ctype_unparse (t2), exprNode_unparse (e1)));
9857 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9865 exprNode_matchArgType (ctype ct, exprNode e)
9869 if (!exprNode_isDefined (e))
9874 et = ctype_realType (exprNode_getType (e));
9876 if (ctype_matchArg (ct, et)) return TRUE;
9878 llassert (!exprNode_isError (e));
9879 return (exprNode_matchLiteral (ct, e));
9882 static /*@only@*/ exprNodeSList
9883 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9885 if (exprNode_isDefined (e))
9887 if (e->kind == XPR_STMTLIST)
9889 return (exprNodeSList_append
9890 (exprNode_flatten (exprData_getPairA (e->edata)),
9891 exprNode_flatten (exprData_getPairB (e->edata))));
9893 else if (e->kind == XPR_BLOCK)
9895 return (exprNode_flatten (exprData_getSingle (e->edata)));
9899 return (exprNodeSList_singleton (e));
9903 return exprNodeSList_new ();
9906 static /*@exposed@*/ exprNode
9907 exprNode_lastStatement (/*@returned@*/ exprNode e)
9909 if (exprNode_isDefined (e))
9911 if (e->kind == XPR_STMTLIST)
9913 exprNode b = exprData_getPairB (e->edata);
9915 if (exprNode_isDefined (b))
9917 return exprNode_lastStatement (b);
9921 return exprNode_lastStatement (exprData_getPairA (e->edata));
9924 else if (e->kind == XPR_BLOCK)
9926 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
9934 return exprNode_undefined;
9937 static /*@exposed@*/ exprNode
9938 exprNode_firstStatement (/*@returned@*/ exprNode e)
9940 if (exprNode_isDefined (e))
9942 if (e->kind == XPR_STMTLIST)
9944 exprNode b = exprData_getPairA (e->edata);
9946 if (exprNode_isDefined (b))
9948 return exprNode_firstStatement (b);
9952 return exprNode_firstStatement (exprData_getPairB (e->edata));
9955 else if (e->kind == XPR_BLOCK)
9957 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
9965 return exprNode_undefined;
9969 exprNode_mergeUSs (exprNode res, exprNode other)
9971 if (exprNode_isDefined (res) && exprNode_isDefined (other))
9973 res->msets = sRefSet_union (res->msets, other->msets);
9974 res->sets = sRefSet_union (res->sets, other->sets);
9975 res->uses = sRefSet_union (res->uses, other->uses);
9980 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
9982 if (exprNode_isDefined (res))
9984 if (exprNode_isDefined (other1))
9986 res->sets = sRefSet_union (res->sets, other1->sets);
9987 res->msets = sRefSet_union (res->msets, other1->msets);
9988 res->uses = sRefSet_union (res->uses, other1->uses);
9990 if (exprNode_isDefined (other2))
9992 res->sets = sRefSet_union (res->sets, other2->sets);
9993 res->msets = sRefSet_union (res->msets, other2->msets);
9994 res->uses = sRefSet_union (res->uses, other2->uses);
10000 ** modifies e->uses
10002 ** Reports errors is s is not defined.
10006 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
10008 if (exprNode_isDefined (e))
10010 e->uses = sRefSet_insert (e->uses, s);
10015 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
10017 if (sRef_isKnown (s) && !sRef_isConst (s))
10020 ** need to check all outer types are useable
10023 DPRINTF (("Check use: %s / %s",
10024 exprNode_unparse (e), sRef_unparse (s)));
10026 exprNode_addUse (e, s);
10028 if (!context_inProtectVars ())
10031 ** only report the deepest error
10034 sRef errorRef = sRef_undefined;
10035 sRef lastRef = sRef_undefined;
10036 bool deadRef = FALSE;
10037 bool unuseable = FALSE;
10038 bool errorMaybe = FALSE;
10040 while (sRef_isValid (s) && sRef_isKnown (s))
10042 ynm readable = sRef_isValidLvalue (s);
10044 DPRINTF (("Readable: %s / %s",
10045 sRef_unparseFull (s), ynm_unparse (readable)));
10047 if (!(ynm_toBoolStrict (readable)))
10049 if (ynm_isMaybe (readable))
10051 lastRef = errorRef;
10053 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
10054 deadRef = sRef_isPossiblyDead (errorRef);
10055 unuseable = sRef_isUnuseable (errorRef);
10060 lastRef = errorRef;
10062 deadRef = sRef_isDead (errorRef);
10063 unuseable = sRef_isUnuseable (errorRef);
10064 errorMaybe = FALSE;
10067 if (!sRef_isPartial (s))
10069 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
10070 sRef_setDefined (s, fileloc_undefined);
10074 s = sRef_getBaseSafe (s);
10077 if (sRef_isValid (errorRef))
10079 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
10080 && sRef_isPointer (errorRef))
10082 errorRef = lastRef;
10087 if (sRef_isThroughArrayFetch (errorRef))
10090 (FLG_STRICTUSERELEASED,
10091 message ("%q %q may be used after being released",
10092 sRef_unparseKindNamePlain (errorRef),
10093 sRef_unparse (errorRef)),
10096 sRef_showRefKilled (errorRef);
10098 if (sRef_isKept (errorRef))
10100 sRef_clearAliasState (errorRef, loc);
10106 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
10110 message ("%q %q %qused after being released",
10111 sRef_unparseKindNamePlain (errorRef),
10112 sRef_unparse (errorRef),
10113 cstring_makeLiteral (errorMaybe
10114 ? "may be " : "")),
10117 sRef_showRefKilled (errorRef);
10119 if (sRef_isKept (errorRef))
10121 sRef_clearAliasState (errorRef, loc);
10126 else if (unuseable)
10130 message ("%q %q%qused in inconsistent state",
10131 sRef_unparseKindName (errorRef),
10132 sRef_unparseOpt (errorRef),
10133 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10136 sRef_showStateInconsistent (errorRef);
10141 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
10145 message ("%q %q%qused before definition",
10146 sRef_unparseKindName (errorRef),
10147 sRef_unparseOpt (errorRef),
10148 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10151 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
10154 sRef_setDefined (errorRef, loc);
10156 if (sRef_isAddress (errorRef))
10158 sRef_setDefined (sRef_getRootBase (errorRef), loc);
10160 } /* end is error */
10168 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
10170 if (exprNode_isDefined (e) && sRef_isKnown (s))
10172 e->uses = sRefSet_insert (e->uses, s);
10177 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
10179 if (exprNode_isDefined (e))
10181 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
10186 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
10188 sRef defines = sRef_undefined;
10190 if (sRef_isValid (s) && !sRef_isNothing (s))
10192 uentry ue = sRef_getBaseUentry (s);
10194 if (uentry_isValid (ue))
10196 uentry_setLset (ue);
10199 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10201 voptgenerror (FLG_USEDEF,
10202 message ("Attempt to set unuseable storage: %q",
10207 if (sRef_isMeaningful (s))
10209 if (sRef_isDead (s))
10211 sRef base = sRef_getBaseSafe (s);
10213 if (sRef_isValid (base)
10214 && sRef_isDead (base))
10216 sRef_setPartial (s, exprNode_loc (e));
10219 defines = s; /* okay - modifies for only param */
10221 else if (sRef_isPartial (s))
10223 sRef eref = exprNode_getSref (e);
10225 if (!sRef_isPartial (eref))
10228 ** should do something different here???
10231 sRef_setDefinedComplete (eref, exprNode_loc (e));
10235 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
10238 if (sRef_isMeaningful (eref))
10247 else if (sRef_isAllocated (s))
10249 sRef eref = exprNode_getSref (e);
10252 if (!sRef_isAllocated (eref))
10254 sRef_setDefinedComplete (eref, exprNode_loc (e));
10258 sRef base = sRef_getBaseSafe (eref);
10260 if (sRef_isValid (base))
10262 sRef_setPdefined (base, exprNode_loc (e));
10270 sRef_setDefinedNCComplete (s, exprNode_loc (e));
10275 else /* not meaningful...but still need to insert it */
10281 if (exprNode_isDefined (e) && sRef_isValid (defines))
10283 e->sets = sRefSet_insert (e->sets, defines);
10288 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
10290 if (sRef_isValid (s) && !sRef_isNothing (s))
10292 uentry ue = sRef_getBaseUentry (s);
10294 if (uentry_isValid (ue))
10296 uentry_setLset (ue);
10299 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10301 voptgenerror (FLG_USEDEF,
10302 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
10306 if (sRef_isMeaningful (s))
10308 sRef_setDefinedComplete (s, exprNode_loc (e));
10311 if (exprNode_isDefined (e))
10313 e->msets = sRefSet_insert (e->msets, s);
10319 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
10321 checkAnyCall (fcn, cstring_undefined, params, args,
10322 FALSE, sRefSet_undefined, FALSE, 0);
10326 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
10327 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
10331 if (uentry_isYield (ucurrent))
10333 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
10334 exprNode_checkSet (current, current->sref);
10338 if (uentry_isSefParam (ucurrent))
10340 sRefSet sets = current->sets;
10341 sRef ref = exprNode_getSref (current);
10343 if (sRef_isMacroParamRef (ref))
10345 uentry ue = sRef_getUentry (ref);
10347 if (!uentry_isSefParam (ue))
10352 ("Parameter %d to %s is declared sef, but "
10353 "the argument is a macro parameter declared "
10355 argno, exprNode_unparse (fcn),
10356 exprNode_unparse (current)),
10357 exprNode_loc (current));
10361 if (!sRefSet_isEmpty (sets))
10363 sRefSet reported = sRefSet_undefined;
10365 sRefSet_realElements (current->sets, el)
10367 if (sRefSet_isSameNameMember (reported, el))
10369 ; /* don't report again */
10373 if (sRef_isUnconstrained (el))
10378 ("Parameter %d to %s is declared sef, but "
10379 "the argument calls unconstrained function %s "
10380 "(no guarantee it will not modify something): %s",
10381 argno, exprNode_unparse (fcn),
10382 sRef_unconstrainedName (el),
10383 exprNode_unparse (current)),
10384 exprNode_loc (current));
10391 ("Parameter %d to %s is declared sef, but "
10392 "the argument may modify %q: %s",
10393 argno, exprNode_unparse (fcn),
10395 exprNode_unparse (current)),
10396 exprNode_loc (current));
10399 } end_sRefSet_realElements;
10403 transferChecks_passParam (current, ucurrent, isSpec, fcn, argno, totargs);
10404 exprNode_mergeUSs (fcn, current);
10409 checkAnyCall (/*@dependent@*/ exprNode fcn,
10410 /*@dependent@*/ cstring fname,
10413 bool hasMods, sRefSet mods,
10418 int nargs = exprNodeList_size (args);
10423 ** concat all args ud's to f, add each arg sref as a use unless
10424 ** it was specified as "out", in which case it is a def.
10427 uentryList_reset (pn);
10430 ** aliasing checks:
10432 ** if paramn is only or unique, no other arg may alias argn
10435 exprNodeList_elements (args, current)
10439 if (exprNode_isDefined (current))
10441 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
10443 uentry ucurrent = uentryList_current (pn);
10445 if (specialArgs == 0
10446 || (paramno < specialArgs))
10448 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
10450 if (context_maybeSet (FLG_ALIASUNIQUE))
10452 if (uentry_isOnly (ucurrent)
10453 || uentry_isUnique (ucurrent))
10455 checkUniqueParams (fcn, current, args,
10456 paramno, ucurrent);
10461 else /* uentry is undefined */
10463 if (specialArgs == 0)
10465 exprNode_checkUseParam (current);
10468 exprNode_mergeUSs (fcn, current);
10471 uentryList_advanceSafe (pn);
10472 } end_exprNodeList_elements;
10478 sRefSet_allElements (mods, s)
10481 sRef rb = sRef_getRootBase (s);
10483 if (sRef_isFileOrGlobalScope (rb))
10485 context_usedGlobal (rb);
10488 fb = sRef_fixBaseParam (s, args);
10490 if (!sRef_isMacroParamRef (fb))
10492 if (sRef_isNothing (fb))
10498 if (sRef_isValid (fb))
10500 uentry ue = sRef_getBaseUentry (s);
10502 if (uentry_isValid (ue))
10504 uentry_setLset (ue);
10508 fcn->sets = sRefSet_insert (fcn->sets, fb);
10511 sRef_clearDerivedComplete (s);
10512 } end_sRefSet_allElements;
10518 if (context_hasMods ())
10520 if (context_maybeSet (FLG_MODUNCON))
10524 message ("Undetected modification possible "
10525 "from call to unconstrained function %s: %s",
10527 exprNode_unparse (fcn)),
10528 exprNode_loc (fcn));
10533 if (context_maybeSet (FLG_MODUNCONNOMODS)
10534 && !(context_inIterDef () || context_inIterEnd ()))
10537 (FLG_MODUNCONNOMODS,
10538 message ("Undetected modification possible "
10539 "from call to unconstrained function %s: %s",
10541 exprNode_unparse (fcn)),
10542 exprNode_loc (fcn));
10546 exprNode_checkSetAny (fcn, fname);
10550 void exprNode_checkUseParam (exprNode current)
10552 if (exprNode_isDefined (current))
10554 exprNode_checkUse (current, current->sref, current->loc);
10559 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10560 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10565 if (!ctype_match (tr1, tr2))
10567 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10568 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10570 DPRINTF (("No error: [%s] %s / [%s] %s",
10571 exprNode_unparse (e1), ctype_unparse (tr1),
10572 exprNode_unparse (e2), ctype_unparse (tr2)));
10576 (void) gentypeerror
10578 message ("Incompatible types for %s (%s, %s): %s %s %s",
10579 lltok_unparse (op),
10580 ctype_unparse (te1),
10581 ctype_unparse (te2),
10582 exprNode_unparse (e1), lltok_unparse (op),
10583 exprNode_unparse (e2)),
10586 ret = ctype_unknown;
10590 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
10592 ret = ctype_resolveNumerics (tr1, tr2);
10594 else if (!context_msgStrictOps ())
10596 if (ctype_isPointer (tr1))
10598 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10602 else if (ctype_isInt (tr2))
10608 ret = ctype_unknown;
10611 else if (ctype_isPointer (tr2))
10613 if (ctype_isPointer (tr1))
10617 else if (ctype_isInt (tr1))
10623 ret = ctype_unknown;
10628 ret = ctype_resolveNumerics (tr1, tr2);
10633 int opid = lltok_getTok (op);
10634 bool comparop = (opid == EQ_OP || opid == NE_OP
10635 || opid == TLT || opid == TGT
10636 || opid == LE_OP || opid == GE_OP);
10638 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10641 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10642 || (ctype_isBool (tr1) && ctype_isBool (tr2))
10643 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10649 if (ctype_sameName (te1, te2))
10653 message ("Operands of %s are non-numeric (%t): %s %s %s",
10654 lltok_unparse (op), te1,
10655 exprNode_unparse (e1), lltok_unparse (op),
10656 exprNode_unparse (e2)),
10663 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10664 lltok_unparse (op), te1, te2,
10665 exprNode_unparse (e1), lltok_unparse (op),
10666 exprNode_unparse (e2)),
10671 else if (!ctype_isNumeric (tr1))
10675 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10676 lltok_unparse (op), te1,
10677 exprNode_unparse (e1), lltok_unparse (op),
10678 exprNode_unparse (e2)),
10683 if (!ctype_isNumeric (tr2))
10687 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10688 lltok_unparse (op), te2,
10689 exprNode_unparse (e1), lltok_unparse (op),
10690 exprNode_unparse (e2)),
10695 ret = ctype_unknown;
10703 abstractOpError (ctype tr1, ctype tr2, lltok op,
10704 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10705 fileloc loc1, fileloc loc2)
10707 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10709 if (ctype_match (tr1, tr2))
10713 message ("Operands of %s are abstract type (%t): %s %s %s",
10714 lltok_unparse (op), tr1,
10715 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10722 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10723 lltok_unparse (op), tr1, tr2,
10724 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10728 else if (ctype_isRealAbstract (tr1))
10732 message ("Left operand of %s is abstract type (%t): %s %s %s",
10733 lltok_unparse (op), tr1,
10734 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10739 if (ctype_isRealAbstract (tr2))
10743 message ("Right operand of %s is abstract type (%t): %s %s %s",
10744 lltok_unparse (op), tr2,
10745 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10754 ** requies e1 and e2 and not error exprNode's.
10758 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10759 ** the rep of the abstract type is exposed.
10761 ** The order is very important:
10763 ** check rep expose (move into check transfer)
10769 ** This isn't really a sensible procedure, but the indententation
10770 ** was getting too deep.
10774 checkOneRepExpose (sRef ysr, sRef base,
10775 /*@notnull@*/ exprNode e1,
10776 /*@notnull@*/ exprNode e2, ctype ct,
10779 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
10780 || sRef_isOwned (ysr)
10781 || sRef_isExposed (ysr)))
10783 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10784 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10787 if (sRef_isIReference (ysr))
10789 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10794 ("Assignment of mutable component of parameter %q "
10795 "to component of abstract "
10796 "type %s exposes rep: %s = %s",
10797 sRef_unparse (base),
10798 ctype_unparse (ct),
10799 exprNode_unparse (e1), exprNode_unparse (e2)),
10807 ("Assignment of mutable component of parameter %q "
10808 "(through alias %q) to component of abstract "
10809 "type %s exposes rep: %s = %s",
10810 sRef_unparse (base),
10811 sRef_unparse (e2->sref),
10812 ctype_unparse (ct),
10813 exprNode_unparse (e1), exprNode_unparse (e2)),
10819 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10823 message ("Assignment of mutable parameter %q "
10824 "to component of abstract type %s "
10825 "exposes rep: %s = %s",
10826 sRef_unparse (base),
10827 ctype_unparse (ct),
10828 exprNode_unparse (e1),
10829 exprNode_unparse (e2)),
10836 message ("Assignment of mutable parameter %q "
10837 "(through alias %q) to "
10838 "component of abstract type %s exposes "
10840 sRef_unparse (base),
10841 sRef_unparse (e2->sref),
10842 ctype_unparse (ct),
10843 exprNode_unparse (e1),
10844 exprNode_unparse (e2)),
10850 if (sRef_isFileOrGlobalScope (s2b))
10852 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10856 message ("Assignment of global %q "
10858 "abstract type %s exposes rep: %s = %s",
10859 sRef_unparse (base),
10860 ctype_unparse (ct),
10861 exprNode_unparse (e1), exprNode_unparse (e2)),
10868 message ("Assignment of global %q (through alias %q) "
10870 "abstract type %s exposes rep: %s = %s",
10871 sRef_unparse (base),
10872 sRef_unparse (e2->sref),
10873 ctype_unparse (ct),
10874 exprNode_unparse (e1), exprNode_unparse (e2)),
10882 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
10884 DPRINTF (("Do assign: %s <- %s",
10885 exprNode_unparse (e1), exprNode_unparse (e2)));
10886 DPRINTF (("Ctype: %s", ctype_unparse (exprNode_getType (e1))));
10888 if (ctype_isRealFunction (exprNode_getType (e1))
10889 && !ctype_isRealPointer (exprNode_getType (e1)))
10893 message ("Invalid left-hand side of assignment (function type %s): %s",
10894 ctype_unparse (exprNode_getType (e1)),
10895 exprNode_unparse (e1)),
10899 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
10901 ctype t2 = exprNode_getType (e2);
10902 sRef sr = sRef_getRootBase (e1->sref);
10903 ctype ct = sRef_getType (sr);
10905 if (ctype_isAbstract (t2)
10906 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
10908 /* it is immutable, okay to reference */
10909 goto donerepexpose;
10912 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
10914 sRef s2b = sRef_getRootBase (e2->sref);
10915 sRef s1 = e1->sref;
10916 sRef s1b = sRef_getRootBase (s1);
10919 aliases = usymtab_canAlias (e2->sref);
10921 if (!sRef_similar (s2b, s1b)
10922 && !sRef_isExposed (s1)
10923 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
10925 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
10926 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
10927 && !sRef_isExposed (s2b))
10929 if (sRef_isIReference (e2->sref))
10934 ("Assignment of mutable component of parameter %q "
10935 "to component of abstract type %s exposes rep: %s = %s",
10936 sRef_unparse (s2b),
10937 ctype_unparse (ct),
10938 exprNode_unparse (e1), exprNode_unparse (e2)),
10945 message ("Assignment of mutable parameter %q to "
10946 "component of abstract type %s exposes rep: %s = %s",
10947 sRef_unparse (s2b),
10948 ctype_unparse (ct),
10949 exprNode_unparse (e1), exprNode_unparse (e2)),
10954 if (sRef_isFileOrGlobalScope (s2b))
10958 message ("Assignment of global %q to component of "
10959 "abstract type %s exposes rep: %s = %s",
10960 sRef_unparse (s2b),
10961 ctype_unparse (ct),
10962 exprNode_unparse (e1), exprNode_unparse (e2)),
10966 sRefSet_realElements (aliases, ysr)
10968 sRef base = sRef_getRootBase (ysr);
10970 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
10971 || sRef_sameName (base, s1b))
10973 ; /* error already reported or same sref */
10977 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
10979 } end_sRefSet_realElements;
10981 sRefSet_free (aliases);
10988 ** function variables don't really work...
10991 if (!ctype_isFunction (ctype_realType (e2->typ)))
10995 DPRINTF (("Check init: %s / %s",
10996 exprNode_unparse (e1), exprNode_unparse (e2)));
10997 transferChecks_initialization (e1, e2);
11001 transferChecks_assign (e1, e2);
11006 sRef fref = e2->sref;
11008 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
11009 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
11011 /* Need to typecheck the annotation on the parameters */
11013 if (ctype_isRealFunction (e1->typ)) {
11014 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
11015 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
11017 if (!uentryList_isMissingParams (e1p)
11018 && !uentryList_isMissingParams (e2p)
11019 && uentryList_size (e1p) > 0) {
11020 if (uentryList_size (e1p) == uentryList_size (e2p)) {
11023 uentryList_elements (e1p, el1) {
11026 el2 = uentryList_getN (e2p, n);
11028 uentry_checkMatchParam (el1, el2, n, e2);
11029 } end_uentryList_elements;
11035 if (exprNode_isStringLiteral (e2))
11037 exprNode_checkStringLiteralLength (exprNode_getType (e1), e2);
11040 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
11046 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
11047 updateAliases (e1, e2);
11052 checkMacroParen (exprNode e)
11054 if (exprNode_isError (e) || e->kind == XPR_CAST)
11060 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
11064 message ("Macro parameter used without parentheses: %s",
11065 exprNode_unparse (e)),
11072 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
11076 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
11080 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
11087 ** if e2 is a parameter or global derived location which
11088 ** can be modified (that is, e2 is a mutable abstract type,
11089 ** or a derived pointer), then e1 can alias e2.
11091 ** e1 can alias everything which e2 can alias.
11093 ** Also, if e1 is guarded, remove from guard sets!
11096 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
11098 if (!context_inProtectVars ())
11101 ** depends on types of e1 and e2
11104 sRef s1 = e1->sref;
11105 sRef s2 = e2->sref;
11106 ctype t1 = exprNode_getType (e1);
11108 /* handle pointer sRefs, record fields, arrays, etc... */
11110 if (!ctype_isRealSU (t1))
11112 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
11113 sRef_copyRealDerivedComplete (s1, s2);
11118 ** Fields should alias
11121 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
11124 if (ctype_isMutable (t1) && sRef_isKnown (s1))
11126 usymtab_clearAlias (s1);
11127 usymtab_addMustAlias (s1, s2);
11128 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
11132 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
11135 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
11137 usymtab_unguard (s1);
11142 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
11144 if (exprNode_isDefined (e))
11146 e->loc = fileloc_update (e->loc, loc);
11150 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
11156 static void checkUniqueParams (exprNode fcn,
11157 /*@notnull@*/ exprNode current,
11159 int paramno, uentry ucurrent)
11162 sRef thisref = exprNode_getSref (current);
11165 ** Check if any argument could match this argument.
11168 exprNodeList_elements (args, icurrent)
11172 if (iparamno != paramno)
11174 sRef sr = exprNode_getSref (icurrent);
11176 if (sRef_similarRelaxed (thisref, sr))
11178 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
11183 ("Parameter %d (%s) to function %s is declared %s but "
11184 "is aliased by parameter %d (%s)",
11186 exprNode_unparse (current),
11187 exprNode_unparse (fcn),
11188 alkind_unparse (uentry_getAliasKind (ucurrent)),
11189 iparamno, exprNode_unparse (icurrent)),
11195 sRefSet aliases = usymtab_canAlias (sr);
11197 sRefSet_allElements (aliases, asr)
11199 if (ctype_isUnknown (sRef_getType (thisref)))
11201 sRef_setType (thisref, uentry_getType (ucurrent));
11204 if (sRef_similarRelaxed (thisref, asr))
11206 if (sRef_isExternal (asr))
11208 if (sRef_isLocalState (thisref))
11214 sRef base = sRef_getRootBase (asr);
11216 if (!sRef_similar (sRef_getBase (asr), thisref))
11218 if (sRef_isUnique (base) || sRef_isOnly (base)
11219 || sRef_isKept (base)
11220 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
11221 || (sRef_isAddress (thisref)
11222 && sRef_isLocalVar (sRef_getRootBase (thisref))))
11224 ; /* okay, no error */
11229 (FLG_MAYALIASUNIQUE,
11231 ("Parameter %d (%s) to function %s is declared %s but "
11232 "may be aliased externally by parameter %d (%s)",
11234 exprNode_unparse (current),
11235 exprNode_unparse (fcn),
11236 alkind_unparse (uentry_getAliasKind (ucurrent)),
11237 iparamno, exprNode_unparse (icurrent)),
11248 ("Parameter %d (%s) to function %s is declared %s but "
11249 "is aliased externally by parameter %d (%s) through "
11252 exprNode_unparse (current),
11253 exprNode_unparse (fcn),
11254 alkind_unparse (uentry_getAliasKind (ucurrent)),
11255 iparamno, exprNode_unparse (icurrent),
11256 sRef_unparse (asr)),
11260 } end_sRefSet_allElements;
11261 sRefSet_free (aliases);
11264 } end_exprNodeList_elements;
11267 long exprNode_getLongValue (exprNode e) {
11270 if (exprNode_hasValue (e)
11271 && multiVal_isInt (exprNode_getValue (e)))
11273 value = multiVal_forceInt (exprNode_getValue (e));
11284 /*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
11286 if (exprNode_isDefined (p_e) )
11287 return ( p_e->loc );
11289 return fileloc_undefined;
11292 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
11295 ** Returns the location of the sequence point following e.
11297 ** Only works for statements (for now).
11300 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
11301 lltok t = exprData_getUopTok (e->edata);
11302 return fileloc_copy(lltok_getLoc (t));
11304 /* drl possible problem : warning fix
11305 llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
11307 return fileloc_undefined;
11311 exprNode exprNode_createNew(ctype c)
11315 ret = exprNode_createPlain (c);
11320 bool exprNode_isInitBlock (exprNode e)
11322 return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);