2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
28 # include <ctype.h> /* for isdigit */
29 # include "splintMacros.nf"
31 # include "cgrammar.h"
32 # include "cgrammar_tokens.h"
34 # include "exprChecks.h"
35 # include "transferChecks.h"
36 # include "exprNodeSList.h"
38 static bool exprNode_sameStorage (exprNode p_e1, exprNode p_e2) /*@*/ ;
39 static bool exprNode_isEmptyStatement (exprNode p_e);
40 static /*@exposed@*/ exprNode exprNode_firstStatement (/*@returned@*/ exprNode p_e);
41 static bool exprNode_isFalseConstant (exprNode p_e) /*@*/ ;
42 static bool exprNode_isBlock (exprNode p_e);
43 static void checkGlobUse (uentry p_glob, bool p_isCall, /*@notnull@*/ exprNode p_e);
44 static void exprNode_addUse (exprNode p_e, /*@exposed@*/ sRef p_s);
45 static bool exprNode_matchArgType (ctype p_ct, exprNode p_e);
46 static exprNode exprNode_fakeCopy (exprNode p_e) /*@*/ ;
47 static exprNode exprNode_statementError (/*@only@*/ exprNode p_e, /*@only@*/ lltok p_t);
48 static bool exprNode_matchTypes (exprNode p_e1, exprNode p_e2);
49 static void checkUniqueParams (exprNode p_fcn,
50 /*@notnull@*/ exprNode p_current, exprNodeList p_args,
51 int p_paramno, uentry p_ucurrent);
52 static void updateAliases (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2);
53 static void abstractOpError (ctype p_tr1, ctype p_tr2, lltok p_op,
54 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2,
55 fileloc p_loc1, fileloc p_loc2);
56 static ctype checkNumerics (ctype p_tr1, ctype p_tr2, ctype p_te1, ctype p_te2,
57 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, lltok p_op);
58 static void doAssign (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, bool p_isInit);
59 static void checkSafeUse (exprNode p_e, /*@exposed@*/ sRef p_s);
60 static void reflectNullTest (/*@notnull@*/ exprNode p_e, bool p_isnull);
61 static void checkMacroParen (exprNode p_e);
62 static exprNodeSList exprNode_flatten (/*@dependent@*/ exprNode p_e);
63 static void exprNode_checkSetAny (exprNode p_e, /*@dependent@*/ cstring p_name);
64 static void exprNode_checkUse (exprNode p_e, /*@exposed@*/ sRef p_s, fileloc p_loc);
65 static void exprNode_mergeUSs (exprNode p_res, exprNode p_other);
66 static void exprNode_mergeCondUSs (exprNode p_res, exprNode p_other1, exprNode p_other2);
67 static /*@only@*/ /*@notnull@*/ exprNode exprNode_fromIdentifierAux (/*@observer@*/ uentry p_c);
68 static void checkAnyCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn,
69 /*@dependent@*/ cstring p_fname,
70 uentryList p_pn, exprNodeList p_args,
71 bool p_hasMods, sRefSet p_mods, bool p_isSpec,
73 static void checkOneArg (uentry p_ucurrent, /*@notnull@*/ exprNode p_current,
74 /*@dependent@*/ exprNode p_fcn, bool p_isSpec, int p_argno, int p_totargs);
76 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn, uentryList p_params, exprNodeList p_args);
78 static /*@only@*/ exprNode exprNode_effect (exprNode p_e)
79 /*@globals internalState@*/ ;
80 static /*@only@*/ cstring exprNode_doUnparse (exprNode p_e);
81 static /*@observer@*/ cstring exprNode_rootVarName (exprNode p_e);
82 static /*@exposed@*/ exprNode
83 exprNode_lastStatement (/*@returned@*/ exprNode p_e);
85 static /*@null@*/ sRef defref = sRef_undefined;
86 static /*@only@*/ exprNode mustExitNode = exprNode_undefined;
88 static int checkArgsReal (uentry p_fcn, /*@dependent@*/ exprNode p_f,
90 exprNodeList p_args, bool p_isIter, exprNode p_ret);
92 static bool inEffect = FALSE;
93 static int nowalloc = 0;
94 static int totalloc = 0;
95 static int maxalloc = 0;
97 static /*@only@*/ uentry regArg;
98 static /*@only@*/ uentry outArg;
99 static /*@only@*/ uentry outStringArg;
100 static /*@exposed@*/ sRef stdinRef;
101 static /*@exposed@*/ sRef stdoutRef;
102 static /*@only@*/ uentry csArg;
103 static /*@only@*/ uentry csOnlyArg;
104 static ctype cstringType;
105 static ctype ctypeType;
106 static ctype filelocType;
107 static bool initMod = FALSE;
109 /*@function void exprNode_swap (sef exprNode, sef exprNode)@*/
111 # define exprNode_swap(e1,e2) do { exprNode m_tmp = (e1); (e1) = (e2); (e2) = m_tmp; } while (FALSE)
114 static void exprNode_defineConstraints(/*@sef@*/ /*@special@*/ /*@notnull@*/ exprNode e)
115 /*@defines e->requiresConstraints, e->ensuresConstraints,
116 e->trueEnsuresConstraints, e->falseEnsuresConstraints @*/
118 e->requiresConstraints = constraintList_makeNew ();
119 e->ensuresConstraints = constraintList_makeNew ();
120 e->trueEnsuresConstraints = constraintList_makeNew ();
121 e->falseEnsuresConstraints = constraintList_makeNew ();
125 ** must occur after library has been read
128 void exprNode_initMod (void)
129 /*@globals undef regArg, undef outArg, undef outStringArg,
130 undef csOnlyArg, undef csArg;
137 cstringType = ctype_unknown;
138 ctypeType = ctype_unknown;
139 filelocType = ctype_unknown;
141 defref = sRef_undefined;
143 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
145 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
148 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
150 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
153 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
155 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
158 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdin")))
160 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdin"));
162 else /* define stdin */
164 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdin"),
166 fileloc_getBuiltin (),
168 uentry_setHasNameError (ue);
169 ue = usymtab_supGlobalEntryReturn (ue);
172 stdinRef = sRef_makePointer (uentry_getSref (ue));
174 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdout")))
176 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdout"));
180 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdout"),
182 fileloc_getBuiltin (),
184 uentry_setHasNameError (ue);
185 ue = usymtab_supGlobalEntryReturn (ue);
188 stdoutRef = sRef_makePointer (uentry_getSref (ue));
190 tmp = idDecl_create (cstring_undefined, qtype_create (ctype_unknown));
192 regArg = uentry_makeParam (tmp, PARAMUNKNOWN);
195 qtype_addQual (qtype_create (ctype_makePointer (ctype_unknown)),
198 outArg = uentry_makeParam (tmp, PARAMUNKNOWN);
200 idDecl_setTyp (tmp, qtype_addQual (qtype_create (ctype_string),
203 outStringArg = uentry_makeParam (tmp, PARAMUNKNOWN);
205 idDecl_setTyp (tmp, qtype_addQual (qtype_addQual (qtype_create (cstringType),
207 qual_createNull ()));
209 csOnlyArg = uentry_makeParam (tmp, PARAMUNKNOWN);
211 idDecl_setTyp (tmp, qtype_addQual (qtype_create (cstringType), qual_createNull ()));
212 csArg = uentry_makeParam (tmp, PARAMUNKNOWN);
218 exprNode_destroyMod (void)
219 /*@globals killed regArg, killed outArg, killed outStringArg,
220 killed mustExitNode, initMod @*/
224 uentry_free (regArg);
225 uentry_free (outArg);
226 uentry_free (outStringArg);
228 exprNode_free (mustExitNode);
235 static void exprNode_resetSref (/*@notnull@*/ exprNode e)
240 exprNode exprNode_fakeCopy (exprNode e)
242 /*@-temptrans@*/ /*@-retalias@*/
244 /*@=temptrans@*/ /*@=retalias@*/
247 static bool isFlagKey (char key)
249 return (key == '-' || key == '+' || key == ' ' || key == '#');
252 static void exprNode_combineControl (/*@notnull@*/ exprNode ret,
253 /*@notnull@*/ exprNode ifclause,
254 /*@notnull@*/ exprNode elseclause)
256 ret->canBreak = ifclause->canBreak || elseclause->canBreak;
259 (ifclause->mustBreak || exprNode_mustEscape (ifclause))
260 && (elseclause->mustBreak || exprNode_mustEscape (elseclause));
262 ret->exitCode = exitkind_combine (ifclause->exitCode,
263 elseclause->exitCode);
268 ** For exprNode's returned by exprNode_effect.
271 static bool shallowKind (exprKind kind)
273 return (kind == XPR_STRINGLITERAL
274 || kind == XPR_NUMLIT
277 || kind == XPR_NODE);
281 exprNode_freeIniter (/*@only@*/ exprNode e)
283 if (!exprNode_isError (e))
289 ** Its a fake copy, don't free the field->rec and field->field
294 sfree (e->edata->field);
300 exprNode_free (e->edata->op->b);
301 /*@-compdestroy@*/ sfree (e->edata->op); /*@=compdestroy@*/
305 llbug (message ("other: %s", exprNode_unparse (e)));
308 multiVal_free (e->val);
309 cstring_free (e->etext);
310 fileloc_free (e->loc);
311 sRefSet_free (e->uses);
312 sRefSet_free (e->sets);
313 sRefSet_free (e->msets);
314 guardSet_free (e->guards);
316 constraintList_free(e->requiresConstraints);
317 constraintList_free(e->ensuresConstraints);
318 constraintList_free(e->trueEnsuresConstraints);
319 constraintList_free(e->falseEnsuresConstraints);
321 e->requiresConstraints = NULL;
322 e->ensuresConstraints = NULL;
323 e->trueEnsuresConstraints = NULL;
324 e->falseEnsuresConstraints = NULL;
331 exprNode_freeShallow (/*@only@*/ exprNode e)
333 if (!exprNode_isError (e))
335 if (shallowKind (e->kind))
342 if (e->kind == XPR_EMPTY
343 || e->kind == XPR_BODY
344 || e->kind == XPR_STRINGLITERAL
345 || e->kind == XPR_NUMLIT
346 || e->kind == XPR_NODE
347 || e->kind == XPR_OFFSETOF
348 || e->kind == XPR_ALIGNOFT
349 || e->kind == XPR_ALIGNOF
350 || e->kind == XPR_SIZEOFT
351 || e->kind == XPR_SIZEOF)
353 /* don't free anything */
357 /* multiVal_free (e->val); */
358 cstring_free (e->etext);
359 fileloc_free (e->loc);
360 sRefSet_free (e->uses);
361 sRefSet_free (e->sets);
362 sRefSet_free (e->msets);
363 guardSet_free (e->guards);
364 exprData_freeShallow (e->edata, e->kind);
366 /*@-compdestroy@*/ sfree (e); /*@=compdestroy@*/
375 exprNode_free (exprNode e)
377 if (!exprNode_isError (e))
381 multiVal_free (e->val);
382 cstring_free (e->etext);
383 fileloc_free (e->loc);
384 sRefSet_free (e->uses);
385 sRefSet_free (e->sets);
386 sRefSet_free (e->msets);
387 guardSet_free (e->guards);
388 exprData_free (e->edata, e->kind);
390 constraintList_free(e->requiresConstraints);
391 constraintList_free(e->ensuresConstraints);
392 constraintList_free(e->trueEnsuresConstraints);
393 constraintList_free(e->falseEnsuresConstraints);
395 e->requiresConstraints = NULL;
396 e->ensuresConstraints = NULL;
397 e->trueEnsuresConstraints = NULL;
398 e->falseEnsuresConstraints = NULL;
408 exprNode_makeError ()
410 return exprNode_undefined;
413 static /*@out@*/ /*@only@*/ /*@notnull@*/ exprNode
416 exprNode ret = (exprNode) dmalloc (sizeof (*ret));
417 /* static int lastexpnodes = 0; */
422 if (nowalloc > maxalloc)
430 static /*@notnull@*/ /*@special@*/ exprNode
431 exprNode_createPlain (ctype c)
433 /*@ensures isnull result->edata, result->loc, result->val, result->guards,
434 result->uses, result->sets, result->msets, result->etext @*/
437 exprNode e = exprNode_new ();
441 e->val = multiVal_undefined;
443 e->etext = cstring_undefined;
444 e->loc = fileloc_undefined;
445 e->guards = guardSet_undefined;
446 e->uses = sRefSet_undefined;
447 e->sets = sRefSet_undefined;
448 e->msets = sRefSet_undefined;
449 e->edata = exprData_undefined;
450 e->exitCode = XK_NEVERESCAPE;
452 e->mustBreak = FALSE;
453 e->isJumpPoint = FALSE;
455 exprNode_defineConstraints(e);
460 /*@observer@*/ exprNode exprNode_makeMustExit (void)
462 if (exprNode_isUndefined (mustExitNode))
464 mustExitNode = exprNode_createPlain (ctype_unknown);
465 mustExitNode->exitCode = XK_MUSTEXIT;
472 static /*@notnull@*/ /*@special@*/ exprNode exprNode_create (ctype c)
474 /*@post:isnull result->edata, result->guards, result->val,
475 result->uses, result->sets, result->msets@*/
478 exprNode e = exprNode_createPlain (c);
479 e->loc = fileloc_copy (g_currentloc);
483 static /*@notnull@*/ /*@special@*/ exprNode exprNode_createUnknown (void)
485 /*@post:isnull result->edata, result->guards,
486 result->uses, result->sets, result->msets@*/
489 return (exprNode_create (ctype_unknown));
492 static /*@notnull@*/ /*@special@*/ exprNode
493 exprNode_createLoc (ctype c, /*@keep@*/ fileloc loc)
495 /*@post:isnull result->edata, result->guards, result->val,
496 result->uses, result->sets, result->msets@*/
499 exprNode e = exprNode_createPlain (c);
505 exprNode_copySets (/*@special@*/ /*@notnull@*/ exprNode ret, exprNode e)
506 /*@defines ret->guards, ret->uses, ret->sets, ret->msets@*/
508 if (exprNode_isDefined (e))
510 ret->guards = guardSet_copy (e->guards);
511 ret->uses = sRefSet_newCopy (e->uses);
512 ret->sets = sRefSet_newCopy (e->sets);
513 ret->msets = sRefSet_newCopy (e->msets);
517 ret->guards = guardSet_undefined;
518 ret->uses = sRefSet_undefined;
519 ret->sets = sRefSet_undefined;
520 ret->msets = sRefSet_undefined;
524 static /*@notnull@*/ /*@special@*/ exprNode
525 exprNode_createPartialLocCopy (exprNode e, /*@only@*/ fileloc loc)
527 /*@post:isnull result->edata, result->etext@*/
530 exprNode ret = exprNode_new ();
532 if (exprNode_isError (e))
534 ret->typ = ctype_unknown;
535 ret->val = multiVal_undefined;
537 ret->guards = guardSet_undefined;
538 ret->uses = sRefSet_undefined;
539 ret->sets = sRefSet_undefined;
540 ret->msets = sRefSet_undefined;
545 ret->val = multiVal_copy (e->val);
547 ret->guards = guardSet_copy (e->guards);
548 ret->uses = sRefSet_newCopy (e->uses);
549 ret->sets = sRefSet_newCopy (e->sets);
550 ret->msets = sRefSet_newCopy (e->msets);
553 ret->kind = XPR_EMPTY;
555 ret->etext = cstring_undefined;
556 ret->exitCode = XK_NEVERESCAPE;
557 ret->canBreak = FALSE;
558 ret->mustBreak = FALSE;
559 ret->isJumpPoint = FALSE;
560 ret->edata = exprData_undefined;
562 exprNode_defineConstraints(ret);
568 static /*@notnull@*/ /*@special@*/ exprNode
569 exprNode_createPartialCopy (exprNode e)
571 /*@post:isnull result->edata, result->etext@*/
574 return (exprNode_createPartialLocCopy (e, fileloc_copy (exprNode_loc (e))));
577 static /*@notnull@*/ /*@special@*/ exprNode
578 exprNode_createPartialNVCopy (exprNode e)
580 /*@post:isnull result->edata, result->etext, result->val @*/
583 exprNode ret = exprNode_new ();
585 if (exprNode_isError (e))
587 ret->typ = ctype_unknown;
588 ret->loc = fileloc_undefined;
589 ret->guards = guardSet_undefined;
590 ret->uses = sRefSet_undefined;
591 ret->sets = sRefSet_undefined;
592 ret->msets = sRefSet_undefined;
597 ret->loc = fileloc_copy (e->loc);
598 ret->guards = guardSet_copy (e->guards);
599 ret->uses = sRefSet_newCopy (e->uses);
600 ret->sets = sRefSet_newCopy (e->sets);
601 ret->msets = sRefSet_newCopy (e->msets);
604 ret->val = multiVal_undefined;
605 ret->kind = XPR_EMPTY;
607 ret->etext = cstring_undefined;
608 ret->exitCode = XK_NEVERESCAPE;
609 ret->canBreak = FALSE;
610 ret->mustBreak = FALSE;
611 ret->isJumpPoint = FALSE;
612 ret->edata = exprData_undefined;
614 exprNode_defineConstraints(ret);
619 static /*@notnull@*/ /*@special@*/ exprNode
620 exprNode_createSemiCopy (exprNode e)
622 /*@post:isnull result->edata, result->etext, result->sets,
623 result->msets, result->uses, result->guards@*/
626 if (exprNode_isError (e))
628 return exprNode_createPlain (ctype_unknown);
632 exprNode ret = exprNode_new ();
635 ret->val = multiVal_copy (e->val);
636 ret->loc = fileloc_copy (e->loc);
637 ret->guards = guardSet_undefined;
638 ret->uses = sRefSet_undefined;
639 ret->sets = sRefSet_undefined;
640 ret->msets = sRefSet_undefined;
642 ret->kind = XPR_EMPTY;
644 ret->etext = cstring_undefined;
645 ret->exitCode = XK_NEVERESCAPE;
646 ret->canBreak = FALSE;
647 ret->mustBreak = FALSE;
648 ret->isJumpPoint = FALSE;
649 ret->edata = exprData_undefined;
651 exprNode_defineConstraints(ret);
658 exprNode_isNullValue (exprNode e)
660 if (exprNode_isDefined (e))
662 multiVal m = exprNode_getValue (e);
664 if (multiVal_isInt (m))
666 return (multiVal_forceInt (m) == 0);
674 exprNode_isUnknownConstant (/*@notnull@*/ exprNode e)
676 while (e->kind == XPR_PARENS)
678 e = exprData_getUopNode (e->edata);
679 llassert (exprNode_isDefined (e));
682 if (e->kind == XPR_CONST)
684 multiVal m = exprNode_getValue (e);
686 if (multiVal_isUnknown (m))
696 exprNode_numLiteral (ctype c, /*@temp@*/ cstring t,
697 /*@only@*/ fileloc loc, long val)
699 exprNode e = exprNode_createLoc (c, loc);
701 e->kind = XPR_NUMLIT;
703 llassert (multiVal_isUndefined (e->val));
704 e->val = multiVal_makeInt (val);
705 e->edata = exprData_makeLiteral (cstring_copy (t));
709 e->sref = sRef_makeUnknown ();
710 sRef_setDefNull (e->sref, e->loc);
713 DPRINTF (("Num lit: %s / %s", exprNode_unparse (e), ctype_unparse (exprNode_getType (e))));
718 exprNode_charLiteral (char c, cstring text, /*@only@*/ fileloc loc)
720 exprNode e = exprNode_createLoc (ctype_char, loc);
722 if (context_getFlag (FLG_CHARINTLITERAL))
724 e->typ = ctype_makeConj (ctype_char, ctype_int);
727 e->kind = XPR_NUMLIT;
728 e->val = multiVal_makeChar (c);
730 e->edata = exprData_makeLiteral (cstring_copy (text));
735 exprNode_floatLiteral (double d, ctype ct, cstring text, /*@only@*/ fileloc loc)
737 exprNode e = exprNode_createLoc (ct, loc);
739 e->kind = XPR_NUMLIT;
740 e->val = multiVal_makeDouble (d);
741 e->edata = exprData_makeLiteral (cstring_copy (text));
745 multiVal exprNode_getValue (exprNode e)
747 while (exprNode_isInParens (e)) {
748 if (e->edata != NULL) {
749 e = exprData_getUopNode (e->edata);
755 if (exprNode_isDefined (e)) {
758 return multiVal_undefined;
763 exprNode_combineLiterals (exprNode e, exprNode rest)
767 /* Both must be string literals. */
769 if (exprNode_isUndefined (rest) || exprNode_isUndefined (e))
771 exprNode_free (rest);
775 if (!exprNode_isStringLiteral (e))
779 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e),
780 exprNode_unparse (rest)),
782 exprNode_free (rest);
786 if (!exprNode_isStringLiteral (rest))
790 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e), exprNode_unparse (rest)),
793 exprNode_free (rest);
797 ns = cstring_concat (multiVal_forceString (exprNode_getValue (e)),
798 multiVal_forceString (exprNode_getValue (rest)));
800 multiVal_free (e->val);
801 exprData_free (e->edata, e->kind);
802 e->edata = exprData_makeLiteral (cstring_copy (ns));
803 e->val = multiVal_makeString (ns);
804 exprNode_free (rest);
809 exprNode_rawStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
811 exprNode e = exprNode_createLoc (ctype_string, loc);
812 int len = cstring_length (t);
814 if (context_getFlag (FLG_STRINGLITERALLEN))
816 if (len > context_getValue (FLG_STRINGLITERALLEN))
818 voptgenerror (FLG_STRINGLITERALLEN,
820 ("String literal length (%d) exceeds maximum "
821 "length (%d): \"%s\"",
823 context_getValue (FLG_STRINGLITERALLEN),
829 e->kind = XPR_STRINGLITERAL;
830 e->val = multiVal_makeString (cstring_copy (t));
831 e->edata = exprData_makeLiteral (t);
832 e->sref = sRef_makeConst (ctype_string);
834 if (context_getFlag (FLG_READONLYSTRINGS))
836 sRef_setAliasKind (e->sref, AK_STATIC, fileloc_undefined);
837 sRef_setExKind (e->sref, XO_OBSERVER, loc);
841 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
844 return (e); /* s released */
848 exprNode_wideStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
850 exprNode res = exprNode_stringLiteral (t, loc);
851 res->typ = ctype_makeWideString ();
857 exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
859 int len = cstring_length (t) - 2;
860 char *ts = cstring_toCharsSafe (t);
861 char *s = cstring_toCharsSafe (cstring_create (len + 1));
863 llassert (*ts == '\"' && *(ts + len + 1) == '\"');
864 strncpy (s, ts+1, size_fromInt (len));
867 return exprNode_rawStringLiteral (cstring_fromCharsO (s), loc);
870 exprNode exprNode_fromUIO (cstring c)
872 fileloc loc = context_getSaveLocation ();
873 exprNode e = exprNode_createPlain (ctype_unknown);
877 if (fileloc_isUndefined (loc))
879 loc = fileloc_copy (g_currentloc);
882 e->loc = loc; /* save loc was mangled */
885 if (usymtab_exists (c))
887 uentry ue = usymtab_lookupEither (c);
889 if (uentry_isDatatype (ue)
890 && uentry_isSpecified (ue))
893 (message ("%q: Specified datatype %s used in code, but not defined. "
894 "(Cannot continue reasonably from this error.)",
895 fileloc_unparse (e->loc), c));
903 llassertprint (!usymtab_exists (c), ("Entry exists: %s", c));
906 ** was supercedeGlobalEntry...is this better?
909 if (!context_inIterEnd ())
911 if (context_inMacro ())
913 if (context_getFlag (FLG_UNRECOG))
917 message ("Unrecognized identifier in macro definition: %s", c), e->loc);
921 flagcode_recordSuppressed (FLG_UNRECOG);
927 (FLG_UNRECOG, message ("Unrecognized identifier: %s", c), e->loc);
931 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
933 /* No alias errors for unrecognized identifiers */
934 sRef_setAliasKind (e->sref, AK_ERROR, loc);
939 exprNode exprNode_makeConstantString (cstring c, /*@only@*/ fileloc loc)
941 exprNode e = exprNode_createPlain (ctype_unknown);
944 e->sref = sRef_makeConst (ctype_string);
945 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
946 e->typ = ctype_string;
948 /* No alias errors for unrecognized identifiers */
949 sRef_setAliasKind (e->sref, AK_STATIC, loc);
950 sRef_setExKind (e->sref, XO_OBSERVER, loc);
955 exprNode exprNode_createId (/*@observer@*/ uentry c)
957 if (uentry_isValid (c))
959 exprNode e = exprNode_new ();
961 DPRINTF (("create id: %s", uentry_unparse (c)));
963 e->typ = uentry_getType (c);
965 if (uentry_isFunction (c)
966 && !sRef_isLocalVar (uentry_getSref (c)))
968 e->sref = sRef_undefined;
972 e->sref = uentry_getSref (c);
975 if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
977 sRef_setDefined (e->sref, fileloc_undefined);
981 ** yoikes! leaving this out was a heinous bug...that would have been
982 ** caught if i had splint working first. gag!
985 e->etext = cstring_undefined;
987 if (uentry_isEitherConstant (c))
990 e->val = multiVal_copy (uentry_getConstantValue (c));
995 e->val = multiVal_unknown ();
998 e->edata = exprData_makeId (c);
999 e->loc = context_getSaveLocation ();
1001 if (fileloc_isUndefined (e->loc))
1003 fileloc_free (e->loc);
1004 e->loc = fileloc_copy (g_currentloc);
1007 e->guards = guardSet_new ();
1008 e->sets = sRefSet_new ();
1009 e->msets = sRefSet_new ();
1010 e->uses = sRefSet_new ();
1012 /*> missing fields, detected by splint <*/
1013 e->exitCode = XK_NEVERESCAPE;
1014 e->isJumpPoint = FALSE;
1015 e->canBreak = FALSE;
1016 e->mustBreak = FALSE;
1018 exprNode_defineConstraints(e);
1024 return exprNode_createUnknown ();
1028 /*@notnull@*/ exprNode
1029 exprNode_fromIdentifier (/*@observer@*/ uentry c)
1033 if (context_justPopped ()) /* watch out! c could be dead */
1035 uentry ce = usymtab_lookupSafe (LastIdentifier ());
1037 if (uentry_isValid (ce))
1043 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
1047 ret = exprNode_fromIdentifierAux (c);
1052 static void exprNode_checkStringLiteralLength (ctype t1, exprNode e2)
1054 multiVal mval = exprNode_getValue (e2);
1058 if (ctype_isFixedArray (t1))
1061 int nelements = long_toInt (ctype_getArraySize (t1));
1063 llassert (multiVal_isString (mval));
1064 slit = multiVal_forceString (mval);
1065 // escapedS = cstring_expandEscapes(slit );
1066 // len = cstring_length (escapedS );
1067 // cstring_free(escapedS);
1069 len = cstring_lengthExpandEscapes (slit);
1072 if (len == nelements)
1076 temp = cstring_expandEscapes(slit);
1078 if (temp[len-1] == '\0')
1081 (FLG_STRINGLITNOROOMFINALNULL,
1082 message ("String literal with %d character%& "
1083 "is assigned to %s (no room for final null terminator): %s",
1086 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 uentry_setDefState (regArg, SS_RELDEF); /* need not be defined */
1656 sRef_setPosNull (uentry_getSref (regArg), fileloc_undefined); /* could be null */
1657 /*@switchbreak@*/ break;
1659 case 'n': /* pointer to int, modified by call! */
1660 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1662 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1663 /*@switchbreak@*/ break;
1665 case 'm': /* in a syslog, it doesn't consume an argument */
1666 /* should check we're really doing syslog */
1668 /*@switchbreak@*/ break;
1672 expecttype = ctype_unknown;
1676 message ("Unrecognized format code: %s",
1677 cstring_fromChars (origcode)),
1678 fileloc_isDefined (formatloc)
1679 ? formatloc : g_currentloc);
1681 /*@switchbreak@*/ break;
1684 if (!(exprNode_matchArgType (expecttype, a)))
1686 if (ctype_isVoidPointer (expecttype)
1687 && ctype_isRealAbstract (a->typ)
1688 && (context_getFlag (FLG_ABSTVOIDP)))
1694 if (llgenformattypeerror
1695 (expecttype, exprNode_undefined,
1697 message ("Format argument %d to %q (%%%s) expects "
1700 uentry_getName (fcn),
1703 a->typ, exprNode_unparse (a)),
1706 if (fileloc_isDefined (formatloc)
1707 && context_getFlag (FLG_SHOWCOL))
1710 (cstring_makeLiteral
1711 ("Corresponding format code"),
1718 uentry_setType (regArg, expecttype);
1719 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1721 if (ctype_equal (expecttype, ctype_string))
1723 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1726 uentry_setType (regArg, ctype_unknown);
1727 uentry_fixupSref (regArg);
1731 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1742 cstring_free (codetext);
1747 voptgenerror (FLG_TYPE,
1748 message ("Format string for %q has %d arg%&, given %d",
1749 uentry_getName (fcn), i - argno, nargs - argno),
1755 /* no checking possible for compile-time unknown format strings */
1756 if (exprNode_isDefined (a))
1760 message ("Format string parameter to %s is not a compile-time constant: %s",
1761 exprNode_unparse (f),
1762 exprNode_unparse (a)),
1767 fileloc_free (formatloc);
1771 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1772 exprNodeList args, exprNode ret, int argno)
1776 int nargs = exprNodeList_size (args);
1777 uentryList params = uentry_getParams (fcn);
1781 ** These should be ensured by checkSpecialFunction
1784 llassert (uentryList_size (params) == argno + 1);
1785 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1787 a = exprNodeList_getN (args, argno - 1);
1788 formatloc = fileloc_copy (exprNode_loc (a));
1790 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1791 && exprNode_knownStringValue (a))
1793 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1794 char *code = format;
1797 nargs = exprNodeList_size (args);
1799 while ((code = strchr (code, '%')) != NULL)
1801 char *origcode = code;
1802 char key = *(++code);
1803 cstring codetext = cstring_newEmpty ();
1804 ctype modtype = ctype_int;
1805 char modifier = '\0';
1806 bool modified = TRUE;
1807 bool ignore = FALSE;
1809 codetext = cstring_appendChar (codetext, key);
1810 fileloc_addColumn (formatloc, code - ocode);
1813 ** this is based on ANSI standard library description of fscanf
1814 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1817 /* '*' suppresses assignment (does not need match argument) */
1822 codetext = cstring_appendChar (codetext, key);
1825 fileloc_incColumn (formatloc);
1828 /* ignore field width */
1829 while (isdigit ((int) key) != 0)
1832 codetext = cstring_appendChar (codetext, key);
1833 fileloc_incColumn (formatloc);
1838 modtype = ctype_sint; /* short */
1840 codetext = cstring_appendChar (codetext, key);
1841 fileloc_incColumn (formatloc);
1843 else if (key == 'l' || key == 'L')
1845 modtype = ctype_lint; /* long */
1849 codetext = cstring_appendChar (codetext, key);
1851 fileloc_incColumn (formatloc);
1853 if (key == 'l' || key == 'L') {
1854 modtype = ctype_llint; /* long long */
1856 codetext = cstring_appendChar (codetext, key);
1857 fileloc_incColumn (formatloc);
1865 /* now, key = type of conversion to apply */
1867 fileloc_incColumn (formatloc);
1881 message ("No argument corresponding to %q format "
1882 "code %d (%%%s): \"%s\"",
1883 uentry_getName (fcn),
1885 cstring_fromChars (format)),
1888 if (fileloc_isDefined (formatloc)
1889 && context_getFlag (FLG_SHOWCOL))
1892 (cstring_makeLiteral ("Corresponding format code"),
1900 a = exprNodeList_getN (args, i);
1903 if (!exprNode_isError (a))
1909 case '*': /* int argument for fieldwidth */
1910 expecttype = ctype_makePointer (ctype_int);
1911 *(--code) = '%'; /* convert it for next code */
1912 fileloc_subColumn (formatloc, 1);
1913 /*@switchbreak@*/ break;
1916 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1917 /*@switchbreak@*/ break;
1922 case 'X': /* unsigned int */
1923 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1924 /*@switchbreak@*/ break;
1931 /* printf is double, scanf is float! */
1933 if (modifier == 'l')
1935 expecttype = ctype_makePointer (ctype_double);
1937 else if (modifier == 'L')
1939 expecttype = ctype_makePointer (ctype_ldouble);
1943 llassert (modifier == '\0');
1944 expecttype = ctype_makePointer (ctype_float);
1946 /*@switchbreak@*/ break;
1948 case 'c': /* int converted to char (check its a char?) */
1949 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1950 /*@switchbreak@*/ break;
1952 case 's': /* string */
1953 expecttype = ctype_string;
1954 /*@switchbreak@*/ break;
1958 while (((key = *(++code)) != ']')
1961 codetext = cstring_appendChar (codetext, key);
1962 fileloc_incColumn (formatloc);
1968 (message ("Bad character set format: %s",
1969 cstring_fromChars (origcode)));
1972 expecttype = ctype_string;
1973 /*@switchbreak@*/ break;
1976 case 'p': /* pointer */
1979 message ("Format code should not be used in scanf: %s",
1980 cstring_fromChars (origcode)),
1981 fileloc_isDefined (formatloc)
1982 ? formatloc : g_currentloc);
1984 expecttype = ctype_unknown;
1985 /*@switchbreak@*/ break;
1987 case 'n': /* pointer to int, modified by call! */
1988 expecttype = ctype_makePointer (ctype_int);
1989 /*@switchbreak@*/ break;
1992 expecttype = ctype_unknown;
1996 message ("Unrecognized format code: %s",
1997 cstring_fromChars (origcode)),
1998 fileloc_isDefined (formatloc)
1999 ? formatloc : g_currentloc);
2001 /*@switchbreak@*/ break;
2004 if (!(exprNode_matchArgType (expecttype, a)))
2006 if (ctype_isVoidPointer (expecttype)
2007 && ctype_isRealAbstract (a->typ)
2008 && (context_getFlag (FLG_ABSTVOIDP)))
2014 if (llgenformattypeerror
2015 (expecttype, exprNode_undefined,
2017 message ("Format argument %d to %q (%%%s) expects "
2020 uentry_getName (fcn),
2021 codetext, expecttype,
2022 a->typ, exprNode_unparse (a)),
2025 if (fileloc_isDefined (formatloc)
2026 && context_getFlag (FLG_SHOWCOL))
2029 (cstring_makeLiteral
2030 ("Corresponding format code"),
2037 uentry_setType (outArg, expecttype);
2038 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
2039 uentry_setType (outArg, ctype_unknown);
2040 uentry_fixupSref (outArg);
2044 exprNode_checkCallModifyVal (a->sref, args, f, ret);
2049 /* a->sref = defref; */
2056 cstring_free (codetext);
2061 voptgenerror (FLG_TYPE,
2062 message ("Format string for %q has %d arg%&, given %d",
2063 uentry_getName (fcn), i - argno, nargs - argno),
2069 /* no checking possible for compile-time unknown format strings */
2072 fileloc_free (formatloc);
2076 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
2079 /*@unused@*/ int argno)
2082 ** the last argument before the elips is the format string
2085 int nargs = exprNodeList_size (args);
2090 a = exprNodeList_getN (args, argno - 1);
2091 formatloc = fileloc_copy (exprNode_loc (a));
2093 if (ctype_isUnknown (cstringType)) {
2094 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
2096 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
2100 if (ctype_isUnknown (ctypeType)) {
2101 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
2103 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
2107 if (ctype_isUnknown (filelocType)) {
2108 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
2110 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
2114 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
2115 && exprNode_knownStringValue (a))
2117 cstring format = multiVal_forceString (exprNode_getValue (a));
2118 char *code = cstring_toCharsSafe (format);
2121 nargs = exprNodeList_size (args);
2123 while ((code = strchr (code, '%')) != NULL)
2125 char *origcode = code;
2126 char key = *(++code);
2127 cstring codetext = cstring_newEmpty ();
2128 bool isOnly = FALSE;
2130 codetext = cstring_appendChar (codetext, key);
2132 fileloc_addColumn (formatloc, code - ocode);
2134 while (key >= '0' && key <= '9')
2137 codetext = cstring_appendChar (codetext, key);
2138 fileloc_incColumn (formatloc);
2142 fileloc_incColumn (formatloc);
2146 if (key == '&') /* plural marker */
2155 message ("Message missing format arg %d (%%%s): \"%s\"",
2156 i + 1, codetext, format),
2162 a = exprNodeList_getN (args, i);
2166 if (!exprNode_isError (a))
2170 /*@-loopswitchbreak@*/
2176 expecttype = ctype_char; break;
2178 expecttype = cstringType; break;
2180 expecttype = cstringType; isOnly = TRUE; break;
2182 expecttype = cstringType; isOnly = TRUE; break;
2183 case 'd': expecttype = ctype_int; break;
2184 case 'u': expecttype = ctype_uint; break;
2185 case 'w': expecttype = ctype_ulint; break;
2186 case 'f': expecttype = ctype_float; break;
2187 case 'b': expecttype = ctype_bool; break;
2188 case 't': expecttype = ctypeType; break;
2189 case 'l': expecttype = filelocType; break;
2190 case '&': /* a wee bit of a hack methinks */
2191 expecttype = ctype_int;
2193 case 'r': expecttype = ctype_bool; break;
2195 expecttype = ctype_unknown;
2198 message ("Unrecognized format code: %s",
2199 cstring_fromChars (origcode)),
2200 fileloc_isDefined (formatloc)
2201 ? formatloc : g_currentloc);
2204 /*@=loopswitchbreak@*/
2206 if (!(exprNode_matchArgType (expecttype, a)))
2208 if (ctype_isVoidPointer (expecttype)
2209 && ctype_isRealAbstract (a->typ)
2210 && (context_getFlag (FLG_ABSTVOIDP)))
2216 if (llgenformattypeerror
2217 (expecttype, exprNode_undefined,
2219 message ("Format argument %d to %q (%%%s) expects "
2222 uentry_getName (fcn),
2223 codetext, expecttype,
2224 a->typ, exprNode_unparse (a)),
2227 if (fileloc_isDefined (formatloc)
2228 && context_getFlag (FLG_SHOWCOL))
2231 (cstring_makeLiteral
2232 ("Corresponding format code"),
2239 if (ctype_equal (expecttype, cstringType))
2243 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2244 uentry_fixupSref (csOnlyArg);
2248 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2249 uentry_fixupSref (csArg);
2254 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2255 uentry_fixupSref (regArg);
2261 cstring_free (codetext);
2266 voptgenerror (FLG_TYPE,
2267 message ("Format string for %q has %d arg%&, given %d",
2268 uentry_getName (fcn), i - argno, nargs -argno),
2274 /* no checking possible for compile-time unknown format strings */
2277 fileloc_free (formatloc);
2281 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2282 /*@notnull@*/ exprNode e2,
2288 bool hadUncon = FALSE;
2290 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
2291 sRefSet_hasUnconstrained (sets2))
2294 (FLG_EVALORDERUNCON,
2296 ("Expression may have undefined behavior (%q used in right operand "
2297 "may set global variable %q used in left operand): %s %s %s",
2298 sRefSet_unparseUnconstrained (sets2),
2299 sRef_unparse (sRef_getRootBase (e1->sref)),
2300 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2304 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
2305 sRefSet_hasUnconstrained (sets1))
2308 (FLG_EVALORDERUNCON,
2310 ("Expression has undefined behavior (%q used in left operand "
2311 "may set global variable %q used in right operand): %s %s %s",
2312 sRefSet_unparseUnconstrained (sets1),
2313 sRef_unparse (e2->sref),
2314 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2318 sRefSet_realElements (e1->uses, sr)
2320 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2325 ("Expression has undefined behavior (left operand uses %q, "
2326 "modified by right operand): %s %s %s",
2328 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2331 } end_sRefSet_realElements;
2333 sRefSet_realElements (sets1, sr)
2335 if (sRef_isMeaningful (sr))
2337 if (sRef_same (sr, e2->sref))
2342 ("Expression has undefined behavior (value of right operand "
2343 "modified by left operand): %s %s %s",
2344 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2347 else if (sRefSet_member (e2->uses, sr))
2352 ("Expression has undefined behavior (left operand modifies %q, "
2353 "used by right operand): %s %s %s",
2355 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2360 if (sRefSet_member (sets2, sr))
2362 if (sRef_isUnconstrained (sr))
2370 hadUncon = optgenerror
2371 (FLG_EVALORDERUNCON,
2373 ("Expression may have undefined behavior. Left operand "
2374 "calls %q; right operand calls %q. The unconstrained "
2375 "functions may modify global state used by "
2376 "the other operand): %s %s %s",
2377 sRefSet_unparseUnconstrained (sets1),
2378 sRefSet_unparseUnconstrained (sets2),
2379 exprNode_unparse (e1), lltok_unparse (op),
2380 exprNode_unparse (e2)),
2389 ("Expression has undefined behavior (both "
2390 "operands modify %q): %s %s %s",
2392 exprNode_unparse (e1),
2393 lltok_unparse (op), exprNode_unparse (e2)),
2399 } end_sRefSet_realElements;
2402 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2404 bool hasError = FALSE;
2406 if (exprNode_isError (e1) || exprNode_isError (e2))
2411 if (sRefSet_member (e2->sets, e1->sref))
2413 if (e2->kind == XPR_CALL)
2419 hasError = optgenerror
2421 message ("Expression has undefined behavior "
2422 "(value of left operand %s is modified "
2423 "by right operand %s): %s %s %s",
2424 exprNode_unparse (e1),
2425 exprNode_unparse (e2),
2426 exprNode_unparse (e1), lltok_unparse (op),
2427 exprNode_unparse (e2)),
2432 if (context_getFlag (FLG_EVALORDERUNCON))
2434 if (sRefSet_member (e2->msets, e1->sref))
2436 if (e2->kind == XPR_CALL)
2442 hasError = optgenerror
2445 ("Expression has undefined behavior (value of left "
2446 "operand may be modified by right operand): %s %s %s",
2447 exprNode_unparse (e1), lltok_unparse (op),
2448 exprNode_unparse (e2)),
2456 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2458 if (context_maybeSet (FLG_EVALORDERUNCON))
2460 checkExpressionDefinedAux (e1, e2, e1->msets,
2461 e2->msets, op, FLG_EVALORDERUNCON);
2466 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2469 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2470 exprNodeList args, bool isIter, exprNode ret)
2474 if (!exprNode_isError (f))
2476 if (!uentryList_isMissingParams (cl))
2478 int nargs = exprNodeList_size (args);
2479 int expectargs = uentryList_size (cl);
2483 if (expectargs == 0)
2491 message ("Iter %q invoked with %d args, "
2493 uentry_getName (fcn),
2501 message ("Function %s called with %d args, "
2503 exprNode_unparse (f), nargs),
2510 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2512 exprNodeList_reset (args);
2514 uentryList_elements (cl, current)
2516 ctype ct = uentry_getType (current);
2519 if (ctype_isElips (ct))
2522 ** do special checking for printf/scanf library functions
2524 ** this is kludgey code, just for handling the special case
2528 if (uentry_isPrintfLike (fcn))
2530 checkPrintfArgs (f, fcn, args, ret, i);
2533 else if (uentry_isScanfLike (fcn))
2535 checkScanfArgs (f, fcn, args, ret, i);
2538 else if (uentry_isMessageLike (fcn))
2540 checkMessageArgs (f, fcn, args, i);
2545 llassert (!uentry_isSpecialFunction (fcn));
2548 nargs = expectargs; /* avoid errors */
2553 if (i >= nargs) break;
2555 a = exprNodeList_current (args);
2556 exprNodeList_advance (args);
2560 if (exprNode_isError (a))
2567 probably necessary? I'm not sure about this one
2568 checkMacroParen (a);
2571 f->guards = guardSet_union (f->guards, a->guards);
2573 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2575 if (!(exprNode_matchArgType (ct, a)))
2577 DPRINTF (("Args mismatch!"));
2579 if (ctype_isVoidPointer (ct)
2580 && (ctype_isPointer (a->typ)
2581 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2586 ("Pointer to abstract type (%t) used "
2588 "(arg %d to %q): %s",
2590 uentry_getName (fcn),
2591 exprNode_unparse (a)),
2599 (ct, exprNode_undefined,
2602 ("Iter %q expects arg %d to "
2603 "be %t gets %t: %s",
2604 uentry_getName (fcn),
2605 i, ct, a->typ, exprNode_unparse (a)),
2616 ("Function %q expects arg %d to be %t gets %t: %s",
2617 uentry_getName (fcn),
2618 i, ct, a->typ, exprNode_unparse (a)),
2621 DPRINTF (("Types: %s / %s",
2623 ctype_unparse (a->typ)));
2627 ** Clear null marker for abstract types.
2628 ** (It is not revealed, so suppress future messages.)
2631 if (ctype_isAbstract (a->typ))
2633 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2640 } end_uentryList_elements ;
2643 if (expectargs != nargs) /* note: not != since we may have ... */
2645 if (ctype_isElips (last))
2649 message ("Function %s called with %d args, expects at least %d",
2650 exprNode_unparse (f),
2651 nargs, expectargs - 1),
2660 message ("Iter %q invoked with %d args, expects %d",
2661 uentry_getName (fcn), nargs, expectargs),
2668 message ("Function %s called with %d args, expects %d",
2669 exprNode_unparse (f),
2682 ** Check for undefined code sequences in function arguments:
2684 ** one parameter sets something used by another parameter
2685 ** one parameter sets something set by another parameter
2689 checkSequencingOne (exprNode f, exprNodeList args,
2690 /*@notnull@*/ exprNode el, int argno)
2693 ** Do second loop, iff +undefunspec
2697 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2699 for (checkloop = 0; checkloop < numloops; checkloop++)
2705 thissets = el->sets;
2709 llassert (checkloop == 1);
2710 thissets = el->msets;
2713 sRefSet_realElements (thissets, thisset)
2717 /*@access exprNodeList@*/
2718 for (j = 0; j < args->nelements; j++)
2720 exprNode jl = args->elements[j];
2721 int thisargno = j + 1;
2723 if (thisargno != argno && exprNode_isDefined (jl))
2725 sRefSet otheruses = jl->uses;
2727 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
2728 sRefSet_hasUnconstrained (thissets))
2731 (FLG_EVALORDERUNCON,
2734 ("%q used in argument %d may set "
2735 "global variable %q used by argument %d: %s(%q)",
2736 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2739 sRef_unparse (sRef_getRootBase (jl->sref)),
2741 exprNode_unparse (f), exprNodeList_unparse (args)),
2745 if (sRefSet_member (otheruses, thisset))
2747 if (sRef_isUnconstrained (thisset))
2750 (FLG_EVALORDERUNCON,
2752 ("Unconstrained functions used in arguments %d (%q) "
2753 "and %d (%s) may modify "
2754 "or use global state in undefined way: %s(%q)",
2756 sRefSet_unparseUnconstrainedPlain (otheruses),
2758 sRef_unconstrainedName (thisset),
2759 exprNode_unparse (f),
2760 exprNodeList_unparse (args)),
2768 ("Argument %d modifies %q, used by argument %d "
2769 "(order of evaluation of actual parameters is "
2770 "undefined): %s(%q)",
2771 argno, sRef_unparse (thisset), thisargno,
2772 exprNode_unparse (f), exprNodeList_unparse (args)),
2778 sRefSet othersets = jl->sets;
2780 if (sRefSet_member (othersets, thisset))
2782 if (sRef_isUnconstrained (thisset))
2785 (FLG_EVALORDERUNCON,
2787 ("Unconstrained functions used in "
2788 "arguments %d (%q) and %d (%s) may modify "
2789 "or use global state in undefined way: %s(%q)",
2791 sRefSet_unparseUnconstrainedPlain (othersets),
2793 sRef_unconstrainedName (thisset),
2794 exprNode_unparse (f), exprNodeList_unparse (args)),
2802 ("Argument %d modifies %q, set by argument %d (order of"
2803 " evaluation of actual parameters is undefined): %s(%q)",
2804 argno, sRef_unparse (thisset), thisargno,
2805 exprNode_unparse (f), exprNodeList_unparse (args)),
2812 /*@noaccess exprNodeList@*/
2813 } end_sRefSet_realElements;
2818 checkSequencing (exprNode f, exprNodeList args)
2820 if (exprNodeList_size (args) > 1)
2825 /*@access exprNodeList*/
2827 for (i = 0; i < args->nelements; i++)
2829 el = args->elements[i];
2831 if (!exprNode_isError (el))
2833 checkSequencingOne (f, args, el, i + 1);
2836 /*@noaccess exprNodeList*/
2841 ** requires le = exprNode_getUentry (f)
2845 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2846 uentry le, exprNodeList args,
2847 /*@notnull@*/ exprNode ret, int specialArgs)
2849 bool isSpec = FALSE;
2850 bool hasMods = FALSE;
2852 globSet usesGlobs = globSet_undefined;
2853 sRefSet mods = sRefSet_undefined;
2854 bool freshMods = FALSE;
2855 uentryList params = uentryList_undefined;
2857 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2860 ** check globals and modifies
2865 if (!uentry_isValid (le))
2867 ctype fr = ctype_realType (f->typ);
2869 if (ctype_isFunction (fr))
2871 params = ctype_argsFunction (fr);
2875 params = uentryList_missingParams;
2878 if (!context_getFlag (FLG_MODNOMODS)
2879 && !context_getFlag (FLG_GLOBUNSPEC))
2881 checkUnspecCall (f, params, args);
2887 fname = uentry_rawName (le);
2891 if (uentry_isFunction (le))
2893 params = uentry_getParams (le);
2894 mods = uentry_getMods (le);
2895 hasMods = uentry_hasMods (le);
2896 usesGlobs = uentry_getGlobs (le);
2897 isSpec = uentry_isSpecified (le);
2899 else /* not a function */
2901 ctype ct = ctype_realType (uentry_getType (le));
2903 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2904 ("checkModGlobs: uentry not a function: %s",
2905 uentry_unparse (le)));
2907 params = ctype_argsFunction (ct);
2908 return; /*@32 ! remove this? */
2917 globSet_allElements (usesGlobs, el)
2919 if (sRef_isValid (el))
2921 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2923 context_usedGlobal (el);
2924 exprNode_checkUse (f, el, f->loc);
2926 if (context_checkInternalUse ())
2928 if (!context_globAccess (el))
2930 if (sRef_isSystemState (el)
2931 && !context_getFlag (FLG_MODFILESYSTEM))
2940 ("Called procedure %s may access %q, but "
2941 "globals list does not include globals %s",
2942 exprNode_unparse (f),
2944 cstring_makeLiteralTemp (sRef_isInternalState (el)
2952 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2958 uentry gle = sRef_getUentry (el);
2959 sRef sr = sRef_updateSref (el);
2961 if (sRef_isUndefGlob (el))
2963 sRef_setDefined (sr, f->loc);
2964 exprNode_checkSet (f, sr);
2972 if (sRef_isAllocated (el))
2974 exprNode_checkSet (f, sr);
2978 if (sRef_isStateUndefined (sr))
2983 ("%s %q used by function undefined before call: %s",
2984 sRef_getScopeName (sr),
2986 exprNode_unparse (f)),
2988 sRef_setDefined (sr, f->loc);
2990 exprNode_checkUse (f, sr, f->loc);
2993 checkGlobUse (gle, TRUE, f);
2996 if (sRef_isKilledGlob (el))
2998 sRef_kill (sr, f->loc);
2999 context_usedGlobal (sr);
3003 } end_globSet_allElements;
3009 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
3011 sRefSet smods = sRefSet_undefined;
3014 ** NEED to check for modifies anything
3018 ** check each sRef that called function modifies (ml), is
3024 sRefSet_allElements (mods, s) /* s is something which may be modified */
3026 DPRINTF (("Check modify: %s", sRef_unparse (s)));
3028 if (sRef_isKindSpecial (s))
3030 if (sRef_isSpecInternalState (s))
3032 if (context_getFlag (FLG_MODINTERNALSTRICT))
3034 exprNode_checkCallModifyVal (s, args, f, ret);
3038 sRefSet mmods = context_modList ();
3040 sRefSet_allElements (mmods, el)
3042 if (sRef_isInternalState (el))
3044 sRef_setModified (el);
3046 } end_sRefSet_allElements ;
3051 exprNode_checkCallModifyVal (s, args, f, ret);
3056 sRef rb = sRef_getRootBase (s);
3058 if (sRef_isFileOrGlobalScope (rb))
3060 context_usedGlobal (rb);
3063 if (sRef_isFileStatic (s)
3064 && !fileId_equal (fileloc_fileId (f->loc),
3065 fileloc_fileId (uentry_whereDefined (le))))
3067 smods = sRefSet_insert (smods, s);
3071 exprNode_checkCallModifyVal (s, args, f, ret);
3074 } end_sRefSet_allElements;
3079 ** Static elements in modifies set can have nasty consequences.
3080 ** (I think...have not been able to reproduce a possible bug.)
3083 if (!sRefSet_isDefined (smods))
3085 mods = sRefSet_newCopy (mods);
3088 sRefSet_allElements (smods, el)
3090 bool res = sRefSet_delete (mods, el);
3093 } end_sRefSet_allElements;
3095 sRefSet_free (smods);
3100 else if (sRefSet_isDefined (mods))
3101 { /* just check observers */
3104 sRefSet_allElements (mods, s) /* s is something which may be modified */
3106 sRef rb = sRef_getRootBase (s);
3110 if (sRef_isParam (rb))
3112 sRef b = sRef_fixBaseParam (s, args);
3114 if (sRef_isObserver (b))
3116 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
3120 message ("Function call may modify observer%q: %s",
3121 sRef_unparsePreOpt (b), exprNode_unparse (e)),
3124 sRef_showExpInfo (b);
3128 } end_sRefSet_allElements;
3132 if (!hasMods) /* no specified modifications */
3134 if (context_getFlag (FLG_MODOBSERVERUNCON))
3136 exprNodeList_elements (args, e)
3138 if (exprNode_isDefined (e))
3140 sRef s = exprNode_getSref (e);
3142 if (sRef_isObserver (s)
3143 && ctype_isMutable (sRef_getType (s)))
3146 (FLG_MODOBSERVERUNCON,
3148 ("Call to unconstrained function %s may modify observer%q: %s",
3149 exprNode_unparse (f),
3150 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3153 sRef_showExpInfo (s);
3157 } end_exprNodeList_elements;
3162 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3164 ret->uses = sRefSet_union (ret->uses, f->uses);
3165 ret->sets = sRefSet_union (ret->sets, f->sets);
3166 ret->msets = sRefSet_union (ret->msets, f->msets);
3171 ** Spurious errors reported, because splint can't tell
3172 ** mods must be fresh if freshMods is true.
3175 /*@i@*/ sRefSet_free (mods);
3181 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3183 if (uentry_isVar (glob))
3185 if (context_inFunctionLike ())
3187 sRef sr = uentry_getSref (glob);
3189 context_usedGlobal (sr);
3191 if (context_checkGlobUse (glob))
3193 if (!context_globAccess (sr))
3199 message ("Called procedure %s may access %s %q",
3200 exprNode_unparse (e),
3201 sRef_unparseScope (sr),
3202 uentry_getName (glob)),
3209 message ("Undocumented use of %s %s",
3210 sRef_unparseScope (sr),
3211 exprNode_unparse (e)),
3220 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3225 reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
3227 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3228 exprNode_unparse (f), exprNodeList_unparse (args),
3229 uentry_unparseFull (le),
3230 stateClauseList_unparse (uentry_getStateClauseList (le))));
3232 if (uentry_isValid (le) && uentry_isFunction (le))
3234 stateClauseList sclauses = uentry_getStateClauseList (le);
3236 if (stateClauseList_isDefined (sclauses))
3238 DPRINTF (("Reflect ensures: %s / %s / %s",
3239 uentry_unparse (le),
3240 exprNode_unparse (f), exprNodeList_unparse (args)));
3242 stateClauseList_elements (sclauses, cl)
3244 if (stateClause_hasEnsures (cl))
3246 /* Same in usymtab.c:1904 */
3247 if (stateClause_setsMetaState (cl))
3249 qual q = stateClause_getMetaQual (cl);
3250 annotationInfo ainfo = qual_getAnnotationInfo (q);
3251 metaStateInfo minfo = annotationInfo_getState (ainfo);
3252 cstring key = metaStateInfo_getName (minfo);
3253 int mvalue = annotationInfo_getValue (ainfo);
3255 sRefSet osrs = sRefSet_undefined;
3258 if (stateClause_isGlobal (cl))
3260 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3265 srs = stateClause_getRefs (cl);
3268 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3271 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3273 sRefSet_elements (srs, sel)
3277 if (sRef_isResult (sRef_getRootBase (sel)))
3279 s = exprNode_getSref (ret);
3283 s = sRef_fixBaseParam (sel, args);
3286 DPRINTF (("Reflecting state clause on: %s / %s",
3287 sRef_unparse (sel), sRef_unparse (s)));
3289 sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3290 } end_sRefSet_elements;
3292 sRefSet_free (osrs);
3296 sRefSet srs = stateClause_getRefs (cl);
3297 sRefModVal modf = stateClause_getEnsuresFunction (cl);
3298 int eparam = stateClause_getStateParameter (cl);
3300 DPRINTF (("Reflect after clause: %s / %s",
3301 stateClause_unparse (cl),
3302 sRefSet_unparse (srs)));
3304 sRefSet_elements (srs, sel)
3308 DPRINTF (("elements: %s", sRef_unparse (sel)));
3309 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3311 if (sRef_isResult (sRef_getRootBase (sel)))
3313 DPRINTF (("Fix base: %s / %s",
3314 sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
3315 s = sRef_fixBase (sel, exprNode_getSref (ret));
3316 DPRINTF (("==> %s", sRef_unparseFull (s)));
3320 s = sRef_fixBaseParam (sel, args);
3323 DPRINTF (("elements: %s", sRef_unparse (s)));
3324 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3326 DPRINTF (("Reflecting state clause on: %s / %s",
3327 sRef_unparseFull (sel), sRef_unparseFull (s)));
3329 /* evans 2001-08-24 - added aliasSetCompleteParam */
3330 sRef_aliasSetCompleteParam (modf, s, eparam, exprNode_loc (f));
3332 DPRINTF (("After reflecting state clause on: %s / %s",
3333 sRef_unparseFull (sel), sRef_unparseFull (s)));
3334 } end_sRefSet_elements;
3337 } end_stateClauseList_elements ;
3340 DPRINTF (("Here: %s / %s",
3341 uentry_unparseFull (le),
3342 bool_unparse (uentry_hasMetaStateEnsures (le))));
3344 if (uentry_hasMetaStateEnsures (le))
3346 fileloc loc = exprNode_loc (f);
3348 metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3350 metaStateConstraintList_elements (mscl, msc)
3352 metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3353 metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3354 metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
3355 cstring key = metaStateInfo_getName (msinfo);
3356 sRef mlsr = metaStateSpecifier_getSref (msspec);
3358 sRef lastref = sRef_undefined;
3359 stateValue sval = stateValue_undefined;
3361 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3362 metaStateConstraint_unparse (msc)));
3363 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3365 if (sRef_isResult (sRef_getRootBase (mlsr)))
3367 s = exprNode_getSref (ret);
3371 s = sRef_fixBaseParam (mlsr, args);
3374 DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3376 while (metaStateExpression_isDefined (msexpr))
3378 metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
3379 metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
3382 DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3384 if (metaStateExpression_isMerge (msexpr))
3386 msexpr = metaStateExpression_getRest (msexpr);
3390 msexpr = metaStateExpression_undefined;
3393 if (metaStateInfo_isDefined (msi))
3395 /* Must match lhs state */
3396 llassert (metaStateInfo_equal (msinfo, msi));
3399 if (metaStateSpecifier_isElipsis (ms))
3402 ** For elipsis, we need to merge all the relevant elipsis parameters
3406 uentryList params = uentry_getParams (le);
3407 int paramno = uentryList_size (params) - 1;
3409 if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
3413 message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3414 uentry_getName (le)),
3415 uentry_whereLast (le));
3416 /*@innerbreak@*/ break;
3419 while (paramno < exprNodeList_size (args))
3421 exprNode arg = exprNodeList_getN (args, paramno);
3422 fs = exprNode_getSref (arg);
3423 DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3425 /* cut and pasted... gack*/
3426 if (stateValue_isDefined (sval))
3428 /* Use combination table to merge old state value with new one: */
3429 stateValue tval = sRef_getMetaStateValue (fs, key);
3431 if (stateValue_isDefined (tval))
3433 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3434 cstring msg = cstring_undefined;
3435 int nval = stateCombinationTable_lookup (sctable,
3436 stateValue_getValue (sval),
3437 stateValue_getValue (tval),
3439 DPRINTF (("Combining: %s + %s -> %d",
3440 stateValue_unparseValue (sval, msinfo),
3441 stateValue_unparseValue (tval, msinfo),
3444 if (nval == stateValue_error)
3449 ("Attributes merged in ensures clause in states that "
3450 "cannot be combined (%q is %q, %q is %q)%q",
3451 sRef_unparse (lastref),
3452 stateValue_unparseValue (sval, msinfo),
3454 stateValue_unparseValue (tval, msinfo),
3455 cstring_isDefined (msg) ?
3456 message (": %s", msg) : cstring_undefined),
3459 sRef_showMetaStateInfo (fs, key);
3463 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3464 loc = exprNode_loc (arg);
3468 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3473 sval = sRef_getMetaStateValue (fs, key);
3478 if (stateValue_isError (sval))
3480 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3489 msr = metaStateSpecifier_getSref (ms);
3492 llassert (sRef_isParam (sRef_getRootBase (msr)));
3493 fs = sRef_fixBaseParam (msr, args);
3495 if (stateValue_isDefined (sval))
3497 /* Use combination table to merge old state value with new one: */
3498 stateValue tval = sRef_getMetaStateValue (fs, key);
3500 if (stateValue_isDefined (tval))
3502 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3503 cstring msg = cstring_undefined;
3504 int nval = stateCombinationTable_lookup (sctable,
3505 stateValue_getValue (sval),
3506 stateValue_getValue (tval),
3508 DPRINTF (("Combining: %s + %s -> %d",
3509 stateValue_unparseValue (sval, msinfo),
3510 stateValue_unparseValue (tval, msinfo),
3513 if (nval == stateValue_error)
3518 ("Attributes merged in ensures clause in states that "
3519 "cannot be combined (%q is %q, %q is %q)%q",
3520 sRef_unparse (lastref),
3521 stateValue_unparseValue (sval, msinfo),
3523 stateValue_unparseValue (tval, msinfo),
3524 cstring_isDefined (msg)
3525 ? message (": %s", msg) : cstring_undefined),
3528 sRef_showMetaStateInfo (fs, key);
3532 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3536 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3541 sval = sRef_getMetaStateValue (fs, key);
3546 if (stateValue_isError (sval))
3548 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3553 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3555 if (stateValue_isDefined (sval))
3557 sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
3561 DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
3563 } end_metaStateConstraintList_elements ;
3565 metaStateConstraintList_free (mscl);
3571 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3573 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3574 exprNode_unparse (f), exprNodeList_unparse (args),
3575 uentry_unparseFull (le),
3576 stateClauseList_unparse (uentry_getStateClauseList (le))));
3578 if (uentry_isValid (le) && uentry_isFunction (le))
3580 stateClauseList sclauses = uentry_getStateClauseList (le);
3582 if (stateClauseList_isDefined (sclauses))
3584 DPRINTF (("Check requires: %s / %s / %s",
3585 uentry_unparse (le),
3586 exprNode_unparse (f), exprNodeList_unparse (args)));
3588 stateClauseList_elements (sclauses, cl)
3590 DPRINTF (("Check clause: %s / %s",
3591 stateClause_unparse (cl),
3592 bool_unparse (stateClause_hasRequires (cl))));
3594 if (stateClause_hasRequires (cl))
3596 sRefSet osrs = sRefSet_undefined;
3599 if (stateClause_isGlobal (cl))
3601 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3606 srs = stateClause_getRefs (cl);
3609 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3611 if (stateClause_setsMetaState (cl))
3613 qual q = stateClause_getMetaQual (cl);
3614 annotationInfo ainfo = qual_getAnnotationInfo (q);
3615 metaStateInfo minfo = annotationInfo_getState (ainfo);
3616 cstring key = metaStateInfo_getName (minfo);
3617 int mvalue = annotationInfo_getValue (ainfo);
3619 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3621 sRefSet_elements (srs, sel)
3623 sRef s = sRef_fixBaseParam (sel, args);
3625 if (sRef_isResult (sRef_getRootBase (sel)))
3631 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3632 sRef_unparseFull (sel), sRef_unparseFull (s),
3635 if (!sRef_checkMetaStateValue (s, key, mvalue))
3637 DPRINTF (("HERE: %s", sRef_unparse (s)));
3641 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3642 uentry_getName (le),
3643 sRef_isGlobalMarker (s)
3645 : message (" by %q", sRef_unparse (s)),
3646 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3648 stateClause_unparse (cl)),
3651 sRef_showAliasInfo (s);
3655 DPRINTF (("Error supressed!"));
3656 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3657 DPRINTF (("Context supress: %s",
3658 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3662 } end_sRefSet_elements;
3666 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3667 int eparam = stateClause_getStateParameter (cl);
3669 DPRINTF (("Reflect after clause: %s / %s",
3670 stateClause_unparse (cl),
3671 sRefSet_unparse (srs)));
3673 sRefSet_elements (srs, sel)
3677 DPRINTF (("elements: %s", sRef_unparse (sel)));
3678 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3680 s = sRef_fixBaseParam (sel, args);
3682 DPRINTF (("elements: %s", sRef_unparse (s)));
3683 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3685 if (sRef_isResult (sRef_getRootBase (sel)))
3687 ; /*@i423 what do we do about results */
3691 DPRINTF (("Reflecting state clause on: %s / %s",
3692 sRef_unparse (sel), sRef_unparse (s)));
3694 modf (s, eparam, exprNode_loc (f));
3696 } end_sRefSet_elements;
3699 sRefSet_free (osrs);
3701 } end_stateClauseList_elements ;
3706 static /*@only@*/ exprNode
3707 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3708 ctype t, /*@keep@*/ exprNodeList args)
3710 /* requires f is a non-error exprNode, with type function */
3711 cstring fname = exprNode_unparse (f);
3712 uentry le = exprNode_getUentry (f);
3713 exprNode ret = exprNode_createPartialCopy (f);
3718 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3720 ret->typ = ctype_getReturnType (t);
3721 ret->kind = XPR_CALL;
3723 ret->edata = exprData_makeCall (f, args);
3726 ** Order of these steps is very important!
3728 ** Must check for argument dependencies before messing up uses and sets.
3731 if (context_getFlag (FLG_EVALORDER))
3733 exprNodeList_elements (args, current)
3735 if (exprNode_isDefined (current))
3737 exprNode_addUse (current, current->sref);
3739 } end_exprNodeList_elements;
3741 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3743 checkSequencing (f, args);
3746 exprNodeList_elements (args, current)
3748 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3750 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3752 } end_exprNodeList_elements ;
3755 special = checkArgs (le, f, t, args, ret);
3756 checkGlobMods (f, le, args, ret, special);
3757 checkRequiresClause (le, f, args);
3760 if (uentry_isValid (le)
3761 && (uentry_isFunction (le)
3762 || (uentry_isVariable (le)
3763 && ctype_isFunction (uentry_getType (le)))))
3765 exitkind exk = uentry_getExitCode (le);
3767 /* f->typ is already set to the return type */
3769 DPRINTF (("Function: %s", uentry_unparseFull (le)));
3770 ret->sref = uentry_returnedRef (le, args);
3771 DPRINTF (("Returned: %s / %s",
3772 uentry_unparseFull (le),
3773 sRef_unparseFull (ret->sref)));
3775 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3777 qual nullPred = uentry_nullPred (le);
3779 if (qual_isTrueNull (nullPred))
3781 exprNode arg = exprNodeList_head (args);
3783 if (exprNode_isDefined (arg))
3785 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3788 else if (qual_isFalseNull (nullPred))
3790 exprNode arg = exprNodeList_head (args);
3792 if (exprNode_isDefined (arg))
3794 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3799 llassert (qual_isUnknown (nullPred));
3803 if (exitkind_isConditionalExit (exk))
3807 ** if (arg0) then { exit! } else { ; }
3809 ** if (arg0) then { ; } else { exit! }
3814 llassert (!exprNodeList_isEmpty (args));
3815 firstArg = exprNodeList_head (args);
3817 if (exprNode_isDefined (firstArg)
3818 && !guardSet_isEmpty (firstArg->guards))
3820 usymtab_trueBranch (guardSet_undefined);
3821 usymtab_altBranch (guardSet_undefined);
3823 if (exitkind_isTrueExit (exk))
3825 usymtab_popBranches (firstArg,
3826 exprNode_makeMustExit (),
3828 TRUE, TRUEEXITCLAUSE);
3832 usymtab_popBranches (firstArg,
3834 exprNode_makeMustExit (),
3835 TRUE, FALSEEXITCLAUSE);
3839 ret->exitCode = XK_MAYEXIT;
3841 else if (exitkind_mustExit (exk))
3843 ret->exitCode = XK_MUSTEXIT;
3845 else if (exitkind_couldExit (exk))
3847 ret->exitCode = XK_MAYEXIT;
3854 if (cstring_equalLit (fname, "exit"))
3856 if (exprNodeList_size (args) == 1)
3858 exprNode arg = exprNodeList_head (args);
3860 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3862 long int val = multiVal_forceInt (exprNode_getValue (arg));
3869 ("Argument to exit has implementation defined behavior: %s",
3870 exprNode_unparse (arg)),
3871 exprNode_loc (arg));
3880 exprNode_checkSetAny (ret, uentry_rawName (le));
3883 DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3884 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3885 reflectEnsuresClause (ret, le, f, args);
3892 ** this is yucky! should keep the uentry as part of exprNode!
3895 uentry exprNode_getUentry (exprNode e)
3897 if (exprNode_isError (e))
3899 return uentry_undefined;
3903 cstring s = exprNode_rootVarName (e);
3904 uentry ue = usymtab_lookupSafe (s);
3911 ** Returns true iff e1 and e2 are both exactly the same storage
3915 static bool exprNode_sameStorage (exprNode e1, exprNode e2)
3917 sRef s1 = exprNode_getSref (e1);
3918 sRef s2 = exprNode_getSref (e2);
3920 return (sRef_realSame (s1, s2));
3924 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3926 exprNode ret = exprNode_createPlain (ctype_unknown);
3928 ret->kind = XPR_INITBLOCK;
3929 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3930 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3936 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3942 if (exprNode_isUndefined (f))
3945 exprNodeList_free (args);
3946 return exprNode_undefined;
3949 t = exprNode_getType (f);
3951 if (sRef_isLocalVar (f->sref))
3953 exprNode_checkUse (f, f->sref, f->loc);
3955 if (sRef_possiblyNull (f->sref))
3957 if (!usymtab_isGuarded (f->sref))
3959 if (optgenerror (FLG_NULLDEREF,
3960 message ("Function call using %s pointer %q",
3961 sRef_nullMessage (f->sref),
3962 sRef_unparse (f->sref)),
3965 sRef_showNullInfo (f->sref);
3966 sRef_setNullError (f->sref);
3974 if (ctype_isRealFunction (t))
3976 exprNode ret = functionCallSafe (f, t, args);
3980 else if (ctype_isUnknown (t))
3982 exprNode ret = exprNode_createPartialCopy (f);
3988 exprNodeList_elements (args, current)
3990 if (exprNode_isDefined (current))
3992 exprNode_checkUse (ret, current->sref, ret->loc);
3995 ** also, anything derivable from current->sref may be used
3998 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3999 exprNode_mergeUSs (ret, current);
4001 } end_exprNodeList_elements;
4003 ret->edata = exprData_makeCall (f, args);
4004 ret->kind = XPR_CALL;
4006 tstring = cstring_copy (exprNode_unparse (f));
4008 cstring_markOwned (tstring);
4009 exprNode_checkSetAny (ret, tstring);
4015 voptgenerror (FLG_TYPE,
4016 message ("Call to non-function (type %t): %s", t,
4017 exprNode_unparse (f)),
4020 exprNodeList_free (args);
4022 return (exprNode_makeError ());
4027 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4028 /*@only@*/ cstring f)
4030 exprNode ret = exprNode_createPartialCopy (s);
4032 ret->kind = XPR_FACCESS;
4034 if (exprNode_isError (s))
4036 ret->edata = exprData_makeField (s, f);
4041 ctype t = exprNode_getType (s);
4042 ctype tr = ctype_realType (t);
4044 checkMacroParen (s);
4046 ret->edata = exprData_makeField (s, f);
4048 if (ctype_isStructorUnion (tr))
4050 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
4052 if (uentry_isUndefined (tf))
4054 voptgenerror (FLG_TYPE,
4055 message ("Access non-existent field %s of %t: %s", f, t,
4056 exprNode_unparse (ret)),
4058 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
4063 uentry_setUsed (tf, exprNode_loc (ret));
4065 ret->typ = uentry_getType (tf);
4066 checkSafeUse (ret, s->sref);
4068 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
4069 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
4073 else /* isStructorUnion */
4075 if (ctype_isRealAbstract (tr))
4079 message ("Access field of abstract type (%t): %s.%s",
4080 t, exprNode_unparse (s), f),
4082 ret->typ = ctype_unknown;
4086 if (ctype_isKnown (tr))
4091 ("Access field of non-struct or union (%t): %s.%s",
4092 t, exprNode_unparse (s), f),
4095 ret->typ = ctype_unknown;
4099 cstring sn = cstring_copy (f);
4101 checkSafeUse (ret, s->sref);
4102 cstring_markOwned (sn);
4103 ret->sref = sRef_makeField (s->sref, sn);
4115 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
4116 /*@only@*/ cstring f)
4118 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
4119 lltok_release (dot);
4124 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
4126 exprNode ret = exprNode_createPartialCopy (e);
4128 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
4129 ret->kind = XPR_PARENS;
4130 ret->edata = exprData_makeUop (e, lpar);
4132 if (!exprNode_isError (e))
4134 ret->exitCode = e->exitCode;
4135 ret->canBreak = e->canBreak;
4136 ret->mustBreak = e->mustBreak;
4137 ret->isJumpPoint = e->isJumpPoint;
4138 ret->sref = e->sref;
4145 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4146 /*@only@*/ cstring f)
4148 exprNode ret = exprNode_createPartialCopy (s);
4150 ret->edata = exprData_makeField (s, f);
4151 ret->kind = XPR_ARROW;
4153 if (exprNode_isError (s))
4159 ctype t = exprNode_getType (s);
4160 ctype tr = ctype_realType (t);
4162 checkMacroParen (s);
4164 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4166 if (ctype_isRealPointer (tr))
4168 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4170 if (ctype_isStructorUnion (b))
4172 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4174 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4176 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4180 message ("Arrow access from %s pointer%q: %s",
4181 sRef_nullMessage (s->sref),
4182 sRef_unparsePreOpt (s->sref),
4183 exprNode_unparse (ret)),
4186 sRef_showNullInfo (s->sref);
4187 sRef_setNullError (s->sref);
4192 if (uentry_isUndefined (fentry))
4196 message ("Access non-existent field %s of %t: %s",
4197 f, t, exprNode_unparse (ret)),
4199 ret->typ = ctype_unknown;
4205 ** was safeUse: shouldn't be safe!
4208 ** rec must be defined,
4209 ** *rec must be allocated
4210 ** rec->field need only be defined it if is an rvalue
4213 uentry_setUsed (fentry, exprNode_loc (ret));
4214 ret->typ = uentry_getType (fentry);
4216 exprNode_checkUse (ret, s->sref, s->loc);
4218 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4219 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4223 else /* Pointer to something that is not a struct or union*/
4225 if (ctype_isRealAbstract (tr))
4227 ctype xrt = ctype_forceRealType (tr);
4231 message ("Arrow access field of abstract type (%t): %s->%s",
4232 t, exprNode_unparse (s), f),
4236 ** Set the state correctly, as if the abstraction is broken.
4239 if (ctype_isRealPointer (xrt) &&
4240 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4241 ctype_isStructorUnion (b)))
4243 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4244 ret->typ = uentry_getType (fentry);
4245 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4249 ret->typ = ctype_unknown;
4250 ret->sref = sRef_undefined;
4253 else /* not a struct, union or abstract */
4255 if (ctype_isUnknown (tr)) {
4256 cstring sn = cstring_copy (f);
4258 DPRINTF (("Here: %s", exprNode_unparse (s)));
4260 exprNode_checkUse (ret, s->sref, s->loc);
4261 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4263 cstring_markOwned (sn);
4264 ret->sref = sRef_makeArrow (s->sref, sn);
4266 ret->kind = XPR_ARROW;
4271 message ("Arrow access field of non-struct or union "
4272 "pointer (%t): %s->%s",
4273 t, exprNode_unparse (s), f),
4276 ret->typ = ctype_unknown;
4277 ret->sref = sRef_undefined;
4282 else /* its not a pointer */
4284 if (!ctype_isUnknown (tr))
4288 message ("Arrow access of non-pointer (%t): %s->%s",
4289 t, exprNode_unparse (s), f),
4292 ret->typ = ctype_unknown;
4293 ret->sref = sRef_undefined;
4297 cstring sn = cstring_copy (f);
4299 DPRINTF (("Here: %s", exprNode_unparse (s)));
4301 exprNode_checkUse (ret, s->sref, s->loc);
4302 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4304 cstring_markOwned (sn);
4305 ret->sref = sRef_makeArrow (s->sref, sn);
4307 ret->kind = XPR_ARROW;
4318 exprNode_arrowAccess (/*@only@*/ exprNode s,
4319 /*@only@*/ lltok arrow,
4320 /*@only@*/ cstring f)
4322 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4323 lltok_release (arrow);
4328 ** only postOp's in C: i++ and i--
4332 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4334 /* check modification also */
4335 /* cstring opname = lltok_unparse (op);*/
4337 exprNode ret = exprNode_createPartialCopy (e);
4339 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4340 ret->kind = XPR_POSTOP;
4341 ret->edata = exprData_makeUop (e, op);
4343 if (!exprNode_isDefined (e))
4348 checkMacroParen (e);
4350 exprNode_checkUse (ret, e->sref, e->loc);
4351 exprNode_checkSet (ret, e->sref);
4353 t = exprNode_getType (e);
4355 if (sRef_isUnsafe (e->sref))
4357 voptgenerror (FLG_MACROPARAMS,
4358 message ("Operand of %s is macro parameter (non-functional): %s%s",
4359 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4361 sRef_makeSafe (e->sref);
4362 sRef_makeSafe (ret->sref);
4365 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4371 if (ctype_isRealAbstract (t))
4375 message ("Operand of %s is abstract type (%t): %s",
4376 lltok_unparse (op), t, exprNode_unparse (e)),
4383 message ("Operand of %s is non-numeric (%t): %s",
4384 lltok_unparse (op), t, exprNode_unparse (e)),
4387 ret->typ = ctype_unknown;
4390 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4392 exprNode_checkModify (e, ret);
4394 /* added 7/11/2000 D.L */
4396 /*DRL 6/8/01 I decided to disable all Splint warnings here since the code
4397 probably needs a rewrite any way */
4402 /* updateEnvironmentForPostOp (e); */
4404 /* start modifications */
4405 /* added by Seejo on 4/16/2000 */
4407 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4409 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4411 ret->sref = sRef_copy (e->sref);
4414 if (lltok_getTok (op) == INC_OP) {
4415 if (sRef_getSize(e->sref) > 0) {
4417 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4419 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4420 /* Assumption: there is only 1 \0 in the buffer */
4421 /* This will not be correct if there are 2 \0's in the buffer */
4422 sRef_setNotNullTerminatedState(ret->sref);
4423 sRef_resetLen(ret->sref);
4425 sRef_setNullTerminatedState(ret->sref);
4426 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4428 if (sRef_isNullTerminated (ret->sref))
4429 printf ("ret->sref is Null Terminated\n");
4430 else if (sRef_isPossiblyNullTerminated (ret->sref))
4431 printf ("ret->sref is Possibly Null Terminated\n");
4432 else if (sRef_isNotNullTerminated (ret->sref))
4433 printf ("ret->sref is Not Null Terminated\n");
4438 if (lltok_getTok (op) == DEC_OP) {
4439 if (sRef_getSize(e->sref) >= 0) {
4440 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4441 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4446 /* end modifications */
4452 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4454 bool checkMod = FALSE;
4456 int opid = lltok_getTok (op);
4457 exprNode ret = exprNode_createSemiCopy (e);
4459 exprNode_copySets (ret, e);
4461 multiVal_free (ret->val);
4462 ret->val = multiVal_undefined;
4463 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4464 ret->kind = XPR_PREOP;
4465 ret->edata = exprData_makeUop (e, op);
4467 if (exprNode_isError (e))
4472 checkMacroParen (e);
4474 te = exprNode_getType (e);
4475 tr = ctype_realType (te);
4477 if (opid != TAMPERSAND)
4479 exprNode_checkUse (ret, e->sref, e->loc);
4481 if (ctype_isRealAbstract (tr)
4482 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4484 if (optgenerror (FLG_ABSTRACT,
4485 message ("Operand of %s is abstract type (%t): %s",
4486 lltok_unparse (op), tr,
4487 exprNode_unparse (ret)),
4490 tr = te = ctype_unknown;
4491 ret->typ = ctype_unknown;
4492 sRef_setNullError (e->sref);
4500 case DEC_OP: /* should also check modification! */
4501 if (sRef_isMacroParamRef (e->sref))
4505 message ("Operand of %s is macro parameter (non-functional): %s",
4506 lltok_unparse (op), exprNode_unparse (ret)),
4511 exprNode_checkSet (ret, e->sref);
4514 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4519 if (context_msgStrictOps ())
4523 message ("Operand of %s is non-numeric (%t): %s",
4524 lltok_unparse (op), te, exprNode_unparse (ret)),
4527 ret->typ = ctype_int;
4530 /* start modifications */
4531 /* added by Seejo on 4/16/2000 */
4533 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4535 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4537 ret->sref = sRef_copy (e->sref);
4540 if (lltok_getTok (op) == INC_OP) {
4541 if (sRef_getSize(e->sref) > 0) {
4543 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4545 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4546 /* Assumption: there is only 1 \0 in the buffer */
4547 /* This will not be correct if there are 2 \0's in the buffer */
4548 sRef_setNotNullTerminatedState(ret->sref);
4549 sRef_resetLen (ret->sref);
4551 sRef_setNullTerminatedState(ret->sref);
4552 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4558 if (lltok_getTok (op) == DEC_OP) {
4559 if (sRef_getSize(e->sref) >= 0) {
4560 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4561 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4566 /* end modifications */
4573 if (ctype_isForceRealNumeric (&tr))
4577 ret->val = multiVal_invert (exprNode_getValue (e));
4581 ret->val = multiVal_copy (exprNode_getValue (e));
4586 if (context_msgStrictOps ())
4590 message ("Operand of %s is non-numeric (%t): %s",
4591 lltok_unparse (op), te, exprNode_unparse (ret)),
4595 ret->typ = ctype_int;
4599 case TEXCL: /* maybe this should be restricted */
4600 guardSet_flip (ret->guards);
4602 if (ctype_isRealBool (te) || ctype_isUnknown (te))
4608 if (ctype_isRealPointer (tr))
4610 if (sRef_isKnown (e->sref))
4612 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4616 (FLG_BOOLOPS, FLG_PTRNEGATE,
4617 message ("Operand of %s is non-boolean (%t): %s",
4618 lltok_unparse (op), te, exprNode_unparse (ret)),
4625 message ("Operand of %s is non-boolean (%t): %s",
4626 lltok_unparse (op), te, exprNode_unparse (ret)),
4630 ret->typ = ctype_bool;
4635 if (ctype_isForceRealInt (&tr))
4640 if (context_msgStrictOps ())
4644 message ("Operand of %s is non-integer (%t): %s",
4645 lltok_unparse (op), te, exprNode_unparse (ret)),
4649 if (ctype_isInt (e->typ))
4655 ret->typ = ctype_int;
4661 ret->typ = ctype_makePointer (e->typ);
4663 if (sRef_isKnown (e->sref))
4665 ret->sref = sRef_makeAddress (e->sref);
4672 if (ctype_isAP (tr))
4674 ret->typ = ctype_baseArrayPtr (e->typ);
4678 if (ctype_isKnown (te))
4680 if (ctype_isFunction (te))
4686 message ("Dereference of function type (%t): %s",
4687 te, exprNode_unparse (ret)),
4692 voptgenerror (FLG_TYPE,
4693 message ("Dereference of non-pointer (%t): %s",
4694 te, exprNode_unparse (ret)),
4696 ret->typ = ctype_unknown;
4701 ret->typ = ctype_unknown;
4706 if (sRef_isKnown (e->sref))
4708 DPRINTF (("Checking possibly null: %s", sRef_unparseFull (e->sref)));
4710 if (sRef_possiblyNull (e->sref))
4712 DPRINTF (("Checking possibly null: %s", sRef_unparse (e->sref)));
4713 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4717 message ("Dereference of %s pointer %q: %s",
4718 sRef_nullMessage (e->sref),
4719 sRef_unparse (e->sref),
4720 exprNode_unparse (ret)),
4723 sRef_showNullInfo (e->sref);
4724 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4729 ret->sref = sRef_makePointer (e->sref);
4734 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4739 exprNode_checkModify (e, ret);
4746 ** any reason to disallow sizeof (abstract type) ?
4750 ** used by both sizeof
4754 ctype sizeof_resultType (void)
4756 static ctype sizet = ctype_unknown;
4758 if (ctype_isUnknown (sizet))
4760 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4762 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4766 sizet = ctype_ulint;
4773 exprNode_sizeofType (/*@only@*/ qtype qt)
4775 exprNode ret = exprNode_create (sizeof_resultType ());
4776 ctype ct = qtype_getType (qt);
4778 ret->kind = XPR_SIZEOFT;
4779 ret->edata = exprData_makeSizeofType (qt);
4781 voptgenerror (FLG_SIZEOFTYPE,
4782 message ("Parameter to sizeof is type %s: %s",
4784 exprNode_unparse (ret)),
4791 exprNode_alignofType (/*@only@*/ qtype qt)
4793 exprNode ret = exprNode_create (sizeof_resultType ());
4794 ctype ct = qtype_getType (qt);
4796 ret->kind = XPR_ALIGNOFT;
4797 ret->edata = exprData_makeSizeofType (qt);
4799 voptgenerror (FLG_SIZEOFTYPE,
4800 message ("Parameter to alignof is type %s: %s",
4802 exprNode_unparse (ret)),
4808 exprNode exprNode_offsetof (qtype qt, cstringList s)
4810 exprNode ret = exprNode_create (sizeof_resultType ());
4811 ctype ct = qtype_getType (qt);
4813 ret->kind = XPR_OFFSETOF;
4814 ret->edata = exprData_makeOffsetof (qt, s);
4816 if (!ctype_isRealSU (ct))
4818 voptgenerror (FLG_TYPE,
4819 message ("First parameter to offsetof is not a "
4820 "struct or union type (type %s): %s",
4822 exprNode_unparse (ret)),
4829 cstringList_elements (s, el) {
4833 if (ctype_isUndefined (lt))
4837 else if (!ctype_isRealSU (lt))
4839 voptgenerror (FLG_TYPE,
4840 message ("Inner offsetof type is not a "
4841 "struct or union type (type %s before field %s): %s",
4842 ctype_unparse (lt), el,
4843 exprNode_unparse (ret)),
4849 fields = ctype_getFields (ctype_realType (lt));
4850 fld = uentryList_lookupField (fields, el);
4851 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4853 if (uentry_isUndefined (fld))
4855 if (ctype_equal (lt, ct)) {
4856 voptgenerror (FLG_TYPE,
4857 message ("Field %s in offsetof is not the "
4858 "name of a field of %s: %s",
4861 exprNode_unparse (ret)),
4864 voptgenerror (FLG_TYPE,
4865 message ("Deep field %s in offsetof is not the "
4866 "name of a field of %s: %s",
4869 exprNode_unparse (ret)),
4875 lt = uentry_getType (fld);
4878 } end_cstringList_elements;
4880 /* Should report error if its a bit field - behavior is undefined! */
4887 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4891 if (exprNode_isUndefined (e))
4893 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4894 ret->edata = exprData_makeSingle (e);
4895 ret->typ = sizeof_resultType ();
4896 ret->kind = XPR_SIZEOF;
4900 uentry u = exprNode_getUentry (e);
4902 ret = exprNode_createPartialCopy (e);
4903 ret->edata = exprData_makeSingle (e);
4905 ret->typ = sizeof_resultType ();
4906 ret->kind = XPR_SIZEOF;
4908 if (uentry_isValid (u)
4909 && uentry_isRefParam (u)
4910 && ctype_isRealArray (uentry_getType (u)))
4913 (FLG_SIZEOFFORMALARRAY,
4914 message ("Parameter to sizeof is an array-type function parameter: %s",
4915 exprNode_unparse (ret)),
4921 ** sizeof (x) doesn't "really" use x
4928 exprNode_alignofExpr (/*@only@*/ exprNode e)
4932 if (exprNode_isUndefined (e))
4934 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4938 ret = exprNode_createPartialCopy (e);
4941 ret->edata = exprData_makeSingle (e);
4942 ret->typ = sizeof_resultType ();
4943 ret->kind = XPR_ALIGNOF;
4946 ** sizeof (x) doesn't "really" use x
4953 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4959 if (exprNode_isError (e))
4962 lltok_release (tok);
4963 return exprNode_undefined;
4966 checkMacroParen (e);
4968 c = qtype_getType (q);
4969 t = exprNode_getType (e);
4971 ret = exprNode_createPartialCopy (e);
4973 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4975 ret->kind = XPR_CAST;
4976 ret->edata = exprData_makeCast (tok, e, q);
4978 if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
4981 ** This is a bit of a hack to avoid a problem
4982 ** when the code does,
4983 ** (some other struct) x
4988 ret->sref = sRef_copy (e->sref);
4989 usymtab_addForceMustAlias (ret->sref, e->sref);
4990 sRef_setTypeFull (ret->sref, c);
4991 DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
4992 sRef_unparseFull (ret->sref)));
4996 ret->sref = e->sref;
4997 sRef_setTypeFull (ret->sref, c);
4998 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
5005 ** void * <-> abstract * (if FLG_ABSTVOIDP)
5006 ** abstract * <-> void * (if FLG_ABSTVOIDP)
5009 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
5013 else if (ctype_isRealAP (c)) /* casting to array or pointer */
5015 ctype bc = ctype_getBaseType (c);
5016 ctype bt = ctype_getBaseType (t);
5017 ctype rt = ctype_realType (t);
5019 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
5020 && (ctype_isArrayPtr (rt)
5021 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5025 message ("Cast from function pointer type (%t) to "
5026 "non-function pointer (%t): %s",
5027 c, t, exprNode_unparse (ret)),
5031 if (!ctype_isFunction (ctype_baseArrayPtr (c))
5032 && (ctype_isArrayPtr (rt)
5033 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5037 message ("Cast from non-function pointer type (%t) to "
5038 "function pointer (%t): %s",
5039 c, t, exprNode_unparse (ret)),
5043 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
5044 !(ctype_isRealAbstract (bc)
5045 && context_hasAccess (ctype_typeId (bc))))
5047 ; /* okay to cast zero */
5051 if (ctype_isRealAbstract (bc)
5052 && !context_hasAccess (ctype_typeId (bc)))
5054 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
5058 message ("Cast to underlying abstract type %t: %s",
5059 c, exprNode_unparse (ret)),
5066 message ("Cast to underlying abstract type %t: %s",
5067 c, exprNode_unparse (ret)),
5072 if (ctype_isRealAbstract (bt)
5073 && !context_hasAccess (ctype_typeId (bt)))
5075 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
5079 message ("Cast from underlying abstract type %t: %s",
5080 t, exprNode_unparse (ret)),
5087 message ("Cast from underlying abstract type %t: %s",
5088 t, exprNode_unparse (ret)),
5096 ctype bt = ctype_realType (ctype_getBaseType (t));
5097 ctype bc = ctype_realType (ctype_getBaseType (c));
5099 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
5101 if (ctype_match (c, t))
5103 if (ctype_equal (c, t))
5107 message ("Redundant cast involving abstract type %t: %s",
5108 bt, exprNode_unparse (ret)),
5116 message ("Cast from abstract type %t: %s",
5117 bt, exprNode_unparse (ret)),
5122 if (ctype_isAbstract (bc)
5123 && !context_hasAccess (ctype_typeId (bc)))
5125 if (ctype_match (c, t))
5131 DPRINTF (("No access to: %s / %d",
5132 ctype_unparse (bc), ctype_typeId (bc)));
5133 DPRINTF (("Context %s %s",
5134 bool_unparse (context_inFunctionLike ()),
5135 context_unparse ()));
5138 message ("Cast to abstract type %t: %s", bc,
5139 exprNode_unparse (ret)),
5145 if (ctype_isAbstract (c))
5147 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
5149 /* okay, cast exposed to abstract */
5150 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
5154 if (ctype_isVisiblySharable (t)
5155 && sRef_isExternallyVisible (e->sref)
5156 && !(ctype_isAbstract (t)
5157 && context_hasAccess (ctype_typeId (t))))
5161 message ("Cast to abstract type from externally visible "
5162 "mutable storage exposes rep of %s: %s",
5164 exprNode_unparse (e)),
5174 evaluationOrderUndefined (lltok op)
5176 int opid = lltok_getTok (op);
5178 return (opid != AND_OP && opid != OR_OP);
5181 static bool checkIntegral (/*@notnull@*/ exprNode e1,
5182 /*@notnull@*/ exprNode e2,
5183 /*@notnull@*/ exprNode ret,
5188 ctype te1 = exprNode_getType (e1);
5189 ctype te2 = exprNode_getType (e2);
5191 ctype tr1 = ctype_realishType (te1);
5192 ctype tr2 = ctype_realishType (te2);
5194 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5200 if (context_msgStrictOps ())
5202 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5204 if (ctype_sameName (te1, te2))
5208 message ("Operands of %s are non-integer (%t): %s",
5209 lltok_unparse (op), te1,
5210 exprNode_unparse (ret)),
5217 message ("Operands of %s are non-integers (%t, %t): %s",
5218 lltok_unparse (op), te1, te2,
5219 exprNode_unparse (ret)),
5223 else if (!ctype_isInt (tr1))
5227 message ("Left operand of %s is non-integer (%t): %s",
5228 lltok_unparse (op), te1, exprNode_unparse (ret)),
5232 /* !ctype_isInt (te2) */
5236 message ("Right operand of %s is non-integer (%t): %s",
5237 lltok_unparse (op), te2, exprNode_unparse (ret)),
5247 ** returns exprNode representing e1 op e2
5249 ** uses msg if there are errors
5250 ** can be used for both assignment ops and regular ops
5255 static /*@only@*/ /*@notnull@*/ exprNode
5256 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
5257 /*@keep@*/ lltok op)
5259 ctype te1, te2, tr1, tr2, tret;
5260 int opid = lltok_getTok (op);
5261 bool hasError = FALSE;
5264 if (exprNode_isError (e1))
5266 ret = exprNode_createPartialNVCopy (e2);
5270 ret = exprNode_createPartialNVCopy (e1);
5273 ret->val = multiVal_undefined;
5276 ret->edata = exprData_makeOp (e1, e2, op);
5278 if (exprNode_isError (e1) || exprNode_isError (e2))
5280 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5281 || opid == EQ_OP || opid == NE_OP
5282 || opid == AND_OP || opid == OR_OP)
5284 ret->typ = ctype_bool;
5287 if (exprNode_isDefined (e1))
5289 exprNode_checkUse (ret, e1->sref, e1->loc);
5292 if (exprNode_isDefined (e2))
5294 exprNode_mergeUSs (ret, e2);
5295 exprNode_checkUse (ret, e2->sref, e2->loc);
5301 tret = ctype_unknown;
5302 te1 = exprNode_getType (e1);
5304 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5306 te2 = exprNode_getType (e2);
5308 tr1 = ctype_realishType (te1);
5309 tr2 = ctype_realishType (te2);
5313 ret->guards = guardSet_or (ret->guards, e2->guards);
5315 else if (opid == AND_OP)
5317 ret->guards = guardSet_and (ret->guards, e2->guards);
5324 if (opid == EQ_OP || opid == NE_OP)
5326 exprNode temp1 = e1, temp2 = e2;
5328 /* could do NULL == x */
5330 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5332 temp1 = e2; temp2 = e1;
5335 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5337 reflectNullTest (temp1, (opid == NE_OP));
5338 guardSet_free (ret->guards);
5339 ret->guards = guardSet_copy (temp1->guards);
5343 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5344 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5349 if (anyAbstract (tr1, tr2) &&
5350 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
5351 (opid == AND_OP || opid == OR_OP
5352 || opid == EQ_OP || opid == NE_OP))))
5354 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
5356 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5358 /* unknown types, no comparisons possible */
5364 case TMULT: /* multiplication and division: */
5366 case MUL_ASSIGN: /* numeric, numeric -> numeric */
5367 case DIV_ASSIGN: /* */
5369 if (opid == TMULT || opid == MUL_ASSIGN)
5371 ret->val = multiVal_multiply (exprNode_getValue (e1),
5372 exprNode_getValue (e2));
5376 ret->val = multiVal_divide (exprNode_getValue (e1),
5377 exprNode_getValue (e2));
5380 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5383 case TPLUS: /* addition and subtraction: */
5384 case TMINUS: /* pointer, int -> pointer */
5385 case SUB_ASSIGN: /* int, pointer -> pointer */
5386 case ADD_ASSIGN: /* numeric, numeric -> numeric */
5388 if (opid == TPLUS || opid == ADD_ASSIGN)
5390 ret->val = multiVal_add (exprNode_getValue (e1),
5391 exprNode_getValue (e2));
5395 ret->val = multiVal_subtract (exprNode_getValue (e1),
5396 exprNode_getValue (e2));
5399 tr1 = ctype_fixArrayPtr (tr1);
5401 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5402 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5406 if (context_msgPointerArith ())
5410 message ("Pointer arithmetic (%t, %t): %s",
5411 te1, te2, exprNode_unparse (ret)),
5416 ** Swap terms so e1 is always the pointer
5419 if (ctype_isRealPointer (tr1))
5425 exprNode_swap (e1, e2);
5429 if (sRef_possiblyNull (e1->sref)
5430 && !usymtab_isGuarded (e1->sref))
5433 (FLG_NULLPOINTERARITH,
5434 message ("Pointer arithmetic involving possibly "
5435 "null pointer %s: %s",
5436 exprNode_unparse (e1),
5437 exprNode_unparse (ret)),
5441 ret->sref = sRef_copy (e1->sref);
5443 /* start modifications */
5444 /* added by Seejo on 4/16/2000 */
5446 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5448 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5451 added ugly fixed to stop
5452 program from crashing on point + int +int
5453 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5455 if (!multiVal_isInt (e2->val) )
5459 val = (int) multiVal_forceInt (e2->val);
5461 /* Operator : + or += */
5462 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5463 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5464 val should not result in a
5465 size < 0 (size = 0 is ok !) */
5467 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5469 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5470 sRef_setNotNullTerminatedState(ret->sref);
5471 sRef_resetLen (ret->sref);
5473 sRef_setNullTerminatedState(ret->sref);
5474 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5479 /* Operator : - or -= */
5480 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5481 if (sRef_getSize(e1->sref) >= 0) {
5482 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5483 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5488 /* end modifications */
5490 sRef_setNullError (ret->sref);
5493 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5494 ** since is points to storage that should not be deallocated
5495 ** through this pointer.
5498 if (sRef_isOnly (ret->sref)
5499 || sRef_isFresh (ret->sref))
5501 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5506 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5507 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5509 if (context_msgPointerArith ())
5513 message ("Pointer arithmetic (%t, %t): %s",
5514 te1, te2, exprNode_unparse (ret)),
5518 if (sRef_possiblyNull (e1->sref)
5519 && !usymtab_isGuarded (e1->sref))
5522 (FLG_NULLPOINTERARITH,
5523 message ("Pointer arithmetic involving possibly "
5524 "null pointer %s: %s",
5525 exprNode_unparse (e2),
5526 exprNode_unparse (ret)),
5530 ret->sref = sRef_copy (e2->sref);
5532 /* start modifications */
5533 /* added by Seejo on 4/16/2000 */
5535 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5538 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5539 int val = (int) multiVal_forceInt (e1->val);
5541 /* Operator : + or += */
5542 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5543 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5544 val should not result in a
5545 size < 0 (size = 0 is ok !) */
5547 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5549 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5550 sRef_setNotNullTerminatedState(ret->sref);
5551 sRef_resetLen (ret->sref);
5553 sRef_setNullTerminatedState(ret->sref);
5554 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5559 /* Operator : - or -= */
5560 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5561 if (sRef_getSize(e2->sref) >= 0) {
5562 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5563 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5567 /* end modifications */
5569 sRef_setNullError (ret->sref);
5572 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5573 ** since is points to storage that should not be deallocated
5574 ** through this pointer.
5577 if (sRef_isOnly (ret->sref)
5578 || sRef_isFresh (ret->sref)) {
5579 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5583 ret->sref = e2->sref;
5587 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5596 case TAMPERSAND: /* bitwise & */
5598 case TCIRC: /* ^ (XOR) */
5603 bool reported = FALSE;
5609 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5610 || opid == RIGHT_OP || opid == RIGHT_ASSIGN)
5613 ** evans 2002-01-01: fixed this to follow ISO 6.5.7.
5616 if (!ctype_isUnsigned (tr2)
5617 && !exprNode_isNonNegative (e2))
5619 reported = optgenerror
5621 message ("Right operand of %s may be negative (%t): %s",
5622 lltok_unparse (op), te2,
5623 exprNode_unparse (ret)),
5627 if (!ctype_isUnsigned (tr1)
5628 && !exprNode_isNonNegative (e1))
5630 reported = optgenerror
5631 (FLG_SHIFTIMPLEMENTATION,
5632 message ("Left operand of %s may be negative (%t): %s",
5633 lltok_unparse (op), te1,
5634 exprNode_unparse (ret)),
5639 ** Should check size of right operand also...
5645 if (!ctype_isUnsigned (tr1))
5647 if (exprNode_isNonNegative (e1)) {
5650 reported = optgenerror
5652 message ("Left operand of %s is not unsigned value (%t): %s",
5653 lltok_unparse (op), te1,
5654 exprNode_unparse (ret)),
5664 if (!ctype_isUnsigned (tr2))
5666 if (!exprNode_isNonNegative (e2)) {
5667 reported = optgenerror
5669 message ("Right operand of %s is not unsigned value (%t): %s",
5670 lltok_unparse (op), te2,
5671 exprNode_unparse (ret)),
5680 if (!checkIntegral (e1, e2, ret, op)) {
5681 te1 = ctype_unknown;
5685 DPRINTF (("Set: %s", ctype_unparse (te1)));
5688 ** tret is the widest type of te1 and te2
5691 tret = ctype_widest (te1, te2);
5696 if (checkIntegral (e1, e2, ret, op)) {
5699 tret = ctype_unknown;
5704 case TLT: /* comparisons */
5705 case TGT: /* numeric, numeric -> bool */
5707 DPRINTF (("Here we go: %s / %s",
5708 ctype_unparse (tr1), ctype_unparse (tr2)));
5710 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5711 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5714 bool fepsilon = FALSE;
5716 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5721 if (opid == TLT || opid == TGT)
5723 uentry ue1 = exprNode_getUentry (e1);
5724 uentry ue2 = exprNode_getUentry (e2);
5727 ** FLT_EPSILON, etc. really is a variable, not
5731 if (uentry_isVariable (ue1))
5733 cstring uname = uentry_rawName (ue1);
5735 if (cstring_equalLit (uname, "FLT_EPSILON")
5736 || cstring_equalLit (uname, "DBL_EPSILON")
5737 || cstring_equalLit (uname, "LDBL_EPSILON"))
5743 if (uentry_isVariable (ue2))
5745 cstring uname = uentry_rawName (ue2);
5747 if (cstring_equalLit (uname, "FLT_EPSILON")
5748 || cstring_equalLit (uname, "DBL_EPSILON")
5749 || cstring_equalLit (uname, "LDBL_EPSILON"))
5758 ; /* Don't complain. */
5764 message ("Dangerous comparison involving %s types: %s",
5765 ctype_unparse (rtype),
5766 exprNode_unparse (ret)),
5775 ** Types should match.
5778 DPRINTF (("Match types: %s / %s", exprNode_unparse (e1),
5779 exprNode_unparse (e2)));
5781 if (!exprNode_matchTypes (e1, e2))
5783 hasError = gentypeerror
5785 message ("Operands of %s have incompatible types (%t, %t): %s",
5786 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5792 || (ctype_isForceRealNumeric (&tr1)
5793 && ctype_isForceRealNumeric (&tr2)) ||
5794 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5800 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5801 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5805 message ("Comparison of pointer and numeric (%t, %t): %s",
5806 te1, te2, exprNode_unparse (ret)),
5811 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5816 /* certain comparisons on unsigned's and zero look suspicious */
5818 if (opid == TLT || opid == LE_OP || opid == GE_OP)
5820 if ((ctype_isUnsigned (tr1) && exprNode_isZero (e2))
5821 || (ctype_isUnsigned (tr2) && exprNode_isZero (e1)))
5824 (FLG_UNSIGNEDCOMPARE,
5825 message ("Comparison of unsigned value involving zero: %s",
5826 exprNode_unparse (ret)),
5831 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5833 if ((opid == EQ_OP || opid == NE_OP) &&
5834 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5837 ** is one a variable?
5840 if (uentry_isVariable (exprNode_getUentry (e1))
5841 || uentry_isVariable (exprNode_getUentry (e2)))
5844 ** comparisons with FALSE are okay
5847 if (exprNode_isFalseConstant (e1)
5848 || exprNode_isFalseConstant (e2))
5857 ("Use of %q with %s variables (risks inconsistency because "
5858 "of multiple true values): %s",
5859 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5860 context_printBoolName (), exprNode_unparse (ret)),
5867 case AND_OP: /* bool, bool -> bool */
5870 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5876 if (context_maybeSet (FLG_BOOLOPS))
5878 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5880 if (ctype_sameName (te1, te2))
5884 message ("Operands of %s are non-boolean (%t): %s",
5885 lltok_unparse (op), te1,
5886 exprNode_unparse (ret)),
5894 ("Operands of %s are non-booleans (%t, %t): %s",
5895 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5899 else if (!ctype_isRealBool (te1))
5903 message ("Left operand of %s is non-boolean (%t): %s",
5904 lltok_unparse (op), te1, exprNode_unparse (ret)),
5907 else if (!ctype_isRealBool (te2))
5911 message ("Right operand of %s is non-boolean (%t): %s",
5912 lltok_unparse (op), te2, exprNode_unparse (ret)),
5925 (cstring_makeLiteral
5926 ("There has been a problem in the parser. This is believed to result "
5927 "from a problem with bison v. 1.25. Please try rebuidling Splint "
5928 "using the pre-compiled grammar files by commenting out the "
5929 "BISON= line in the top-level Makefile."));
5934 DPRINTF (("Return type: %s", ctype_unparse (tret)));
5937 exprNode_checkUse (ret, e1->sref, e1->loc);
5938 exprNode_mergeUSs (ret, e2);
5939 exprNode_checkUse (ret, e2->sref, e2->loc);
5945 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5946 /*@only@*/ lltok op)
5950 checkMacroParen (e1);
5951 checkMacroParen (e2);
5953 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5955 checkExpressionDefined (e1, e2, op);
5958 ret = exprNode_makeOp (e1, e2, op);
5963 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5966 ** This is somewhat bogus!
5968 ** Assigning to a nested observer in a non-observer datatype
5969 ** should not produce an error.
5972 sRef ref = exprNode_getSref (e1);
5974 DPRINTF (("Check assign mod: %s",
5975 sRef_unparseFull (ref)));
5977 if (sRef_isObserver (ref)
5978 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
5979 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5981 sRef base = sRef_getBase (ref);
5983 if (sRef_isValid (base) && sRef_isObserver (base))
5985 exprNode_checkModify (e1, ret);
5989 exprNode_checkModifyVal (e1, ret);
5994 exprNode_checkModify (e1, ret);
5999 exprNode_assign (/*@only@*/ exprNode e1,
6000 /*@only@*/ exprNode e2, /*@only@*/ lltok op)
6002 bool isalloc = FALSE;
6003 bool isjustalloc = FALSE;
6004 bool noalias = FALSE;
6007 DPRINTF (("%s [%s] <- %s [%s]",
6008 exprNode_unparse (e1),
6009 ctype_unparse (e1->typ),
6010 exprNode_unparse (e2),
6011 ctype_unparse (e2->typ)));
6013 if (lltok_getTok (op) != TASSIGN)
6015 ret = exprNode_makeOp (e1, e2, op);
6017 DPRINTF (("Here goes: %s %s",
6018 ctype_unparse (e1->typ),
6019 ctype_unparse (e2->typ)));
6021 if (ctype_isNumeric (e2->typ)
6022 || ctype_isNumeric (e1->typ))
6024 /* Its a pointer arithmetic expression like ptr += i */
6030 ret = exprNode_createPartialCopy (e1);
6031 ret->kind = XPR_ASSIGN;
6032 ret->edata = exprData_makeOp (e1, e2, op);
6034 if (!exprNode_isError (e2))
6036 ret->sets = sRefSet_union (ret->sets, e2->sets);
6037 ret->msets = sRefSet_union (ret->msets, e2->msets);
6038 ret->uses = sRefSet_union (ret->uses, e2->uses);
6042 checkExpressionDefined (e1, e2, op);
6044 if (exprNode_isError (e1))
6046 if (!exprNode_isError (e2))
6048 ret->loc = fileloc_update (ret->loc, e2->loc);
6052 ret->loc = fileloc_update (ret->loc, g_currentloc);
6056 if (!exprNode_isError (e2))
6058 checkMacroParen (e2);
6061 if (exprNode_isDefined (e1))
6063 if (sRef_isMacroParamRef (e1->sref))
6065 if (context_inIterDef ())
6067 uentry ue = sRef_getUentry (e1->sref);
6069 if (uentry_isYield (ue))
6075 if (fileloc_isDefined (e1->loc))
6079 message ("Assignment to non-yield iter parameter: %q",
6080 sRef_unparse (e1->sref)),
6087 message ("Assignment to non-yield iter parameter: %q",
6088 sRef_unparse (e1->sref)),
6095 if (fileloc_isDefined (e1->loc))
6099 message ("Assignment to macro parameter: %q",
6100 sRef_unparse (e1->sref)),
6107 message ("Assignment to macro parameter: %q",
6108 sRef_unparse (e1->sref)),
6112 exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
6117 exprNode_checkAssignMod (e1, ret);
6120 if (exprNode_isDefined (e2))
6122 if (lltok_getTok (op) == TASSIGN)
6124 ctype te1 = exprNode_getType (e1);
6125 ctype te2 = exprNode_getType (e2);
6127 if (!ctype_forceMatch (te1, te2))
6129 if (exprNode_matchLiteral (te1, e2))
6137 message ("Assignment of %t to %t: %s %s %s",
6138 te2, te1, exprNode_unparse (e1),
6140 exprNode_unparse (e2)),
6146 exprNode_mergeUSs (ret, e2);
6147 exprNode_checkUse (ret, e2->sref, e2->loc);
6149 DPRINTF (("Do assign! %s %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6156 doAssign (e1, e2, FALSE);
6159 ret->sref = e1->sref;
6163 if (exprNode_isDefined (e2))
6165 exprNode_mergeUSs (ret, e2);
6166 exprNode_checkUse (ret, e2->sref, e2->loc);
6170 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
6172 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
6175 isjustalloc = sRef_isJustAllocated (e1->sref);
6176 isalloc = sRef_isAllocated (e1->sref);
6178 if (sRef_isField (e1->sref))
6180 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
6182 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
6184 exprNode_checkUse (ret, root, e1->loc);
6190 ** be careful! this defines e1->sref.
6193 /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
6195 DPRINTF (("Setting: %s -> %s", exprNode_unparse (ret), sRef_unparse (e1->sref)));
6196 exprNode_checkSet (ret, e1->sref);
6200 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
6201 ? e2->loc : e1->loc);
6207 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
6216 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
6217 /*@keep@*/ exprNode elseclause)
6221 if (!exprNode_isError (pred))
6223 ret = exprNode_createPartialCopy (pred);
6224 checkMacroParen (pred);
6225 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
6227 if (!exprNode_isError (ifclause))
6229 checkMacroParen (ifclause); /* update macro counts! */
6231 if (!exprNode_isError (elseclause))
6233 checkMacroParen (elseclause);
6235 if (!exprNode_matchTypes (ifclause, elseclause))
6238 (exprNode_getType (ifclause),
6240 exprNode_getType (elseclause),
6242 message ("Conditional clauses are not of same type: "
6244 exprNode_unparse (ifclause),
6245 exprNode_getType (ifclause),
6246 exprNode_unparse (elseclause),
6247 exprNode_getType (elseclause)),
6250 ret->sref = sRef_undefined;
6251 ret->typ = ctype_unknown;
6256 /* for now...should merge the states */
6257 ret->sref = ifclause->sref;
6258 ret->typ = ifclause->typ;
6260 if (exprNode_isNullValue (ifclause))
6262 ret->typ = elseclause->typ;
6266 exprNode_checkUse (ret, pred->sref, pred->loc);
6267 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6268 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6270 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6275 ret->typ = ifclause->typ;
6277 exprNode_checkUse (pred, pred->sref, pred->loc);
6278 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6280 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6285 if (!exprNode_isError (elseclause))
6287 ret->typ = elseclause->typ;
6289 exprNode_checkUse (pred, pred->sref, pred->loc);
6290 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6292 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6296 else /* pred is error */
6298 if (!exprNode_isError (ifclause))
6300 ret = exprNode_createSemiCopy (ifclause);
6302 checkMacroParen (ifclause); /* update macro counts! */
6304 if (!exprNode_isError (elseclause))
6306 checkMacroParen (elseclause);
6308 ret->typ = ifclause->typ;
6310 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6313 (exprNode_getType (ifclause),
6315 exprNode_getType (elseclause),
6317 message ("Conditional clauses are not of same type: "
6319 exprNode_unparse (ifclause),
6320 exprNode_getType (ifclause),
6321 exprNode_unparse (elseclause),
6322 exprNode_getType (elseclause)),
6325 ret->typ = ctype_unknown;
6329 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6330 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6332 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6335 else if (!exprNode_isError (elseclause)) /* pred, if errors */
6337 ret = exprNode_createSemiCopy (ifclause);
6339 ret->typ = elseclause->typ;
6340 checkMacroParen (elseclause);
6342 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6343 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6345 else /* all errors! */
6347 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6351 ret->kind = XPR_COND;
6352 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
6354 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6356 exprNode_combineControl (ret, ifclause, elseclause);
6363 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6365 ctype totype = qtype_getType (qt);
6367 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6371 ** check use of va_arg : <valist>, type -> type
6374 if (exprNode_isError (arg))
6379 targ = exprNode_getType (arg);
6382 ** arg should have be a pointer
6385 if (!ctype_isUA (targ) ||
6386 (!usymId_equal (ctype_typeId (targ),
6387 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6391 message ("First argument to va_arg is not a va_list (type %t): %s",
6392 targ, exprNode_unparse (arg)),
6396 exprNode_checkSet (ret, arg->sref);
6400 ** return type is totype
6404 ret->kind = XPR_VAARG;
6405 ret->edata = exprData_makeCast (tok, arg, qt);
6410 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6412 exprNode ret = exprNode_createPlain (ctype_undefined);
6413 ret->kind = XPR_LABEL;
6414 ret->edata = exprData_makeLiteral (label);
6415 ret->isJumpPoint = TRUE;
6417 return (ret); /* for now, ignore label */
6420 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6422 if (exprNode_isDefined (stmt))
6424 stmt->isJumpPoint = TRUE;
6426 /* This prevent stray no return path errors, etc. */
6427 stmt->exitCode = XK_MUSTEXIT;
6433 bool exprNode_isDefaultMarker (exprNode e)
6435 if (exprNode_isDefined (e))
6437 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6443 bool exprNode_isCaseMarker (exprNode e)
6445 if (exprNode_isDefined (e))
6447 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6453 bool exprNode_isLabelMarker (exprNode e)
6455 if (exprNode_isDefined (e))
6457 return (e->kind == XPR_LABEL);
6463 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6465 exprNode ret = exprNode_createPartialCopy (test);
6467 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6469 if (exprNode_isError (test)) {
6473 exprNode_checkUse (ret, test->sref, test->loc);
6475 usymtab_setExitCode (ret->exitCode);
6479 usymtab_setMustBreak ();
6482 ret->edata = exprData_makeSingle (test);
6483 ret->isJumpPoint = TRUE;
6489 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6491 exprNode ret = exprNode_createPartialCopy (test);
6493 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6494 ret->edata = exprData_makePair (test, stmt);
6495 ret->isJumpPoint = TRUE;
6497 if (exprNode_isError (test))
6502 exprNode_checkUse (ret, test->sref, test->loc);
6504 if (exprNode_isError (stmt))
6509 exprNode_mergeUSs (ret, stmt);
6511 ret->exitCode = stmt->exitCode;
6512 ret->mustBreak = stmt->mustBreak;
6513 ret->canBreak = stmt->canBreak;
6515 usymtab_setExitCode (ret->exitCode);
6519 usymtab_setMustBreak ();
6526 /*@notnull@*/ /*@only@*/ exprNode
6527 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6529 exprNode ret = exprNode_createTok (def);
6531 ret->isJumpPoint = TRUE;
6532 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6537 exprNode_mayEscape (exprNode e)
6539 if (exprNode_isDefined (e))
6541 return exitkind_couldEscape (e->exitCode);
6547 exprNode_mustBreak (exprNode e)
6549 if (exprNode_isDefined (e))
6551 return e->mustBreak;
6558 exprNode_mustEscape (exprNode e)
6560 if (exprNode_isDefined (e))
6562 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6569 exprNode_errorEscape (exprNode e)
6571 if (exprNode_isDefined (e))
6573 return exitkind_isError (e->exitCode);
6579 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6581 exprNode ret = exprNode_createPartialCopy (e1);
6583 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6585 ret->edata = exprData_makePair (e1, e2);
6586 ret->kind = XPR_STMTLIST;
6588 if (exprNode_isDefined (e1))
6590 ret->isJumpPoint = e1->isJumpPoint;
6591 ret->canBreak = e1->canBreak;
6595 if (exprNode_isDefined (e2))
6597 ret->loc = fileloc_update (ret->loc, e2->loc);
6601 if (exprNode_isDefined (e2))
6603 ret->exitCode = e2->exitCode;
6604 ret->mustBreak = e2->mustBreak;
6605 if (e2->canBreak) ret->canBreak = TRUE;
6609 ** if e1 must return, then e2 is unreachable!
6612 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6614 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6615 && !(e2->isJumpPoint))
6617 if (context_getFlag (FLG_UNREACHABLE))
6621 if (e2->kind == XPR_STMT)
6623 nr = exprData_getUopNode (e2->edata);
6626 if ((nr->kind == XPR_TOK
6627 && lltok_isSemi (exprData_getTok (nr->edata))))
6629 /* okay to have unreachable ";" */
6630 ret->exitCode = XK_MUSTEXIT;
6631 ret->canBreak = TRUE;
6635 if (optgenerror (FLG_UNREACHABLE,
6636 message ("Unreachable code: %s",
6637 exprNode_unparseFirst (nr)),
6640 ret->isJumpPoint = TRUE;
6641 ret->mustBreak = FALSE;
6642 ret->exitCode = XK_ERROR;
6643 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6647 ret->exitCode = XK_MUSTEXIT;
6648 ret->canBreak = TRUE;
6656 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6659 ** We want a warning anytime we have:
6661 ** yyy; <<<- no break or return
6665 exprNode lastStmt = exprNode_lastStatement (e1);
6667 if (exprNode_isDefined (lastStmt)
6668 && !exprNode_mustEscape (lastStmt)
6669 && !exprNode_mustBreak (lastStmt)
6670 && !exprNode_isCaseMarker (lastStmt)
6671 && !exprNode_isDefaultMarker (lastStmt)
6672 && !exprNode_isLabelMarker (lastStmt))
6674 voptgenerror (FLG_CASEBREAK,
6676 ("Fall through case (no preceding break)"),
6683 exprNode_mergeUSs (ret, e2);
6685 usymtab_setExitCode (ret->exitCode);
6689 usymtab_setMustBreak ();
6695 exprNode exprNode_createTok (/*@only@*/ lltok t)
6697 exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6698 ret = exprNode_create (ctype_unknown);
6699 ret->kind = XPR_TOK;
6700 ret->edata = exprData_makeTok (t);
6704 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6706 if (!exprNode_isError (e))
6708 exprNode_checkStatement(e);
6711 return (exprNode_statementError (e, t));
6714 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6716 exprNode ret = exprNode_createPartialCopy (e);
6718 if (!exprNode_isError (e))
6720 if (e->kind != XPR_ASSIGN)
6722 exprNode_checkUse (ret, e->sref, e->loc);
6725 ret->exitCode = e->exitCode;
6726 ret->canBreak = e->canBreak;
6727 ret->mustBreak = e->mustBreak;
6730 ret->edata = exprData_makeUop (e, t);
6731 ret->kind = XPR_STMT;
6736 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6738 if (!exprNode_isError (e))
6740 if (e->kind != XPR_ASSIGN)
6742 exprNode_checkUse (e, e->sref, e->loc);
6749 void exprNode_produceGuards (exprNode pred)
6751 if (!exprNode_isError (pred))
6753 if (ctype_isRealPointer (pred->typ))
6755 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6758 exprNode_checkUse (pred, pred->sref, pred->loc);
6759 exprNode_resetSref (pred);
6763 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6765 exprNode ret = exprNode_createPartialCopy (e);
6767 if (!exprNode_isError (e))
6769 ret->exitCode = e->exitCode;
6770 ret->canBreak = e->canBreak;
6771 ret->mustBreak = e->mustBreak;
6774 ret->edata = exprData_makeSingle (e);
6775 ret->kind = XPR_BLOCK;
6779 bool exprNode_isBlock (exprNode e)
6781 return (exprNode_isDefined (e)
6782 && ((e)->kind == XPR_BLOCK));
6785 bool exprNode_isAssign (exprNode e)
6787 if (exprNode_isDefined (e))
6789 return (e->kind == XPR_ASSIGN);
6795 bool exprNode_isEmptyStatement (exprNode e)
6797 return (exprNode_isDefined (e)
6798 && (e->kind == XPR_TOK)
6799 && (lltok_isSemi (exprData_getTok (e->edata))));
6802 void exprNode_checkIfPred (exprNode pred)
6804 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6807 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6810 bool emptyErr = FALSE;
6812 if (context_maybeSet (FLG_IFEMPTY))
6814 if (exprNode_isEmptyStatement (tclause))
6816 emptyErr = optgenerror (FLG_IFEMPTY,
6818 ("Body of if statement is empty"),
6819 exprNode_loc (tclause));
6823 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6825 if (exprNode_isDefined (tclause)
6826 && !exprNode_isBlock (tclause))
6828 voptgenerror (FLG_IFBLOCK,
6830 ("Body of if statement is not a block: %s",
6831 exprNode_unparse (tclause)),
6832 exprNode_loc (tclause));
6836 if (exprNode_isError (pred))
6838 if (exprNode_isError (tclause))
6840 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6844 ret = exprNode_createPartialCopy (tclause);
6849 if (exprNode_mustEscape (pred))
6853 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6854 exprNode_loc (pred));
6857 /*! exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred); */ /*@i523@*/
6858 exprNode_checkUse (pred, pred->sref, pred->loc);
6860 if (!exprNode_isError (tclause))
6862 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
6865 ret = exprNode_createPartialCopy (pred);
6869 ret->edata = exprData_makePair (pred, tclause);
6871 ret->exitCode = XK_UNKNOWN;
6873 if (exprNode_isDefined (tclause))
6875 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
6876 ret->canBreak = tclause->canBreak;
6877 ret->sets = sRefSet_union (ret->sets, tclause->sets);
6878 ret->msets = sRefSet_union (ret->msets, tclause->msets);
6879 ret->uses = sRefSet_union (ret->uses, tclause->uses);
6882 ret->mustBreak = FALSE;
6887 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
6888 /*@only@*/ exprNode tclause,
6889 /*@only@*/ exprNode eclause)
6892 bool tEmptyErr = FALSE;
6893 bool eEmptyErr = FALSE;
6895 if (context_maybeSet (FLG_IFEMPTY))
6897 if (exprNode_isEmptyStatement (tclause))
6899 tEmptyErr = optgenerror
6902 ("Body of if clause of if statement is empty"),
6903 exprNode_loc (tclause));
6906 if (exprNode_isEmptyStatement (eclause))
6908 eEmptyErr = optgenerror
6911 ("Body of else clause of if statement is empty"),
6912 exprNode_loc (eclause));
6916 if (context_maybeSet (FLG_IFBLOCK))
6919 && exprNode_isDefined (tclause)
6920 && !exprNode_isBlock (tclause))
6922 voptgenerror (FLG_IFBLOCK,
6924 ("Body of if clause of if statement is not a block: %s",
6925 exprNode_unparse (tclause)),
6926 exprNode_loc (tclause));
6930 && exprNode_isDefined (eclause)
6931 && !exprNode_isBlock (eclause)
6932 && !(eclause->kind == XPR_IF)
6933 && !(eclause->kind == XPR_IFELSE))
6938 ("Body of else clause of if statement is not a block: %s",
6939 exprNode_unparse (eclause)),
6940 exprNode_loc (eclause));
6944 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
6946 if (exprNode_isDefined (eclause)
6947 && (eclause->kind == XPR_IF))
6949 voptgenerror (FLG_ELSEIFCOMPLETE,
6950 message ("Incomplete else if logic (no final else): %s",
6951 exprNode_unparse (eclause)),
6952 exprNode_loc (eclause));
6956 if (exprNode_isError (pred))
6958 if (exprNode_isError (tclause))
6960 if (exprNode_isError (eclause))
6962 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6966 ret = exprNode_createPartialCopy (eclause);
6971 ret = exprNode_createPartialCopy (tclause);
6974 else /* pred is okay */
6976 ret = exprNode_createPartialCopy (pred);
6978 if (exprNode_mustEscape (pred))
6982 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6983 exprNode_loc (pred));
6986 /*@i3423 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);*/
6987 exprNode_checkUse (ret, pred->sref, pred->loc);
6989 exprNode_mergeCondUSs (ret, tclause, eclause);
6992 ret->kind = XPR_IFELSE;
6993 ret->edata = exprData_makeCond (pred, tclause, eclause);
6995 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
6997 exprNode_combineControl (ret, tclause, eclause);
6998 ret->loc = fileloc_update (ret->loc, eclause->loc);
7005 ** *allpaths <- TRUE iff all executions paths must go through the switch
7009 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
7011 exprNodeSList el = exprNode_flatten (e);
7012 bool mustReturn = TRUE; /* find a branch that doesn't */
7013 bool thisReturn = FALSE;
7014 bool hasDefault = FALSE;
7015 bool hasAllMembers = FALSE;
7016 bool inSwitch = FALSE;
7017 bool isEnumSwitch = FALSE;
7018 bool canBreak = FALSE;
7019 bool fallThrough = FALSE;
7020 ctype ct = ctype_unknown;
7021 enumNameSList usedEnums;
7024 if (exprNode_isDefined (test))
7029 ttype = ctype_realType (ct);
7031 if (ctype_isEnum (ttype))
7033 isEnumSwitch = TRUE;
7034 enums = ctype_elist (ttype);
7035 usedEnums = enumNameSList_new ();
7039 exprNodeSList_elements (el, current)
7041 if (exprNode_isDefined (current))
7043 switch (current->kind)
7050 (FLG_DUPLICATECASES,
7051 message ("Duplicate default cases in switch"),
7052 exprNode_loc (current));
7057 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
7065 exprNode st = exprData_getSingle (current->edata);
7066 uentry ue = exprNode_getUentry (st);
7068 if (uentry_isValid (ue))
7070 cstring cname = uentry_rawName (ue);
7072 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
7074 if (enumNameSList_member
7075 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
7078 (FLG_DUPLICATECASES,
7079 message ("Duplicate case in switch: %s",
7085 enumNameSList_addh (usedEnums, cname);
7092 message ("Case in switch not %s member: %s",
7093 ctype_unparse (ct), cname),
7100 if (inSwitch && !fallThrough)
7102 if (!thisReturn || canBreak)
7112 /*@switchbreak@*/ break;
7114 thisReturn = thisReturn || exprNode_mustEscape (current);
7115 canBreak = canBreak || current->canBreak;
7116 if (canBreak) fallThrough = FALSE;
7119 } end_exprNodeSList_elements;
7121 if (inSwitch) /* check the last one! */
7123 if (!thisReturn || canBreak)
7132 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
7133 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
7135 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
7137 voptgenerror (FLG_MISSCASE,
7138 message ("Missing case%s in switch: %q",
7139 cstring_makeLiteralTemp
7140 ((enumNameSList_size (unused) > 1) ? "s" : ""),
7141 enumNameSList_unparse (unused)),
7144 enumNameSList_free (unused);
7145 *allpaths = FALSE; /* evans 2002-01-01 */
7149 hasAllMembers = TRUE;
7153 enumNameSList_free (usedEnums);
7157 *allpaths = hasDefault;
7160 exprNodeSList_free (el);
7161 return ((hasDefault || hasAllMembers) && mustReturn);
7164 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
7166 exprNode ret = exprNode_createPartialCopy (e);
7169 DPRINTF (("Switch: %s", exprNode_unparse (s)));
7171 ret->kind = XPR_SWITCH;
7172 ret->edata = exprData_makePair (e, s);
7174 if (!exprNode_isError (s))
7176 exprNode fs = exprNode_firstStatement (s);
7177 ret->loc = fileloc_update (ret->loc, s->loc);
7179 if (exprNode_isUndefined (fs)
7180 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
7181 || exprNode_isDefaultMarker (fs)) {
7184 voptgenerror (FLG_FIRSTCASE,
7186 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
7191 if (!exprNode_isError (e))
7193 if (checkSwitchExpr (e, s, &allpaths))
7195 ret->exitCode = XK_MUSTRETURN;
7199 ret->exitCode = e->exitCode;
7202 ret->canBreak = e->canBreak;
7203 ret->mustBreak = e->mustBreak;
7207 ** exprNode.c:3883,32: Variable allpaths used before definition
7214 DPRINTF (("Context exit switch!"));
7215 context_exitSwitch (ret, allpaths);
7216 DPRINTF (("Context exit switch done!"));
7221 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
7222 /*@notnull@*/ exprNode body)
7224 sRefSet tuses = test->uses;
7226 if (!sRefSet_isEmpty (test->uses))
7228 sRefSet sets = sRefSet_newCopy (body->sets);
7229 bool hasError = TRUE;
7230 bool innerState = FALSE;
7231 sRefSet tuncon = sRefSet_undefined;
7233 sets = sRefSet_union (sets, test->sets);
7234 sets = sRefSet_union (sets, body->msets);
7235 sets = sRefSet_union (sets, test->msets);
7237 sRefSet_allElements (tuses, el)
7239 if (sRef_isUnconstrained (el))
7241 tuncon = sRefSet_insert (tuncon, el);
7245 if (sRefSet_member (sets, el))
7252 if (sRef_isInternalState (el)
7253 || sRef_isFileStatic (sRef_getRootBase (el)))
7257 } end_sRefSet_allElements ;
7261 sRefSet suncon = sRefSet_undefined;
7262 bool sinner = FALSE;
7264 sRefSet_allElements (sets, el)
7266 if (sRef_isUnconstrained (el))
7268 suncon = sRefSet_insert (suncon, el);
7270 else if (sRef_isInternalState (el))
7278 } end_sRefSet_allElements ;
7280 if (sinner && innerState)
7284 else if (sRefSet_isEmpty (tuncon)
7285 && sRefSet_isEmpty (suncon))
7290 ("Suspected infinite loop. No value used in loop test (%q) "
7291 "is modified by test or loop body.",
7292 sRefSet_unparsePlain (tuses)),
7297 if (sRefSet_isEmpty (tuncon))
7301 message ("Suspected infinite loop. No condition values "
7302 "modified. Modification possible through "
7303 "unconstrained calls: %q",
7304 sRefSet_unparsePlain (suncon)),
7311 message ("Suspected infinite loop. No condition values "
7312 "modified. Possible undetected dependency through "
7313 "unconstrained calls in loop test: %q",
7314 sRefSet_unparsePlain (tuncon)),
7320 sRefSet_free (sets);
7324 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7327 bool emptyErr = FALSE;
7329 if (context_maybeSet (FLG_WHILEEMPTY))
7331 if (exprNode_isEmptyStatement (b))
7333 emptyErr = optgenerror
7336 ("Body of while statement is empty"),
7341 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7343 if (exprNode_isDefined (b)
7344 && !exprNode_isBlock (b))
7346 if (context_inIterDef ()
7347 && (b->kind == XPR_STMTLIST
7348 || b->kind == XPR_TOK))
7354 voptgenerror (FLG_WHILEBLOCK,
7356 ("Body of while statement is not a block: %s",
7357 exprNode_unparse (b)),
7363 if (exprNode_isError (t))
7365 if (exprNode_isError (b))
7367 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7371 ret = exprNode_createPartialCopy (b);
7378 ret = exprNode_createPartialCopy (t);
7380 llassert (t->kind == XPR_WHILEPRED);
7382 test = exprData_getSingle (t->edata);
7384 if (!exprNode_isError (b) && exprNode_isDefined (test))
7386 if (context_maybeSet (FLG_INFLOOPS)
7387 || context_maybeSet (FLG_INFLOOPSUNCON))
7390 ** check that some variable in the predicate is set by the body
7391 ** if the predicate uses any variables
7394 checkInfiniteLoop (test, b);
7397 exprNode_mergeUSs (ret, b);
7399 if (exprNode_isDefined (b))
7401 ret->exitCode = exitkind_makeConditional (b->exitCode);
7406 ret->edata = exprData_makePair (t, b);
7407 ret->kind = XPR_WHILE;
7409 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7413 message ("Predicate always exits: %s", exprNode_unparse (t)),
7417 ret->exitCode = XK_NEVERESCAPE;
7420 ** If loop is infinite, and there is no break inside,
7421 ** exit code is never reach.
7424 if (exprNode_knownIntValue (t))
7426 if (!exprNode_isZero (t))
7428 if (exprNode_isDefined (b))
7432 /* Really, it means never reached. */
7433 ret->exitCode = XK_MUSTEXIT;
7443 ret->canBreak = FALSE;
7444 ret->mustBreak = FALSE;
7450 ** do { b } while (t);
7452 ** note: body passed as first argument
7455 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7459 DPRINTF (("Do while: %s / %s",
7460 exprNode_unparse (b), exprNode_unparse (t)));
7462 if (exprNode_isError (t))
7464 if (exprNode_isError (b))
7466 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7470 ret = exprNode_createPartialCopy (b);
7472 ret->exitCode = exitkind_makeConditional (b->exitCode);
7473 exprNode_checkUse (ret, b->sref, b->loc);
7474 ret->exitCode = b->exitCode;
7475 ret->canBreak = b->canBreak;
7476 ret->mustBreak = FALSE;
7481 DPRINTF (("Do while: %s / %s",
7482 exitkind_unparse (t->exitCode),
7483 exitkind_unparse (b->exitCode)));
7485 ret = exprNode_createPartialCopy (t);
7486 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7488 if (!exprNode_isError (b))
7491 ** forgot the copy's --- why wasn't this detected??
7494 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7495 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7496 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
7498 /* left this out --- causes and aliasing bug (infinite loop)
7499 should be detected?? */
7501 exprNode_checkUse (ret, b->sref, b->loc);
7502 exprNode_mergeUSs (ret, t);
7503 exprNode_checkUse (ret, t->sref, t->loc);
7505 /* evans 2001-10-05: while loop can break */
7506 ret->exitCode = exitkind_makeConditional (b->exitCode);
7508 DPRINTF (("Do while: %s",
7509 exitkind_unparse (ret->exitCode)));
7511 ret->canBreak = b->canBreak;
7513 /* Always FALSE for doWhile loops - break's when test is false */
7514 ret->mustBreak = FALSE; /* b->mustBreak; */
7518 context_exitDoWhileClause (t);
7520 ret->kind = XPR_DOWHILE;
7521 ret->edata = exprData_makePair (t, b);
7525 bool exprNode_loopMustExec (exprNode forPred)
7528 ** Returns true if it is obvious that the loop always executes at least once
7530 ** For now, we only identify the most obvious cases. Should be true anytime
7531 ** we can prove init => !test.
7534 if (exprNode_isDefined (forPred))
7536 exprNode init, test, inc;
7539 llassert (forPred->kind == XPR_FORPRED);
7541 edata = forPred->edata;
7542 init = exprData_getTripleInit (edata);
7543 test = exprData_getTripleTest (edata);
7544 inc = exprData_getTripleInc (edata);
7546 if (exprNode_isAssign (init))
7548 exprNode loopVar = exprData_getOpA (init->edata);
7549 exprNode loopInit = exprData_getOpB (init->edata);
7551 if (exprNode_isDefined (test) && test->kind == XPR_OP)
7553 exprNode testVar = exprData_getOpA (test->edata);
7554 exprNode testVal = exprData_getOpB (test->edata);
7555 lltok comp = exprData_getOpTok (test->edata);
7556 int opid = lltok_getTok (comp);
7558 DPRINTF (("Same storage: %s / %s", exprNode_unparse (loopVar),
7559 exprNode_unparse (testVar)));
7561 if (exprNode_sameStorage (loopVar, testVar))
7563 multiVal valinit = exprNode_getValue (loopInit);
7564 multiVal valtest = exprNode_getValue (testVal);
7566 DPRINTF (("Values: %s / %s", multiVal_unparse (valinit),
7567 multiVal_unparse (valtest)));
7569 if (multiVal_isInt (valinit) && multiVal_isInt (valtest))
7571 long v1 = multiVal_forceInt (valinit);
7572 long v2 = multiVal_forceInt (valtest);
7574 DPRINTF (("Here: %ld %ld", v1, v2));
7576 if ((opid == EQ_OP && v1 < v2)
7577 || (opid == NE_OP && v1 != v2)
7578 || (opid == TLT && v1 <= v2)
7579 || (opid == TGT && v1 >= v2)
7580 || (opid == LE_OP && v1 < v2)
7581 || (opid == GE_OP && v1 > v2))
7583 DPRINTF (("mustexec if inc"));
7592 DPRINTF (("loop must exec: FALSE"));
7596 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7599 bool emptyErr = FALSE;
7601 if (context_maybeSet (FLG_FOREMPTY))
7603 if (exprNode_isEmptyStatement (body))
7605 emptyErr = optgenerror
7608 ("Body of for statement is empty"),
7609 exprNode_loc (body));
7613 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7615 if (exprNode_isDefined (body)
7616 && !exprNode_isBlock (body))
7618 if (context_inIterDef ()
7619 && (body->kind == XPR_STMTLIST
7620 || body->kind == XPR_TOK))
7626 voptgenerror (FLG_FORBLOCK,
7628 ("Body of for statement is not a block: %s",
7629 exprNode_unparse (body)),
7630 exprNode_loc (body));
7636 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7639 if (exprNode_isError (body))
7641 ret = exprNode_createPartialCopy (inc);
7645 ret = exprNode_createPartialCopy (body);
7647 ret->exitCode = exitkind_makeConditional (body->exitCode);
7649 exprNode_mergeUSs (inc, body);
7651 if (exprNode_isDefined (inc))
7655 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7657 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7658 exprNode_freeShallow (tmp);
7660 context_clearMessageAnnote ();
7661 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7663 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7664 exprNode_freeShallow (tmp);
7666 context_clearMessageAnnote ();
7668 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7669 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7670 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7674 ret->kind = XPR_FOR;
7675 ret->edata = exprData_makePair (inc, body);
7677 if (exprNode_isDefined (inc)) {
7678 exprNode test = exprData_getTripleTest (inc->edata);
7680 if (exprNode_isUndefined (test)) {
7681 if (exprNode_isDefined (body)) {
7682 if (!body->canBreak) {
7683 /* Really, it means never reached. */
7684 ret->exitCode = XK_MUSTEXIT;
7694 ** for (init; test; inc)
7697 ** while (test) { body; inc; }
7699 ** Now: check use of init (may set vars for test)
7700 ** check use of test
7704 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7708 if (exprNode_isError (pred)) return guardSet_undefined;
7710 llassert (pred->kind == XPR_FORPRED);
7712 test = exprData_getTripleTest (pred->edata);
7714 if (!exprNode_isError (test))
7716 return (test->guards);
7719 return guardSet_undefined;
7722 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7724 exprNode ret = exprNode_createSemiCopy (test);
7726 if (exprNode_isDefined (test))
7728 exprNode_copySets (ret, test);
7729 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7730 exprNode_checkUse (ret, test->sref, test->loc);
7732 exprNode_produceGuards (test);
7734 ret->guards = guardSet_copy (test->guards);
7737 ret->edata = exprData_makeSingle (test);
7738 ret->kind = XPR_WHILEPRED;
7742 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7743 /*@only@*/ exprNode inc)
7748 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7751 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7753 if (!exprNode_isError (inc))
7755 ret = exprNode_createPartialCopy (inc);
7759 if (!exprNode_isError (init))
7761 ret = exprNode_createPartialCopy (init);
7763 else if (!exprNode_isError (test))
7765 ret = exprNode_createPartialCopy (test);
7769 ret = exprNode_createUnknown ();
7773 exprNode_mergeUSs (ret, init);
7775 if (exprNode_isDefined (init))
7777 exprNode_checkUse (ret, init->sref, init->loc);
7780 exprNode_mergeUSs (ret, test);
7782 if (exprNode_isDefined (test))
7784 exprNode_checkUse (ret, test->sref, test->loc);
7787 ret->kind = XPR_FORPRED;
7788 ret->edata = exprData_makeFor (init, test, inc);
7792 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7794 exprNode ret = exprNode_createUnknown ();
7796 if (context_inMacro ())
7798 voptgenerror (FLG_MACROSTMT,
7799 message ("Macro %s uses goto (not functional)",
7800 context_inFunctionName ()),
7804 ret->kind = XPR_GOTO;
7805 ret->edata = exprData_makeLiteral (label);
7806 ret->mustBreak = TRUE;
7807 ret->exitCode = XK_GOTO;
7808 ret->canBreak = TRUE;
7812 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7814 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7816 ret->kind = XPR_CONTINUE;
7817 ret->edata = exprData_makeTok (l);
7818 ret->canBreak = TRUE;
7819 ret->mustBreak = TRUE;
7821 if (qcontinue == QSAFEBREAK)
7825 else if (qcontinue == QINNERCONTINUE)
7827 if (!context_inDeepLoop ())
7830 (FLG_LOOPLOOPCONTINUE,
7831 cstring_makeLiteral ("Continue statement marked with innercontinue "
7832 "is not inside a nested loop"),
7833 exprNode_loc (ret));
7836 else if (qcontinue == BADTOK)
7838 if (context_inDeepLoop ())
7841 (FLG_LOOPLOOPCONTINUE,
7842 cstring_makeLiteral ("Continue statement in nested loop"),
7843 exprNode_loc (ret));
7848 llbuglit ("exprNode_continue: bad qcontinue");
7854 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
7856 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7857 clause breakClause = context_breakClause ();
7859 ret->kind = XPR_BREAK;
7860 ret->edata = exprData_makeTok (l);
7861 ret->canBreak = TRUE;
7862 ret->mustBreak = TRUE;
7864 if (breakClause == NOCLAUSE)
7868 cstring_makeLiteral ("Break not inside while, for or switch statement"),
7869 exprNode_loc (ret));
7873 if (bqual != BADTOK)
7880 if (breakClause == SWITCHCLAUSE)
7882 if (!context_inDeepSwitch ())
7884 voptgenerror (FLG_SYNTAX,
7886 ("Break preceded by innerbreak is not in a deep switch"),
7887 exprNode_loc (ret));
7892 if (!context_inDeepLoop ())
7894 voptgenerror (FLG_SYNTAX,
7896 ("Break preceded by innerbreak is not in a deep loop"),
7897 exprNode_loc (ret));
7902 if (breakClause == SWITCHCLAUSE)
7904 voptgenerror (FLG_SYNTAX,
7906 ("Break preceded by loopbreak is breaking a switch"),
7907 exprNode_loc (ret));
7911 if (breakClause != SWITCHCLAUSE)
7915 message ("Break preceded by switchbreak is breaking %s",
7916 cstring_makeLiteralTemp
7917 ((breakClause == WHILECLAUSE
7918 || breakClause == DOWHILECLAUSE) ? "a while loop"
7919 : (breakClause == FORCLAUSE) ? "a for loop"
7920 : (breakClause == ITERCLAUSE) ? "an iterator"
7922 exprNode_loc (ret));
7930 if (breakClause == SWITCHCLAUSE)
7932 clause nextBreakClause = context_nextBreakClause ();
7934 switch (nextBreakClause)
7936 case NOCLAUSE: break;
7942 (FLG_LOOPSWITCHBREAK,
7943 cstring_makeLiteral ("Break statement in switch inside loop"),
7944 exprNode_loc (ret));
7948 (FLG_SWITCHSWITCHBREAK,
7949 cstring_makeLiteral ("Break statement in switch inside switch"),
7950 exprNode_loc (ret));
7957 if (context_inDeepLoop ())
7961 cstring_makeLiteral ("Break statement in nested loop"),
7962 exprNode_loc (ret));
7966 if (context_inDeepLoopSwitch ())
7969 (FLG_SWITCHLOOPBREAK,
7970 cstring_makeLiteral ("Break statement in loop inside switch"),
7971 exprNode_loc (ret));
7981 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
7983 fileloc loc = lltok_getLoc (t);
7984 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
7986 context_returnFunction ();
7987 exprChecks_checkNullReturn (loc);
7989 ret->kind = XPR_NULLRETURN;
7990 ret->edata = exprData_makeTok (t);
7991 ret->exitCode = XK_MUSTRETURN;
7995 exprNode exprNode_return (/*@only@*/ exprNode e)
7999 if (exprNode_isError (e))
8001 ret = exprNode_createUnknown ();
8005 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
8007 exprNode_checkUse (ret, e->sref, e->loc);
8008 exprNode_checkReturn (e);
8011 context_returnFunction ();
8012 ret->kind = XPR_RETURN;
8013 ret->edata = exprData_makeSingle (e);
8014 ret->exitCode = XK_MUSTRETURN;
8019 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
8023 if (exprNode_isError (e1))
8025 if (exprNode_isError (e2))
8027 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
8031 ret = exprNode_createPartialCopy (e2);
8032 exprNode_checkUse (ret, e2->sref, e2->loc);
8033 ret->sref = e2->sref;
8038 ret = exprNode_createPartialCopy (e1);
8040 exprNode_checkUse (ret, e1->sref, e1->loc);
8042 if (!exprNode_isError (e2))
8044 exprNode_mergeUSs (ret, e2);
8045 exprNode_checkUse (ret, e2->sref, e2->loc);
8046 ret->sref = e2->sref;
8050 ret->kind = XPR_COMMA;
8051 ret->edata = exprData_makePair (e1, e2);
8053 if (exprNode_isDefined (e1))
8055 if (exprNode_isDefined (e2))
8059 if (exprNode_mustEscape (e1) || e1->mustBreak)
8063 message ("Second clause of comma expression is unreachable: %s",
8064 exprNode_unparse (e2)),
8068 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
8069 ret->mustBreak = e1->mustBreak || e2->mustBreak;
8070 ret->canBreak = e1->canBreak || e2->canBreak;
8074 if (exprNode_mustEscape (e1) || e1->mustBreak)
8078 message ("Second clause of comma expression is unreachable: %s",
8079 exprNode_unparse (e2)),
8083 ret->exitCode = e1->exitCode;
8084 ret->canBreak = e1->canBreak;
8089 if (exprNode_isDefined (e2))
8091 ret->exitCode = e2->exitCode;
8092 ret->mustBreak = e2->mustBreak;
8093 ret->canBreak = e2->canBreak;
8100 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
8102 ctype t1 = exprNode_getType (el);
8103 ctype t2 = exprNode_getType (val);
8104 bool hasError = FALSE;
8106 DPRINTF (("Check one init: %s / %s",
8107 exprNode_unparse (el),
8108 exprNode_unparse (val)));
8110 if (ctype_isUnknown (t1))
8112 voptgenerror (FLG_IMPTYPE,
8113 message ("Variable has unknown (implicitly int) type: %s",
8114 exprNode_unparse (el)),
8118 el->typ = ctype_int;
8121 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
8123 exprNodeList vals = exprData_getArgs (val->edata);
8125 DPRINTF (("Check one init: %s", exprNodeList_unparse (vals)));
8126 DPRINTF (("Type: %s", ctype_unparse (t1)));
8128 if (ctype_isRealAP (t1))
8133 if (ctype_isFixedArray (t1))
8135 int nelements = long_toInt (ctype_getArraySize (t1));
8137 DPRINTF (("Checked array: %s / %d",
8138 ctype_unparse (t1), nelements));
8140 if (exprNode_isStringLiteral (val))
8142 exprNode_checkStringLiteralLength (t1, val);
8146 if (exprNodeList_size (vals) != nelements)
8148 hasError = optgenerror
8149 (exprNodeList_size (vals) > nelements ? FLG_INITSIZE : FLG_INITALLELEMENTS,
8150 message ("Initializer block for "
8151 "%s has %d element%&, but declared as %s: %q",
8152 exprNode_unparse (el),
8153 exprNodeList_size (vals),
8155 exprNodeList_unparse (vals)),
8161 exprNodeList_elements (vals, oneval)
8163 cstring istring = message ("%d", i);
8166 (exprNode_fakeCopy (el),
8167 exprNode_numLiteral (ctype_int, istring,
8168 fileloc_copy (el->loc), i));
8170 if (exprNode_isDefined (newel))
8172 if (exprNodeList_size (vals) == 1
8173 && ctype_isString (exprNode_getType (oneval))
8174 && ctype_isChar (exprNode_getType (newel)))
8176 exprNode_freeIniter (newel);
8180 if (exprNode_checkOneInit (newel, oneval))
8185 if (nerrors > 3 && exprNodeList_size (vals) > 6)
8188 (message ("Additional initialization errors "
8189 "for %s not reported",
8190 exprNode_unparse (el)),
8192 exprNode_freeIniter (newel);
8197 exprNode_freeIniter (newel);
8202 exprNode_freeIniter (newel);
8207 cstring_free (istring);
8210 } end_exprNodeList_elements;
8213 else if (ctype_isStruct (ctype_realType (t1)))
8215 uentryList fields = ctype_getFields (t1);
8218 if (uentryList_size (fields) != exprNodeList_size (vals))
8220 if (uentryList_size (fields) > exprNodeList_size (vals))
8222 hasError = optgenerror
8224 message ("Initializer block for "
8225 "%s has %d field%&, but %s has %d field%&: %q",
8226 exprNode_unparse (el),
8227 exprNodeList_size (vals),
8229 uentryList_size (fields),
8230 exprNodeList_unparse (vals)),
8235 hasError = optgenerror
8237 message ("Initializer block for "
8238 "%s has %d field%&, but %s has %d field%&: %q",
8239 exprNode_unparse (el),
8240 exprNodeList_size (vals),
8242 uentryList_size (fields),
8243 exprNodeList_unparse (vals)),
8249 exprNodeList_elements (vals, oneval)
8251 uentry thisfield = uentryList_getN (fields, i);
8253 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8255 uentry_getName (thisfield));
8257 if (exprNode_isDefined (newel))
8259 if (exprNode_checkOneInit (newel, oneval))
8264 exprNode_freeIniter (newel);
8268 } end_exprNodeList_elements;
8271 /* evans 2001-12-30: added to fix bug reported by Jim Zelenka */
8272 else if (ctype_isUnion (ctype_realType (t1)))
8274 uentryList fields = ctype_getFields (t1);
8278 ** Union initializers set the first member always.
8281 DPRINTF (("Union initializer: %s / %s",
8282 exprNode_unparse (el), ctype_unparse (ctype_realType (t1))));
8284 if (exprNodeList_size (vals) != 1)
8286 hasError = optgenerror
8288 message ("Initializer block for union "
8289 "%s has %d elements, union initializers should have one element: %q",
8290 exprNode_unparse (el),
8291 exprNodeList_size (vals),
8292 exprNodeList_unparse (vals)),
8297 exprNode oneval = exprNodeList_head (vals);
8298 uentry thisfield = uentryList_getN (fields, i);
8300 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8302 uentry_getName (thisfield));
8304 if (exprNode_isDefined (newel))
8306 if (exprNode_checkOneInit (newel, oneval))
8311 exprNode_freeIniter (newel);
8317 hasError = optgenerror
8319 message ("Initializer block used for "
8320 "%s where %t is expected: %s",
8321 exprNode_unparse (el), t1, exprNode_unparse (val)),
8327 if (exprNode_isDefined (val))
8329 doAssign (el, val, TRUE);
8331 if (!exprNode_matchType (t1, val))
8333 hasError = gentypeerror
8335 message ("Initial value of %s is type %t, "
8337 exprNode_unparse (el),
8338 t2, t1, exprNode_unparse (val)),
8348 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
8352 DPRINTF (("Initialization: %s", idDecl_unparse (t)));
8354 if (usymtab_exists (idDecl_observeId (t)))
8356 uentry ue = usymtab_lookup (idDecl_observeId (t));
8357 ret = exprNode_createId (ue);
8359 /*@i723 don't do this...but why? */
8361 ct = ctype_realishType (ret->typ);
8363 DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
8365 if (ctype_isUnknown (ct))
8367 if (uentry_isAnyTag (ue))
8371 message ("%s used but not previously declared: %s",
8372 uentry_ekindName (ue),
8373 idDecl_getName (t)),
8381 message ("Variable has unknown (implicitly int) type: %s",
8382 idDecl_getName (t)),
8394 DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
8396 ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
8397 /*!! fileloc_copy (g_currentloc)); */
8398 /*@i32!!! should get error without this */
8400 ret = exprNode_fromIdentifierAux (ue);
8403 ** No error - this happens in old style declarations:
8407 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8414 exprData_free (ret->edata, ret->kind);
8415 ret->edata = exprData_undefined;
8417 ret->exitCode = XK_NEVERESCAPE;
8418 ret->mustBreak = FALSE;
8419 ret->kind = XPR_INIT;
8423 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8425 exprNode ret = exprNode_makeInitializationAux (t);
8426 llassert (ret->edata == exprData_undefined);
8427 ret->edata = exprData_makeInit (t, exprNode_undefined);
8431 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8432 /*@only@*/ exprNode e)
8434 uentry ue = usymtab_lookup (idDecl_observeId (t));
8435 exprNode ret = exprNode_makeInitializationAux (t);
8436 fileloc loc = exprNode_loc (e);
8438 if (exprNode_isError (e))
8440 e = exprNode_createUnknown ();
8443 /* error: assume initializer is defined */
8444 sRef_setDefined (ret->sref, g_currentloc);
8448 ctype ct = ctype_realishType (ret->typ);
8453 ** was addSafeUse --- what's the problem?
8455 ** int x = 3, y = x ?
8458 exprData_free (ret->edata, ret->kind);
8459 ret->edata = exprData_makeInit (t, e);
8461 exprNode_checkUse (ret, e->sref, e->loc);
8463 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8465 exprNode lhs = exprNode_createId (ue);
8468 ** static storage should be undefined before initializing
8471 if (uentry_isStatic (ue))
8473 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8476 (void) exprNode_checkOneInit (lhs, e);
8478 if (uentry_isStatic (ue))
8480 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8483 exprNode_free (lhs);
8487 if (!exprNode_matchType (ct, e))
8489 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
8496 (exprNode_getType (e), e, exprNode_getType (ret), ret,
8498 ("Variable %q initialized to type %t, expects %t: %s",
8499 uentry_getName (ue), exprNode_getType (e),
8500 exprNode_getType (ret),
8501 exprNode_unparse (e)),
8507 if (uentry_isStatic (ue))
8509 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8512 doAssign (ret, e, TRUE);
8514 if (uentry_isStatic (ue))
8516 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8520 if (context_inIterDef ())
8522 /* should check if it is yield */
8523 uentry_setUsed (ue, loc);
8530 exprNode_mergeUSs (ret, e);
8534 exprNode exprNode_iter (/*@observer@*/ uentry name,
8535 /*@only@*/ exprNodeList alist,
8536 /*@only@*/ exprNode body,
8537 /*@observer@*/ uentry end)
8542 llassert (uentry_isValid (name));
8544 uentry_setUsed (name, exprNode_loc (body));
8546 ret = exprNode_createPartialCopy (body);
8547 iname = uentry_getName (name);
8549 if (uentry_isInvalid (end))
8551 llerror (FLG_ITERBALANCE,
8552 message ("Iter %s not balanced with end_%s", iname, iname));
8556 cstring ename = uentry_getName (end);
8558 if (!cstring_equalPrefixLit (ename, "end_"))
8560 llerror (FLG_ITERBALANCE, message ("Iter %s not balanced with end_%s: %s",
8561 iname, iname, ename));
8565 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8567 llerror (FLG_ITERBALANCE,
8568 message ("Iter %s not balanced with end_%s: %s",
8569 iname, iname, ename));
8573 cstring_free (ename);
8576 context_exitIterClause (body);
8578 ret->kind = XPR_ITER;
8579 ret->edata = exprData_makeIter (name, alist, body, end);
8581 if (uentry_isIter (name))
8583 (void) checkArgsReal (name, body,
8584 uentry_getParams (name), alist, TRUE, ret);
8587 cstring_free (iname);
8593 exprNode_iterNewId (/*@only@*/ cstring s)
8595 exprNode e = exprNode_new ();
8596 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8598 llassert (processingIterVars ());
8600 e->loc = context_getSaveLocation ();
8602 if (fileloc_isUndefined (e->loc))
8604 fileloc_free (e->loc);
8605 e->loc = fileloc_copy (g_currentloc);
8608 e->uses = sRefSet_new ();
8609 e->sets = sRefSet_new ();
8610 e->msets = sRefSet_new ();
8612 e->val = multiVal_unknown ();
8613 e->guards = guardSet_new ();
8615 e->isJumpPoint = FALSE;
8616 e->exitCode = XK_NEVERESCAPE;
8618 /*> missing fields, detected by splint <*/
8619 e->canBreak = FALSE;
8620 e->mustBreak = FALSE;
8621 e->etext = cstring_undefined;
8623 if (uentry_isYield (ue))
8625 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8626 fileloc_copy (e->loc),
8630 uue = usymtab_supEntrySrefReturn (uue);
8632 sr = uentry_getSref (uue);
8633 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8634 sr = uentry_getSref (uue);
8635 sRef_setDefined (sr, e->loc);
8637 e->typ = uentry_getType (uue);
8639 e->edata = exprData_makeId (uue);
8640 uentry_setUsed (uue, g_currentloc);
8646 sRef_setGlobalScope ();
8647 uue = uentry_makeVariableLoc (s, ctype_unknown);
8649 e->typ = ctype_unknown;
8650 e->edata = exprData_makeId (uue);
8652 uentry_setUsed (uue, e->loc);
8653 uentry_setHasNameError (uue);
8655 if (context_getFlag (FLG_REPEATUNRECOG))
8657 uentry_markOwned (uue);
8661 usymtab_supGlobalEntry (uue);
8664 sRef_clearGlobalScope ();
8666 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8673 exprNode_defineConstraints(e);
8678 exprNode_iterExpr (/*@returned@*/ exprNode e)
8680 if (!processingIterVars ())
8682 llcontbuglit ("checkIterParam: not in iter");
8686 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8689 if (exprNode_isDefined (e))
8691 if (fileloc_isDefined (e->loc))
8695 message ("Yield parameter is not simple identifier: %s",
8696 exprNode_unparse (e)),
8703 message ("Yield parameter is not simple identifier: %s",
8704 exprNode_unparse (e)),
8714 exprNode_iterId (/*@observer@*/ uentry c)
8718 llassert (processingIterVars ());
8720 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8723 if (uentry_isYield (ue))
8725 ctype ct = uentry_getType (ue);
8726 exprNode e = exprNode_createPlain (ct);
8727 cstring name = uentry_getName (c);
8728 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8730 uentry_setUsed (ue, g_currentloc);
8731 uentry_setHasNameError (ue);
8733 cstring_free (name);
8736 e->edata = exprData_makeId (le);
8737 e->loc = context_getSaveLocation ();
8738 e->sref = uentry_getSref (le);
8740 usymtab_supEntrySref (le);
8742 if (!context_inHeader ())
8746 message ("Yield parameter shadows local declaration: %q",
8747 uentry_getName (c)),
8748 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8750 uentry_showWhereDeclared (c);
8757 return (exprNode_fromIdentifierAux (c));
8760 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8762 exprNode ret = exprNode_create (ctype_unknown);
8764 ret->kind = XPR_ITERCALL;
8765 ret->edata = exprData_makeIterCall (name, alist);
8767 if (uentry_isIter (name))
8769 uentryList params = uentry_getParams (name);
8771 if (context_inIterDef ()
8772 && uentryList_size (params) == exprNodeList_size (alist))
8776 exprNodeList_elements (alist, arg)
8778 uentry parg = uentryList_getN (params, i);
8780 if (uentry_isYield (parg))
8782 uentry ue = exprNode_getUentry (arg);
8784 if (uentry_isValid (ue))
8791 } end_exprNodeList_elements;
8794 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8795 checkUnspecCall (ret, params, alist);
8801 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8803 if (exprNode_isDefined (e))
8806 if (e->sref == defref) /*@noaccess sRef@*/
8809 e->sref = sRef_makeUnknown ();
8810 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8821 return sRef_undefined;
8825 /*@observer@*/ cstring
8826 exprNode_unparseFirst (exprNode e)
8828 if (exprNode_isDefined (e))
8832 if (e->kind == XPR_STMTLIST
8833 || e->kind == XPR_COMMA || e->kind == XPR_COND)
8835 exprNode first = exprData_getPairA (e->edata);
8837 if (exprNode_isDefined (first))
8839 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8843 return (cstring_makeLiteralTemp ("..."));
8847 ret = cstring_elide (exprNode_unparse (e), 20);
8848 cstring_markOwned (ret);
8854 return cstring_makeLiteralTemp ("<error>");
8858 /*@observer@*/ cstring
8859 exprNode_unparse (/*@temp@*/ exprNode e)
8861 if (exprNode_isError (e))
8863 return cstring_makeLiteralTemp ("<error>");
8866 if (cstring_isDefined (e->etext))
8872 cstring ret = exprNode_doUnparse (e);
8874 /*@-modifies@*/ /* benevolent */
8881 /*@observer@*/ fileloc
8882 exprNode_loc (exprNode e)
8884 if (exprNode_isError (e))
8886 return (g_currentloc);
8895 ** executes exprNode e
8896 ** recursively rexecutes as though in original parse using
8897 ** information in e->edata
8900 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
8902 exprNodeList ret = exprNodeList_new ();
8904 exprNodeList_elements (e, current)
8906 exprNodeList_addh (ret, exprNode_effect (current));
8907 } end_exprNodeList_elements;
8912 static /*@only@*/ exprNode exprNode_effect (exprNode e)
8913 /*@globals internalState@*/
8915 bool innerEffect = inEffect;
8921 context_clearJustPopped ();
8923 if (exprNode_isError (e))
8925 ret = exprNode_undefined;
8930 ** Turn off expose and dependent transfer checking.
8931 ** Need to pass exposed internal nodes,
8932 ** [ copying would be a waste! ]
8933 ** [ Actually, I think I wasted a lot more time than its worth ]
8934 ** [ trying to do this. ]
8938 /*@-observertrans@*/
8939 /*@-dependenttrans@*/
8946 ret = exprNode_addParens (exprData_getUopTok (data),
8947 exprNode_effect (exprData_getUopNode (data)));
8950 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
8951 exprNode_effect (exprData_getOpB (data)),
8952 exprData_getOpTok (data));
8955 ret = exprNode_undefined;
8958 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
8959 exprNodeList_effect (exprData_getArgs (data)));
8972 cstring id = exprData_getId (data);
8973 uentry ue = usymtab_lookupSafe (id);
8975 ret = exprNode_fromIdentifierAux (ue);
8976 ret->loc = fileloc_update (ret->loc, e->loc);
8983 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
8984 exprNode_effect (exprData_getPairB (data)));
8987 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
8988 exprNode_effect (exprData_getOpB (data)),
8989 exprData_getOpTok (data));
8993 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
8994 exprData_getUopTok (data));
8997 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
8998 exprData_getUopTok (data));
9010 ret = exprNode_vaArg (exprData_getCastTok (data),
9011 exprNode_effect (exprData_getCastNode (data)),
9012 exprData_getCastType (data));
9016 ret = exprNode_cast (exprData_getCastTok (data),
9017 exprNode_effect (exprData_getCastNode (data)),
9018 exprData_getCastType (data));
9021 ret = exprNode_iterStart (exprData_getIterCallIter (data),
9023 (exprData_getIterCallArgs (data)));
9027 ret = exprNode_iter (exprData_getIterSname (data),
9028 exprNodeList_effect (exprData_getIterAlist (data)),
9029 exprNode_effect (exprData_getIterBody (data)),
9030 exprData_getIterEname (data));
9034 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
9035 exprNode_effect (exprData_getPairB (data)));
9039 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
9040 exprNode_effect (exprData_getTripleTest (data)),
9041 exprNode_effect (exprData_getTripleInc (data)));
9045 ret = exprNode_createTok (exprData_getTok (data));
9049 ret = exprNode_goto (exprData_getLiteral (data));
9050 ret->loc = fileloc_update (ret->loc, e->loc);
9054 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
9058 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
9062 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
9065 case XPR_NULLRETURN:
9066 ret = exprNode_nullReturn (exprData_getTok (data));
9070 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
9071 exprNode_effect (exprData_getPairB (data)));
9075 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
9076 exprNode_effect (exprData_getTripleTrue (data)),
9077 exprNode_effect (exprData_getTripleFalse (data)));
9080 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
9081 exprNode_effect (exprData_getPairB (data)));
9085 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
9086 exprNode_effect (exprData_getTripleTrue (data)),
9087 exprNode_effect (exprData_getTripleFalse (data)));
9090 ret = exprNode_whilePred (exprData_getSingle (data));
9094 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
9095 exprNode_effect (exprData_getPairB (data)));
9099 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
9100 exprNode_effect (exprData_getPairB (data)));
9104 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
9108 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
9109 exprData_getUopTok (data));
9113 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
9114 exprNode_effect (exprData_getPairB (data)));
9119 ret = exprNode_caseMarker
9120 (exprNode_effect (exprData_getSingle (data)),
9126 ret = exprNode_createTok (exprData_getTok (data));
9130 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
9131 exprNode_effect (exprData_getPairB (data)));
9135 ret = exprNode_makeInitialization
9136 (exprData_getInitId (data),
9137 exprNode_effect (exprData_getInitNode (data)));
9141 ret = exprNode_fieldAccessAux
9142 (exprNode_effect (exprData_getFieldNode (data)),
9143 exprNode_loc (exprData_getFieldNode (data)),
9144 cstring_copy (exprData_getFieldName (data)));
9148 ret = exprNode_arrowAccessAux
9149 (exprNode_effect (exprData_getFieldNode (data)),
9150 exprNode_loc (exprData_getFieldNode (data)),
9151 cstring_copy (exprData_getFieldName (data)));
9154 case XPR_STRINGLITERAL:
9168 /*@=observertrans@*/
9170 /*@=dependenttrans@*/
9181 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
9186 if (exprNode_isError (e))
9188 return cstring_undefined;
9196 ret = exprNode_rootVarName (exprData_getUopNode (data));
9199 ret = exprNode_rootVarName (exprData_getOpA (data));
9203 ret = exprData_getId (data);
9206 ret = idDecl_getName (exprData_getInitId (data));
9231 case XPR_NULLRETURN:
9253 case XPR_STRINGLITERAL:
9254 ret = cstring_undefined;
9261 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
9266 if (exprNode_isError (e))
9268 static /*@only@*/ cstring error = cstring_undefined;
9270 if (!cstring_isDefined (error))
9272 error = cstring_makeLiteral ("<error>");
9283 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
9286 ret = message ("%s %s %s",
9287 exprNode_unparse (exprData_getOpA (data)),
9288 lltok_unparse (exprData_getOpTok (data)),
9289 exprNode_unparse (exprData_getOpB (data)));
9292 ret = message ("%s(%q)",
9293 exprNode_unparse (exprData_getFcn (data)),
9294 exprNodeList_unparse (exprData_getArgs (data)));
9297 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
9300 ret = cstring_undefined;
9303 ret = message ("%s:", exprData_getId (data));
9307 ret = cstring_copy (exprData_getId (data));
9310 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
9311 exprNode_unparse (exprData_getPairB (data)));
9314 ret = message ("<body>");
9317 ret = message ("%s %s %s",
9318 exprNode_unparse (exprData_getOpA (data)),
9319 lltok_unparse (exprData_getOpTok (data)),
9320 exprNode_unparse (exprData_getOpB (data)));
9324 ret = message ("%s%s",
9325 lltok_unparse (exprData_getUopTok (data)),
9326 exprNode_unparse (exprData_getUopNode (data)));
9330 ret = message ("%s%s",
9331 exprNode_unparse (exprData_getUopNode (data)),
9332 lltok_unparse (exprData_getUopTok (data)));
9336 ret = message ("offsetof(%s,%q)",
9337 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
9338 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
9342 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9346 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
9350 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9354 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
9358 ret = message ("va_arg(%s, %q)",
9359 exprNode_unparse (exprData_getCastNode (data)),
9360 qtype_unparse (exprData_getCastType (data)));
9364 ret = message ("%q(%q)",
9365 uentry_getName (exprData_getIterCallIter (data)),
9366 exprNodeList_unparse (exprData_getIterCallArgs (data)));
9369 ret = message ("%q(%q) %s %q",
9370 uentry_getName (exprData_getIterSname (data)),
9371 exprNodeList_unparse (exprData_getIterAlist (data)),
9372 exprNode_unparse (exprData_getIterBody (data)),
9373 uentry_getName (exprData_getIterEname (data)));
9376 ret = message ("(%q)%s",
9377 qtype_unparse (exprData_getCastType (data)),
9378 exprNode_unparse (exprData_getCastNode (data)));
9382 ret = message ("%s %s",
9383 exprNode_unparse (exprData_getPairA (data)),
9384 exprNode_unparse (exprData_getPairB (data)));
9388 ret = message ("for (%s; %s; %s)",
9389 exprNode_unparse (exprData_getTripleInit (data)),
9390 exprNode_unparse (exprData_getTripleTest (data)),
9391 exprNode_unparse (exprData_getTripleInc (data)));
9395 ret = message ("goto %s", exprData_getLiteral (data));
9399 ret = cstring_makeLiteral ("continue");
9403 ret = cstring_makeLiteral ("break");
9407 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
9410 case XPR_NULLRETURN:
9411 ret = cstring_makeLiteral ("return");
9415 ret = message ("%s, %s",
9416 exprNode_unparse (exprData_getPairA (data)),
9417 exprNode_unparse (exprData_getPairB (data)));
9421 ret = message ("%s ? %s : %s",
9422 exprNode_unparse (exprData_getTriplePred (data)),
9423 exprNode_unparse (exprData_getTripleTrue (data)),
9424 exprNode_unparse (exprData_getTripleFalse (data)));
9427 ret = message ("if (%s) %s",
9428 exprNode_unparse (exprData_getPairA (data)),
9429 exprNode_unparse (exprData_getPairB (data)));
9433 ret = message ("if (%s) %s else %s",
9434 exprNode_unparse (exprData_getTriplePred (data)),
9435 exprNode_unparse (exprData_getTripleTrue (data)),
9436 exprNode_unparse (exprData_getTripleFalse (data)));
9439 ret = message ("while (%s) %s",
9440 exprNode_unparse (exprData_getPairA (data)),
9441 exprNode_unparse (exprData_getPairB (data)));
9445 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9449 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9453 ret = message ("do { %s } while (%s)",
9454 exprNode_unparse (exprData_getPairB (data)),
9455 exprNode_unparse (exprData_getPairA (data)));
9459 ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
9463 ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
9467 ret = message ("%s; %s",
9468 exprNode_unparse (exprData_getPairA (data)),
9469 exprNode_unparse (exprData_getPairB (data)));
9474 ret = cstring_makeLiteral ("default:");
9478 ret = message ("switch (%s) %s",
9479 exprNode_unparse (exprData_getPairA (data)),
9480 exprNode_unparse (exprData_getPairB (data)));
9485 ret = message ("case %s:",
9486 exprNode_unparse (exprData_getSingle (data)));
9490 if (exprNode_isError (exprData_getInitNode (data)))
9492 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9496 ret = message ("%q = %s",
9497 idDecl_unparseC (exprData_getInitId (data)),
9498 exprNode_unparse (exprData_getInitNode (data)));
9503 ret = message ("%s.%s",
9504 exprNode_unparse (exprData_getFieldNode (data)),
9505 exprData_getFieldName (data));
9509 ret = message ("%s->%s",
9510 exprNode_unparse (exprData_getFieldNode (data)),
9511 exprData_getFieldName (data));
9514 case XPR_STRINGLITERAL:
9515 if (ctype_isWideString (e->typ))
9517 ret = message ("L\"%s\"", exprData_getLiteral (data));
9521 ret = message ("\"%s\"", exprData_getLiteral (data));
9526 ret = cstring_copy (exprData_getLiteral (data));
9530 ret = cstring_makeLiteral ("<node>");
9538 exprNode_isInitializer (exprNode e)
9540 return (exprNode_isDefined (e)
9541 && e->kind == XPR_INIT);
9545 exprNode_isCharLit (exprNode e)
9547 if (exprNode_isDefined (e))
9549 return (multiVal_isChar (exprNode_getValue (e)));
9558 exprNode_isNumLit (exprNode e)
9560 if (exprNode_isDefined (e))
9562 return (multiVal_isInt (exprNode_getValue (e)));
9571 exprNode_isFalseConstant (exprNode e)
9573 if (exprNode_isDefined (e))
9575 cstring s = exprNode_rootVarName (e);
9577 if (cstring_equal (s, context_getFalseName ()))
9587 exprNode_matchLiteral (ctype expected, exprNode e)
9589 if (exprNode_isDefined (e))
9591 multiVal m = exprNode_getValue (e);
9593 if (multiVal_isDefined (m))
9595 if (multiVal_isInt (m))
9597 long int val = multiVal_forceInt (m);
9599 if (ctype_isDirectBool (ctype_realishType (expected)))
9603 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9611 if (ctype_isRealInt (expected))
9614 ** unsigned <- [ constant >= 0 is okay ]
9617 if (ctype_isUnsigned (expected))
9626 ** No checks on sizes of integers...maybe add
9630 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9631 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9632 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9634 if (context_getFlag (FLG_NUMLITERAL)
9635 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9641 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9645 else if (ctype_isChar (expected))
9649 else if (ctype_isArrayPtr (expected))
9652 ** evans 2001-10-14: We allow 0 to match any pointer, but only if the type matches or is void *.
9657 if (ctype_match (exprNode_getType (e), expected)
9658 || ctype_isVoidPointer (exprNode_getType (e)))
9668 else if (ctype_isAnyFloat (expected))
9670 return (context_getFlag (FLG_NUMLITERAL));
9677 else if (multiVal_isDouble (m))
9679 if (ctype_isAnyFloat (expected))
9684 else if (multiVal_isChar (m))
9686 char val = multiVal_forceChar (m);
9688 if (ctype_isChar (expected))
9690 if (ctype_isUnsigned (expected) && ((int)val) < 0)
9711 exprNode_matchType (ctype expected, exprNode e)
9715 if (!exprNode_isDefined (e)) return TRUE;
9717 actual = ctype_realishType (exprNode_getType (e));
9719 if (ctype_match (ctype_realishType (expected), actual))
9724 llassert (!exprNode_isError (e));
9725 return (exprNode_matchLiteral (expected, e));
9729 exprNode_matchTypes (exprNode e1, exprNode e2)
9734 if (!exprNode_isDefined (e1)) return TRUE;
9735 if (!exprNode_isDefined (e2)) return TRUE;
9738 ** realish type --- keep bools, bools
9741 t1 = ctype_realishType (exprNode_getType (e1));
9742 t2 = ctype_realishType (exprNode_getType (e2));
9744 if (ctype_match (t1, t2))
9749 DPRINTF (("Matching literal! %s %s %s %s",
9750 ctype_unparse (t1), exprNode_unparse (e2),
9751 ctype_unparse (t2), exprNode_unparse (e1)));
9753 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9761 exprNode_matchArgType (ctype ct, exprNode e)
9765 if (!exprNode_isDefined (e))
9770 et = ctype_realType (exprNode_getType (e));
9772 if (ctype_matchArg (ct, et)) return TRUE;
9774 llassert (!exprNode_isError (e));
9775 return (exprNode_matchLiteral (ct, e));
9778 static /*@only@*/ exprNodeSList
9779 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9781 if (exprNode_isDefined (e))
9783 if (e->kind == XPR_STMTLIST)
9785 return (exprNodeSList_append
9786 (exprNode_flatten (exprData_getPairA (e->edata)),
9787 exprNode_flatten (exprData_getPairB (e->edata))));
9789 else if (e->kind == XPR_BLOCK)
9791 return (exprNode_flatten (exprData_getSingle (e->edata)));
9795 return (exprNodeSList_singleton (e));
9799 return exprNodeSList_new ();
9802 static /*@exposed@*/ exprNode
9803 exprNode_lastStatement (/*@returned@*/ exprNode e)
9805 if (exprNode_isDefined (e))
9807 if (e->kind == XPR_STMTLIST)
9809 exprNode b = exprData_getPairB (e->edata);
9811 if (exprNode_isDefined (b))
9813 return exprNode_lastStatement (b);
9817 return exprNode_lastStatement (exprData_getPairA (e->edata));
9820 else if (e->kind == XPR_BLOCK)
9822 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
9830 return exprNode_undefined;
9833 static /*@exposed@*/ exprNode
9834 exprNode_firstStatement (/*@returned@*/ exprNode e)
9836 if (exprNode_isDefined (e))
9838 if (e->kind == XPR_STMTLIST)
9840 exprNode b = exprData_getPairA (e->edata);
9842 if (exprNode_isDefined (b))
9844 return exprNode_firstStatement (b);
9848 return exprNode_firstStatement (exprData_getPairB (e->edata));
9851 else if (e->kind == XPR_BLOCK)
9853 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
9861 return exprNode_undefined;
9865 exprNode_mergeUSs (exprNode res, exprNode other)
9867 if (exprNode_isDefined (res) && exprNode_isDefined (other))
9869 res->msets = sRefSet_union (res->msets, other->msets);
9870 res->sets = sRefSet_union (res->sets, other->sets);
9871 res->uses = sRefSet_union (res->uses, other->uses);
9876 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
9878 if (exprNode_isDefined (res))
9880 if (exprNode_isDefined (other1))
9882 res->sets = sRefSet_union (res->sets, other1->sets);
9883 res->msets = sRefSet_union (res->msets, other1->msets);
9884 res->uses = sRefSet_union (res->uses, other1->uses);
9886 if (exprNode_isDefined (other2))
9888 res->sets = sRefSet_union (res->sets, other2->sets);
9889 res->msets = sRefSet_union (res->msets, other2->msets);
9890 res->uses = sRefSet_union (res->uses, other2->uses);
9898 ** Reports errors is s is not defined.
9902 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
9904 if (exprNode_isDefined (e))
9906 e->uses = sRefSet_insert (e->uses, s);
9911 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
9913 if (sRef_isKnown (s) && !sRef_isConst (s))
9916 ** need to check all outer types are useable
9919 DPRINTF (("Check use: %s / %s",
9920 exprNode_unparse (e), sRef_unparse (s)));
9922 exprNode_addUse (e, s);
9924 if (!context_inProtectVars ())
9927 ** only report the deepest error
9930 sRef errorRef = sRef_undefined;
9931 sRef lastRef = sRef_undefined;
9932 bool deadRef = FALSE;
9933 bool unuseable = FALSE;
9934 bool errorMaybe = FALSE;
9936 while (sRef_isValid (s) && sRef_isKnown (s))
9938 ynm readable = sRef_isValidLvalue (s);
9940 DPRINTF (("Readable: %s / %s",
9941 sRef_unparseFull (s), ynm_unparse (readable)));
9943 if (!(ynm_toBoolStrict (readable)))
9945 if (ynm_isMaybe (readable))
9949 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
9950 deadRef = sRef_isPossiblyDead (errorRef);
9951 unuseable = sRef_isUnuseable (errorRef);
9958 deadRef = sRef_isDead (errorRef);
9959 unuseable = sRef_isUnuseable (errorRef);
9963 if (!sRef_isPartial (s))
9965 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
9966 sRef_setDefined (s, fileloc_undefined);
9970 s = sRef_getBaseSafe (s);
9973 if (sRef_isValid (errorRef))
9975 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
9976 && sRef_isPointer (errorRef))
9983 if (sRef_isThroughArrayFetch (errorRef))
9986 (FLG_STRICTUSERELEASED,
9987 message ("%q %q may be used after being released",
9988 sRef_unparseKindNamePlain (errorRef),
9989 sRef_unparse (errorRef)),
9992 sRef_showRefKilled (errorRef);
9994 if (sRef_isKept (errorRef))
9996 sRef_clearAliasState (errorRef, loc);
10002 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
10006 message ("%q %q %qused after being released",
10007 sRef_unparseKindNamePlain (errorRef),
10008 sRef_unparse (errorRef),
10009 cstring_makeLiteral (errorMaybe
10010 ? "may be " : "")),
10013 sRef_showRefKilled (errorRef);
10015 if (sRef_isKept (errorRef))
10017 sRef_clearAliasState (errorRef, loc);
10022 else if (unuseable)
10026 message ("%q %q%qused in inconsistent state",
10027 sRef_unparseKindName (errorRef),
10028 sRef_unparseOpt (errorRef),
10029 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10032 sRef_showStateInconsistent (errorRef);
10037 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
10041 message ("%q %q%qused before definition",
10042 sRef_unparseKindName (errorRef),
10043 sRef_unparseOpt (errorRef),
10044 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10047 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
10050 sRef_setDefined (errorRef, loc);
10052 if (sRef_isAddress (errorRef))
10054 sRef_setDefined (sRef_getRootBase (errorRef), loc);
10056 } /* end is error */
10064 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
10066 if (exprNode_isDefined (e) && sRef_isKnown (s))
10068 e->uses = sRefSet_insert (e->uses, s);
10073 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
10075 if (exprNode_isDefined (e))
10077 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
10082 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
10084 sRef defines = sRef_undefined;
10086 if (sRef_isValid (s) && !sRef_isNothing (s))
10088 uentry ue = sRef_getBaseUentry (s);
10090 if (uentry_isValid (ue))
10092 uentry_setLset (ue);
10095 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10097 voptgenerror (FLG_USEDEF,
10098 message ("Attempt to set unuseable storage: %q",
10103 if (sRef_isMeaningful (s))
10105 if (sRef_isDead (s))
10107 sRef base = sRef_getBaseSafe (s);
10109 if (sRef_isValid (base)
10110 && sRef_isDead (base))
10112 sRef_setPartial (s, exprNode_loc (e));
10115 defines = s; /* okay - modifies for only param */
10117 else if (sRef_isPartial (s))
10119 sRef eref = exprNode_getSref (e);
10121 if (!sRef_isPartial (eref))
10124 ** should do something different here???
10127 sRef_setDefinedComplete (eref, exprNode_loc (e));
10131 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
10134 if (sRef_isMeaningful (eref))
10143 else if (sRef_isAllocated (s))
10145 sRef eref = exprNode_getSref (e);
10148 if (!sRef_isAllocated (eref))
10150 sRef_setDefinedComplete (eref, exprNode_loc (e));
10154 sRef base = sRef_getBaseSafe (eref);
10156 if (sRef_isValid (base))
10158 sRef_setPdefined (base, exprNode_loc (e));
10166 sRef_setDefinedNCComplete (s, exprNode_loc (e));
10171 else /* not meaningful...but still need to insert it */
10177 if (exprNode_isDefined (e) && sRef_isValid (defines))
10179 e->sets = sRefSet_insert (e->sets, defines);
10184 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
10186 if (sRef_isValid (s) && !sRef_isNothing (s))
10188 uentry ue = sRef_getBaseUentry (s);
10190 if (uentry_isValid (ue))
10192 uentry_setLset (ue);
10195 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10197 voptgenerror (FLG_USEDEF,
10198 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
10202 if (sRef_isMeaningful (s))
10204 sRef_setDefinedComplete (s, exprNode_loc (e));
10207 if (exprNode_isDefined (e))
10209 e->msets = sRefSet_insert (e->msets, s);
10215 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
10217 checkAnyCall (fcn, cstring_undefined, params, args,
10218 FALSE, sRefSet_undefined, FALSE, 0);
10222 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
10223 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
10227 if (uentry_isYield (ucurrent))
10229 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
10230 exprNode_checkSet (current, current->sref);
10234 if (uentry_isSefParam (ucurrent))
10236 sRefSet sets = current->sets;
10237 sRef ref = exprNode_getSref (current);
10239 if (sRef_isMacroParamRef (ref))
10241 uentry ue = sRef_getUentry (ref);
10243 if (!uentry_isSefParam (ue))
10248 ("Parameter %d to %s is declared sef, but "
10249 "the argument is a macro parameter declared "
10251 argno, exprNode_unparse (fcn),
10252 exprNode_unparse (current)),
10253 exprNode_loc (current));
10257 if (!sRefSet_isEmpty (sets))
10259 sRefSet reported = sRefSet_undefined;
10261 sRefSet_realElements (current->sets, el)
10263 if (sRefSet_isSameNameMember (reported, el))
10265 ; /* don't report again */
10269 if (sRef_isUnconstrained (el))
10274 ("Parameter %d to %s is declared sef, but "
10275 "the argument calls unconstrained function %s "
10276 "(no guarantee it will not modify something): %s",
10277 argno, exprNode_unparse (fcn),
10278 sRef_unconstrainedName (el),
10279 exprNode_unparse (current)),
10280 exprNode_loc (current));
10287 ("Parameter %d to %s is declared sef, but "
10288 "the argument may modify %q: %s",
10289 argno, exprNode_unparse (fcn),
10291 exprNode_unparse (current)),
10292 exprNode_loc (current));
10295 } end_sRefSet_realElements;
10299 transferChecks_passParam (current, ucurrent, isSpec, fcn, argno, totargs);
10300 exprNode_mergeUSs (fcn, current);
10305 checkAnyCall (/*@dependent@*/ exprNode fcn,
10306 /*@dependent@*/ cstring fname,
10309 bool hasMods, sRefSet mods,
10314 int nargs = exprNodeList_size (args);
10319 ** concat all args ud's to f, add each arg sref as a use unless
10320 ** it was specified as "out", in which case it is a def.
10323 uentryList_reset (pn);
10326 ** aliasing checks:
10328 ** if paramn is only or unique, no other arg may alias argn
10331 exprNodeList_elements (args, current)
10335 if (exprNode_isDefined (current))
10337 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
10339 uentry ucurrent = uentryList_current (pn);
10341 if (specialArgs == 0
10342 || (paramno < specialArgs))
10344 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
10346 if (context_maybeSet (FLG_ALIASUNIQUE))
10348 if (uentry_isOnly (ucurrent)
10349 || uentry_isUnique (ucurrent))
10351 checkUniqueParams (fcn, current, args,
10352 paramno, ucurrent);
10357 else /* uentry is undefined */
10359 if (specialArgs == 0)
10361 exprNode_checkUseParam (current);
10364 exprNode_mergeUSs (fcn, current);
10367 uentryList_advanceSafe (pn);
10368 } end_exprNodeList_elements;
10374 sRefSet_allElements (mods, s)
10377 sRef rb = sRef_getRootBase (s);
10379 if (sRef_isFileOrGlobalScope (rb))
10381 context_usedGlobal (rb);
10384 fb = sRef_fixBaseParam (s, args);
10386 if (!sRef_isMacroParamRef (fb))
10388 if (sRef_isNothing (fb))
10394 if (sRef_isValid (fb))
10396 uentry ue = sRef_getBaseUentry (s);
10398 if (uentry_isValid (ue))
10400 uentry_setLset (ue);
10404 fcn->sets = sRefSet_insert (fcn->sets, fb);
10407 sRef_clearDerivedComplete (s);
10408 } end_sRefSet_allElements;
10414 if (context_hasMods ())
10416 if (context_maybeSet (FLG_MODUNCON))
10420 message ("Undetected modification possible "
10421 "from call to unconstrained function %s: %s",
10423 exprNode_unparse (fcn)),
10424 exprNode_loc (fcn));
10429 if (context_maybeSet (FLG_MODUNCONNOMODS)
10430 && !(context_inIterDef () || context_inIterEnd ()))
10433 (FLG_MODUNCONNOMODS,
10434 message ("Undetected modification possible "
10435 "from call to unconstrained function %s: %s",
10437 exprNode_unparse (fcn)),
10438 exprNode_loc (fcn));
10442 exprNode_checkSetAny (fcn, fname);
10446 void exprNode_checkUseParam (exprNode current)
10448 if (exprNode_isDefined (current))
10450 exprNode_checkUse (current, current->sref, current->loc);
10455 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10456 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10461 if (!ctype_match (tr1, tr2))
10463 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10464 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10466 DPRINTF (("No error: [%s] %s / [%s] %s",
10467 exprNode_unparse (e1), ctype_unparse (tr1),
10468 exprNode_unparse (e2), ctype_unparse (tr2)));
10472 (void) gentypeerror
10474 message ("Incompatible types for %s (%s, %s): %s %s %s",
10475 lltok_unparse (op),
10476 ctype_unparse (te1),
10477 ctype_unparse (te2),
10478 exprNode_unparse (e1), lltok_unparse (op),
10479 exprNode_unparse (e2)),
10482 ret = ctype_unknown;
10486 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
10488 ret = ctype_resolveNumerics (tr1, tr2);
10490 else if (!context_msgStrictOps ())
10492 if (ctype_isPointer (tr1))
10494 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10498 else if (ctype_isInt (tr2))
10504 ret = ctype_unknown;
10507 else if (ctype_isPointer (tr2))
10509 if (ctype_isPointer (tr1))
10513 else if (ctype_isInt (tr1))
10519 ret = ctype_unknown;
10524 ret = ctype_resolveNumerics (tr1, tr2);
10529 int opid = lltok_getTok (op);
10530 bool comparop = (opid == EQ_OP || opid == NE_OP
10531 || opid == TLT || opid == TGT
10532 || opid == LE_OP || opid == GE_OP);
10534 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10537 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10538 || (ctype_isBool (tr1) && ctype_isBool (tr2))
10539 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10545 if (ctype_sameName (te1, te2))
10549 message ("Operands of %s are non-numeric (%t): %s %s %s",
10550 lltok_unparse (op), te1,
10551 exprNode_unparse (e1), lltok_unparse (op),
10552 exprNode_unparse (e2)),
10559 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10560 lltok_unparse (op), te1, te2,
10561 exprNode_unparse (e1), lltok_unparse (op),
10562 exprNode_unparse (e2)),
10567 else if (!ctype_isNumeric (tr1))
10571 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10572 lltok_unparse (op), te1,
10573 exprNode_unparse (e1), lltok_unparse (op),
10574 exprNode_unparse (e2)),
10579 if (!ctype_isNumeric (tr2))
10583 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10584 lltok_unparse (op), te2,
10585 exprNode_unparse (e1), lltok_unparse (op),
10586 exprNode_unparse (e2)),
10591 ret = ctype_unknown;
10599 abstractOpError (ctype tr1, ctype tr2, lltok op,
10600 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10601 fileloc loc1, fileloc loc2)
10603 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10605 if (ctype_match (tr1, tr2))
10609 message ("Operands of %s are abstract type (%t): %s %s %s",
10610 lltok_unparse (op), tr1,
10611 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10618 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10619 lltok_unparse (op), tr1, tr2,
10620 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10624 else if (ctype_isRealAbstract (tr1))
10628 message ("Left operand of %s is abstract type (%t): %s %s %s",
10629 lltok_unparse (op), tr1,
10630 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10635 if (ctype_isRealAbstract (tr2))
10639 message ("Right operand of %s is abstract type (%t): %s %s %s",
10640 lltok_unparse (op), tr2,
10641 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10650 ** requies e1 and e2 and not error exprNode's.
10654 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10655 ** the rep of the abstract type is exposed.
10657 ** The order is very important:
10659 ** check rep expose (move into check transfer)
10665 ** This isn't really a sensible procedure, but the indententation
10666 ** was getting too deep.
10670 checkOneRepExpose (sRef ysr, sRef base,
10671 /*@notnull@*/ exprNode e1,
10672 /*@notnull@*/ exprNode e2, ctype ct,
10675 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
10676 || sRef_isOwned (ysr)
10677 || sRef_isExposed (ysr)))
10679 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10680 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10683 if (sRef_isIReference (ysr))
10685 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10690 ("Assignment of mutable component of parameter %q "
10691 "to component of abstract "
10692 "type %s exposes rep: %s = %s",
10693 sRef_unparse (base),
10694 ctype_unparse (ct),
10695 exprNode_unparse (e1), exprNode_unparse (e2)),
10703 ("Assignment of mutable component of parameter %q "
10704 "(through alias %q) to component of abstract "
10705 "type %s exposes rep: %s = %s",
10706 sRef_unparse (base),
10707 sRef_unparse (e2->sref),
10708 ctype_unparse (ct),
10709 exprNode_unparse (e1), exprNode_unparse (e2)),
10715 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10719 message ("Assignment of mutable parameter %q "
10720 "to component of abstract type %s "
10721 "exposes rep: %s = %s",
10722 sRef_unparse (base),
10723 ctype_unparse (ct),
10724 exprNode_unparse (e1),
10725 exprNode_unparse (e2)),
10732 message ("Assignment of mutable parameter %q "
10733 "(through alias %q) to "
10734 "component of abstract type %s exposes "
10736 sRef_unparse (base),
10737 sRef_unparse (e2->sref),
10738 ctype_unparse (ct),
10739 exprNode_unparse (e1),
10740 exprNode_unparse (e2)),
10746 if (sRef_isFileOrGlobalScope (s2b))
10748 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10752 message ("Assignment of global %q "
10754 "abstract type %s exposes rep: %s = %s",
10755 sRef_unparse (base),
10756 ctype_unparse (ct),
10757 exprNode_unparse (e1), exprNode_unparse (e2)),
10764 message ("Assignment of global %q (through alias %q) "
10766 "abstract type %s exposes rep: %s = %s",
10767 sRef_unparse (base),
10768 sRef_unparse (e2->sref),
10769 ctype_unparse (ct),
10770 exprNode_unparse (e1), exprNode_unparse (e2)),
10778 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
10780 DPRINTF (("Do assign: %s <- %s",
10781 exprNode_unparse (e1), exprNode_unparse (e2)));
10782 DPRINTF (("Ctype: %s", ctype_unparse (exprNode_getType (e1))));
10784 if (ctype_isRealFunction (exprNode_getType (e1))
10785 && !ctype_isRealPointer (exprNode_getType (e1)))
10789 message ("Invalid left-hand side of assignment (function type %s): %s",
10790 ctype_unparse (exprNode_getType (e1)),
10791 exprNode_unparse (e1)),
10795 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
10797 ctype t2 = exprNode_getType (e2);
10798 sRef sr = sRef_getRootBase (e1->sref);
10799 ctype ct = sRef_getType (sr);
10801 if (ctype_isAbstract (t2)
10802 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
10804 /* it is immutable, okay to reference */
10805 goto donerepexpose;
10808 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
10810 sRef s2b = sRef_getRootBase (e2->sref);
10811 sRef s1 = e1->sref;
10812 sRef s1b = sRef_getRootBase (s1);
10815 aliases = usymtab_canAlias (e2->sref);
10817 if (!sRef_similar (s2b, s1b)
10818 && !sRef_isExposed (s1)
10819 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
10821 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
10822 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
10823 && !sRef_isExposed (s2b))
10825 if (sRef_isIReference (e2->sref))
10830 ("Assignment of mutable component of parameter %q "
10831 "to component of abstract type %s exposes rep: %s = %s",
10832 sRef_unparse (s2b),
10833 ctype_unparse (ct),
10834 exprNode_unparse (e1), exprNode_unparse (e2)),
10841 message ("Assignment of mutable parameter %q to "
10842 "component of abstract type %s exposes rep: %s = %s",
10843 sRef_unparse (s2b),
10844 ctype_unparse (ct),
10845 exprNode_unparse (e1), exprNode_unparse (e2)),
10850 if (sRef_isFileOrGlobalScope (s2b))
10854 message ("Assignment of global %q to component of "
10855 "abstract type %s exposes rep: %s = %s",
10856 sRef_unparse (s2b),
10857 ctype_unparse (ct),
10858 exprNode_unparse (e1), exprNode_unparse (e2)),
10862 sRefSet_realElements (aliases, ysr)
10864 sRef base = sRef_getRootBase (ysr);
10866 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
10867 || sRef_sameName (base, s1b))
10869 ; /* error already reported or same sref */
10873 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
10875 } end_sRefSet_realElements;
10877 sRefSet_free (aliases);
10884 ** function variables don't really work...
10887 if (!ctype_isFunction (ctype_realType (e2->typ)))
10891 DPRINTF (("Check init: %s / %s",
10892 exprNode_unparse (e1), exprNode_unparse (e2)));
10893 transferChecks_initialization (e1, e2);
10897 transferChecks_assign (e1, e2);
10902 sRef fref = e2->sref;
10904 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
10905 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
10907 /* Need to typecheck the annotation on the parameters */
10909 if (ctype_isRealFunction (e1->typ)) {
10910 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
10911 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
10913 if (!uentryList_isMissingParams (e1p)
10914 && !uentryList_isMissingParams (e2p)
10915 && uentryList_size (e1p) > 0) {
10916 if (uentryList_size (e1p) == uentryList_size (e2p)) {
10919 uentryList_elements (e1p, el1) {
10922 el2 = uentryList_getN (e2p, n);
10924 uentry_checkMatchParam (el1, el2, n, e2);
10925 } end_uentryList_elements;
10931 if (exprNode_isStringLiteral (e2))
10933 exprNode_checkStringLiteralLength (exprNode_getType (e1), e2);
10936 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
10942 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
10943 updateAliases (e1, e2);
10948 checkMacroParen (exprNode e)
10950 if (exprNode_isError (e) || e->kind == XPR_CAST)
10956 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
10960 message ("Macro parameter used without parentheses: %s",
10961 exprNode_unparse (e)),
10968 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
10972 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
10976 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
10983 ** if e2 is a parameter or global derived location which
10984 ** can be modified (that is, e2 is a mutable abstract type,
10985 ** or a derived pointer), then e1 can alias e2.
10987 ** e1 can alias everything which e2 can alias.
10989 ** Also, if e1 is guarded, remove from guard sets!
10992 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
10994 if (!context_inProtectVars ())
10997 ** depends on types of e1 and e2
11000 sRef s1 = e1->sref;
11001 sRef s2 = e2->sref;
11002 ctype t1 = exprNode_getType (e1);
11004 /* handle pointer sRefs, record fields, arrays, etc... */
11006 if (!ctype_isRealSU (t1))
11008 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
11009 sRef_copyRealDerivedComplete (s1, s2);
11014 ** Fields should alias
11017 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
11020 if (ctype_isMutable (t1) && sRef_isKnown (s1))
11022 usymtab_clearAlias (s1);
11023 usymtab_addMustAlias (s1, s2);
11024 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
11028 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
11031 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
11033 usymtab_unguard (s1);
11038 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
11040 if (exprNode_isDefined (e))
11042 e->loc = fileloc_update (e->loc, loc);
11046 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
11052 static void checkUniqueParams (exprNode fcn,
11053 /*@notnull@*/ exprNode current,
11055 int paramno, uentry ucurrent)
11058 sRef thisref = exprNode_getSref (current);
11061 ** Check if any argument could match this argument.
11064 exprNodeList_elements (args, icurrent)
11068 if (iparamno != paramno)
11070 sRef sr = exprNode_getSref (icurrent);
11072 if (sRef_similarRelaxed (thisref, sr))
11074 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
11079 ("Parameter %d (%s) to function %s is declared %s but "
11080 "is aliased by parameter %d (%s)",
11082 exprNode_unparse (current),
11083 exprNode_unparse (fcn),
11084 alkind_unparse (uentry_getAliasKind (ucurrent)),
11085 iparamno, exprNode_unparse (icurrent)),
11091 sRefSet aliases = usymtab_canAlias (sr);
11093 sRefSet_allElements (aliases, asr)
11095 if (ctype_isUnknown (sRef_getType (thisref)))
11097 sRef_setType (thisref, uentry_getType (ucurrent));
11100 if (sRef_similarRelaxed (thisref, asr))
11102 if (sRef_isExternal (asr))
11104 if (sRef_isLocalState (thisref))
11110 sRef base = sRef_getRootBase (asr);
11112 if (!sRef_similar (sRef_getBase (asr), thisref))
11114 if (sRef_isUnique (base) || sRef_isOnly (base)
11115 || sRef_isKept (base)
11116 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
11117 || (sRef_isAddress (thisref)
11118 && sRef_isLocalVar (sRef_getRootBase (thisref))))
11120 ; /* okay, no error */
11125 (FLG_MAYALIASUNIQUE,
11127 ("Parameter %d (%s) to function %s is declared %s but "
11128 "may be aliased externally by parameter %d (%s)",
11130 exprNode_unparse (current),
11131 exprNode_unparse (fcn),
11132 alkind_unparse (uentry_getAliasKind (ucurrent)),
11133 iparamno, exprNode_unparse (icurrent)),
11144 ("Parameter %d (%s) to function %s is declared %s but "
11145 "is aliased externally by parameter %d (%s) through "
11148 exprNode_unparse (current),
11149 exprNode_unparse (fcn),
11150 alkind_unparse (uentry_getAliasKind (ucurrent)),
11151 iparamno, exprNode_unparse (icurrent),
11152 sRef_unparse (asr)),
11156 } end_sRefSet_allElements;
11157 sRefSet_free (aliases);
11160 } end_exprNodeList_elements;
11163 long exprNode_getLongValue (exprNode e) {
11166 if (exprNode_hasValue (e)
11167 && multiVal_isInt (exprNode_getValue (e)))
11169 value = multiVal_forceInt (exprNode_getValue (e));
11180 /*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
11182 if (exprNode_isDefined (p_e) )
11183 return ( p_e->loc );
11185 return fileloc_undefined;
11188 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
11191 ** Returns the location of the sequence point following e.
11193 ** Only works for statements (for now).
11196 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
11197 lltok t = exprData_getUopTok (e->edata);
11198 return fileloc_copy(lltok_getLoc (t));
11200 /* drl possible problem : warning fix
11201 llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
11203 return fileloc_undefined;
11207 exprNode exprNode_createNew(ctype c)
11211 ret = exprNode_createPlain (c);
11216 bool exprNode_isInitBlock (exprNode e)
11218 return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);