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 lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://www.splint.org
28 # include <ctype.h> /* for isdigit */
29 # include "lclintMacros.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 lclint 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 lclint <*/
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))
1060 int nelements = long_toInt (ctype_getArraySize (t1));
1062 llassert (multiVal_isString (mval));
1063 slit = multiVal_forceString (mval);
1064 len = cstring_length (slit);
1066 if (len == nelements)
1069 (FLG_STRINGLITNOROOM,
1070 message ("String literal with %d character%& "
1071 "is assigned to %s (no room for null terminator): %s",
1072 cstring_length (slit),
1074 exprNode_unparse (e2)),
1077 else if (len > nelements)
1080 (FLG_STRINGLITTOOLONG,
1081 message ("Stirng literal with %d character%& (counting null terminator) "
1082 "is assigned to %s (insufficient storage available): %s",
1083 cstring_length (slit),
1085 exprNode_unparse (e2)),
1088 else if (len < nelements - 1)
1091 (FLG_STRINGLITSMALLER,
1092 message ("String literal with %d character%& is assigned to %s (possible waste of storage): %s",
1093 cstring_length (slit),
1095 exprNode_unparse (e2)),
1105 static /*@only@*/ /*@notnull@*/ exprNode
1106 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
1108 exprNode e = exprNode_createId (c);
1111 uentry_setUsed (c, e->loc);
1113 if (uentry_isVar (c) && sRef_isFileOrGlobalScope (sr))
1115 checkGlobUse (c, FALSE, e);
1122 exprNode_isZero (exprNode e)
1124 if (exprNode_isDefined (e))
1126 multiVal m = exprNode_getValue (e);
1128 if (multiVal_isInt (m))
1130 return (multiVal_forceInt (m) == 0);
1138 exprNode_isNonNegative (exprNode e)
1140 if (exprNode_isDefined (e))
1142 multiVal m = exprNode_getValue (e);
1144 if (multiVal_isInt (m))
1146 return (multiVal_forceInt (m) >= 0);
1150 ** This is not always true if programmer defines enum
1151 ** values, but then the constant should be known.
1154 if (ctype_isEnum (ctype_realType (e->typ)))
1164 ** a[x] - uses a but NOT a[]
1165 ** result sref = a[] (set/use in assignment)
1167 ** The syntax x[a] is also legal in C, and has the same
1168 ** semantics. If ind is an array, and arr is an int, flip
1173 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
1176 ** error in arr, error propagates (no new messages)
1177 ** error in ind, assume valid and continue
1180 DPRINTF (("Array fetch: %s / %s",
1181 exprNode_unparse (e1), exprNode_unparse (e2)));
1183 if (exprNode_isError (e1))
1186 return (exprNode_makeError ());
1192 ctype carr = exprNode_getType (e1);
1193 ctype crarr = ctype_realType (carr);
1196 ** this sets up funny aliasing, that leads to spurious
1197 ** lclint errors. Hence, the i2 comments.
1200 /* evans 2001-09-09 added ctype_isKnown so there is no swap when e1 type is unknown */
1201 if (ctype_isKnown (crarr)
1202 && !ctype_isRealArray (crarr)
1203 && ctype_isRealNumeric (crarr)
1204 && !exprNode_isError (e2)
1205 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1210 carr = exprNode_getType (arr);
1211 crarr = ctype_realType (carr);
1219 DPRINTF (("arr: %s", exprNode_unparse (arr)));
1221 if (sRef_possiblyNull (arr->sref))
1223 if (!usymtab_isGuarded (arr->sref))
1225 if (optgenerror (FLG_NULLDEREF,
1226 message ("Index of %s pointer %q: %s",
1227 sRef_nullMessage (arr->sref),
1228 sRef_unparse (arr->sref),
1229 exprNode_unparse (arr)),
1232 DPRINTF (("ref: %s", sRef_unparseFull (arr->sref)));
1233 sRef_showNullInfo (arr->sref);
1235 /* suppress future messages */
1236 sRef_setNullError (arr->sref);
1241 if (exprNode_isError (ind))
1243 if ((ctype_isArrayPtr (crarr)
1244 && !ctype_isFunction (crarr))
1245 || ctype_isUnknown (carr))
1247 exprNode ret = exprNode_createPartialCopy (arr);
1249 if (ctype_isKnown (carr))
1251 ret->typ = ctype_baseArrayPtr (crarr);
1255 ret->typ = ctype_unknown;
1258 ret->sref = sRef_makeArrayFetch (arr->sref);
1260 ret->kind = XPR_FETCH;
1263 ** Because of funny aliasing (when arr and ind are
1264 ** flipped) spurious errors would be reported here.
1267 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1268 checkSafeUse (ret, arr->sref);
1273 voptgenerror (FLG_TYPE,
1274 message ("Array fetch from non-array (%t): %s[%s]", carr,
1275 exprNode_unparse (e1), exprNode_unparse (e2)),
1277 exprNode_free (arr);
1278 return (exprNode_makeError ());
1283 if (!ctype_isForceRealInt (&(ind->typ)))
1285 ctype rt = ctype_realType (ind->typ);
1287 if (ctype_isChar (rt))
1291 message ("Array fetch using non-integer, %t: %s[%s]",
1293 exprNode_unparse (e1), exprNode_unparse (e2)),
1296 else if (ctype_isEnum (rt))
1300 message ("Array fetch using non-integer, %t: %s[%s]",
1302 exprNode_unparse (e1), exprNode_unparse (e2)),
1309 message ("Array fetch using non-integer, %t: %s[%s]",
1311 exprNode_unparse (e1), exprNode_unparse (e2)),
1315 multiVal_free (ind->val);
1316 ind->val = multiVal_unknown ();
1319 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1321 exprNode ret = exprNode_createSemiCopy (arr);
1322 multiVal m = exprNode_getValue (ind);
1324 ret->typ = ctype_baseArrayPtr (crarr);
1325 ret->kind = XPR_FETCH;
1327 if (multiVal_isInt (m))
1329 int i = (int) multiVal_forceInt (m);
1331 if (sRef_isValid (arr->sref)) {
1332 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1334 ret->sref = sRef_undefined;
1339 ret->sref = sRef_makeArrayFetch (arr->sref);
1342 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1343 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1344 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1346 /* (see comment on spurious errors above) */
1347 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1349 exprNode_checkUse (ret, ind->sref, ind->loc);
1350 exprNode_checkUse (ret, arr->sref, arr->loc);
1356 if (ctype_isUnknown (carr))
1358 exprNode ret = exprNode_createPartialCopy (arr);
1360 ret->kind = XPR_FETCH;
1361 ret->typ = ctype_unknown;
1362 ret->sets = sRefSet_union (ret->sets, ind->sets);
1363 ret->msets = sRefSet_union (ret->msets, ind->msets);
1364 ret->uses = sRefSet_union (ret->uses, ind->uses);
1366 /* (see comment on spurious errors above) */
1367 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1369 exprNode_checkUse (ret, ind->sref, ind->loc);
1370 exprNode_checkUse (ret, arr->sref, arr->loc);
1377 message ("Array fetch from non-array (%t): %s[%s]", carr,
1378 exprNode_unparse (e1), exprNode_unparse (e2)),
1381 exprNode_free (arr);
1382 exprNode_free (ind);
1384 return (exprNode_makeError ());
1394 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1395 exprNodeList args, exprNode ret)
1397 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1401 ** checkPrintfArgs --- checks arguments for printf-like functions
1402 ** Arguments before ... have already been checked.
1403 ** The argument before the ... is a char *.
1404 ** argno is the format string argument.
1408 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1409 exprNodeList args, exprNode ret, int argno)
1412 ** the last argument before the elips is the format string
1417 int nargs = exprNodeList_size (args);
1418 uentryList params = uentry_getParams (fcn);
1422 ** These should be ensured by checkSpecialFunction
1425 llassert (uentryList_size (params) == argno + 1);
1426 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1428 a = exprNodeList_getN (args, argno - 1);
1429 formatloc = fileloc_copy (exprNode_loc (a));
1431 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1432 && exprNode_knownStringValue (a))
1434 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1435 char *code = format;
1438 nargs = exprNodeList_size (args);
1440 while ((code = strchr (code, '%')) != NULL)
1442 char *origcode = code;
1443 cstring codetext = cstring_newEmpty ();
1444 char key = *(++code);
1445 ctype modtype = ctype_int;
1446 bool modified = FALSE;
1448 fileloc_addColumn (formatloc, code - ocode);
1450 codetext = cstring_appendChar (codetext, key);
1453 while (isFlagKey (key))
1456 codetext = cstring_appendChar (codetext, key);
1457 fileloc_incColumn (formatloc);
1460 if (key == 'm') /* skipped in syslog */
1465 /* ignore field width */
1466 while (isdigit ((int) key) != 0)
1469 codetext = cstring_appendChar (codetext, key);
1470 fileloc_incColumn (formatloc);
1473 /* ignore precision */
1477 codetext = cstring_appendChar (codetext, key);
1478 fileloc_incColumn (formatloc);
1481 ** In printf, '*' means: read the next arg as an int for the
1482 ** field width. This seems to be missing from my copy of the
1483 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1484 ** later) but never does.
1489 ; /* don't do anything --- handle later */
1493 while (isdigit ((int) key) != 0)
1496 codetext = cstring_appendChar (codetext, key);
1497 fileloc_incColumn (formatloc);
1504 modtype = ctype_sint; /* short */
1506 codetext = cstring_appendChar (codetext, key);
1507 fileloc_incColumn (formatloc);
1509 else if (key == 'l' || key == 'L')
1511 modtype = ctype_lint; /* long */
1513 codetext = cstring_appendChar (codetext, key);
1514 fileloc_incColumn (formatloc);
1516 if (key == 'l' || key == 'L') {
1517 modtype = ctype_llint; /* long long */
1519 codetext = cstring_appendChar (codetext, key);
1520 fileloc_incColumn (formatloc);
1528 /* now, key = type of conversion to apply */
1530 fileloc_incColumn (formatloc);
1538 message ("No argument corresponding to %q format "
1539 "code %d (%%%s): \"%s\"",
1540 uentry_getName (fcn),
1542 cstring_fromChars (format)),
1545 if (fileloc_isDefined (formatloc)
1546 && context_getFlag (FLG_SHOWCOL))
1548 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1556 a = exprNodeList_getN (args, i);
1559 if (!exprNode_isError (a))
1565 case '*': /* int argument for fieldwidth */
1566 expecttype = ctype_int;
1567 *(--code) = '%'; /* convert it for next code */
1568 fileloc_subColumn (formatloc, 1);
1569 /*@switchbreak@*/ break;
1572 expecttype = ctype_combine (ctype_uint, modtype);
1573 /*@switchbreak@*/ break;
1575 case 'i': /* int argument */
1577 expecttype = ctype_combine (ctype_int, modtype);
1578 /*@switchbreak@*/ break;
1580 case 'x': /* unsigned int */
1582 expecttype = ctype_combine (ctype_uint, modtype);
1584 /*@switchbreak@*/ break;
1590 case 'f': /* double */
1591 expecttype = ctype_combine (ctype_double, modtype);
1592 /*@switchbreak@*/ break;
1594 case 'c': /* int converted to char (check its a char?) */
1595 expecttype = ctype_makeConj (ctype_int,
1596 ctype_makeConj (ctype_char,
1599 /* evans 2001-10-05 - changed to reflect correct ISO spec:
1600 int converted to char */
1602 /* expecttype = ctype_makeConj (ctype_char, ctype_uchar); */
1603 /*@switchbreak@*/ break;
1605 case 's': /* string */
1606 expecttype = ctype_string;
1607 /*@switchbreak@*/ break;
1610 while (((key = *(++code)) != ']')
1613 codetext = cstring_appendChar (codetext, key);
1614 fileloc_incColumn (formatloc);
1620 (message ("Bad character set format: %s",
1621 cstring_fromChars (origcode)));
1624 expecttype = ctype_string;
1625 /*@switchbreak@*/ break;
1627 case 'p': /* pointer */
1628 expecttype = ctype_makePointer (ctype_void);
1629 uentry_setDefState (regArg, SS_RELDEF); /* need not be defined */
1630 sRef_setPosNull (uentry_getSref (regArg), fileloc_undefined); /* could be null */
1631 /*@switchbreak@*/ break;
1633 case 'n': /* pointer to int, modified by call! */
1634 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1636 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1637 /*@switchbreak@*/ break;
1639 case 'm': /* in a syslog, it doesn't consume an argument */
1640 /* should check we're really doing syslog */
1642 /*@switchbreak@*/ break;
1646 expecttype = ctype_unknown;
1650 message ("Unrecognized format code: %s",
1651 cstring_fromChars (origcode)),
1652 fileloc_isDefined (formatloc)
1653 ? formatloc : g_currentloc);
1655 /*@switchbreak@*/ break;
1658 if (!(exprNode_matchArgType (expecttype, a)))
1660 if (ctype_isVoidPointer (expecttype)
1661 && ctype_isRealAbstract (a->typ)
1662 && (context_getFlag (FLG_ABSTVOIDP)))
1668 if (llgenformattypeerror
1669 (expecttype, exprNode_undefined,
1671 message ("Format argument %d to %q (%%%s) expects "
1674 uentry_getName (fcn),
1677 a->typ, exprNode_unparse (a)),
1680 if (fileloc_isDefined (formatloc)
1681 && context_getFlag (FLG_SHOWCOL))
1684 (cstring_makeLiteral
1685 ("Corresponding format code"),
1692 uentry_setType (regArg, expecttype);
1693 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1695 if (ctype_equal (expecttype, ctype_string))
1697 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1700 uentry_setType (regArg, ctype_unknown);
1701 uentry_fixupSref (regArg);
1705 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1716 cstring_free (codetext);
1721 voptgenerror (FLG_TYPE,
1722 message ("Format string for %q has %d arg%&, given %d",
1723 uentry_getName (fcn), i - argno, nargs - argno),
1729 /* no checking possible for compile-time unknown format strings */
1730 if (exprNode_isDefined (a))
1734 message ("Format string parameter to %s is not a compile-time constant: %s",
1735 exprNode_unparse (f),
1736 exprNode_unparse (a)),
1741 fileloc_free (formatloc);
1745 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1746 exprNodeList args, exprNode ret, int argno)
1750 int nargs = exprNodeList_size (args);
1751 uentryList params = uentry_getParams (fcn);
1755 ** These should be ensured by checkSpecialFunction
1758 llassert (uentryList_size (params) == argno + 1);
1759 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1761 a = exprNodeList_getN (args, argno - 1);
1762 formatloc = fileloc_copy (exprNode_loc (a));
1764 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1765 && exprNode_knownStringValue (a))
1767 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1768 char *code = format;
1771 nargs = exprNodeList_size (args);
1773 while ((code = strchr (code, '%')) != NULL)
1775 char *origcode = code;
1776 char key = *(++code);
1777 cstring codetext = cstring_newEmpty ();
1778 ctype modtype = ctype_int;
1779 char modifier = '\0';
1780 bool modified = TRUE;
1781 bool ignore = FALSE;
1783 codetext = cstring_appendChar (codetext, key);
1784 fileloc_addColumn (formatloc, code - ocode);
1787 ** this is based on ANSI standard library description of fscanf
1788 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1791 /* '*' suppresses assignment (does not need match argument) */
1796 codetext = cstring_appendChar (codetext, key);
1799 fileloc_incColumn (formatloc);
1802 /* ignore field width */
1803 while (isdigit ((int) key) != 0)
1806 codetext = cstring_appendChar (codetext, key);
1807 fileloc_incColumn (formatloc);
1812 modtype = ctype_sint; /* short */
1814 codetext = cstring_appendChar (codetext, key);
1815 fileloc_incColumn (formatloc);
1817 else if (key == 'l' || key == 'L')
1819 modtype = ctype_lint; /* long */
1823 codetext = cstring_appendChar (codetext, key);
1825 fileloc_incColumn (formatloc);
1827 if (key == 'l' || key == 'L') {
1828 modtype = ctype_llint; /* long long */
1830 codetext = cstring_appendChar (codetext, key);
1831 fileloc_incColumn (formatloc);
1839 /* now, key = type of conversion to apply */
1841 fileloc_incColumn (formatloc);
1855 message ("No argument corresponding to %q format "
1856 "code %d (%%%s): \"%s\"",
1857 uentry_getName (fcn),
1859 cstring_fromChars (format)),
1862 if (fileloc_isDefined (formatloc)
1863 && context_getFlag (FLG_SHOWCOL))
1866 (cstring_makeLiteral ("Corresponding format code"),
1874 a = exprNodeList_getN (args, i);
1877 if (!exprNode_isError (a))
1883 case '*': /* int argument for fieldwidth */
1884 expecttype = ctype_makePointer (ctype_int);
1885 *(--code) = '%'; /* convert it for next code */
1886 fileloc_subColumn (formatloc, 1);
1887 /*@switchbreak@*/ break;
1890 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1891 /*@switchbreak@*/ break;
1896 case 'X': /* unsigned int */
1897 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1898 /*@switchbreak@*/ break;
1905 /* printf is double, scanf is float! */
1907 if (modifier == 'l')
1909 expecttype = ctype_makePointer (ctype_double);
1911 else if (modifier == 'L')
1913 expecttype = ctype_makePointer (ctype_ldouble);
1917 llassert (modifier == '\0');
1918 expecttype = ctype_makePointer (ctype_float);
1920 /*@switchbreak@*/ break;
1922 case 'c': /* int converted to char (check its a char?) */
1923 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1924 /*@switchbreak@*/ break;
1926 case 's': /* string */
1927 expecttype = ctype_string;
1928 /*@switchbreak@*/ break;
1932 while (((key = *(++code)) != ']')
1935 codetext = cstring_appendChar (codetext, key);
1936 fileloc_incColumn (formatloc);
1942 (message ("Bad character set format: %s",
1943 cstring_fromChars (origcode)));
1946 expecttype = ctype_string;
1947 /*@switchbreak@*/ break;
1950 case 'p': /* pointer */
1953 message ("Format code should not be used in scanf: %s",
1954 cstring_fromChars (origcode)),
1955 fileloc_isDefined (formatloc)
1956 ? formatloc : g_currentloc);
1958 expecttype = ctype_unknown;
1959 /*@switchbreak@*/ break;
1961 case 'n': /* pointer to int, modified by call! */
1962 expecttype = ctype_makePointer (ctype_int);
1963 /*@switchbreak@*/ break;
1966 expecttype = ctype_unknown;
1970 message ("Unrecognized format code: %s",
1971 cstring_fromChars (origcode)),
1972 fileloc_isDefined (formatloc)
1973 ? formatloc : g_currentloc);
1975 /*@switchbreak@*/ break;
1978 if (!(exprNode_matchArgType (expecttype, a)))
1980 if (ctype_isVoidPointer (expecttype)
1981 && ctype_isRealAbstract (a->typ)
1982 && (context_getFlag (FLG_ABSTVOIDP)))
1988 if (llgenformattypeerror
1989 (expecttype, exprNode_undefined,
1991 message ("Format argument %d to %q (%%%s) expects "
1994 uentry_getName (fcn),
1995 codetext, expecttype,
1996 a->typ, exprNode_unparse (a)),
1999 if (fileloc_isDefined (formatloc)
2000 && context_getFlag (FLG_SHOWCOL))
2003 (cstring_makeLiteral
2004 ("Corresponding format code"),
2011 uentry_setType (outArg, expecttype);
2012 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
2013 uentry_setType (outArg, ctype_unknown);
2014 uentry_fixupSref (outArg);
2018 exprNode_checkCallModifyVal (a->sref, args, f, ret);
2023 /* a->sref = defref; */
2030 cstring_free (codetext);
2035 voptgenerror (FLG_TYPE,
2036 message ("Format string for %q has %d arg%&, given %d",
2037 uentry_getName (fcn), i - argno, nargs - argno),
2043 /* no checking possible for compile-time unknown format strings */
2046 fileloc_free (formatloc);
2050 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
2053 /*@unused@*/ int argno)
2056 ** the last argument before the elips is the format string
2059 int nargs = exprNodeList_size (args);
2064 a = exprNodeList_getN (args, argno - 1);
2065 formatloc = fileloc_copy (exprNode_loc (a));
2067 if (ctype_isUnknown (cstringType)) {
2068 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
2070 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
2074 if (ctype_isUnknown (ctypeType)) {
2075 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
2077 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
2081 if (ctype_isUnknown (filelocType)) {
2082 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
2084 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
2088 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
2089 && exprNode_knownStringValue (a))
2091 cstring format = multiVal_forceString (exprNode_getValue (a));
2092 char *code = cstring_toCharsSafe (format);
2095 nargs = exprNodeList_size (args);
2097 while ((code = strchr (code, '%')) != NULL)
2099 char *origcode = code;
2100 char key = *(++code);
2101 cstring codetext = cstring_newEmpty ();
2102 bool isOnly = FALSE;
2104 codetext = cstring_appendChar (codetext, key);
2106 fileloc_addColumn (formatloc, code - ocode);
2108 while (key >= '0' && key <= '9')
2111 codetext = cstring_appendChar (codetext, key);
2112 fileloc_incColumn (formatloc);
2116 fileloc_incColumn (formatloc);
2120 if (key == '&') /* plural marker */
2129 message ("Message missing format arg %d (%%%s): \"%s\"",
2130 i + 1, codetext, format),
2136 a = exprNodeList_getN (args, i);
2140 if (!exprNode_isError (a))
2144 /*@-loopswitchbreak@*/
2150 expecttype = ctype_char; break;
2152 expecttype = cstringType; break;
2154 expecttype = cstringType; isOnly = TRUE; break;
2156 expecttype = cstringType; isOnly = TRUE; break;
2157 case 'd': expecttype = ctype_int; break;
2158 case 'u': expecttype = ctype_uint; break;
2159 case 'w': expecttype = ctype_ulint; break;
2160 case 'f': expecttype = ctype_float; break;
2161 case 'b': expecttype = ctype_bool; break;
2162 case 't': expecttype = ctypeType; break;
2163 case 'l': expecttype = filelocType; break;
2164 case '&': /* a wee bit of a hack methinks */
2165 expecttype = ctype_int;
2167 case 'r': expecttype = ctype_bool; break;
2169 expecttype = ctype_unknown;
2172 message ("Unrecognized format code: %s",
2173 cstring_fromChars (origcode)),
2174 fileloc_isDefined (formatloc)
2175 ? formatloc : g_currentloc);
2178 /*@=loopswitchbreak@*/
2180 if (!(exprNode_matchArgType (expecttype, a)))
2182 if (ctype_isVoidPointer (expecttype)
2183 && ctype_isRealAbstract (a->typ)
2184 && (context_getFlag (FLG_ABSTVOIDP)))
2190 if (llgenformattypeerror
2191 (expecttype, exprNode_undefined,
2193 message ("Format argument %d to %q (%%%s) expects "
2196 uentry_getName (fcn),
2197 codetext, expecttype,
2198 a->typ, exprNode_unparse (a)),
2201 if (fileloc_isDefined (formatloc)
2202 && context_getFlag (FLG_SHOWCOL))
2205 (cstring_makeLiteral
2206 ("Corresponding format code"),
2213 if (ctype_equal (expecttype, cstringType))
2217 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2218 uentry_fixupSref (csOnlyArg);
2222 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2223 uentry_fixupSref (csArg);
2228 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2229 uentry_fixupSref (regArg);
2235 cstring_free (codetext);
2240 voptgenerror (FLG_TYPE,
2241 message ("Format string for %q has %d arg%&, given %d",
2242 uentry_getName (fcn), i - argno, nargs -argno),
2248 /* no checking possible for compile-time unknown format strings */
2251 fileloc_free (formatloc);
2255 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2256 /*@notnull@*/ exprNode e2,
2262 bool hadUncon = FALSE;
2264 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
2265 sRefSet_hasUnconstrained (sets2))
2268 (FLG_EVALORDERUNCON,
2270 ("Expression may have undefined behavior (%q used in right operand "
2271 "may set global variable %q used in left operand): %s %s %s",
2272 sRefSet_unparseUnconstrained (sets2),
2273 sRef_unparse (sRef_getRootBase (e1->sref)),
2274 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2278 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
2279 sRefSet_hasUnconstrained (sets1))
2282 (FLG_EVALORDERUNCON,
2284 ("Expression has undefined behavior (%q used in left operand "
2285 "may set global variable %q used in right operand): %s %s %s",
2286 sRefSet_unparseUnconstrained (sets1),
2287 sRef_unparse (e2->sref),
2288 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2292 sRefSet_realElements (e1->uses, sr)
2294 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2299 ("Expression has undefined behavior (left operand uses %q, "
2300 "modified by right operand): %s %s %s",
2302 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2305 } end_sRefSet_realElements;
2307 sRefSet_realElements (sets1, sr)
2309 if (sRef_isMeaningful (sr))
2311 if (sRef_same (sr, e2->sref))
2316 ("Expression has undefined behavior (value of right operand "
2317 "modified by left operand): %s %s %s",
2318 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2321 else if (sRefSet_member (e2->uses, sr))
2326 ("Expression has undefined behavior (left operand modifies %q, "
2327 "used by right operand): %s %s %s",
2329 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2334 if (sRefSet_member (sets2, sr))
2336 if (sRef_isUnconstrained (sr))
2344 hadUncon = optgenerror
2345 (FLG_EVALORDERUNCON,
2347 ("Expression may have undefined behavior. Left operand "
2348 "calls %q; right operand calls %q. The unconstrained "
2349 "functions may modify global state used by "
2350 "the other operand): %s %s %s",
2351 sRefSet_unparseUnconstrained (sets1),
2352 sRefSet_unparseUnconstrained (sets2),
2353 exprNode_unparse (e1), lltok_unparse (op),
2354 exprNode_unparse (e2)),
2363 ("Expression has undefined behavior (both "
2364 "operands modify %q): %s %s %s",
2366 exprNode_unparse (e1),
2367 lltok_unparse (op), exprNode_unparse (e2)),
2373 } end_sRefSet_realElements;
2376 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2378 bool hasError = FALSE;
2380 if (exprNode_isError (e1) || exprNode_isError (e2))
2385 if (sRefSet_member (e2->sets, e1->sref))
2387 if (e2->kind == XPR_CALL)
2393 hasError = optgenerror
2395 message ("Expression has undefined behavior "
2396 "(value of left operand %s is modified "
2397 "by right operand %s): %s %s %s",
2398 exprNode_unparse (e1),
2399 exprNode_unparse (e2),
2400 exprNode_unparse (e1), lltok_unparse (op),
2401 exprNode_unparse (e2)),
2406 if (context_getFlag (FLG_EVALORDERUNCON))
2408 if (sRefSet_member (e2->msets, e1->sref))
2410 if (e2->kind == XPR_CALL)
2416 hasError = optgenerror
2419 ("Expression has undefined behavior (value of left "
2420 "operand may be modified by right operand): %s %s %s",
2421 exprNode_unparse (e1), lltok_unparse (op),
2422 exprNode_unparse (e2)),
2430 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2432 if (context_maybeSet (FLG_EVALORDERUNCON))
2434 checkExpressionDefinedAux (e1, e2, e1->msets,
2435 e2->msets, op, FLG_EVALORDERUNCON);
2440 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2443 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2444 exprNodeList args, bool isIter, exprNode ret)
2448 if (!exprNode_isError (f))
2450 if (!uentryList_isMissingParams (cl))
2452 int nargs = exprNodeList_size (args);
2453 int expectargs = uentryList_size (cl);
2457 if (expectargs == 0)
2465 message ("Iter %q invoked with %d args, "
2467 uentry_getName (fcn),
2475 message ("Function %s called with %d args, "
2477 exprNode_unparse (f), nargs),
2484 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2486 exprNodeList_reset (args);
2488 uentryList_elements (cl, current)
2490 ctype ct = uentry_getType (current);
2493 if (ctype_isElips (ct))
2496 ** do special checking for printf/scanf library functions
2498 ** this is kludgey code, just for handling the special case
2502 if (uentry_isPrintfLike (fcn))
2504 checkPrintfArgs (f, fcn, args, ret, i);
2507 else if (uentry_isScanfLike (fcn))
2509 checkScanfArgs (f, fcn, args, ret, i);
2512 else if (uentry_isMessageLike (fcn))
2514 checkMessageArgs (f, fcn, args, i);
2519 llassert (!uentry_isSpecialFunction (fcn));
2522 nargs = expectargs; /* avoid errors */
2527 if (i >= nargs) break;
2529 a = exprNodeList_current (args);
2530 exprNodeList_advance (args);
2534 if (exprNode_isError (a))
2541 probably necessary? I'm not sure about this one
2542 checkMacroParen (a);
2545 f->guards = guardSet_union (f->guards, a->guards);
2547 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2549 if (!(exprNode_matchArgType (ct, a)))
2551 DPRINTF (("Args mismatch!"));
2553 if (ctype_isVoidPointer (ct)
2554 && (ctype_isPointer (a->typ)
2555 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2560 ("Pointer to abstract type (%t) used "
2562 "(arg %d to %q): %s",
2564 uentry_getName (fcn),
2565 exprNode_unparse (a)),
2573 (ct, exprNode_undefined,
2576 ("Iter %q expects arg %d to "
2577 "be %t gets %t: %s",
2578 uentry_getName (fcn),
2579 i, ct, a->typ, exprNode_unparse (a)),
2590 ("Function %q expects arg %d to be %t gets %t: %s",
2591 uentry_getName (fcn),
2592 i, ct, a->typ, exprNode_unparse (a)),
2595 DPRINTF (("Types: %s / %s",
2597 ctype_unparse (a->typ)));
2601 ** Clear null marker for abstract types.
2602 ** (It is not revealed, so suppress future messages.)
2605 if (ctype_isAbstract (a->typ))
2607 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2614 } end_uentryList_elements ;
2617 if (expectargs != nargs) /* note: not != since we may have ... */
2619 if (ctype_isElips (last))
2623 message ("Function %s called with %d args, expects at least %d",
2624 exprNode_unparse (f),
2625 nargs, expectargs - 1),
2634 message ("Iter %q invoked with %d args, expects %d",
2635 uentry_getName (fcn), nargs, expectargs),
2642 message ("Function %s called with %d args, expects %d",
2643 exprNode_unparse (f),
2656 ** Check for undefined code sequences in function arguments:
2658 ** one parameter sets something used by another parameter
2659 ** one parameter sets something set by another parameter
2663 checkSequencingOne (exprNode f, exprNodeList args,
2664 /*@notnull@*/ exprNode el, int argno)
2667 ** Do second loop, iff +undefunspec
2671 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2673 for (checkloop = 0; checkloop < numloops; checkloop++)
2679 thissets = el->sets;
2683 llassert (checkloop == 1);
2684 thissets = el->msets;
2687 sRefSet_realElements (thissets, thisset)
2691 /*@access exprNodeList@*/
2692 for (j = 0; j < args->nelements; j++)
2694 exprNode jl = args->elements[j];
2695 int thisargno = j + 1;
2697 if (thisargno != argno && exprNode_isDefined (jl))
2699 sRefSet otheruses = jl->uses;
2701 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
2702 sRefSet_hasUnconstrained (thissets))
2705 (FLG_EVALORDERUNCON,
2708 ("%q used in argument %d may set "
2709 "global variable %q used by argument %d: %s(%q)",
2710 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2713 sRef_unparse (sRef_getRootBase (jl->sref)),
2715 exprNode_unparse (f), exprNodeList_unparse (args)),
2719 if (sRefSet_member (otheruses, thisset))
2721 if (sRef_isUnconstrained (thisset))
2724 (FLG_EVALORDERUNCON,
2726 ("Unconstrained functions used in arguments %d (%q) "
2727 "and %d (%s) may modify "
2728 "or use global state in undefined way: %s(%q)",
2730 sRefSet_unparseUnconstrainedPlain (otheruses),
2732 sRef_unconstrainedName (thisset),
2733 exprNode_unparse (f),
2734 exprNodeList_unparse (args)),
2742 ("Argument %d modifies %q, used by argument %d "
2743 "(order of evaluation of actual parameters is "
2744 "undefined): %s(%q)",
2745 argno, sRef_unparse (thisset), thisargno,
2746 exprNode_unparse (f), exprNodeList_unparse (args)),
2752 sRefSet othersets = jl->sets;
2754 if (sRefSet_member (othersets, thisset))
2756 if (sRef_isUnconstrained (thisset))
2759 (FLG_EVALORDERUNCON,
2761 ("Unconstrained functions used in "
2762 "arguments %d (%q) and %d (%s) may modify "
2763 "or use global state in undefined way: %s(%q)",
2765 sRefSet_unparseUnconstrainedPlain (othersets),
2767 sRef_unconstrainedName (thisset),
2768 exprNode_unparse (f), exprNodeList_unparse (args)),
2776 ("Argument %d modifies %q, set by argument %d (order of"
2777 " evaluation of actual parameters is undefined): %s(%q)",
2778 argno, sRef_unparse (thisset), thisargno,
2779 exprNode_unparse (f), exprNodeList_unparse (args)),
2786 /*@noaccess exprNodeList@*/
2787 } end_sRefSet_realElements;
2792 checkSequencing (exprNode f, exprNodeList args)
2794 if (exprNodeList_size (args) > 1)
2799 /*@access exprNodeList*/
2801 for (i = 0; i < args->nelements; i++)
2803 el = args->elements[i];
2805 if (!exprNode_isError (el))
2807 checkSequencingOne (f, args, el, i + 1);
2810 /*@noaccess exprNodeList*/
2815 ** requires le = exprNode_getUentry (f)
2819 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2820 uentry le, exprNodeList args,
2821 /*@notnull@*/ exprNode ret, int specialArgs)
2823 bool isSpec = FALSE;
2824 bool hasMods = FALSE;
2826 globSet usesGlobs = globSet_undefined;
2827 sRefSet mods = sRefSet_undefined;
2828 bool freshMods = FALSE;
2829 uentryList params = uentryList_undefined;
2831 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2834 ** check globals and modifies
2839 if (!uentry_isValid (le))
2841 ctype fr = ctype_realType (f->typ);
2843 if (ctype_isFunction (fr))
2845 params = ctype_argsFunction (fr);
2849 params = uentryList_missingParams;
2852 if (!context_getFlag (FLG_MODNOMODS)
2853 && !context_getFlag (FLG_GLOBUNSPEC))
2855 checkUnspecCall (f, params, args);
2861 fname = uentry_rawName (le);
2865 if (uentry_isFunction (le))
2867 params = uentry_getParams (le);
2868 mods = uentry_getMods (le);
2869 hasMods = uentry_hasMods (le);
2870 usesGlobs = uentry_getGlobs (le);
2871 isSpec = uentry_isSpecified (le);
2873 else /* not a function */
2875 ctype ct = ctype_realType (uentry_getType (le));
2877 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2878 ("checkModGlobs: uentry not a function: %s",
2879 uentry_unparse (le)));
2881 params = ctype_argsFunction (ct);
2882 return; /*@32 ! remove this? */
2891 globSet_allElements (usesGlobs, el)
2893 if (sRef_isValid (el))
2895 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2897 context_usedGlobal (el);
2898 exprNode_checkUse (f, el, f->loc);
2900 if (context_checkInternalUse ())
2902 if (!context_globAccess (el))
2904 if (sRef_isSystemState (el)
2905 && !context_getFlag (FLG_MODFILESYSTEM))
2914 ("Called procedure %s may access %q, but "
2915 "globals list does not include globals %s",
2916 exprNode_unparse (f),
2918 cstring_makeLiteralTemp (sRef_isInternalState (el)
2926 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2932 uentry gle = sRef_getUentry (el);
2933 sRef sr = sRef_updateSref (el);
2935 if (sRef_isUndefGlob (el))
2937 sRef_setDefined (sr, f->loc);
2938 exprNode_checkSet (f, sr);
2946 if (sRef_isAllocated (el))
2948 exprNode_checkSet (f, sr);
2952 if (sRef_isStateUndefined (sr))
2957 ("%s %q used by function undefined before call: %s",
2958 sRef_getScopeName (sr),
2960 exprNode_unparse (f)),
2962 sRef_setDefined (sr, f->loc);
2964 exprNode_checkUse (f, sr, f->loc);
2967 checkGlobUse (gle, TRUE, f);
2970 if (sRef_isKilledGlob (el))
2972 sRef_kill (sr, f->loc);
2973 context_usedGlobal (sr);
2977 } end_globSet_allElements;
2983 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
2985 sRefSet smods = sRefSet_undefined;
2988 ** NEED to check for modifies anything
2992 ** check each sRef that called function modifies (ml), is
2998 sRefSet_allElements (mods, s) /* s is something which may be modified */
3000 DPRINTF (("Check modify: %s", sRef_unparse (s)));
3002 if (sRef_isKindSpecial (s))
3004 if (sRef_isSpecInternalState (s))
3006 if (context_getFlag (FLG_MODINTERNALSTRICT))
3008 exprNode_checkCallModifyVal (s, args, f, ret);
3012 sRefSet mmods = context_modList ();
3014 sRefSet_allElements (mmods, el)
3016 if (sRef_isInternalState (el))
3018 sRef_setModified (el);
3020 } end_sRefSet_allElements ;
3025 exprNode_checkCallModifyVal (s, args, f, ret);
3030 sRef rb = sRef_getRootBase (s);
3032 if (sRef_isFileOrGlobalScope (rb))
3034 context_usedGlobal (rb);
3037 if (sRef_isFileStatic (s)
3038 && !fileId_equal (fileloc_fileId (f->loc),
3039 fileloc_fileId (uentry_whereDefined (le))))
3041 smods = sRefSet_insert (smods, s);
3045 exprNode_checkCallModifyVal (s, args, f, ret);
3048 } end_sRefSet_allElements;
3053 ** Static elements in modifies set can have nasty consequences.
3054 ** (I think...have not been able to reproduce a possible bug.)
3057 if (!sRefSet_isDefined (smods))
3059 mods = sRefSet_newCopy (mods);
3062 sRefSet_allElements (smods, el)
3064 bool res = sRefSet_delete (mods, el);
3067 } end_sRefSet_allElements;
3069 sRefSet_free (smods);
3074 else if (sRefSet_isDefined (mods))
3075 { /* just check observers */
3078 sRefSet_allElements (mods, s) /* s is something which may be modified */
3080 sRef rb = sRef_getRootBase (s);
3084 if (sRef_isParam (rb))
3086 sRef b = sRef_fixBaseParam (s, args);
3088 if (sRef_isObserver (b))
3090 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
3094 message ("Function call may modify observer%q: %s",
3095 sRef_unparsePreOpt (b), exprNode_unparse (e)),
3098 sRef_showExpInfo (b);
3102 } end_sRefSet_allElements;
3106 if (!hasMods) /* no specified modifications */
3108 if (context_getFlag (FLG_MODOBSERVERUNCON))
3110 exprNodeList_elements (args, e)
3112 if (exprNode_isDefined (e))
3114 sRef s = exprNode_getSref (e);
3116 if (sRef_isObserver (s)
3117 && ctype_isMutable (sRef_getType (s)))
3120 (FLG_MODOBSERVERUNCON,
3122 ("Call to unconstrained function %s may modify observer%q: %s",
3123 exprNode_unparse (f),
3124 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3127 sRef_showExpInfo (s);
3131 } end_exprNodeList_elements;
3136 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3138 ret->uses = sRefSet_union (ret->uses, f->uses);
3139 ret->sets = sRefSet_union (ret->sets, f->sets);
3140 ret->msets = sRefSet_union (ret->msets, f->msets);
3145 ** Spurious errors reported, because lclint can't tell
3146 ** mods must be fresh if freshMods is true.
3149 /*@i@*/ sRefSet_free (mods);
3155 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3157 if (uentry_isVar (glob))
3159 if (context_inFunctionLike ())
3161 sRef sr = uentry_getSref (glob);
3163 context_usedGlobal (sr);
3165 if (context_checkGlobUse (glob))
3167 if (!context_globAccess (sr))
3173 message ("Called procedure %s may access %s %q",
3174 exprNode_unparse (e),
3175 sRef_unparseScope (sr),
3176 uentry_getName (glob)),
3183 message ("Undocumented use of %s %s",
3184 sRef_unparseScope (sr),
3185 exprNode_unparse (e)),
3194 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3199 reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
3201 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3202 exprNode_unparse (f), exprNodeList_unparse (args),
3203 uentry_unparseFull (le),
3204 stateClauseList_unparse (uentry_getStateClauseList (le))));
3206 if (uentry_isValid (le) && uentry_isFunction (le))
3208 stateClauseList sclauses = uentry_getStateClauseList (le);
3210 if (stateClauseList_isDefined (sclauses))
3212 DPRINTF (("Reflect ensures: %s / %s / %s",
3213 uentry_unparse (le),
3214 exprNode_unparse (f), exprNodeList_unparse (args)));
3216 stateClauseList_elements (sclauses, cl)
3218 if (stateClause_hasEnsures (cl))
3220 /* Same in usymtab.c:1904 */
3221 if (stateClause_setsMetaState (cl))
3223 qual q = stateClause_getMetaQual (cl);
3224 annotationInfo ainfo = qual_getAnnotationInfo (q);
3225 metaStateInfo minfo = annotationInfo_getState (ainfo);
3226 cstring key = metaStateInfo_getName (minfo);
3227 int mvalue = annotationInfo_getValue (ainfo);
3229 sRefSet osrs = sRefSet_undefined;
3232 if (stateClause_isGlobal (cl))
3234 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3239 srs = stateClause_getRefs (cl);
3242 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3245 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3247 sRefSet_elements (srs, sel)
3251 if (sRef_isResult (sRef_getRootBase (sel)))
3253 s = exprNode_getSref (ret);
3257 s = sRef_fixBaseParam (sel, args);
3260 DPRINTF (("Reflecting state clause on: %s / %s",
3261 sRef_unparse (sel), sRef_unparse (s)));
3263 sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3264 } end_sRefSet_elements;
3266 sRefSet_free (osrs);
3270 sRefSet srs = stateClause_getRefs (cl);
3271 sRefModVal modf = stateClause_getEnsuresFunction (cl);
3272 int eparam = stateClause_getStateParameter (cl);
3274 DPRINTF (("Reflect after clause: %s / %s",
3275 stateClause_unparse (cl),
3276 sRefSet_unparse (srs)));
3278 sRefSet_elements (srs, sel)
3282 DPRINTF (("elements: %s", sRef_unparse (sel)));
3283 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3285 if (sRef_isResult (sRef_getRootBase (sel)))
3287 DPRINTF (("Fix base: %s / %s",
3288 sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
3289 s = sRef_fixBase (sel, exprNode_getSref (ret));
3290 DPRINTF (("==> %s", sRef_unparseFull (s)));
3294 s = sRef_fixBaseParam (sel, args);
3297 DPRINTF (("elements: %s", sRef_unparse (s)));
3298 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3300 DPRINTF (("Reflecting state clause on: %s / %s",
3301 sRef_unparseFull (sel), sRef_unparseFull (s)));
3303 /* evans 2001-08-24 - added aliasSetCompleteParam */
3304 sRef_aliasSetCompleteParam (modf, s, eparam, exprNode_loc (f));
3306 DPRINTF (("After reflecting state clause on: %s / %s",
3307 sRef_unparseFull (sel), sRef_unparseFull (s)));
3308 } end_sRefSet_elements;
3311 } end_stateClauseList_elements ;
3314 DPRINTF (("Here: %s / %s",
3315 uentry_unparseFull (le),
3316 bool_unparse (uentry_hasMetaStateEnsures (le))));
3318 if (uentry_hasMetaStateEnsures (le))
3320 fileloc loc = exprNode_loc (f);
3322 metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3324 metaStateConstraintList_elements (mscl, msc)
3326 metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3327 metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3328 metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
3329 cstring key = metaStateInfo_getName (msinfo);
3330 sRef mlsr = metaStateSpecifier_getSref (msspec);
3332 sRef lastref = sRef_undefined;
3333 stateValue sval = stateValue_undefined;
3335 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3336 metaStateConstraint_unparse (msc)));
3337 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3339 if (sRef_isResult (sRef_getRootBase (mlsr)))
3341 s = exprNode_getSref (ret);
3345 s = sRef_fixBaseParam (mlsr, args);
3348 DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3350 while (metaStateExpression_isDefined (msexpr))
3352 metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
3353 metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
3356 DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3358 if (metaStateExpression_isMerge (msexpr))
3360 msexpr = metaStateExpression_getRest (msexpr);
3364 msexpr = metaStateExpression_undefined;
3367 if (metaStateInfo_isDefined (msi))
3369 /* Must match lhs state */
3370 llassert (metaStateInfo_equal (msinfo, msi));
3373 if (metaStateSpecifier_isElipsis (ms))
3376 ** For elipsis, we need to merge all the relevant elipsis parameters
3380 uentryList params = uentry_getParams (le);
3381 int paramno = uentryList_size (params) - 1;
3383 if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
3387 message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3388 uentry_getName (le)),
3389 uentry_whereLast (le));
3390 /*@innerbreak@*/ break;
3393 while (paramno < exprNodeList_size (args))
3395 exprNode arg = exprNodeList_getN (args, paramno);
3396 fs = exprNode_getSref (arg);
3397 DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3399 /* cut and pasted... gack*/
3400 if (stateValue_isDefined (sval))
3402 /* Use combination table to merge old state value with new one: */
3403 stateValue tval = sRef_getMetaStateValue (fs, key);
3405 if (stateValue_isDefined (tval))
3407 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3408 cstring msg = cstring_undefined;
3409 int nval = stateCombinationTable_lookup (sctable,
3410 stateValue_getValue (sval),
3411 stateValue_getValue (tval),
3413 DPRINTF (("Combining: %s + %s -> %d",
3414 stateValue_unparseValue (sval, msinfo),
3415 stateValue_unparseValue (tval, msinfo),
3418 if (nval == stateValue_error)
3423 ("Attributes merged in ensures clause in states that "
3424 "cannot be combined (%q is %q, %q is %q)%q",
3425 sRef_unparse (lastref),
3426 stateValue_unparseValue (sval, msinfo),
3428 stateValue_unparseValue (tval, msinfo),
3429 cstring_isDefined (msg) ?
3430 message (": %s", msg) : cstring_undefined),
3433 sRef_showMetaStateInfo (fs, key);
3437 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3438 loc = exprNode_loc (arg);
3442 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3447 sval = sRef_getMetaStateValue (fs, key);
3452 if (stateValue_isError (sval))
3454 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3463 msr = metaStateSpecifier_getSref (ms);
3466 llassert (sRef_isParam (sRef_getRootBase (msr)));
3467 fs = sRef_fixBaseParam (msr, args);
3469 if (stateValue_isDefined (sval))
3471 /* Use combination table to merge old state value with new one: */
3472 stateValue tval = sRef_getMetaStateValue (fs, key);
3474 if (stateValue_isDefined (tval))
3476 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3477 cstring msg = cstring_undefined;
3478 int nval = stateCombinationTable_lookup (sctable,
3479 stateValue_getValue (sval),
3480 stateValue_getValue (tval),
3482 DPRINTF (("Combining: %s + %s -> %d",
3483 stateValue_unparseValue (sval, msinfo),
3484 stateValue_unparseValue (tval, msinfo),
3487 if (nval == stateValue_error)
3492 ("Attributes merged in ensures clause in states that "
3493 "cannot be combined (%q is %q, %q is %q)%q",
3494 sRef_unparse (lastref),
3495 stateValue_unparseValue (sval, msinfo),
3497 stateValue_unparseValue (tval, msinfo),
3498 cstring_isDefined (msg)
3499 ? message (": %s", msg) : cstring_undefined),
3502 sRef_showMetaStateInfo (fs, key);
3506 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3510 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3515 sval = sRef_getMetaStateValue (fs, key);
3520 if (stateValue_isError (sval))
3522 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3527 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3529 if (stateValue_isDefined (sval))
3531 sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
3535 DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
3537 } end_metaStateConstraintList_elements ;
3539 metaStateConstraintList_free (mscl);
3545 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3547 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3548 exprNode_unparse (f), exprNodeList_unparse (args),
3549 uentry_unparseFull (le),
3550 stateClauseList_unparse (uentry_getStateClauseList (le))));
3552 if (uentry_isValid (le) && uentry_isFunction (le))
3554 stateClauseList sclauses = uentry_getStateClauseList (le);
3556 if (stateClauseList_isDefined (sclauses))
3558 DPRINTF (("Check requires: %s / %s / %s",
3559 uentry_unparse (le),
3560 exprNode_unparse (f), exprNodeList_unparse (args)));
3562 stateClauseList_elements (sclauses, cl)
3564 DPRINTF (("Check clause: %s / %s",
3565 stateClause_unparse (cl),
3566 bool_unparse (stateClause_hasRequires (cl))));
3568 if (stateClause_hasRequires (cl))
3570 sRefSet osrs = sRefSet_undefined;
3573 if (stateClause_isGlobal (cl))
3575 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3580 srs = stateClause_getRefs (cl);
3583 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3585 if (stateClause_setsMetaState (cl))
3587 qual q = stateClause_getMetaQual (cl);
3588 annotationInfo ainfo = qual_getAnnotationInfo (q);
3589 metaStateInfo minfo = annotationInfo_getState (ainfo);
3590 cstring key = metaStateInfo_getName (minfo);
3591 int mvalue = annotationInfo_getValue (ainfo);
3593 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3595 sRefSet_elements (srs, sel)
3597 sRef s = sRef_fixBaseParam (sel, args);
3599 if (sRef_isResult (sRef_getRootBase (sel)))
3605 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3606 sRef_unparseFull (sel), sRef_unparseFull (s),
3609 if (!sRef_checkMetaStateValue (s, key, mvalue))
3611 DPRINTF (("HERE: %s", sRef_unparse (s)));
3615 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3616 uentry_getName (le),
3617 sRef_isGlobalMarker (s)
3619 : message (" by %q", sRef_unparse (s)),
3620 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3622 stateClause_unparse (cl)),
3625 sRef_showAliasInfo (s);
3629 DPRINTF (("Error supressed!"));
3630 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3631 DPRINTF (("Context supress: %s",
3632 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3636 } end_sRefSet_elements;
3640 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3641 int eparam = stateClause_getStateParameter (cl);
3643 DPRINTF (("Reflect after clause: %s / %s",
3644 stateClause_unparse (cl),
3645 sRefSet_unparse (srs)));
3647 sRefSet_elements (srs, sel)
3651 DPRINTF (("elements: %s", sRef_unparse (sel)));
3652 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3654 s = sRef_fixBaseParam (sel, args);
3656 DPRINTF (("elements: %s", sRef_unparse (s)));
3657 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3659 if (sRef_isResult (sRef_getRootBase (sel)))
3661 ; /*@i423 what do we do about results */
3665 DPRINTF (("Reflecting state clause on: %s / %s",
3666 sRef_unparse (sel), sRef_unparse (s)));
3668 modf (s, eparam, exprNode_loc (f));
3670 } end_sRefSet_elements;
3673 sRefSet_free (osrs);
3675 } end_stateClauseList_elements ;
3680 static /*@only@*/ exprNode
3681 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3682 ctype t, /*@keep@*/ exprNodeList args)
3684 /* requires f is a non-error exprNode, with type function */
3685 cstring fname = exprNode_unparse (f);
3686 uentry le = exprNode_getUentry (f);
3687 exprNode ret = exprNode_createPartialCopy (f);
3692 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3694 ret->typ = ctype_getReturnType (t);
3695 ret->kind = XPR_CALL;
3697 ret->edata = exprData_makeCall (f, args);
3700 ** Order of these steps is very important!
3702 ** Must check for argument dependencies before messing up uses and sets.
3705 if (context_getFlag (FLG_EVALORDER))
3707 exprNodeList_elements (args, current)
3709 if (exprNode_isDefined (current))
3711 exprNode_addUse (current, current->sref);
3713 } end_exprNodeList_elements;
3715 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3717 checkSequencing (f, args);
3720 exprNodeList_elements (args, current)
3722 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3724 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3726 } end_exprNodeList_elements ;
3729 special = checkArgs (le, f, t, args, ret);
3730 checkGlobMods (f, le, args, ret, special);
3731 checkRequiresClause (le, f, args);
3734 if (uentry_isValid (le)
3735 && (uentry_isFunction (le)
3736 || (uentry_isVariable (le)
3737 && ctype_isFunction (uentry_getType (le)))))
3739 exitkind exk = uentry_getExitCode (le);
3741 /* f->typ is already set to the return type */
3743 DPRINTF (("Function: %s", uentry_unparseFull (le)));
3744 ret->sref = uentry_returnedRef (le, args);
3745 DPRINTF (("Returned: %s / %s",
3746 uentry_unparseFull (le),
3747 sRef_unparseFull (ret->sref)));
3749 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3751 qual nullPred = uentry_nullPred (le);
3753 if (qual_isTrueNull (nullPred))
3755 exprNode arg = exprNodeList_head (args);
3757 if (exprNode_isDefined (arg))
3759 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3762 else if (qual_isFalseNull (nullPred))
3764 exprNode arg = exprNodeList_head (args);
3766 if (exprNode_isDefined (arg))
3768 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3773 llassert (qual_isUnknown (nullPred));
3777 if (exitkind_isConditionalExit (exk))
3781 ** if (arg0) then { exit! } else { ; }
3783 ** if (arg0) then { ; } else { exit! }
3788 llassert (!exprNodeList_isEmpty (args));
3789 firstArg = exprNodeList_head (args);
3791 if (exprNode_isDefined (firstArg)
3792 && !guardSet_isEmpty (firstArg->guards))
3794 usymtab_trueBranch (guardSet_undefined);
3795 usymtab_altBranch (guardSet_undefined);
3797 if (exitkind_isTrueExit (exk))
3799 usymtab_popBranches (firstArg,
3800 exprNode_makeMustExit (),
3802 TRUE, TRUEEXITCLAUSE);
3806 usymtab_popBranches (firstArg,
3808 exprNode_makeMustExit (),
3809 TRUE, FALSEEXITCLAUSE);
3813 ret->exitCode = XK_MAYEXIT;
3815 else if (exitkind_mustExit (exk))
3817 ret->exitCode = XK_MUSTEXIT;
3819 else if (exitkind_couldExit (exk))
3821 ret->exitCode = XK_MAYEXIT;
3828 if (cstring_equalLit (fname, "exit"))
3830 if (exprNodeList_size (args) == 1)
3832 exprNode arg = exprNodeList_head (args);
3834 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3836 long int val = multiVal_forceInt (exprNode_getValue (arg));
3843 ("Argument to exit has implementation defined behavior: %s",
3844 exprNode_unparse (arg)),
3845 exprNode_loc (arg));
3854 exprNode_checkSetAny (ret, uentry_rawName (le));
3857 DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3858 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3859 reflectEnsuresClause (ret, le, f, args);
3866 ** this is yucky! should keep the uentry as part of exprNode!
3869 uentry exprNode_getUentry (exprNode e)
3871 if (exprNode_isError (e))
3873 return uentry_undefined;
3877 cstring s = exprNode_rootVarName (e);
3878 uentry ue = usymtab_lookupSafe (s);
3885 ** Returns true iff e1 and e2 are both exactly the same storage
3889 static bool exprNode_sameStorage (exprNode e1, exprNode e2)
3891 sRef s1 = exprNode_getSref (e1);
3892 sRef s2 = exprNode_getSref (e2);
3894 return (sRef_realSame (s1, s2));
3898 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3900 exprNode ret = exprNode_createPlain (ctype_unknown);
3902 ret->kind = XPR_INITBLOCK;
3903 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3904 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3910 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3916 if (exprNode_isUndefined (f))
3919 exprNodeList_free (args);
3920 return exprNode_undefined;
3923 t = exprNode_getType (f);
3925 if (sRef_isLocalVar (f->sref))
3927 exprNode_checkUse (f, f->sref, f->loc);
3929 if (sRef_possiblyNull (f->sref))
3931 if (!usymtab_isGuarded (f->sref))
3933 if (optgenerror (FLG_NULLDEREF,
3934 message ("Function call using %s pointer %q",
3935 sRef_nullMessage (f->sref),
3936 sRef_unparse (f->sref)),
3939 sRef_showNullInfo (f->sref);
3940 sRef_setNullError (f->sref);
3948 if (ctype_isRealFunction (t))
3950 exprNode ret = functionCallSafe (f, t, args);
3954 else if (ctype_isUnknown (t))
3956 exprNode ret = exprNode_createPartialCopy (f);
3962 exprNodeList_elements (args, current)
3964 if (exprNode_isDefined (current))
3966 exprNode_checkUse (ret, current->sref, ret->loc);
3969 ** also, anything derivable from current->sref may be used
3972 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3973 exprNode_mergeUSs (ret, current);
3975 } end_exprNodeList_elements;
3977 ret->edata = exprData_makeCall (f, args);
3978 ret->kind = XPR_CALL;
3980 tstring = cstring_copy (exprNode_unparse (f));
3982 cstring_markOwned (tstring);
3983 exprNode_checkSetAny (ret, tstring);
3989 voptgenerror (FLG_TYPE,
3990 message ("Call to non-function (type %t): %s", t,
3991 exprNode_unparse (f)),
3994 exprNodeList_free (args);
3996 return (exprNode_makeError ());
4001 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4002 /*@only@*/ cstring f)
4004 exprNode ret = exprNode_createPartialCopy (s);
4006 ret->kind = XPR_FACCESS;
4008 if (exprNode_isError (s))
4010 ret->edata = exprData_makeField (s, f);
4015 ctype t = exprNode_getType (s);
4016 ctype tr = ctype_realType (t);
4018 checkMacroParen (s);
4020 ret->edata = exprData_makeField (s, f);
4022 if (ctype_isStructorUnion (tr))
4024 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
4026 if (uentry_isUndefined (tf))
4028 voptgenerror (FLG_TYPE,
4029 message ("Access non-existent field %s of %t: %s", f, t,
4030 exprNode_unparse (ret)),
4032 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
4037 uentry_setUsed (tf, exprNode_loc (ret));
4039 ret->typ = uentry_getType (tf);
4040 checkSafeUse (ret, s->sref);
4042 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
4043 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
4047 else /* isStructorUnion */
4049 if (ctype_isRealAbstract (tr))
4053 message ("Access field of abstract type (%t): %s.%s",
4054 t, exprNode_unparse (s), f),
4056 ret->typ = ctype_unknown;
4060 if (ctype_isKnown (tr))
4065 ("Access field of non-struct or union (%t): %s.%s",
4066 t, exprNode_unparse (s), f),
4069 ret->typ = ctype_unknown;
4073 cstring sn = cstring_copy (f);
4075 checkSafeUse (ret, s->sref);
4076 cstring_markOwned (sn);
4077 ret->sref = sRef_makeField (s->sref, sn);
4089 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
4090 /*@only@*/ cstring f)
4092 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
4093 lltok_release (dot);
4098 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
4100 exprNode ret = exprNode_createPartialCopy (e);
4102 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
4103 ret->kind = XPR_PARENS;
4104 ret->edata = exprData_makeUop (e, lpar);
4106 if (!exprNode_isError (e))
4108 ret->exitCode = e->exitCode;
4109 ret->canBreak = e->canBreak;
4110 ret->mustBreak = e->mustBreak;
4111 ret->isJumpPoint = e->isJumpPoint;
4112 ret->sref = e->sref;
4119 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4120 /*@only@*/ cstring f)
4122 exprNode ret = exprNode_createPartialCopy (s);
4124 ret->edata = exprData_makeField (s, f);
4125 ret->kind = XPR_ARROW;
4127 if (exprNode_isError (s))
4133 ctype t = exprNode_getType (s);
4134 ctype tr = ctype_realType (t);
4136 checkMacroParen (s);
4138 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4140 if (ctype_isRealPointer (tr))
4142 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4144 if (ctype_isStructorUnion (b))
4146 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4148 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4150 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4154 message ("Arrow access from %s pointer%q: %s",
4155 sRef_nullMessage (s->sref),
4156 sRef_unparsePreOpt (s->sref),
4157 exprNode_unparse (ret)),
4160 sRef_showNullInfo (s->sref);
4161 sRef_setNullError (s->sref);
4166 if (uentry_isUndefined (fentry))
4170 message ("Access non-existent field %s of %t: %s",
4171 f, t, exprNode_unparse (ret)),
4173 ret->typ = ctype_unknown;
4179 ** was safeUse: shouldn't be safe!
4182 ** rec must be defined,
4183 ** *rec must be allocated
4184 ** rec->field need only be defined it if is an rvalue
4187 uentry_setUsed (fentry, exprNode_loc (ret));
4188 ret->typ = uentry_getType (fentry);
4190 exprNode_checkUse (ret, s->sref, s->loc);
4192 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4193 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4197 else /* Pointer to something that is not a struct or union*/
4199 if (ctype_isRealAbstract (tr))
4201 ctype xrt = ctype_forceRealType (tr);
4205 message ("Arrow access field of abstract type (%t): %s->%s",
4206 t, exprNode_unparse (s), f),
4210 ** Set the state correctly, as if the abstraction is broken.
4213 if (ctype_isRealPointer (xrt) &&
4214 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4215 ctype_isStructorUnion (b)))
4217 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4218 ret->typ = uentry_getType (fentry);
4219 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4223 ret->typ = ctype_unknown;
4224 ret->sref = sRef_undefined;
4227 else /* not a struct, union or abstract */
4229 if (ctype_isUnknown (tr)) {
4230 cstring sn = cstring_copy (f);
4232 DPRINTF (("Here: %s", exprNode_unparse (s)));
4234 exprNode_checkUse (ret, s->sref, s->loc);
4235 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4237 cstring_markOwned (sn);
4238 ret->sref = sRef_makeArrow (s->sref, sn);
4240 ret->kind = XPR_ARROW;
4245 message ("Arrow access field of non-struct or union "
4246 "pointer (%t): %s->%s",
4247 t, exprNode_unparse (s), f),
4250 ret->typ = ctype_unknown;
4251 ret->sref = sRef_undefined;
4256 else /* its not a pointer */
4258 if (!ctype_isUnknown (tr))
4262 message ("Arrow access of non-pointer (%t): %s->%s",
4263 t, exprNode_unparse (s), f),
4266 ret->typ = ctype_unknown;
4267 ret->sref = sRef_undefined;
4271 cstring sn = cstring_copy (f);
4273 DPRINTF (("Here: %s", exprNode_unparse (s)));
4275 exprNode_checkUse (ret, s->sref, s->loc);
4276 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4278 cstring_markOwned (sn);
4279 ret->sref = sRef_makeArrow (s->sref, sn);
4281 ret->kind = XPR_ARROW;
4292 exprNode_arrowAccess (/*@only@*/ exprNode s,
4293 /*@only@*/ lltok arrow,
4294 /*@only@*/ cstring f)
4296 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4297 lltok_release (arrow);
4302 ** only postOp's in C: i++ and i--
4306 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4308 /* check modification also */
4309 /* cstring opname = lltok_unparse (op);*/
4311 exprNode ret = exprNode_createPartialCopy (e);
4313 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4314 ret->kind = XPR_POSTOP;
4315 ret->edata = exprData_makeUop (e, op);
4317 if (!exprNode_isDefined (e))
4322 checkMacroParen (e);
4324 exprNode_checkUse (ret, e->sref, e->loc);
4325 exprNode_checkSet (ret, e->sref);
4327 t = exprNode_getType (e);
4329 if (sRef_isUnsafe (e->sref))
4331 voptgenerror (FLG_MACROPARAMS,
4332 message ("Operand of %s is macro parameter (non-functional): %s%s",
4333 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4335 sRef_makeSafe (e->sref);
4336 sRef_makeSafe (ret->sref);
4339 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4345 if (ctype_isRealAbstract (t))
4349 message ("Operand of %s is abstract type (%t): %s",
4350 lltok_unparse (op), t, exprNode_unparse (e)),
4357 message ("Operand of %s is non-numeric (%t): %s",
4358 lltok_unparse (op), t, exprNode_unparse (e)),
4361 ret->typ = ctype_unknown;
4364 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4366 exprNode_checkModify (e, ret);
4368 /* added 7/11/2000 D.L */
4370 /*DRL 6/8/01 I decided to disable all Splint warnings here since the code
4371 probably needs a rewrite any way */
4376 /* updateEnvironmentForPostOp (e); */
4378 /* start modifications */
4379 /* added by Seejo on 4/16/2000 */
4381 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4383 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4385 ret->sref = sRef_copy (e->sref);
4388 if (lltok_getTok (op) == INC_OP) {
4389 if (sRef_getSize(e->sref) > 0) {
4391 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4393 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4394 /* Assumption: there is only 1 \0 in the buffer */
4395 /* This will not be correct if there are 2 \0's in the buffer */
4396 sRef_setNotNullTerminatedState(ret->sref);
4397 sRef_resetLen(ret->sref);
4399 sRef_setNullTerminatedState(ret->sref);
4400 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4402 if (sRef_isNullTerminated (ret->sref))
4403 printf ("ret->sref is Null Terminated\n");
4404 else if (sRef_isPossiblyNullTerminated (ret->sref))
4405 printf ("ret->sref is Possibly Null Terminated\n");
4406 else if (sRef_isNotNullTerminated (ret->sref))
4407 printf ("ret->sref is Not Null Terminated\n");
4412 if (lltok_getTok (op) == DEC_OP) {
4413 if (sRef_getSize(e->sref) >= 0) {
4414 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4415 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4420 /* end modifications */
4426 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4428 bool checkMod = FALSE;
4430 int opid = lltok_getTok (op);
4431 exprNode ret = exprNode_createSemiCopy (e);
4433 exprNode_copySets (ret, e);
4435 multiVal_free (ret->val);
4436 ret->val = multiVal_undefined;
4437 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4438 ret->kind = XPR_PREOP;
4439 ret->edata = exprData_makeUop (e, op);
4441 if (exprNode_isError (e))
4446 checkMacroParen (e);
4448 te = exprNode_getType (e);
4449 tr = ctype_realType (te);
4451 if (opid != TAMPERSAND)
4453 exprNode_checkUse (ret, e->sref, e->loc);
4455 if (ctype_isRealAbstract (tr)
4456 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4458 if (optgenerror (FLG_ABSTRACT,
4459 message ("Operand of %s is abstract type (%t): %s",
4460 lltok_unparse (op), tr,
4461 exprNode_unparse (ret)),
4464 tr = te = ctype_unknown;
4465 ret->typ = ctype_unknown;
4466 sRef_setNullError (e->sref);
4474 case DEC_OP: /* should also check modification! */
4475 if (sRef_isMacroParamRef (e->sref))
4479 message ("Operand of %s is macro parameter (non-functional): %s",
4480 lltok_unparse (op), exprNode_unparse (ret)),
4485 exprNode_checkSet (ret, e->sref);
4488 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4493 if (context_msgStrictOps ())
4497 message ("Operand of %s is non-numeric (%t): %s",
4498 lltok_unparse (op), te, exprNode_unparse (ret)),
4501 ret->typ = ctype_int;
4504 /* start modifications */
4505 /* added by Seejo on 4/16/2000 */
4507 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4509 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4511 ret->sref = sRef_copy (e->sref);
4514 if (lltok_getTok (op) == INC_OP) {
4515 if (sRef_getSize(e->sref) > 0) {
4517 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4519 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4520 /* Assumption: there is only 1 \0 in the buffer */
4521 /* This will not be correct if there are 2 \0's in the buffer */
4522 sRef_setNotNullTerminatedState(ret->sref);
4523 sRef_resetLen (ret->sref);
4525 sRef_setNullTerminatedState(ret->sref);
4526 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4532 if (lltok_getTok (op) == DEC_OP) {
4533 if (sRef_getSize(e->sref) >= 0) {
4534 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4535 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4540 /* end modifications */
4547 if (ctype_isForceRealNumeric (&tr))
4551 ret->val = multiVal_invert (exprNode_getValue (e));
4555 ret->val = multiVal_copy (exprNode_getValue (e));
4560 if (context_msgStrictOps ())
4564 message ("Operand of %s is non-numeric (%t): %s",
4565 lltok_unparse (op), te, exprNode_unparse (ret)),
4569 ret->typ = ctype_int;
4573 case TEXCL: /* maybe this should be restricted */
4574 guardSet_flip (ret->guards);
4576 if (ctype_isRealBool (te) || ctype_isUnknown (te))
4582 if (ctype_isRealPointer (tr))
4584 if (sRef_isKnown (e->sref))
4586 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4590 (FLG_BOOLOPS, FLG_PTRNEGATE,
4591 message ("Operand of %s is non-boolean (%t): %s",
4592 lltok_unparse (op), te, exprNode_unparse (ret)),
4599 message ("Operand of %s is non-boolean (%t): %s",
4600 lltok_unparse (op), te, exprNode_unparse (ret)),
4604 ret->typ = ctype_bool;
4609 if (ctype_isForceRealInt (&tr))
4614 if (context_msgStrictOps ())
4618 message ("Operand of %s is non-integer (%t): %s",
4619 lltok_unparse (op), te, exprNode_unparse (ret)),
4623 if (ctype_isInt (e->typ))
4629 ret->typ = ctype_int;
4635 ret->typ = ctype_makePointer (e->typ);
4637 if (sRef_isKnown (e->sref))
4639 ret->sref = sRef_makeAddress (e->sref);
4646 if (ctype_isAP (tr))
4648 ret->typ = ctype_baseArrayPtr (e->typ);
4652 if (ctype_isKnown (te))
4654 if (ctype_isFunction (te))
4660 message ("Dereference of function type (%t): %s",
4661 te, exprNode_unparse (ret)),
4666 voptgenerror (FLG_TYPE,
4667 message ("Dereference of non-pointer (%t): %s",
4668 te, exprNode_unparse (ret)),
4670 ret->typ = ctype_unknown;
4675 ret->typ = ctype_unknown;
4680 if (sRef_isKnown (e->sref))
4682 DPRINTF (("Checking possibly null: %s", sRef_unparseFull (e->sref)));
4684 if (sRef_possiblyNull (e->sref))
4686 DPRINTF (("Checking possibly null: %s", sRef_unparse (e->sref)));
4687 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4691 message ("Dereference of %s pointer %q: %s",
4692 sRef_nullMessage (e->sref),
4693 sRef_unparse (e->sref),
4694 exprNode_unparse (ret)),
4697 sRef_showNullInfo (e->sref);
4698 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4703 ret->sref = sRef_makePointer (e->sref);
4708 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4713 exprNode_checkModify (e, ret);
4720 ** any reason to disallow sizeof (abstract type) ?
4724 ** used by both sizeof
4728 ctype sizeof_resultType (void)
4730 static ctype sizet = ctype_unknown;
4732 if (ctype_isUnknown (sizet))
4734 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4736 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4740 sizet = ctype_ulint;
4747 exprNode_sizeofType (/*@only@*/ qtype qt)
4749 exprNode ret = exprNode_create (sizeof_resultType ());
4750 ctype ct = qtype_getType (qt);
4752 ret->kind = XPR_SIZEOFT;
4753 ret->edata = exprData_makeSizeofType (qt);
4755 voptgenerror (FLG_SIZEOFTYPE,
4756 message ("Parameter to sizeof is type %s: %s",
4758 exprNode_unparse (ret)),
4765 exprNode_alignofType (/*@only@*/ qtype qt)
4767 exprNode ret = exprNode_create (sizeof_resultType ());
4768 ctype ct = qtype_getType (qt);
4770 ret->kind = XPR_ALIGNOFT;
4771 ret->edata = exprData_makeSizeofType (qt);
4773 voptgenerror (FLG_SIZEOFTYPE,
4774 message ("Parameter to alignof is type %s: %s",
4776 exprNode_unparse (ret)),
4782 exprNode exprNode_offsetof (qtype qt, cstringList s)
4784 exprNode ret = exprNode_create (sizeof_resultType ());
4785 ctype ct = qtype_getType (qt);
4787 ret->kind = XPR_OFFSETOF;
4788 ret->edata = exprData_makeOffsetof (qt, s);
4790 if (!ctype_isRealSU (ct))
4792 voptgenerror (FLG_TYPE,
4793 message ("First parameter to offsetof is not a "
4794 "struct or union type (type %s): %s",
4796 exprNode_unparse (ret)),
4803 cstringList_elements (s, el) {
4807 if (ctype_isUndefined (lt))
4811 else if (!ctype_isRealSU (lt))
4813 voptgenerror (FLG_TYPE,
4814 message ("Inner offsetof type is not a "
4815 "struct or union type (type %s before field %s): %s",
4816 ctype_unparse (lt), el,
4817 exprNode_unparse (ret)),
4823 fields = ctype_getFields (ctype_realType (lt));
4824 fld = uentryList_lookupField (fields, el);
4825 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4827 if (uentry_isUndefined (fld))
4829 if (ctype_equal (lt, ct)) {
4830 voptgenerror (FLG_TYPE,
4831 message ("Field %s in offsetof is not the "
4832 "name of a field of %s: %s",
4835 exprNode_unparse (ret)),
4838 voptgenerror (FLG_TYPE,
4839 message ("Deep field %s in offsetof is not the "
4840 "name of a field of %s: %s",
4843 exprNode_unparse (ret)),
4849 lt = uentry_getType (fld);
4852 } end_cstringList_elements;
4854 /* Should report error if its a bit field - behavior is undefined! */
4861 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4865 if (exprNode_isUndefined (e))
4867 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4868 ret->edata = exprData_makeSingle (e);
4869 ret->typ = sizeof_resultType ();
4870 ret->kind = XPR_SIZEOF;
4874 uentry u = exprNode_getUentry (e);
4876 ret = exprNode_createPartialCopy (e);
4877 ret->edata = exprData_makeSingle (e);
4879 ret->typ = sizeof_resultType ();
4880 ret->kind = XPR_SIZEOF;
4882 if (uentry_isValid (u)
4883 && uentry_isRefParam (u)
4884 && ctype_isRealArray (uentry_getType (u)))
4887 (FLG_SIZEOFFORMALARRAY,
4888 message ("Parameter to sizeof is an array-type function parameter: %s",
4889 exprNode_unparse (ret)),
4895 ** sizeof (x) doesn't "really" use x
4902 exprNode_alignofExpr (/*@only@*/ exprNode e)
4906 if (exprNode_isUndefined (e))
4908 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4912 ret = exprNode_createPartialCopy (e);
4915 ret->edata = exprData_makeSingle (e);
4916 ret->typ = sizeof_resultType ();
4917 ret->kind = XPR_ALIGNOF;
4920 ** sizeof (x) doesn't "really" use x
4927 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4933 if (exprNode_isError (e))
4936 lltok_release (tok);
4937 return exprNode_undefined;
4940 checkMacroParen (e);
4942 c = qtype_getType (q);
4943 t = exprNode_getType (e);
4945 ret = exprNode_createPartialCopy (e);
4947 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4949 ret->kind = XPR_CAST;
4950 ret->edata = exprData_makeCast (tok, e, q);
4952 if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
4955 ** This is a bit of a hack to avoid a problem
4956 ** when the code does,
4957 ** (some other struct) x
4962 ret->sref = sRef_copy (e->sref);
4963 usymtab_addForceMustAlias (ret->sref, e->sref);
4964 sRef_setTypeFull (ret->sref, c);
4965 DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
4966 sRef_unparseFull (ret->sref)));
4970 ret->sref = e->sref;
4971 sRef_setTypeFull (ret->sref, c);
4972 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
4979 ** void * <-> abstract * (if FLG_ABSTVOIDP)
4980 ** abstract * <-> void * (if FLG_ABSTVOIDP)
4983 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
4987 else if (ctype_isRealAP (c)) /* casting to array or pointer */
4989 ctype bc = ctype_getBaseType (c);
4990 ctype bt = ctype_getBaseType (t);
4991 ctype rt = ctype_realType (t);
4993 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
4994 && (ctype_isArrayPtr (rt)
4995 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4999 message ("Cast from function pointer type (%t) to "
5000 "non-function pointer (%t): %s",
5001 c, t, exprNode_unparse (ret)),
5005 if (!ctype_isFunction (ctype_baseArrayPtr (c))
5006 && (ctype_isArrayPtr (rt)
5007 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5011 message ("Cast from non-function pointer type (%t) to "
5012 "function pointer (%t): %s",
5013 c, t, exprNode_unparse (ret)),
5017 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
5018 !(ctype_isRealAbstract (bc)
5019 && context_hasAccess (ctype_typeId (bc))))
5021 ; /* okay to cast zero */
5025 if (ctype_isRealAbstract (bc)
5026 && !context_hasAccess (ctype_typeId (bc)))
5028 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
5032 message ("Cast to underlying abstract type %t: %s",
5033 c, exprNode_unparse (ret)),
5040 message ("Cast to underlying abstract type %t: %s",
5041 c, exprNode_unparse (ret)),
5046 if (ctype_isRealAbstract (bt)
5047 && !context_hasAccess (ctype_typeId (bt)))
5049 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
5053 message ("Cast from underlying abstract type %t: %s",
5054 t, exprNode_unparse (ret)),
5061 message ("Cast from underlying abstract type %t: %s",
5062 t, exprNode_unparse (ret)),
5070 ctype bt = ctype_realType (ctype_getBaseType (t));
5071 ctype bc = ctype_realType (ctype_getBaseType (c));
5073 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
5075 if (ctype_match (c, t))
5077 if (ctype_equal (c, t))
5081 message ("Redundant cast involving abstract type %t: %s",
5082 bt, exprNode_unparse (ret)),
5090 message ("Cast from abstract type %t: %s",
5091 bt, exprNode_unparse (ret)),
5096 if (ctype_isAbstract (bc)
5097 && !context_hasAccess (ctype_typeId (bc)))
5099 if (ctype_match (c, t))
5105 DPRINTF (("No access to: %s / %d",
5106 ctype_unparse (bc), ctype_typeId (bc)));
5107 DPRINTF (("Context %s %s",
5108 bool_unparse (context_inFunctionLike ()),
5109 context_unparse ()));
5112 message ("Cast to abstract type %t: %s", bc,
5113 exprNode_unparse (ret)),
5119 if (ctype_isAbstract (c))
5121 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
5123 /* okay, cast exposed to abstract */
5124 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
5128 if (ctype_isVisiblySharable (t)
5129 && sRef_isExternallyVisible (e->sref)
5130 && !(ctype_isAbstract (t)
5131 && context_hasAccess (ctype_typeId (t))))
5135 message ("Cast to abstract type from externally visible "
5136 "mutable storage exposes rep of %s: %s",
5138 exprNode_unparse (e)),
5148 evaluationOrderUndefined (lltok op)
5150 int opid = lltok_getTok (op);
5152 return (opid != AND_OP && opid != OR_OP);
5155 static bool checkIntegral (/*@notnull@*/ exprNode e1,
5156 /*@notnull@*/ exprNode e2,
5157 /*@notnull@*/ exprNode ret,
5162 ctype te1 = exprNode_getType (e1);
5163 ctype te2 = exprNode_getType (e2);
5165 ctype tr1 = ctype_realishType (te1);
5166 ctype tr2 = ctype_realishType (te2);
5168 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5174 if (context_msgStrictOps ())
5176 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5178 if (ctype_sameName (te1, te2))
5182 message ("Operands of %s are non-integer (%t): %s",
5183 lltok_unparse (op), te1,
5184 exprNode_unparse (ret)),
5191 message ("Operands of %s are non-integers (%t, %t): %s",
5192 lltok_unparse (op), te1, te2,
5193 exprNode_unparse (ret)),
5197 else if (!ctype_isInt (tr1))
5201 message ("Left operand of %s is non-integer (%t): %s",
5202 lltok_unparse (op), te1, exprNode_unparse (ret)),
5206 /* !ctype_isInt (te2) */
5210 message ("Right operand of %s is non-integer (%t): %s",
5211 lltok_unparse (op), te2, exprNode_unparse (ret)),
5221 ** returns exprNode representing e1 op e2
5223 ** uses msg if there are errors
5224 ** can be used for both assignment ops and regular ops
5229 static /*@only@*/ /*@notnull@*/ exprNode
5230 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
5231 /*@keep@*/ lltok op)
5233 ctype te1, te2, tr1, tr2, tret;
5234 int opid = lltok_getTok (op);
5235 bool hasError = FALSE;
5238 if (exprNode_isError (e1))
5240 ret = exprNode_createPartialNVCopy (e2);
5244 ret = exprNode_createPartialNVCopy (e1);
5247 ret->val = multiVal_undefined;
5250 ret->edata = exprData_makeOp (e1, e2, op);
5252 if (exprNode_isError (e1) || exprNode_isError (e2))
5254 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5255 || opid == EQ_OP || opid == NE_OP
5256 || opid == AND_OP || opid == OR_OP)
5258 ret->typ = ctype_bool;
5261 if (exprNode_isDefined (e1))
5263 exprNode_checkUse (ret, e1->sref, e1->loc);
5266 if (exprNode_isDefined (e2))
5268 exprNode_mergeUSs (ret, e2);
5269 exprNode_checkUse (ret, e2->sref, e2->loc);
5275 tret = ctype_unknown;
5276 te1 = exprNode_getType (e1);
5278 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5280 te2 = exprNode_getType (e2);
5282 tr1 = ctype_realishType (te1);
5283 tr2 = ctype_realishType (te2);
5287 ret->guards = guardSet_or (ret->guards, e2->guards);
5289 else if (opid == AND_OP)
5291 ret->guards = guardSet_and (ret->guards, e2->guards);
5298 if (opid == EQ_OP || opid == NE_OP)
5300 exprNode temp1 = e1, temp2 = e2;
5302 /* could do NULL == x */
5304 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5306 temp1 = e2; temp2 = e1;
5309 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5311 reflectNullTest (temp1, (opid == NE_OP));
5312 guardSet_free (ret->guards);
5313 ret->guards = guardSet_copy (temp1->guards);
5317 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5318 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5323 if (anyAbstract (tr1, tr2) &&
5324 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
5325 (opid == AND_OP || opid == OR_OP
5326 || opid == EQ_OP || opid == NE_OP))))
5328 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
5330 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5332 /* unknown types, no comparisons possible */
5338 case TMULT: /* multiplication and division: */
5340 case MUL_ASSIGN: /* numeric, numeric -> numeric */
5341 case DIV_ASSIGN: /* */
5343 if (opid == TMULT || opid == MUL_ASSIGN)
5345 ret->val = multiVal_multiply (exprNode_getValue (e1),
5346 exprNode_getValue (e2));
5350 ret->val = multiVal_divide (exprNode_getValue (e1),
5351 exprNode_getValue (e2));
5354 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5357 case TPLUS: /* addition and subtraction: */
5358 case TMINUS: /* pointer, int -> pointer */
5359 case SUB_ASSIGN: /* int, pointer -> pointer */
5360 case ADD_ASSIGN: /* numeric, numeric -> numeric */
5362 if (opid == TPLUS || opid == ADD_ASSIGN)
5364 ret->val = multiVal_add (exprNode_getValue (e1),
5365 exprNode_getValue (e2));
5369 ret->val = multiVal_subtract (exprNode_getValue (e1),
5370 exprNode_getValue (e2));
5373 tr1 = ctype_fixArrayPtr (tr1);
5375 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5376 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5380 if (context_msgPointerArith ())
5384 message ("Pointer arithmetic (%t, %t): %s",
5385 te1, te2, exprNode_unparse (ret)),
5390 ** Swap terms so e1 is always the pointer
5393 if (ctype_isRealPointer (tr1))
5399 exprNode_swap (e1, e2);
5403 if (sRef_possiblyNull (e1->sref)
5404 && !usymtab_isGuarded (e1->sref))
5407 (FLG_NULLPOINTERARITH,
5408 message ("Pointer arithmetic involving possibly "
5409 "null pointer %s: %s",
5410 exprNode_unparse (e1),
5411 exprNode_unparse (ret)),
5415 ret->sref = sRef_copy (e1->sref);
5417 /* start modifications */
5418 /* added by Seejo on 4/16/2000 */
5420 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5422 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5425 added ugly fixed to stop
5426 program from crashing on point + int +int
5427 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5429 if (!multiVal_isInt (e2->val) )
5433 val = (int) multiVal_forceInt (e2->val);
5435 /* Operator : + or += */
5436 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5437 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5438 val should not result in a
5439 size < 0 (size = 0 is ok !) */
5441 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5443 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5444 sRef_setNotNullTerminatedState(ret->sref);
5445 sRef_resetLen (ret->sref);
5447 sRef_setNullTerminatedState(ret->sref);
5448 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5453 /* Operator : - or -= */
5454 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5455 if (sRef_getSize(e1->sref) >= 0) {
5456 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5457 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5462 /* end modifications */
5464 sRef_setNullError (ret->sref);
5467 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5468 ** since is points to storage that should not be deallocated
5469 ** through this pointer.
5472 if (sRef_isOnly (ret->sref)
5473 || sRef_isFresh (ret->sref))
5475 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5480 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5481 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5483 if (context_msgPointerArith ())
5487 message ("Pointer arithmetic (%t, %t): %s",
5488 te1, te2, exprNode_unparse (ret)),
5492 if (sRef_possiblyNull (e1->sref)
5493 && !usymtab_isGuarded (e1->sref))
5496 (FLG_NULLPOINTERARITH,
5497 message ("Pointer arithmetic involving possibly "
5498 "null pointer %s: %s",
5499 exprNode_unparse (e2),
5500 exprNode_unparse (ret)),
5504 ret->sref = sRef_copy (e2->sref);
5506 /* start modifications */
5507 /* added by Seejo on 4/16/2000 */
5509 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5512 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5513 int val = (int) multiVal_forceInt (e1->val);
5515 /* Operator : + or += */
5516 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5517 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5518 val should not result in a
5519 size < 0 (size = 0 is ok !) */
5521 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5523 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5524 sRef_setNotNullTerminatedState(ret->sref);
5525 sRef_resetLen (ret->sref);
5527 sRef_setNullTerminatedState(ret->sref);
5528 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5533 /* Operator : - or -= */
5534 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5535 if (sRef_getSize(e2->sref) >= 0) {
5536 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5537 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5541 /* end modifications */
5543 sRef_setNullError (ret->sref);
5546 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5547 ** since is points to storage that should not be deallocated
5548 ** through this pointer.
5551 if (sRef_isOnly (ret->sref)
5552 || sRef_isFresh (ret->sref)) {
5553 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5557 ret->sref = e2->sref;
5561 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5570 case TAMPERSAND: /* bitwise & */
5572 case TCIRC: /* ^ (XOR) */
5577 bool reported = FALSE;
5583 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5584 || opid == RIGHT_OP || opid == RIGHT_ASSIGN)
5587 ** evans 2002-01-01: fixed this to follow ISO 6.5.7.
5590 if (!ctype_isUnsigned (tr2)
5591 && !exprNode_isNonNegative (e2))
5593 reported = optgenerror
5595 message ("Right operand of %s may be negative (%t): %s",
5596 lltok_unparse (op), te2,
5597 exprNode_unparse (ret)),
5601 if (!ctype_isUnsigned (tr1)
5602 && !exprNode_isNonNegative (e1))
5604 reported = optgenerror
5605 (FLG_SHIFTIMPLEMENTATION,
5606 message ("Left operand of %s may be negative (%t): %s",
5607 lltok_unparse (op), te1,
5608 exprNode_unparse (ret)),
5613 ** Should check size of right operand also...
5619 if (!ctype_isUnsigned (tr1))
5621 if (exprNode_isNonNegative (e1)) {
5624 reported = optgenerror
5626 message ("Left operand of %s is not unsigned value (%t): %s",
5627 lltok_unparse (op), te1,
5628 exprNode_unparse (ret)),
5638 if (!ctype_isUnsigned (tr2))
5640 if (!exprNode_isNonNegative (e2)) {
5641 reported = optgenerror
5643 message ("Right operand of %s is not unsigned value (%t): %s",
5644 lltok_unparse (op), te2,
5645 exprNode_unparse (ret)),
5654 if (!checkIntegral (e1, e2, ret, op)) {
5655 te1 = ctype_unknown;
5659 DPRINTF (("Set: %s", ctype_unparse (te1)));
5662 ** tret is the widest type of te1 and te2
5665 tret = ctype_widest (te1, te2);
5670 if (checkIntegral (e1, e2, ret, op)) {
5673 tret = ctype_unknown;
5678 case TLT: /* comparisons */
5679 case TGT: /* numeric, numeric -> bool */
5681 DPRINTF (("Here we go: %s / %s",
5682 ctype_unparse (tr1), ctype_unparse (tr2)));
5684 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5685 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5688 bool fepsilon = FALSE;
5690 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5695 if (opid == TLT || opid == TGT)
5697 uentry ue1 = exprNode_getUentry (e1);
5698 uentry ue2 = exprNode_getUentry (e2);
5701 ** FLT_EPSILON, etc. really is a variable, not
5705 if (uentry_isVariable (ue1))
5707 cstring uname = uentry_rawName (ue1);
5709 if (cstring_equalLit (uname, "FLT_EPSILON")
5710 || cstring_equalLit (uname, "DBL_EPSILON")
5711 || cstring_equalLit (uname, "LDBL_EPSILON"))
5717 if (uentry_isVariable (ue2))
5719 cstring uname = uentry_rawName (ue2);
5721 if (cstring_equalLit (uname, "FLT_EPSILON")
5722 || cstring_equalLit (uname, "DBL_EPSILON")
5723 || cstring_equalLit (uname, "LDBL_EPSILON"))
5732 ; /* Don't complain. */
5738 message ("Dangerous comparison involving %s types: %s",
5739 ctype_unparse (rtype),
5740 exprNode_unparse (ret)),
5749 ** Types should match.
5752 DPRINTF (("Match types: %s / %s", exprNode_unparse (e1),
5753 exprNode_unparse (e2)));
5755 if (!exprNode_matchTypes (e1, e2))
5757 hasError = gentypeerror
5759 message ("Operands of %s have incompatible types (%t, %t): %s",
5760 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5766 || (ctype_isForceRealNumeric (&tr1)
5767 && ctype_isForceRealNumeric (&tr2)) ||
5768 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5774 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5775 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5779 message ("Comparison of pointer and numeric (%t, %t): %s",
5780 te1, te2, exprNode_unparse (ret)),
5785 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5790 /* certain comparisons on unsigned's and zero look suspicious */
5792 if (opid == TLT || opid == LE_OP || opid == GE_OP)
5794 if ((ctype_isUnsigned (tr1) && exprNode_isZero (e2))
5795 || (ctype_isUnsigned (tr2) && exprNode_isZero (e1)))
5798 (FLG_UNSIGNEDCOMPARE,
5799 message ("Comparison of unsigned value involving zero: %s",
5800 exprNode_unparse (ret)),
5805 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5807 if ((opid == EQ_OP || opid == NE_OP) &&
5808 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5811 ** is one a variable?
5814 if (uentry_isVariable (exprNode_getUentry (e1))
5815 || uentry_isVariable (exprNode_getUentry (e2)))
5818 ** comparisons with FALSE are okay
5821 if (exprNode_isFalseConstant (e1)
5822 || exprNode_isFalseConstant (e2))
5831 ("Use of %q with %s variables (risks inconsistency because "
5832 "of multiple true values): %s",
5833 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5834 context_printBoolName (), exprNode_unparse (ret)),
5841 case AND_OP: /* bool, bool -> bool */
5844 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5850 if (context_maybeSet (FLG_BOOLOPS))
5852 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5854 if (ctype_sameName (te1, te2))
5858 message ("Operands of %s are non-boolean (%t): %s",
5859 lltok_unparse (op), te1,
5860 exprNode_unparse (ret)),
5868 ("Operands of %s are non-booleans (%t, %t): %s",
5869 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5873 else if (!ctype_isRealBool (te1))
5877 message ("Left operand of %s is non-boolean (%t): %s",
5878 lltok_unparse (op), te1, exprNode_unparse (ret)),
5881 else if (!ctype_isRealBool (te2))
5885 message ("Right operand of %s is non-boolean (%t): %s",
5886 lltok_unparse (op), te2, exprNode_unparse (ret)),
5899 (cstring_makeLiteral
5900 ("There has been a problem in the parser. This is believed to result "
5901 "from a problem with bison v. 1.25. Please try rebuidling Splint "
5902 "using the pre-compiled grammar files by commenting out the "
5903 "BISON= line in the top-level Makefile."));
5908 DPRINTF (("Return type: %s", ctype_unparse (tret)));
5911 exprNode_checkUse (ret, e1->sref, e1->loc);
5912 exprNode_mergeUSs (ret, e2);
5913 exprNode_checkUse (ret, e2->sref, e2->loc);
5919 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5920 /*@only@*/ lltok op)
5924 checkMacroParen (e1);
5925 checkMacroParen (e2);
5927 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5929 checkExpressionDefined (e1, e2, op);
5932 ret = exprNode_makeOp (e1, e2, op);
5937 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5940 ** This is somewhat bogus!
5942 ** Assigning to a nested observer in a non-observer datatype
5943 ** should not produce an error.
5946 sRef ref = exprNode_getSref (e1);
5948 DPRINTF (("Check assign mod: %s",
5949 sRef_unparseFull (ref)));
5951 if (sRef_isObserver (ref)
5952 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
5953 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5955 sRef base = sRef_getBase (ref);
5957 if (sRef_isValid (base) && sRef_isObserver (base))
5959 exprNode_checkModify (e1, ret);
5963 exprNode_checkModifyVal (e1, ret);
5968 exprNode_checkModify (e1, ret);
5973 exprNode_assign (/*@only@*/ exprNode e1,
5974 /*@only@*/ exprNode e2, /*@only@*/ lltok op)
5976 bool isalloc = FALSE;
5977 bool isjustalloc = FALSE;
5978 bool noalias = FALSE;
5981 DPRINTF (("%s [%s] <- %s [%s]",
5982 exprNode_unparse (e1),
5983 ctype_unparse (e1->typ),
5984 exprNode_unparse (e2),
5985 ctype_unparse (e2->typ)));
5987 if (lltok_getTok (op) != TASSIGN)
5989 ret = exprNode_makeOp (e1, e2, op);
5991 DPRINTF (("Here goes: %s %s",
5992 ctype_unparse (e1->typ),
5993 ctype_unparse (e2->typ)));
5995 if (ctype_isNumeric (e2->typ)
5996 || ctype_isNumeric (e1->typ))
5998 /* Its a pointer arithmetic expression like ptr += i */
6004 ret = exprNode_createPartialCopy (e1);
6005 ret->kind = XPR_ASSIGN;
6006 ret->edata = exprData_makeOp (e1, e2, op);
6008 if (!exprNode_isError (e2))
6010 ret->sets = sRefSet_union (ret->sets, e2->sets);
6011 ret->msets = sRefSet_union (ret->msets, e2->msets);
6012 ret->uses = sRefSet_union (ret->uses, e2->uses);
6016 checkExpressionDefined (e1, e2, op);
6018 if (exprNode_isError (e1))
6020 if (!exprNode_isError (e2))
6022 ret->loc = fileloc_update (ret->loc, e2->loc);
6026 ret->loc = fileloc_update (ret->loc, g_currentloc);
6030 if (!exprNode_isError (e2))
6032 checkMacroParen (e2);
6035 if (exprNode_isDefined (e1))
6037 if (sRef_isMacroParamRef (e1->sref))
6039 if (context_inIterDef ())
6041 uentry ue = sRef_getUentry (e1->sref);
6043 if (uentry_isYield (ue))
6049 if (fileloc_isDefined (e1->loc))
6053 message ("Assignment to non-yield iter parameter: %q",
6054 sRef_unparse (e1->sref)),
6061 message ("Assignment to non-yield iter parameter: %q",
6062 sRef_unparse (e1->sref)),
6069 if (fileloc_isDefined (e1->loc))
6073 message ("Assignment to macro parameter: %q",
6074 sRef_unparse (e1->sref)),
6081 message ("Assignment to macro parameter: %q",
6082 sRef_unparse (e1->sref)),
6086 exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
6091 exprNode_checkAssignMod (e1, ret);
6094 if (exprNode_isDefined (e2))
6096 if (lltok_getTok (op) == TASSIGN)
6098 ctype te1 = exprNode_getType (e1);
6099 ctype te2 = exprNode_getType (e2);
6101 if (!ctype_forceMatch (te1, te2))
6103 if (exprNode_matchLiteral (te1, e2))
6111 message ("Assignment of %t to %t: %s %s %s",
6112 te2, te1, exprNode_unparse (e1),
6114 exprNode_unparse (e2)),
6120 exprNode_mergeUSs (ret, e2);
6121 exprNode_checkUse (ret, e2->sref, e2->loc);
6123 DPRINTF (("Do assign! %s %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6130 doAssign (e1, e2, FALSE);
6133 ret->sref = e1->sref;
6137 if (exprNode_isDefined (e2))
6139 exprNode_mergeUSs (ret, e2);
6140 exprNode_checkUse (ret, e2->sref, e2->loc);
6144 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
6146 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
6149 isjustalloc = sRef_isJustAllocated (e1->sref);
6150 isalloc = sRef_isAllocated (e1->sref);
6152 if (sRef_isField (e1->sref))
6154 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
6156 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
6158 exprNode_checkUse (ret, root, e1->loc);
6164 ** be careful! this defines e1->sref.
6167 /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
6169 DPRINTF (("Setting: %s -> %s", exprNode_unparse (ret), sRef_unparse (e1->sref)));
6170 exprNode_checkSet (ret, e1->sref);
6174 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
6175 ? e2->loc : e1->loc);
6181 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
6190 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
6191 /*@keep@*/ exprNode elseclause)
6195 if (!exprNode_isError (pred))
6197 ret = exprNode_createPartialCopy (pred);
6198 checkMacroParen (pred);
6199 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
6201 if (!exprNode_isError (ifclause))
6203 checkMacroParen (ifclause); /* update macro counts! */
6205 if (!exprNode_isError (elseclause))
6207 checkMacroParen (elseclause);
6209 if (!exprNode_matchTypes (ifclause, elseclause))
6212 (exprNode_getType (ifclause),
6214 exprNode_getType (elseclause),
6216 message ("Conditional clauses are not of same type: "
6218 exprNode_unparse (ifclause),
6219 exprNode_getType (ifclause),
6220 exprNode_unparse (elseclause),
6221 exprNode_getType (elseclause)),
6224 ret->sref = sRef_undefined;
6225 ret->typ = ctype_unknown;
6230 /* for now...should merge the states */
6231 ret->sref = ifclause->sref;
6232 ret->typ = ifclause->typ;
6234 if (exprNode_isNullValue (ifclause))
6236 ret->typ = elseclause->typ;
6240 exprNode_checkUse (ret, pred->sref, pred->loc);
6241 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6242 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6244 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6249 ret->typ = ifclause->typ;
6251 exprNode_checkUse (pred, pred->sref, pred->loc);
6252 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6254 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6259 if (!exprNode_isError (elseclause))
6261 ret->typ = elseclause->typ;
6263 exprNode_checkUse (pred, pred->sref, pred->loc);
6264 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6266 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6270 else /* pred is error */
6272 if (!exprNode_isError (ifclause))
6274 ret = exprNode_createSemiCopy (ifclause);
6276 checkMacroParen (ifclause); /* update macro counts! */
6278 if (!exprNode_isError (elseclause))
6280 checkMacroParen (elseclause);
6282 ret->typ = ifclause->typ;
6284 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6287 (exprNode_getType (ifclause),
6289 exprNode_getType (elseclause),
6291 message ("Conditional clauses are not of same type: "
6293 exprNode_unparse (ifclause),
6294 exprNode_getType (ifclause),
6295 exprNode_unparse (elseclause),
6296 exprNode_getType (elseclause)),
6299 ret->typ = ctype_unknown;
6303 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6304 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6306 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6309 else if (!exprNode_isError (elseclause)) /* pred, if errors */
6311 ret = exprNode_createSemiCopy (ifclause);
6313 ret->typ = elseclause->typ;
6314 checkMacroParen (elseclause);
6316 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6317 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6319 else /* all errors! */
6321 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6325 ret->kind = XPR_COND;
6326 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
6328 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6330 exprNode_combineControl (ret, ifclause, elseclause);
6337 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6339 ctype totype = qtype_getType (qt);
6341 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6345 ** check use of va_arg : <valist>, type -> type
6348 if (exprNode_isError (arg))
6353 targ = exprNode_getType (arg);
6356 ** arg should have be a pointer
6359 if (!ctype_isUA (targ) ||
6360 (!usymId_equal (ctype_typeId (targ),
6361 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6365 message ("First argument to va_arg is not a va_list (type %t): %s",
6366 targ, exprNode_unparse (arg)),
6370 exprNode_checkSet (ret, arg->sref);
6374 ** return type is totype
6378 ret->kind = XPR_VAARG;
6379 ret->edata = exprData_makeCast (tok, arg, qt);
6384 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6386 exprNode ret = exprNode_createPlain (ctype_undefined);
6387 ret->kind = XPR_LABEL;
6388 ret->edata = exprData_makeLiteral (label);
6389 ret->isJumpPoint = TRUE;
6391 return (ret); /* for now, ignore label */
6394 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6396 if (exprNode_isDefined (stmt))
6398 stmt->isJumpPoint = TRUE;
6400 /* This prevent stray no return path errors, etc. */
6401 stmt->exitCode = XK_MUSTEXIT;
6407 bool exprNode_isDefaultMarker (exprNode e)
6409 if (exprNode_isDefined (e))
6411 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6417 bool exprNode_isCaseMarker (exprNode e)
6419 if (exprNode_isDefined (e))
6421 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6427 bool exprNode_isLabelMarker (exprNode e)
6429 if (exprNode_isDefined (e))
6431 return (e->kind == XPR_LABEL);
6437 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6439 exprNode ret = exprNode_createPartialCopy (test);
6441 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6443 if (exprNode_isError (test)) {
6447 exprNode_checkUse (ret, test->sref, test->loc);
6449 usymtab_setExitCode (ret->exitCode);
6453 usymtab_setMustBreak ();
6456 ret->edata = exprData_makeSingle (test);
6457 ret->isJumpPoint = TRUE;
6463 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6465 exprNode ret = exprNode_createPartialCopy (test);
6467 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6468 ret->edata = exprData_makePair (test, stmt);
6469 ret->isJumpPoint = TRUE;
6471 if (exprNode_isError (test))
6476 exprNode_checkUse (ret, test->sref, test->loc);
6478 if (exprNode_isError (stmt))
6483 exprNode_mergeUSs (ret, stmt);
6485 ret->exitCode = stmt->exitCode;
6486 ret->mustBreak = stmt->mustBreak;
6487 ret->canBreak = stmt->canBreak;
6489 usymtab_setExitCode (ret->exitCode);
6493 usymtab_setMustBreak ();
6500 /*@notnull@*/ /*@only@*/ exprNode
6501 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6503 exprNode ret = exprNode_createTok (def);
6505 ret->isJumpPoint = TRUE;
6506 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6511 exprNode_mayEscape (exprNode e)
6513 if (exprNode_isDefined (e))
6515 return exitkind_couldEscape (e->exitCode);
6521 exprNode_mustBreak (exprNode e)
6523 if (exprNode_isDefined (e))
6525 return e->mustBreak;
6532 exprNode_mustEscape (exprNode e)
6534 if (exprNode_isDefined (e))
6536 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6543 exprNode_errorEscape (exprNode e)
6545 if (exprNode_isDefined (e))
6547 return exitkind_isError (e->exitCode);
6553 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6555 exprNode ret = exprNode_createPartialCopy (e1);
6557 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6559 ret->edata = exprData_makePair (e1, e2);
6560 ret->kind = XPR_STMTLIST;
6562 if (exprNode_isDefined (e1))
6564 ret->isJumpPoint = e1->isJumpPoint;
6565 ret->canBreak = e1->canBreak;
6569 if (exprNode_isDefined (e2))
6571 ret->loc = fileloc_update (ret->loc, e2->loc);
6575 if (exprNode_isDefined (e2))
6577 ret->exitCode = e2->exitCode;
6578 ret->mustBreak = e2->mustBreak;
6579 if (e2->canBreak) ret->canBreak = TRUE;
6583 ** if e1 must return, then e2 is unreachable!
6586 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6588 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6589 && !(e2->isJumpPoint))
6591 if (context_getFlag (FLG_UNREACHABLE))
6595 if (e2->kind == XPR_STMT)
6597 nr = exprData_getUopNode (e2->edata);
6600 if ((nr->kind == XPR_TOK
6601 && lltok_isSemi (exprData_getTok (nr->edata))))
6603 /* okay to have unreachable ";" */
6604 ret->exitCode = XK_MUSTEXIT;
6605 ret->canBreak = TRUE;
6609 if (optgenerror (FLG_UNREACHABLE,
6610 message ("Unreachable code: %s",
6611 exprNode_unparseFirst (nr)),
6614 ret->isJumpPoint = TRUE;
6615 ret->mustBreak = FALSE;
6616 ret->exitCode = XK_ERROR;
6617 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6621 ret->exitCode = XK_MUSTEXIT;
6622 ret->canBreak = TRUE;
6630 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6633 ** We want a warning anytime we have:
6635 ** yyy; <<<- no break or return
6639 exprNode lastStmt = exprNode_lastStatement (e1);
6641 if (exprNode_isDefined (lastStmt)
6642 && !exprNode_mustEscape (lastStmt)
6643 && !exprNode_mustBreak (lastStmt)
6644 && !exprNode_isCaseMarker (lastStmt)
6645 && !exprNode_isDefaultMarker (lastStmt)
6646 && !exprNode_isLabelMarker (lastStmt))
6648 voptgenerror (FLG_CASEBREAK,
6650 ("Fall through case (no preceding break)"),
6657 exprNode_mergeUSs (ret, e2);
6659 usymtab_setExitCode (ret->exitCode);
6663 usymtab_setMustBreak ();
6669 exprNode exprNode_createTok (/*@only@*/ lltok t)
6671 exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6672 ret = exprNode_create (ctype_unknown);
6673 ret->kind = XPR_TOK;
6674 ret->edata = exprData_makeTok (t);
6678 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6680 if (!exprNode_isError (e))
6682 exprNode_checkStatement(e);
6685 return (exprNode_statementError (e, t));
6688 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6690 exprNode ret = exprNode_createPartialCopy (e);
6692 if (!exprNode_isError (e))
6694 if (e->kind != XPR_ASSIGN)
6696 exprNode_checkUse (ret, e->sref, e->loc);
6699 ret->exitCode = e->exitCode;
6700 ret->canBreak = e->canBreak;
6701 ret->mustBreak = e->mustBreak;
6704 ret->edata = exprData_makeUop (e, t);
6705 ret->kind = XPR_STMT;
6710 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6712 if (!exprNode_isError (e))
6714 if (e->kind != XPR_ASSIGN)
6716 exprNode_checkUse (e, e->sref, e->loc);
6723 void exprNode_produceGuards (exprNode pred)
6725 if (!exprNode_isError (pred))
6727 if (ctype_isRealPointer (pred->typ))
6729 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6732 exprNode_checkUse (pred, pred->sref, pred->loc);
6733 exprNode_resetSref (pred);
6737 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6739 exprNode ret = exprNode_createPartialCopy (e);
6741 if (!exprNode_isError (e))
6743 ret->exitCode = e->exitCode;
6744 ret->canBreak = e->canBreak;
6745 ret->mustBreak = e->mustBreak;
6748 ret->edata = exprData_makeSingle (e);
6749 ret->kind = XPR_BLOCK;
6753 bool exprNode_isBlock (exprNode e)
6755 return (exprNode_isDefined (e)
6756 && ((e)->kind == XPR_BLOCK));
6759 bool exprNode_isAssign (exprNode e)
6761 if (exprNode_isDefined (e))
6763 return (e->kind == XPR_ASSIGN);
6769 bool exprNode_isEmptyStatement (exprNode e)
6771 return (exprNode_isDefined (e)
6772 && (e->kind == XPR_TOK)
6773 && (lltok_isSemi (exprData_getTok (e->edata))));
6776 void exprNode_checkIfPred (exprNode pred)
6778 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6781 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6784 bool emptyErr = FALSE;
6786 if (context_maybeSet (FLG_IFEMPTY))
6788 if (exprNode_isEmptyStatement (tclause))
6790 emptyErr = optgenerror (FLG_IFEMPTY,
6792 ("Body of if statement is empty"),
6793 exprNode_loc (tclause));
6797 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6799 if (exprNode_isDefined (tclause)
6800 && !exprNode_isBlock (tclause))
6802 voptgenerror (FLG_IFBLOCK,
6804 ("Body of if statement is not a block: %s",
6805 exprNode_unparse (tclause)),
6806 exprNode_loc (tclause));
6810 if (exprNode_isError (pred))
6812 if (exprNode_isError (tclause))
6814 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6818 ret = exprNode_createPartialCopy (tclause);
6823 if (exprNode_mustEscape (pred))
6827 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6828 exprNode_loc (pred));
6831 /*! exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred); */ /*@i523@*/
6832 exprNode_checkUse (pred, pred->sref, pred->loc);
6834 if (!exprNode_isError (tclause))
6836 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
6839 ret = exprNode_createPartialCopy (pred);
6843 ret->edata = exprData_makePair (pred, tclause);
6845 ret->exitCode = XK_UNKNOWN;
6847 if (exprNode_isDefined (tclause))
6849 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
6850 ret->canBreak = tclause->canBreak;
6851 ret->sets = sRefSet_union (ret->sets, tclause->sets);
6852 ret->msets = sRefSet_union (ret->msets, tclause->msets);
6853 ret->uses = sRefSet_union (ret->uses, tclause->uses);
6856 ret->mustBreak = FALSE;
6861 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
6862 /*@only@*/ exprNode tclause,
6863 /*@only@*/ exprNode eclause)
6866 bool tEmptyErr = FALSE;
6867 bool eEmptyErr = FALSE;
6869 if (context_maybeSet (FLG_IFEMPTY))
6871 if (exprNode_isEmptyStatement (tclause))
6873 tEmptyErr = optgenerror
6876 ("Body of if clause of if statement is empty"),
6877 exprNode_loc (tclause));
6880 if (exprNode_isEmptyStatement (eclause))
6882 eEmptyErr = optgenerror
6885 ("Body of else clause of if statement is empty"),
6886 exprNode_loc (eclause));
6890 if (context_maybeSet (FLG_IFBLOCK))
6893 && exprNode_isDefined (tclause)
6894 && !exprNode_isBlock (tclause))
6896 voptgenerror (FLG_IFBLOCK,
6898 ("Body of if clause of if statement is not a block: %s",
6899 exprNode_unparse (tclause)),
6900 exprNode_loc (tclause));
6904 && exprNode_isDefined (eclause)
6905 && !exprNode_isBlock (eclause)
6906 && !(eclause->kind == XPR_IF)
6907 && !(eclause->kind == XPR_IFELSE))
6912 ("Body of else clause of if statement is not a block: %s",
6913 exprNode_unparse (eclause)),
6914 exprNode_loc (eclause));
6918 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
6920 if (exprNode_isDefined (eclause)
6921 && (eclause->kind == XPR_IF))
6923 voptgenerror (FLG_ELSEIFCOMPLETE,
6924 message ("Incomplete else if logic (no final else): %s",
6925 exprNode_unparse (eclause)),
6926 exprNode_loc (eclause));
6930 if (exprNode_isError (pred))
6932 if (exprNode_isError (tclause))
6934 if (exprNode_isError (eclause))
6936 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6940 ret = exprNode_createPartialCopy (eclause);
6945 ret = exprNode_createPartialCopy (tclause);
6948 else /* pred is okay */
6950 ret = exprNode_createPartialCopy (pred);
6952 if (exprNode_mustEscape (pred))
6956 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6957 exprNode_loc (pred));
6960 /*@i3423 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);*/
6961 exprNode_checkUse (ret, pred->sref, pred->loc);
6963 exprNode_mergeCondUSs (ret, tclause, eclause);
6966 ret->kind = XPR_IFELSE;
6967 ret->edata = exprData_makeCond (pred, tclause, eclause);
6969 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
6971 exprNode_combineControl (ret, tclause, eclause);
6972 ret->loc = fileloc_update (ret->loc, eclause->loc);
6979 ** *allpaths <- TRUE iff all executions paths must go through the switch
6983 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
6985 exprNodeSList el = exprNode_flatten (e);
6986 bool mustReturn = TRUE; /* find a branch that doesn't */
6987 bool thisReturn = FALSE;
6988 bool hasDefault = FALSE;
6989 bool hasAllMembers = FALSE;
6990 bool inSwitch = FALSE;
6991 bool isEnumSwitch = FALSE;
6992 bool canBreak = FALSE;
6993 bool fallThrough = FALSE;
6994 ctype ct = ctype_unknown;
6995 enumNameSList usedEnums;
6998 if (exprNode_isDefined (test))
7003 ttype = ctype_realType (ct);
7005 if (ctype_isEnum (ttype))
7007 isEnumSwitch = TRUE;
7008 enums = ctype_elist (ttype);
7009 usedEnums = enumNameSList_new ();
7013 exprNodeSList_elements (el, current)
7015 if (exprNode_isDefined (current))
7017 switch (current->kind)
7024 (FLG_DUPLICATECASES,
7025 message ("Duplicate default cases in switch"),
7026 exprNode_loc (current));
7031 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
7039 exprNode st = exprData_getSingle (current->edata);
7040 uentry ue = exprNode_getUentry (st);
7042 if (uentry_isValid (ue))
7044 cstring cname = uentry_rawName (ue);
7046 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
7048 if (enumNameSList_member
7049 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
7052 (FLG_DUPLICATECASES,
7053 message ("Duplicate case in switch: %s",
7059 enumNameSList_addh (usedEnums, cname);
7066 message ("Case in switch not %s member: %s",
7067 ctype_unparse (ct), cname),
7074 if (inSwitch && !fallThrough)
7076 if (!thisReturn || canBreak)
7086 /*@switchbreak@*/ break;
7088 thisReturn = thisReturn || exprNode_mustEscape (current);
7089 canBreak = canBreak || current->canBreak;
7090 if (canBreak) fallThrough = FALSE;
7093 } end_exprNodeSList_elements;
7095 if (inSwitch) /* check the last one! */
7097 if (!thisReturn || canBreak)
7106 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
7107 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
7109 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
7111 voptgenerror (FLG_MISSCASE,
7112 message ("Missing case%s in switch: %q",
7113 cstring_makeLiteralTemp
7114 ((enumNameSList_size (unused) > 1) ? "s" : ""),
7115 enumNameSList_unparse (unused)),
7118 enumNameSList_free (unused);
7119 *allpaths = FALSE; /* evans 2002-01-01 */
7123 hasAllMembers = TRUE;
7127 enumNameSList_free (usedEnums);
7131 *allpaths = hasDefault;
7134 exprNodeSList_free (el);
7135 return ((hasDefault || hasAllMembers) && mustReturn);
7138 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
7140 exprNode ret = exprNode_createPartialCopy (e);
7143 DPRINTF (("Switch: %s", exprNode_unparse (s)));
7145 ret->kind = XPR_SWITCH;
7146 ret->edata = exprData_makePair (e, s);
7148 if (!exprNode_isError (s))
7150 exprNode fs = exprNode_firstStatement (s);
7151 ret->loc = fileloc_update (ret->loc, s->loc);
7153 if (exprNode_isUndefined (fs)
7154 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
7155 || exprNode_isDefaultMarker (fs)) {
7158 voptgenerror (FLG_FIRSTCASE,
7160 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
7165 if (!exprNode_isError (e))
7167 if (checkSwitchExpr (e, s, &allpaths))
7169 ret->exitCode = XK_MUSTRETURN;
7173 ret->exitCode = e->exitCode;
7176 ret->canBreak = e->canBreak;
7177 ret->mustBreak = e->mustBreak;
7181 ** exprNode.c:3883,32: Variable allpaths used before definition
7188 DPRINTF (("Context exit switch!"));
7189 context_exitSwitch (ret, allpaths);
7190 DPRINTF (("Context exit switch done!"));
7195 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
7196 /*@notnull@*/ exprNode body)
7198 sRefSet tuses = test->uses;
7200 if (!sRefSet_isEmpty (test->uses))
7202 sRefSet sets = sRefSet_newCopy (body->sets);
7203 bool hasError = TRUE;
7204 bool innerState = FALSE;
7205 sRefSet tuncon = sRefSet_undefined;
7207 sets = sRefSet_union (sets, test->sets);
7208 sets = sRefSet_union (sets, body->msets);
7209 sets = sRefSet_union (sets, test->msets);
7211 sRefSet_allElements (tuses, el)
7213 if (sRef_isUnconstrained (el))
7215 tuncon = sRefSet_insert (tuncon, el);
7219 if (sRefSet_member (sets, el))
7226 if (sRef_isInternalState (el)
7227 || sRef_isFileStatic (sRef_getRootBase (el)))
7231 } end_sRefSet_allElements ;
7235 sRefSet suncon = sRefSet_undefined;
7236 bool sinner = FALSE;
7238 sRefSet_allElements (sets, el)
7240 if (sRef_isUnconstrained (el))
7242 suncon = sRefSet_insert (suncon, el);
7244 else if (sRef_isInternalState (el))
7252 } end_sRefSet_allElements ;
7254 if (sinner && innerState)
7258 else if (sRefSet_isEmpty (tuncon)
7259 && sRefSet_isEmpty (suncon))
7264 ("Suspected infinite loop. No value used in loop test (%q) "
7265 "is modified by test or loop body.",
7266 sRefSet_unparsePlain (tuses)),
7271 if (sRefSet_isEmpty (tuncon))
7275 message ("Suspected infinite loop. No condition values "
7276 "modified. Modification possible through "
7277 "unconstrained calls: %q",
7278 sRefSet_unparsePlain (suncon)),
7285 message ("Suspected infinite loop. No condition values "
7286 "modified. Possible undetected dependency through "
7287 "unconstrained calls in loop test: %q",
7288 sRefSet_unparsePlain (tuncon)),
7294 sRefSet_free (sets);
7298 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7301 bool emptyErr = FALSE;
7303 if (context_maybeSet (FLG_WHILEEMPTY))
7305 if (exprNode_isEmptyStatement (b))
7307 emptyErr = optgenerror
7310 ("Body of while statement is empty"),
7315 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7317 if (exprNode_isDefined (b)
7318 && !exprNode_isBlock (b))
7320 if (context_inIterDef ()
7321 && (b->kind == XPR_STMTLIST
7322 || b->kind == XPR_TOK))
7328 voptgenerror (FLG_WHILEBLOCK,
7330 ("Body of while statement is not a block: %s",
7331 exprNode_unparse (b)),
7337 if (exprNode_isError (t))
7339 if (exprNode_isError (b))
7341 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7345 ret = exprNode_createPartialCopy (b);
7352 ret = exprNode_createPartialCopy (t);
7354 llassert (t->kind == XPR_WHILEPRED);
7356 test = exprData_getSingle (t->edata);
7358 if (!exprNode_isError (b) && exprNode_isDefined (test))
7360 if (context_maybeSet (FLG_INFLOOPS)
7361 || context_maybeSet (FLG_INFLOOPSUNCON))
7364 ** check that some variable in the predicate is set by the body
7365 ** if the predicate uses any variables
7368 checkInfiniteLoop (test, b);
7371 exprNode_mergeUSs (ret, b);
7373 if (exprNode_isDefined (b))
7375 ret->exitCode = exitkind_makeConditional (b->exitCode);
7380 ret->edata = exprData_makePair (t, b);
7381 ret->kind = XPR_WHILE;
7383 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7387 message ("Predicate always exits: %s", exprNode_unparse (t)),
7391 ret->exitCode = XK_NEVERESCAPE;
7394 ** If loop is infinite, and there is no break inside,
7395 ** exit code is never reach.
7398 if (exprNode_knownIntValue (t))
7400 if (!exprNode_isZero (t))
7402 if (exprNode_isDefined (b))
7406 /* Really, it means never reached. */
7407 ret->exitCode = XK_MUSTEXIT;
7417 ret->canBreak = FALSE;
7418 ret->mustBreak = FALSE;
7424 ** do { b } while (t);
7426 ** note: body passed as first argument
7429 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7433 DPRINTF (("Do while: %s / %s",
7434 exprNode_unparse (b), exprNode_unparse (t)));
7436 if (exprNode_isError (t))
7438 if (exprNode_isError (b))
7440 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7444 ret = exprNode_createPartialCopy (b);
7446 ret->exitCode = exitkind_makeConditional (b->exitCode);
7447 exprNode_checkUse (ret, b->sref, b->loc);
7448 ret->exitCode = b->exitCode;
7449 ret->canBreak = b->canBreak;
7450 ret->mustBreak = FALSE;
7455 DPRINTF (("Do while: %s / %s",
7456 exitkind_unparse (t->exitCode),
7457 exitkind_unparse (b->exitCode)));
7459 ret = exprNode_createPartialCopy (t);
7460 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7462 if (!exprNode_isError (b))
7465 ** forgot the copy's --- why wasn't this detected??
7468 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7469 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7470 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
7472 /* left this out --- causes and aliasing bug (infinite loop)
7473 should be detected?? */
7475 exprNode_checkUse (ret, b->sref, b->loc);
7476 exprNode_mergeUSs (ret, t);
7477 exprNode_checkUse (ret, t->sref, t->loc);
7479 /* evans 2001-10-05: while loop can break */
7480 ret->exitCode = exitkind_makeConditional (b->exitCode);
7482 DPRINTF (("Do while: %s",
7483 exitkind_unparse (ret->exitCode)));
7485 ret->canBreak = b->canBreak;
7487 /* Always FALSE for doWhile loops - break's when test is false */
7488 ret->mustBreak = FALSE; /* b->mustBreak; */
7492 context_exitDoWhileClause (t);
7494 ret->kind = XPR_DOWHILE;
7495 ret->edata = exprData_makePair (t, b);
7499 bool exprNode_loopMustExec (exprNode forPred)
7502 ** Returns true if it is obvious that the loop always executes at least once
7504 ** For now, we only identify the most obvious cases. Should be true anytime
7505 ** we can prove init => !test.
7508 if (exprNode_isDefined (forPred))
7510 exprNode init, test, inc;
7513 llassert (forPred->kind == XPR_FORPRED);
7515 edata = forPred->edata;
7516 init = exprData_getTripleInit (edata);
7517 test = exprData_getTripleTest (edata);
7518 inc = exprData_getTripleInc (edata);
7520 if (exprNode_isAssign (init))
7522 exprNode loopVar = exprData_getOpA (init->edata);
7523 exprNode loopInit = exprData_getOpB (init->edata);
7525 if (exprNode_isDefined (test) && test->kind == XPR_OP)
7527 exprNode testVar = exprData_getOpA (test->edata);
7528 exprNode testVal = exprData_getOpB (test->edata);
7529 lltok comp = exprData_getOpTok (test->edata);
7530 int opid = lltok_getTok (comp);
7532 DPRINTF (("Same storage: %s / %s", exprNode_unparse (loopVar),
7533 exprNode_unparse (testVar)));
7535 if (exprNode_sameStorage (loopVar, testVar))
7537 multiVal valinit = exprNode_getValue (loopInit);
7538 multiVal valtest = exprNode_getValue (testVal);
7540 DPRINTF (("Values: %s / %s", multiVal_unparse (valinit),
7541 multiVal_unparse (valtest)));
7543 if (multiVal_isInt (valinit) && multiVal_isInt (valtest))
7545 long v1 = multiVal_forceInt (valinit);
7546 long v2 = multiVal_forceInt (valtest);
7548 DPRINTF (("Here: %ld %ld", v1, v2));
7550 if ((opid == EQ_OP && v1 < v2)
7551 || (opid == NE_OP && v1 != v2)
7552 || (opid == TLT && v1 <= v2)
7553 || (opid == TGT && v1 >= v2)
7554 || (opid == LE_OP && v1 < v2)
7555 || (opid == GE_OP && v1 > v2))
7557 DPRINTF (("mustexec if inc"));
7566 DPRINTF (("loop must exec: FALSE"));
7570 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7573 bool emptyErr = FALSE;
7575 if (context_maybeSet (FLG_FOREMPTY))
7577 if (exprNode_isEmptyStatement (body))
7579 emptyErr = optgenerror
7582 ("Body of for statement is empty"),
7583 exprNode_loc (body));
7587 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7589 if (exprNode_isDefined (body)
7590 && !exprNode_isBlock (body))
7592 if (context_inIterDef ()
7593 && (body->kind == XPR_STMTLIST
7594 || body->kind == XPR_TOK))
7600 voptgenerror (FLG_FORBLOCK,
7602 ("Body of for statement is not a block: %s",
7603 exprNode_unparse (body)),
7604 exprNode_loc (body));
7610 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7613 if (exprNode_isError (body))
7615 ret = exprNode_createPartialCopy (inc);
7619 ret = exprNode_createPartialCopy (body);
7621 ret->exitCode = exitkind_makeConditional (body->exitCode);
7623 exprNode_mergeUSs (inc, body);
7625 if (exprNode_isDefined (inc))
7629 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7631 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7632 exprNode_freeShallow (tmp);
7634 context_clearMessageAnnote ();
7635 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7637 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7638 exprNode_freeShallow (tmp);
7640 context_clearMessageAnnote ();
7642 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7643 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7644 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7648 ret->kind = XPR_FOR;
7649 ret->edata = exprData_makePair (inc, body);
7651 if (exprNode_isDefined (inc)) {
7652 exprNode test = exprData_getTripleTest (inc->edata);
7654 if (exprNode_isUndefined (test)) {
7655 if (exprNode_isDefined (body)) {
7656 if (!body->canBreak) {
7657 /* Really, it means never reached. */
7658 ret->exitCode = XK_MUSTEXIT;
7668 ** for (init; test; inc)
7671 ** while (test) { body; inc; }
7673 ** Now: check use of init (may set vars for test)
7674 ** check use of test
7678 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7682 if (exprNode_isError (pred)) return guardSet_undefined;
7684 llassert (pred->kind == XPR_FORPRED);
7686 test = exprData_getTripleTest (pred->edata);
7688 if (!exprNode_isError (test))
7690 return (test->guards);
7693 return guardSet_undefined;
7696 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7698 exprNode ret = exprNode_createSemiCopy (test);
7700 if (exprNode_isDefined (test))
7702 exprNode_copySets (ret, test);
7703 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7704 exprNode_checkUse (ret, test->sref, test->loc);
7706 exprNode_produceGuards (test);
7708 ret->guards = guardSet_copy (test->guards);
7711 ret->edata = exprData_makeSingle (test);
7712 ret->kind = XPR_WHILEPRED;
7716 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7717 /*@only@*/ exprNode inc)
7722 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7725 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7727 if (!exprNode_isError (inc))
7729 ret = exprNode_createPartialCopy (inc);
7733 if (!exprNode_isError (init))
7735 ret = exprNode_createPartialCopy (init);
7737 else if (!exprNode_isError (test))
7739 ret = exprNode_createPartialCopy (test);
7743 ret = exprNode_createUnknown ();
7747 exprNode_mergeUSs (ret, init);
7749 if (exprNode_isDefined (init))
7751 exprNode_checkUse (ret, init->sref, init->loc);
7754 exprNode_mergeUSs (ret, test);
7756 if (exprNode_isDefined (test))
7758 exprNode_checkUse (ret, test->sref, test->loc);
7761 ret->kind = XPR_FORPRED;
7762 ret->edata = exprData_makeFor (init, test, inc);
7766 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7768 exprNode ret = exprNode_createUnknown ();
7770 if (context_inMacro ())
7772 voptgenerror (FLG_MACROSTMT,
7773 message ("Macro %s uses goto (not functional)",
7774 context_inFunctionName ()),
7778 ret->kind = XPR_GOTO;
7779 ret->edata = exprData_makeLiteral (label);
7780 ret->mustBreak = TRUE;
7781 ret->exitCode = XK_GOTO;
7782 ret->canBreak = TRUE;
7786 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7788 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7790 ret->kind = XPR_CONTINUE;
7791 ret->edata = exprData_makeTok (l);
7792 ret->canBreak = TRUE;
7793 ret->mustBreak = TRUE;
7795 if (qcontinue == QSAFEBREAK)
7799 else if (qcontinue == QINNERCONTINUE)
7801 if (!context_inDeepLoop ())
7804 (FLG_LOOPLOOPCONTINUE,
7805 cstring_makeLiteral ("Continue statement marked with innercontinue "
7806 "is not inside a nested loop"),
7807 exprNode_loc (ret));
7810 else if (qcontinue == BADTOK)
7812 if (context_inDeepLoop ())
7815 (FLG_LOOPLOOPCONTINUE,
7816 cstring_makeLiteral ("Continue statement in nested loop"),
7817 exprNode_loc (ret));
7822 llbuglit ("exprNode_continue: bad qcontinue");
7828 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
7830 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7831 clause breakClause = context_breakClause ();
7833 ret->kind = XPR_BREAK;
7834 ret->edata = exprData_makeTok (l);
7835 ret->canBreak = TRUE;
7836 ret->mustBreak = TRUE;
7838 if (breakClause == NOCLAUSE)
7842 cstring_makeLiteral ("Break not inside while, for or switch statement"),
7843 exprNode_loc (ret));
7847 if (bqual != BADTOK)
7854 if (breakClause == SWITCHCLAUSE)
7856 if (!context_inDeepSwitch ())
7858 voptgenerror (FLG_SYNTAX,
7860 ("Break preceded by innerbreak is not in a deep switch"),
7861 exprNode_loc (ret));
7866 if (!context_inDeepLoop ())
7868 voptgenerror (FLG_SYNTAX,
7870 ("Break preceded by innerbreak is not in a deep loop"),
7871 exprNode_loc (ret));
7876 if (breakClause == SWITCHCLAUSE)
7878 voptgenerror (FLG_SYNTAX,
7880 ("Break preceded by loopbreak is breaking a switch"),
7881 exprNode_loc (ret));
7885 if (breakClause != SWITCHCLAUSE)
7889 message ("Break preceded by switchbreak is breaking %s",
7890 cstring_makeLiteralTemp
7891 ((breakClause == WHILECLAUSE
7892 || breakClause == DOWHILECLAUSE) ? "a while loop"
7893 : (breakClause == FORCLAUSE) ? "a for loop"
7894 : (breakClause == ITERCLAUSE) ? "an iterator"
7896 exprNode_loc (ret));
7904 if (breakClause == SWITCHCLAUSE)
7906 clause nextBreakClause = context_nextBreakClause ();
7908 switch (nextBreakClause)
7910 case NOCLAUSE: break;
7916 (FLG_LOOPSWITCHBREAK,
7917 cstring_makeLiteral ("Break statement in switch inside loop"),
7918 exprNode_loc (ret));
7922 (FLG_SWITCHSWITCHBREAK,
7923 cstring_makeLiteral ("Break statement in switch inside switch"),
7924 exprNode_loc (ret));
7931 if (context_inDeepLoop ())
7935 cstring_makeLiteral ("Break statement in nested loop"),
7936 exprNode_loc (ret));
7940 if (context_inDeepLoopSwitch ())
7943 (FLG_SWITCHLOOPBREAK,
7944 cstring_makeLiteral ("Break statement in loop inside switch"),
7945 exprNode_loc (ret));
7955 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
7957 fileloc loc = lltok_getLoc (t);
7958 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
7960 context_returnFunction ();
7961 exprChecks_checkNullReturn (loc);
7963 ret->kind = XPR_NULLRETURN;
7964 ret->edata = exprData_makeTok (t);
7965 ret->exitCode = XK_MUSTRETURN;
7969 exprNode exprNode_return (/*@only@*/ exprNode e)
7973 if (exprNode_isError (e))
7975 ret = exprNode_createUnknown ();
7979 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
7981 exprNode_checkUse (ret, e->sref, e->loc);
7982 exprNode_checkReturn (e);
7985 context_returnFunction ();
7986 ret->kind = XPR_RETURN;
7987 ret->edata = exprData_makeSingle (e);
7988 ret->exitCode = XK_MUSTRETURN;
7993 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
7997 if (exprNode_isError (e1))
7999 if (exprNode_isError (e2))
8001 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
8005 ret = exprNode_createPartialCopy (e2);
8006 exprNode_checkUse (ret, e2->sref, e2->loc);
8007 ret->sref = e2->sref;
8012 ret = exprNode_createPartialCopy (e1);
8014 exprNode_checkUse (ret, e1->sref, e1->loc);
8016 if (!exprNode_isError (e2))
8018 exprNode_mergeUSs (ret, e2);
8019 exprNode_checkUse (ret, e2->sref, e2->loc);
8020 ret->sref = e2->sref;
8024 ret->kind = XPR_COMMA;
8025 ret->edata = exprData_makePair (e1, e2);
8027 if (exprNode_isDefined (e1))
8029 if (exprNode_isDefined (e2))
8033 if (exprNode_mustEscape (e1) || e1->mustBreak)
8037 message ("Second clause of comma expression is unreachable: %s",
8038 exprNode_unparse (e2)),
8042 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
8043 ret->mustBreak = e1->mustBreak || e2->mustBreak;
8044 ret->canBreak = e1->canBreak || e2->canBreak;
8048 if (exprNode_mustEscape (e1) || e1->mustBreak)
8052 message ("Second clause of comma expression is unreachable: %s",
8053 exprNode_unparse (e2)),
8057 ret->exitCode = e1->exitCode;
8058 ret->canBreak = e1->canBreak;
8063 if (exprNode_isDefined (e2))
8065 ret->exitCode = e2->exitCode;
8066 ret->mustBreak = e2->mustBreak;
8067 ret->canBreak = e2->canBreak;
8074 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
8076 ctype t1 = exprNode_getType (el);
8077 ctype t2 = exprNode_getType (val);
8078 bool hasError = FALSE;
8080 DPRINTF (("Check one init: %s / %s",
8081 exprNode_unparse (el),
8082 exprNode_unparse (val)));
8084 if (ctype_isUnknown (t1))
8086 voptgenerror (FLG_IMPTYPE,
8087 message ("Variable has unknown (implicitly int) type: %s",
8088 exprNode_unparse (el)),
8092 el->typ = ctype_int;
8095 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
8097 exprNodeList vals = exprData_getArgs (val->edata);
8099 DPRINTF (("Check one init: %s", exprNodeList_unparse (vals)));
8100 DPRINTF (("Type: %s", ctype_unparse (t1)));
8102 if (ctype_isRealAP (t1))
8107 if (ctype_isFixedArray (t1))
8109 int nelements = long_toInt (ctype_getArraySize (t1));
8111 if (exprNode_isStringLiteral (val))
8113 exprNode_checkStringLiteralLength (t1, val);
8117 if (exprNodeList_size (vals) != nelements)
8119 hasError = optgenerror
8120 (exprNodeList_size (vals) > nelements ? FLG_INITSIZE : FLG_INITALLELEMENTS,
8121 message ("Initializer block for "
8122 "%s has %d element%&, but declared as %s: %q",
8123 exprNode_unparse (el),
8124 exprNodeList_size (vals),
8126 exprNodeList_unparse (vals)),
8132 exprNodeList_elements (vals, oneval)
8134 cstring istring = message ("%d", i);
8137 (exprNode_fakeCopy (el),
8138 exprNode_numLiteral (ctype_int, istring,
8139 fileloc_copy (el->loc), i));
8141 if (exprNode_isDefined (newel))
8143 if (exprNodeList_size (vals) == 1
8144 && ctype_isString (exprNode_getType (oneval))
8145 && ctype_isChar (exprNode_getType (newel)))
8147 exprNode_freeIniter (newel);
8151 if (exprNode_checkOneInit (newel, oneval))
8156 if (nerrors > 3 && exprNodeList_size (vals) > 6)
8159 (message ("Additional initialization errors "
8160 "for %s not reported",
8161 exprNode_unparse (el)),
8163 exprNode_freeIniter (newel);
8168 exprNode_freeIniter (newel);
8173 exprNode_freeIniter (newel);
8178 cstring_free (istring);
8181 } end_exprNodeList_elements;
8184 else if (ctype_isStruct (ctype_realType (t1)))
8186 uentryList fields = ctype_getFields (t1);
8189 if (uentryList_size (fields) != exprNodeList_size (vals))
8191 if (uentryList_size (fields) > exprNodeList_size (vals))
8193 hasError = optgenerror
8195 message ("Initializer block for "
8196 "%s has %d field%&, but %s has %d field%&: %q",
8197 exprNode_unparse (el),
8198 exprNodeList_size (vals),
8200 uentryList_size (fields),
8201 exprNodeList_unparse (vals)),
8206 hasError = optgenerror
8208 message ("Initializer block for "
8209 "%s has %d field%&, but %s has %d field%&: %q",
8210 exprNode_unparse (el),
8211 exprNodeList_size (vals),
8213 uentryList_size (fields),
8214 exprNodeList_unparse (vals)),
8220 exprNodeList_elements (vals, oneval)
8222 uentry thisfield = uentryList_getN (fields, i);
8224 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8226 uentry_getName (thisfield));
8228 if (exprNode_isDefined (newel))
8230 if (exprNode_checkOneInit (newel, oneval))
8235 exprNode_freeIniter (newel);
8239 } end_exprNodeList_elements;
8242 /* evans 2001-12-30: added to fix bug reported by Jim Zelenka */
8243 else if (ctype_isUnion (ctype_realType (t1)))
8245 uentryList fields = ctype_getFields (t1);
8249 ** Union initializers set the first member always.
8252 DPRINTF (("Union initializer: %s / %s",
8253 exprNode_unparse (el), ctype_unparse (ctype_realType (t1))));
8255 if (exprNodeList_size (vals) != 1)
8257 hasError = optgenerror
8259 message ("Initializer block for union "
8260 "%s has %d elements, union initializers should have one element: %q",
8261 exprNode_unparse (el),
8262 exprNodeList_size (vals),
8263 exprNodeList_unparse (vals)),
8268 exprNode oneval = exprNodeList_head (vals);
8269 uentry thisfield = uentryList_getN (fields, i);
8271 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8273 uentry_getName (thisfield));
8275 if (exprNode_isDefined (newel))
8277 if (exprNode_checkOneInit (newel, oneval))
8282 exprNode_freeIniter (newel);
8288 hasError = optgenerror
8290 message ("Initializer block used for "
8291 "%s where %t is expected: %s",
8292 exprNode_unparse (el), t1, exprNode_unparse (val)),
8298 if (exprNode_isDefined (val))
8300 doAssign (el, val, TRUE);
8302 if (!exprNode_matchType (t1, val))
8304 hasError = gentypeerror
8306 message ("Initial value of %s is type %t, "
8308 exprNode_unparse (el),
8309 t2, t1, exprNode_unparse (val)),
8319 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
8323 DPRINTF (("Initialization: %s", idDecl_unparse (t)));
8325 if (usymtab_exists (idDecl_observeId (t)))
8327 uentry ue = usymtab_lookup (idDecl_observeId (t));
8328 ret = exprNode_createId (ue);
8330 /*@i723 don't do this...but why? */
8332 ct = ctype_realishType (ret->typ);
8334 DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
8336 if (ctype_isUnknown (ct))
8338 if (uentry_isAnyTag (ue))
8342 message ("%s used but not previously declared: %s",
8343 uentry_ekindName (ue),
8344 idDecl_getName (t)),
8352 message ("Variable has unknown (implicitly int) type: %s",
8353 idDecl_getName (t)),
8365 DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
8367 ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
8368 /*!! fileloc_copy (g_currentloc)); */
8369 /*@i32!!! should get error without this */
8371 ret = exprNode_fromIdentifierAux (ue);
8374 ** No error - this happens in old style declarations:
8378 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8385 exprData_free (ret->edata, ret->kind);
8386 ret->edata = exprData_undefined;
8388 ret->exitCode = XK_NEVERESCAPE;
8389 ret->mustBreak = FALSE;
8390 ret->kind = XPR_INIT;
8394 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8396 exprNode ret = exprNode_makeInitializationAux (t);
8397 llassert (ret->edata == exprData_undefined);
8398 ret->edata = exprData_makeInit (t, exprNode_undefined);
8402 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8403 /*@only@*/ exprNode e)
8405 uentry ue = usymtab_lookup (idDecl_observeId (t));
8406 exprNode ret = exprNode_makeInitializationAux (t);
8407 fileloc loc = exprNode_loc (e);
8409 if (exprNode_isError (e))
8411 e = exprNode_createUnknown ();
8414 /* error: assume initializer is defined */
8415 sRef_setDefined (ret->sref, g_currentloc);
8419 ctype ct = ctype_realishType (ret->typ);
8424 ** was addSafeUse --- what's the problem?
8426 ** int x = 3, y = x ?
8429 exprData_free (ret->edata, ret->kind);
8430 ret->edata = exprData_makeInit (t, e);
8432 exprNode_checkUse (ret, e->sref, e->loc);
8434 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8436 exprNode lhs = exprNode_createId (ue);
8439 ** static storage should be undefined before initializing
8442 if (uentry_isStatic (ue))
8444 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8447 (void) exprNode_checkOneInit (lhs, e);
8449 if (uentry_isStatic (ue))
8451 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8454 exprNode_free (lhs);
8458 if (!exprNode_matchType (ct, e))
8460 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
8467 (exprNode_getType (e), e, exprNode_getType (ret), ret,
8469 ("Variable %q initialized to type %t, expects %t: %s",
8470 uentry_getName (ue), exprNode_getType (e),
8471 exprNode_getType (ret),
8472 exprNode_unparse (e)),
8478 if (uentry_isStatic (ue))
8480 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8483 doAssign (ret, e, TRUE);
8485 if (uentry_isStatic (ue))
8487 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8491 if (context_inIterDef ())
8493 /* should check if it is yield */
8494 uentry_setUsed (ue, loc);
8501 exprNode_mergeUSs (ret, e);
8505 exprNode exprNode_iter (/*@observer@*/ uentry name,
8506 /*@only@*/ exprNodeList alist,
8507 /*@only@*/ exprNode body,
8508 /*@observer@*/ uentry end)
8513 llassert (uentry_isValid (name));
8515 uentry_setUsed (name, exprNode_loc (body));
8517 ret = exprNode_createPartialCopy (body);
8518 iname = uentry_getName (name);
8520 if (uentry_isInvalid (end))
8522 llerror (FLG_ITERBALANCE,
8523 message ("Iter %s not balanced with end_%s", iname, iname));
8527 cstring ename = uentry_getName (end);
8529 if (!cstring_equalPrefixLit (ename, "end_"))
8531 llerror (FLG_ITERBALANCE, message ("Iter %s not balanced with end_%s: %s",
8532 iname, iname, ename));
8536 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8538 llerror (FLG_ITERBALANCE,
8539 message ("Iter %s not balanced with end_%s: %s",
8540 iname, iname, ename));
8544 cstring_free (ename);
8547 context_exitIterClause (body);
8549 ret->kind = XPR_ITER;
8550 ret->edata = exprData_makeIter (name, alist, body, end);
8552 if (uentry_isIter (name))
8554 (void) checkArgsReal (name, body,
8555 uentry_getParams (name), alist, TRUE, ret);
8558 cstring_free (iname);
8564 exprNode_iterNewId (/*@only@*/ cstring s)
8566 exprNode e = exprNode_new ();
8567 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8569 llassert (processingIterVars ());
8571 e->loc = context_getSaveLocation ();
8573 if (fileloc_isUndefined (e->loc))
8575 fileloc_free (e->loc);
8576 e->loc = fileloc_copy (g_currentloc);
8579 e->uses = sRefSet_new ();
8580 e->sets = sRefSet_new ();
8581 e->msets = sRefSet_new ();
8583 e->val = multiVal_unknown ();
8584 e->guards = guardSet_new ();
8586 e->isJumpPoint = FALSE;
8587 e->exitCode = XK_NEVERESCAPE;
8589 /*> missing fields, detected by lclint <*/
8590 e->canBreak = FALSE;
8591 e->mustBreak = FALSE;
8592 e->etext = cstring_undefined;
8594 if (uentry_isYield (ue))
8596 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8597 fileloc_copy (e->loc),
8601 uue = usymtab_supEntrySrefReturn (uue);
8603 sr = uentry_getSref (uue);
8604 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8605 sr = uentry_getSref (uue);
8606 sRef_setDefined (sr, e->loc);
8608 e->typ = uentry_getType (uue);
8610 e->edata = exprData_makeId (uue);
8611 uentry_setUsed (uue, g_currentloc);
8617 sRef_setGlobalScope ();
8618 uue = uentry_makeVariableLoc (s, ctype_unknown);
8620 e->typ = ctype_unknown;
8621 e->edata = exprData_makeId (uue);
8623 uentry_setUsed (uue, e->loc);
8624 uentry_setHasNameError (uue);
8626 if (context_getFlag (FLG_REPEATUNRECOG))
8628 uentry_markOwned (uue);
8632 usymtab_supGlobalEntry (uue);
8635 sRef_clearGlobalScope ();
8637 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8644 exprNode_defineConstraints(e);
8649 exprNode_iterExpr (/*@returned@*/ exprNode e)
8651 if (!processingIterVars ())
8653 llcontbuglit ("checkIterParam: not in iter");
8657 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8660 if (exprNode_isDefined (e))
8662 if (fileloc_isDefined (e->loc))
8666 message ("Yield parameter is not simple identifier: %s",
8667 exprNode_unparse (e)),
8674 message ("Yield parameter is not simple identifier: %s",
8675 exprNode_unparse (e)),
8685 exprNode_iterId (/*@observer@*/ uentry c)
8689 llassert (processingIterVars ());
8691 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8694 if (uentry_isYield (ue))
8696 ctype ct = uentry_getType (ue);
8697 exprNode e = exprNode_createPlain (ct);
8698 cstring name = uentry_getName (c);
8699 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8701 uentry_setUsed (ue, g_currentloc);
8702 uentry_setHasNameError (ue);
8704 cstring_free (name);
8707 e->edata = exprData_makeId (le);
8708 e->loc = context_getSaveLocation ();
8709 e->sref = uentry_getSref (le);
8711 usymtab_supEntrySref (le);
8713 if (!context_inHeader ())
8717 message ("Yield parameter shadows local declaration: %q",
8718 uentry_getName (c)),
8719 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8721 uentry_showWhereDeclared (c);
8728 return (exprNode_fromIdentifierAux (c));
8731 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8733 exprNode ret = exprNode_create (ctype_unknown);
8735 ret->kind = XPR_ITERCALL;
8736 ret->edata = exprData_makeIterCall (name, alist);
8738 if (uentry_isIter (name))
8740 uentryList params = uentry_getParams (name);
8742 if (context_inIterDef ()
8743 && uentryList_size (params) == exprNodeList_size (alist))
8747 exprNodeList_elements (alist, arg)
8749 uentry parg = uentryList_getN (params, i);
8751 if (uentry_isYield (parg))
8753 uentry ue = exprNode_getUentry (arg);
8755 if (uentry_isValid (ue))
8762 } end_exprNodeList_elements;
8765 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8766 checkUnspecCall (ret, params, alist);
8772 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8774 if (exprNode_isDefined (e))
8777 if (e->sref == defref) /*@noaccess sRef@*/
8780 e->sref = sRef_makeUnknown ();
8781 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8792 return sRef_undefined;
8796 /*@observer@*/ cstring
8797 exprNode_unparseFirst (exprNode e)
8799 if (exprNode_isDefined (e))
8803 if (e->kind == XPR_STMTLIST
8804 || e->kind == XPR_COMMA || e->kind == XPR_COND)
8806 exprNode first = exprData_getPairA (e->edata);
8808 if (exprNode_isDefined (first))
8810 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8814 return (cstring_makeLiteralTemp ("..."));
8818 ret = cstring_elide (exprNode_unparse (e), 20);
8819 cstring_markOwned (ret);
8825 return cstring_makeLiteralTemp ("<error>");
8829 /*@observer@*/ cstring
8830 exprNode_unparse (/*@temp@*/ exprNode e)
8832 if (exprNode_isError (e))
8834 return cstring_makeLiteralTemp ("<error>");
8837 if (cstring_isDefined (e->etext))
8843 cstring ret = exprNode_doUnparse (e);
8845 /*@-modifies@*/ /* benevolent */
8852 /*@observer@*/ fileloc
8853 exprNode_loc (exprNode e)
8855 if (exprNode_isError (e))
8857 return (g_currentloc);
8866 ** executes exprNode e
8867 ** recursively rexecutes as though in original parse using
8868 ** information in e->edata
8871 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
8873 exprNodeList ret = exprNodeList_new ();
8875 exprNodeList_elements (e, current)
8877 exprNodeList_addh (ret, exprNode_effect (current));
8878 } end_exprNodeList_elements;
8883 static /*@only@*/ exprNode exprNode_effect (exprNode e)
8884 /*@globals internalState@*/
8886 bool innerEffect = inEffect;
8892 context_clearJustPopped ();
8894 if (exprNode_isError (e))
8896 ret = exprNode_undefined;
8901 ** Turn off expose and dependent transfer checking.
8902 ** Need to pass exposed internal nodes,
8903 ** [ copying would be a waste! ]
8904 ** [ Actually, I think I wasted a lot more time than its worth ]
8905 ** [ trying to do this. ]
8909 /*@-observertrans@*/
8910 /*@-dependenttrans@*/
8917 ret = exprNode_addParens (exprData_getUopTok (data),
8918 exprNode_effect (exprData_getUopNode (data)));
8921 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
8922 exprNode_effect (exprData_getOpB (data)),
8923 exprData_getOpTok (data));
8926 ret = exprNode_undefined;
8929 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
8930 exprNodeList_effect (exprData_getArgs (data)));
8943 cstring id = exprData_getId (data);
8944 uentry ue = usymtab_lookupSafe (id);
8946 ret = exprNode_fromIdentifierAux (ue);
8947 ret->loc = fileloc_update (ret->loc, e->loc);
8954 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
8955 exprNode_effect (exprData_getPairB (data)));
8958 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
8959 exprNode_effect (exprData_getOpB (data)),
8960 exprData_getOpTok (data));
8964 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
8965 exprData_getUopTok (data));
8968 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
8969 exprData_getUopTok (data));
8981 ret = exprNode_vaArg (exprData_getCastTok (data),
8982 exprNode_effect (exprData_getCastNode (data)),
8983 exprData_getCastType (data));
8987 ret = exprNode_cast (exprData_getCastTok (data),
8988 exprNode_effect (exprData_getCastNode (data)),
8989 exprData_getCastType (data));
8992 ret = exprNode_iterStart (exprData_getIterCallIter (data),
8994 (exprData_getIterCallArgs (data)));
8998 ret = exprNode_iter (exprData_getIterSname (data),
8999 exprNodeList_effect (exprData_getIterAlist (data)),
9000 exprNode_effect (exprData_getIterBody (data)),
9001 exprData_getIterEname (data));
9005 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
9006 exprNode_effect (exprData_getPairB (data)));
9010 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
9011 exprNode_effect (exprData_getTripleTest (data)),
9012 exprNode_effect (exprData_getTripleInc (data)));
9016 ret = exprNode_createTok (exprData_getTok (data));
9020 ret = exprNode_goto (exprData_getLiteral (data));
9021 ret->loc = fileloc_update (ret->loc, e->loc);
9025 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
9029 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
9033 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
9036 case XPR_NULLRETURN:
9037 ret = exprNode_nullReturn (exprData_getTok (data));
9041 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
9042 exprNode_effect (exprData_getPairB (data)));
9046 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
9047 exprNode_effect (exprData_getTripleTrue (data)),
9048 exprNode_effect (exprData_getTripleFalse (data)));
9051 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
9052 exprNode_effect (exprData_getPairB (data)));
9056 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
9057 exprNode_effect (exprData_getTripleTrue (data)),
9058 exprNode_effect (exprData_getTripleFalse (data)));
9061 ret = exprNode_whilePred (exprData_getSingle (data));
9065 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
9066 exprNode_effect (exprData_getPairB (data)));
9070 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
9071 exprNode_effect (exprData_getPairB (data)));
9075 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
9079 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
9080 exprData_getUopTok (data));
9084 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
9085 exprNode_effect (exprData_getPairB (data)));
9090 ret = exprNode_caseMarker
9091 (exprNode_effect (exprData_getSingle (data)),
9097 ret = exprNode_createTok (exprData_getTok (data));
9101 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
9102 exprNode_effect (exprData_getPairB (data)));
9106 ret = exprNode_makeInitialization
9107 (exprData_getInitId (data),
9108 exprNode_effect (exprData_getInitNode (data)));
9112 ret = exprNode_fieldAccessAux
9113 (exprNode_effect (exprData_getFieldNode (data)),
9114 exprNode_loc (exprData_getFieldNode (data)),
9115 cstring_copy (exprData_getFieldName (data)));
9119 ret = exprNode_arrowAccessAux
9120 (exprNode_effect (exprData_getFieldNode (data)),
9121 exprNode_loc (exprData_getFieldNode (data)),
9122 cstring_copy (exprData_getFieldName (data)));
9125 case XPR_STRINGLITERAL:
9139 /*@=observertrans@*/
9141 /*@=dependenttrans@*/
9152 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
9157 if (exprNode_isError (e))
9159 return cstring_undefined;
9167 ret = exprNode_rootVarName (exprData_getUopNode (data));
9170 ret = exprNode_rootVarName (exprData_getOpA (data));
9174 ret = exprData_getId (data);
9177 ret = idDecl_getName (exprData_getInitId (data));
9202 case XPR_NULLRETURN:
9224 case XPR_STRINGLITERAL:
9225 ret = cstring_undefined;
9232 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
9237 if (exprNode_isError (e))
9239 static /*@only@*/ cstring error = cstring_undefined;
9241 if (!cstring_isDefined (error))
9243 error = cstring_makeLiteral ("<error>");
9254 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
9257 ret = message ("%s %s %s",
9258 exprNode_unparse (exprData_getOpA (data)),
9259 lltok_unparse (exprData_getOpTok (data)),
9260 exprNode_unparse (exprData_getOpB (data)));
9263 ret = message ("%s(%q)",
9264 exprNode_unparse (exprData_getFcn (data)),
9265 exprNodeList_unparse (exprData_getArgs (data)));
9268 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
9271 ret = cstring_undefined;
9274 ret = message ("%s:", exprData_getId (data));
9278 ret = cstring_copy (exprData_getId (data));
9281 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
9282 exprNode_unparse (exprData_getPairB (data)));
9285 ret = message ("<body>");
9288 ret = message ("%s %s %s",
9289 exprNode_unparse (exprData_getOpA (data)),
9290 lltok_unparse (exprData_getOpTok (data)),
9291 exprNode_unparse (exprData_getOpB (data)));
9295 ret = message ("%s%s",
9296 lltok_unparse (exprData_getUopTok (data)),
9297 exprNode_unparse (exprData_getUopNode (data)));
9301 ret = message ("%s%s",
9302 exprNode_unparse (exprData_getUopNode (data)),
9303 lltok_unparse (exprData_getUopTok (data)));
9307 ret = message ("offsetof(%s,%q)",
9308 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
9309 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
9313 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9317 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
9321 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9325 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
9329 ret = message ("va_arg(%s, %q)",
9330 exprNode_unparse (exprData_getCastNode (data)),
9331 qtype_unparse (exprData_getCastType (data)));
9335 ret = message ("%q(%q)",
9336 uentry_getName (exprData_getIterCallIter (data)),
9337 exprNodeList_unparse (exprData_getIterCallArgs (data)));
9340 ret = message ("%q(%q) %s %q",
9341 uentry_getName (exprData_getIterSname (data)),
9342 exprNodeList_unparse (exprData_getIterAlist (data)),
9343 exprNode_unparse (exprData_getIterBody (data)),
9344 uentry_getName (exprData_getIterEname (data)));
9347 ret = message ("(%q)%s",
9348 qtype_unparse (exprData_getCastType (data)),
9349 exprNode_unparse (exprData_getCastNode (data)));
9353 ret = message ("%s %s",
9354 exprNode_unparse (exprData_getPairA (data)),
9355 exprNode_unparse (exprData_getPairB (data)));
9359 ret = message ("for (%s; %s; %s)",
9360 exprNode_unparse (exprData_getTripleInit (data)),
9361 exprNode_unparse (exprData_getTripleTest (data)),
9362 exprNode_unparse (exprData_getTripleInc (data)));
9366 ret = message ("goto %s", exprData_getLiteral (data));
9370 ret = cstring_makeLiteral ("continue");
9374 ret = cstring_makeLiteral ("break");
9378 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
9381 case XPR_NULLRETURN:
9382 ret = cstring_makeLiteral ("return");
9386 ret = message ("%s, %s",
9387 exprNode_unparse (exprData_getPairA (data)),
9388 exprNode_unparse (exprData_getPairB (data)));
9392 ret = message ("%s ? %s : %s",
9393 exprNode_unparse (exprData_getTriplePred (data)),
9394 exprNode_unparse (exprData_getTripleTrue (data)),
9395 exprNode_unparse (exprData_getTripleFalse (data)));
9398 ret = message ("if (%s) %s",
9399 exprNode_unparse (exprData_getPairA (data)),
9400 exprNode_unparse (exprData_getPairB (data)));
9404 ret = message ("if (%s) %s else %s",
9405 exprNode_unparse (exprData_getTriplePred (data)),
9406 exprNode_unparse (exprData_getTripleTrue (data)),
9407 exprNode_unparse (exprData_getTripleFalse (data)));
9410 ret = message ("while (%s) %s",
9411 exprNode_unparse (exprData_getPairA (data)),
9412 exprNode_unparse (exprData_getPairB (data)));
9416 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9420 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9424 ret = message ("do { %s } while (%s)",
9425 exprNode_unparse (exprData_getPairB (data)),
9426 exprNode_unparse (exprData_getPairA (data)));
9430 ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
9434 ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
9438 ret = message ("%s; %s",
9439 exprNode_unparse (exprData_getPairA (data)),
9440 exprNode_unparse (exprData_getPairB (data)));
9445 ret = cstring_makeLiteral ("default:");
9449 ret = message ("switch (%s) %s",
9450 exprNode_unparse (exprData_getPairA (data)),
9451 exprNode_unparse (exprData_getPairB (data)));
9456 ret = message ("case %s:",
9457 exprNode_unparse (exprData_getSingle (data)));
9461 if (exprNode_isError (exprData_getInitNode (data)))
9463 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9467 ret = message ("%q = %s",
9468 idDecl_unparseC (exprData_getInitId (data)),
9469 exprNode_unparse (exprData_getInitNode (data)));
9474 ret = message ("%s.%s",
9475 exprNode_unparse (exprData_getFieldNode (data)),
9476 exprData_getFieldName (data));
9480 ret = message ("%s->%s",
9481 exprNode_unparse (exprData_getFieldNode (data)),
9482 exprData_getFieldName (data));
9485 case XPR_STRINGLITERAL:
9486 if (ctype_isWideString (e->typ))
9488 ret = message ("L\"%s\"", exprData_getLiteral (data));
9492 ret = message ("\"%s\"", exprData_getLiteral (data));
9497 ret = cstring_copy (exprData_getLiteral (data));
9501 ret = cstring_makeLiteral ("<node>");
9509 exprNode_isInitializer (exprNode e)
9511 return (exprNode_isDefined (e)
9512 && e->kind == XPR_INIT);
9516 exprNode_isCharLit (exprNode e)
9518 if (exprNode_isDefined (e))
9520 return (multiVal_isChar (exprNode_getValue (e)));
9529 exprNode_isNumLit (exprNode e)
9531 if (exprNode_isDefined (e))
9533 return (multiVal_isInt (exprNode_getValue (e)));
9542 exprNode_isFalseConstant (exprNode e)
9544 if (exprNode_isDefined (e))
9546 cstring s = exprNode_rootVarName (e);
9548 if (cstring_equal (s, context_getFalseName ()))
9558 exprNode_matchLiteral (ctype expected, exprNode e)
9560 if (exprNode_isDefined (e))
9562 multiVal m = exprNode_getValue (e);
9564 if (multiVal_isDefined (m))
9566 if (multiVal_isInt (m))
9568 long int val = multiVal_forceInt (m);
9570 if (ctype_isDirectBool (ctype_realishType (expected)))
9574 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9582 if (ctype_isRealInt (expected))
9585 ** unsigned <- [ constant >= 0 is okay ]
9588 if (ctype_isUnsigned (expected))
9597 ** No checks on sizes of integers...maybe add
9601 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9602 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9603 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9605 if (context_getFlag (FLG_NUMLITERAL)
9606 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9612 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9616 else if (ctype_isChar (expected))
9620 else if (ctype_isArrayPtr (expected))
9623 ** evans 2001-10-14: We allow 0 to match any pointer, but only if the type matches or is void *.
9628 if (ctype_match (exprNode_getType (e), expected)
9629 || ctype_isVoidPointer (exprNode_getType (e)))
9639 else if (ctype_isAnyFloat (expected))
9641 return (context_getFlag (FLG_NUMLITERAL));
9648 else if (multiVal_isDouble (m))
9650 if (ctype_isAnyFloat (expected))
9655 else if (multiVal_isChar (m))
9657 char val = multiVal_forceChar (m);
9659 if (ctype_isChar (expected))
9661 if (ctype_isUnsigned (expected) && ((int)val) < 0)
9682 exprNode_matchType (ctype expected, exprNode e)
9686 if (!exprNode_isDefined (e)) return TRUE;
9688 actual = ctype_realishType (exprNode_getType (e));
9690 if (ctype_match (ctype_realishType (expected), actual))
9695 llassert (!exprNode_isError (e));
9696 return (exprNode_matchLiteral (expected, e));
9700 exprNode_matchTypes (exprNode e1, exprNode e2)
9705 if (!exprNode_isDefined (e1)) return TRUE;
9706 if (!exprNode_isDefined (e2)) return TRUE;
9709 ** realish type --- keep bools, bools
9712 t1 = ctype_realishType (exprNode_getType (e1));
9713 t2 = ctype_realishType (exprNode_getType (e2));
9715 if (ctype_match (t1, t2))
9720 DPRINTF (("Matching literal! %s %s %s %s",
9721 ctype_unparse (t1), exprNode_unparse (e2),
9722 ctype_unparse (t2), exprNode_unparse (e1)));
9724 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9732 exprNode_matchArgType (ctype ct, exprNode e)
9736 if (!exprNode_isDefined (e))
9741 et = ctype_realType (exprNode_getType (e));
9743 if (ctype_matchArg (ct, et)) return TRUE;
9745 llassert (!exprNode_isError (e));
9746 return (exprNode_matchLiteral (ct, e));
9749 static /*@only@*/ exprNodeSList
9750 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9752 if (exprNode_isDefined (e))
9754 if (e->kind == XPR_STMTLIST)
9756 return (exprNodeSList_append
9757 (exprNode_flatten (exprData_getPairA (e->edata)),
9758 exprNode_flatten (exprData_getPairB (e->edata))));
9760 else if (e->kind == XPR_BLOCK)
9762 return (exprNode_flatten (exprData_getSingle (e->edata)));
9766 return (exprNodeSList_singleton (e));
9770 return exprNodeSList_new ();
9773 static /*@exposed@*/ exprNode
9774 exprNode_lastStatement (/*@returned@*/ exprNode e)
9776 if (exprNode_isDefined (e))
9778 if (e->kind == XPR_STMTLIST)
9780 exprNode b = exprData_getPairB (e->edata);
9782 if (exprNode_isDefined (b))
9784 return exprNode_lastStatement (b);
9788 return exprNode_lastStatement (exprData_getPairA (e->edata));
9791 else if (e->kind == XPR_BLOCK)
9793 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
9801 return exprNode_undefined;
9804 static /*@exposed@*/ exprNode
9805 exprNode_firstStatement (/*@returned@*/ exprNode e)
9807 if (exprNode_isDefined (e))
9809 if (e->kind == XPR_STMTLIST)
9811 exprNode b = exprData_getPairA (e->edata);
9813 if (exprNode_isDefined (b))
9815 return exprNode_firstStatement (b);
9819 return exprNode_firstStatement (exprData_getPairB (e->edata));
9822 else if (e->kind == XPR_BLOCK)
9824 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
9832 return exprNode_undefined;
9836 exprNode_mergeUSs (exprNode res, exprNode other)
9838 if (exprNode_isDefined (res) && exprNode_isDefined (other))
9840 res->msets = sRefSet_union (res->msets, other->msets);
9841 res->sets = sRefSet_union (res->sets, other->sets);
9842 res->uses = sRefSet_union (res->uses, other->uses);
9847 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
9849 if (exprNode_isDefined (res))
9851 if (exprNode_isDefined (other1))
9853 res->sets = sRefSet_union (res->sets, other1->sets);
9854 res->msets = sRefSet_union (res->msets, other1->msets);
9855 res->uses = sRefSet_union (res->uses, other1->uses);
9857 if (exprNode_isDefined (other2))
9859 res->sets = sRefSet_union (res->sets, other2->sets);
9860 res->msets = sRefSet_union (res->msets, other2->msets);
9861 res->uses = sRefSet_union (res->uses, other2->uses);
9869 ** Reports errors is s is not defined.
9873 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
9875 if (exprNode_isDefined (e))
9877 e->uses = sRefSet_insert (e->uses, s);
9882 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
9884 if (sRef_isKnown (s) && !sRef_isConst (s))
9887 ** need to check all outer types are useable
9890 DPRINTF (("Check use: %s / %s",
9891 exprNode_unparse (e), sRef_unparse (s)));
9893 exprNode_addUse (e, s);
9895 if (!context_inProtectVars ())
9898 ** only report the deepest error
9901 sRef errorRef = sRef_undefined;
9902 sRef lastRef = sRef_undefined;
9903 bool deadRef = FALSE;
9904 bool unuseable = FALSE;
9905 bool errorMaybe = FALSE;
9907 while (sRef_isValid (s) && sRef_isKnown (s))
9909 ynm readable = sRef_isValidLvalue (s);
9911 DPRINTF (("Readable: %s / %s",
9912 sRef_unparseFull (s), ynm_unparse (readable)));
9914 if (!(ynm_toBoolStrict (readable)))
9916 if (ynm_isMaybe (readable))
9920 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
9921 deadRef = sRef_isPossiblyDead (errorRef);
9922 unuseable = sRef_isUnuseable (errorRef);
9929 deadRef = sRef_isDead (errorRef);
9930 unuseable = sRef_isUnuseable (errorRef);
9934 if (!sRef_isPartial (s))
9936 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
9937 sRef_setDefined (s, fileloc_undefined);
9941 s = sRef_getBaseSafe (s);
9944 if (sRef_isValid (errorRef))
9946 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
9947 && sRef_isPointer (errorRef))
9954 if (sRef_isThroughArrayFetch (errorRef))
9957 (FLG_STRICTUSERELEASED,
9958 message ("%q %q may be used after being released",
9959 sRef_unparseKindNamePlain (errorRef),
9960 sRef_unparse (errorRef)),
9963 sRef_showRefKilled (errorRef);
9965 if (sRef_isKept (errorRef))
9967 sRef_clearAliasState (errorRef, loc);
9973 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
9977 message ("%q %q %qused after being released",
9978 sRef_unparseKindNamePlain (errorRef),
9979 sRef_unparse (errorRef),
9980 cstring_makeLiteral (errorMaybe
9984 sRef_showRefKilled (errorRef);
9986 if (sRef_isKept (errorRef))
9988 sRef_clearAliasState (errorRef, loc);
9997 message ("%q %q%qused in inconsistent state",
9998 sRef_unparseKindName (errorRef),
9999 sRef_unparseOpt (errorRef),
10000 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10003 sRef_showStateInconsistent (errorRef);
10008 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
10012 message ("%q %q%qused before definition",
10013 sRef_unparseKindName (errorRef),
10014 sRef_unparseOpt (errorRef),
10015 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10018 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
10021 sRef_setDefined (errorRef, loc);
10023 if (sRef_isAddress (errorRef))
10025 sRef_setDefined (sRef_getRootBase (errorRef), loc);
10027 } /* end is error */
10035 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
10037 if (exprNode_isDefined (e) && sRef_isKnown (s))
10039 e->uses = sRefSet_insert (e->uses, s);
10044 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
10046 if (exprNode_isDefined (e))
10048 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
10053 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
10055 sRef defines = sRef_undefined;
10057 if (sRef_isValid (s) && !sRef_isNothing (s))
10059 uentry ue = sRef_getBaseUentry (s);
10061 if (uentry_isValid (ue))
10063 uentry_setLset (ue);
10066 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10068 voptgenerror (FLG_USEDEF,
10069 message ("Attempt to set unuseable storage: %q",
10074 if (sRef_isMeaningful (s))
10076 if (sRef_isDead (s))
10078 sRef base = sRef_getBaseSafe (s);
10080 if (sRef_isValid (base)
10081 && sRef_isDead (base))
10083 sRef_setPartial (s, exprNode_loc (e));
10086 defines = s; /* okay - modifies for only param */
10088 else if (sRef_isPartial (s))
10090 sRef eref = exprNode_getSref (e);
10092 if (!sRef_isPartial (eref))
10095 ** should do something different here???
10098 sRef_setDefinedComplete (eref, exprNode_loc (e));
10102 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
10105 if (sRef_isMeaningful (eref))
10114 else if (sRef_isAllocated (s))
10116 sRef eref = exprNode_getSref (e);
10119 if (!sRef_isAllocated (eref))
10121 sRef_setDefinedComplete (eref, exprNode_loc (e));
10125 sRef base = sRef_getBaseSafe (eref);
10127 if (sRef_isValid (base))
10129 sRef_setPdefined (base, exprNode_loc (e));
10137 sRef_setDefinedNCComplete (s, exprNode_loc (e));
10142 else /* not meaningful...but still need to insert it */
10148 if (exprNode_isDefined (e) && sRef_isValid (defines))
10150 e->sets = sRefSet_insert (e->sets, defines);
10155 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
10157 if (sRef_isValid (s) && !sRef_isNothing (s))
10159 uentry ue = sRef_getBaseUentry (s);
10161 if (uentry_isValid (ue))
10163 uentry_setLset (ue);
10166 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10168 voptgenerror (FLG_USEDEF,
10169 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
10173 if (sRef_isMeaningful (s))
10175 sRef_setDefinedComplete (s, exprNode_loc (e));
10178 if (exprNode_isDefined (e))
10180 e->msets = sRefSet_insert (e->msets, s);
10186 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
10188 checkAnyCall (fcn, cstring_undefined, params, args,
10189 FALSE, sRefSet_undefined, FALSE, 0);
10193 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
10194 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
10198 if (uentry_isYield (ucurrent))
10200 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
10201 exprNode_checkSet (current, current->sref);
10205 if (uentry_isSefParam (ucurrent))
10207 sRefSet sets = current->sets;
10208 sRef ref = exprNode_getSref (current);
10210 if (sRef_isMacroParamRef (ref))
10212 uentry ue = sRef_getUentry (ref);
10214 if (!uentry_isSefParam (ue))
10219 ("Parameter %d to %s is declared sef, but "
10220 "the argument is a macro parameter declared "
10222 argno, exprNode_unparse (fcn),
10223 exprNode_unparse (current)),
10224 exprNode_loc (current));
10228 if (!sRefSet_isEmpty (sets))
10230 sRefSet reported = sRefSet_undefined;
10232 sRefSet_realElements (current->sets, el)
10234 if (sRefSet_isSameNameMember (reported, el))
10236 ; /* don't report again */
10240 if (sRef_isUnconstrained (el))
10245 ("Parameter %d to %s is declared sef, but "
10246 "the argument calls unconstrained function %s "
10247 "(no guarantee it will not modify something): %s",
10248 argno, exprNode_unparse (fcn),
10249 sRef_unconstrainedName (el),
10250 exprNode_unparse (current)),
10251 exprNode_loc (current));
10258 ("Parameter %d to %s is declared sef, but "
10259 "the argument may modify %q: %s",
10260 argno, exprNode_unparse (fcn),
10262 exprNode_unparse (current)),
10263 exprNode_loc (current));
10266 } end_sRefSet_realElements;
10270 transferChecks_passParam (current, ucurrent, isSpec, fcn, argno, totargs);
10271 exprNode_mergeUSs (fcn, current);
10276 checkAnyCall (/*@dependent@*/ exprNode fcn,
10277 /*@dependent@*/ cstring fname,
10280 bool hasMods, sRefSet mods,
10285 int nargs = exprNodeList_size (args);
10290 ** concat all args ud's to f, add each arg sref as a use unless
10291 ** it was specified as "out", in which case it is a def.
10294 uentryList_reset (pn);
10297 ** aliasing checks:
10299 ** if paramn is only or unique, no other arg may alias argn
10302 exprNodeList_elements (args, current)
10306 if (exprNode_isDefined (current))
10308 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
10310 uentry ucurrent = uentryList_current (pn);
10312 if (specialArgs == 0
10313 || (paramno < specialArgs))
10315 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
10317 if (context_maybeSet (FLG_ALIASUNIQUE))
10319 if (uentry_isOnly (ucurrent)
10320 || uentry_isUnique (ucurrent))
10322 checkUniqueParams (fcn, current, args,
10323 paramno, ucurrent);
10328 else /* uentry is undefined */
10330 if (specialArgs == 0)
10332 exprNode_checkUseParam (current);
10335 exprNode_mergeUSs (fcn, current);
10338 uentryList_advanceSafe (pn);
10339 } end_exprNodeList_elements;
10345 sRefSet_allElements (mods, s)
10348 sRef rb = sRef_getRootBase (s);
10350 if (sRef_isFileOrGlobalScope (rb))
10352 context_usedGlobal (rb);
10355 fb = sRef_fixBaseParam (s, args);
10357 if (!sRef_isMacroParamRef (fb))
10359 if (sRef_isNothing (fb))
10365 if (sRef_isValid (fb))
10367 uentry ue = sRef_getBaseUentry (s);
10369 if (uentry_isValid (ue))
10371 uentry_setLset (ue);
10375 fcn->sets = sRefSet_insert (fcn->sets, fb);
10378 sRef_clearDerivedComplete (s);
10379 } end_sRefSet_allElements;
10385 if (context_hasMods ())
10387 if (context_maybeSet (FLG_MODUNCON))
10391 message ("Undetected modification possible "
10392 "from call to unconstrained function %s: %s",
10394 exprNode_unparse (fcn)),
10395 exprNode_loc (fcn));
10400 if (context_maybeSet (FLG_MODUNCONNOMODS)
10401 && !(context_inIterDef () || context_inIterEnd ()))
10404 (FLG_MODUNCONNOMODS,
10405 message ("Undetected modification possible "
10406 "from call to unconstrained function %s: %s",
10408 exprNode_unparse (fcn)),
10409 exprNode_loc (fcn));
10413 exprNode_checkSetAny (fcn, fname);
10417 void exprNode_checkUseParam (exprNode current)
10419 if (exprNode_isDefined (current))
10421 exprNode_checkUse (current, current->sref, current->loc);
10426 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10427 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10432 if (!ctype_match (tr1, tr2))
10434 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10435 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10437 DPRINTF (("No error: [%s] %s / [%s] %s",
10438 exprNode_unparse (e1), ctype_unparse (tr1),
10439 exprNode_unparse (e2), ctype_unparse (tr2)));
10443 (void) gentypeerror
10445 message ("Incompatible types for %s (%s, %s): %s %s %s",
10446 lltok_unparse (op),
10447 ctype_unparse (te1),
10448 ctype_unparse (te2),
10449 exprNode_unparse (e1), lltok_unparse (op),
10450 exprNode_unparse (e2)),
10453 ret = ctype_unknown;
10457 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
10459 ret = ctype_resolveNumerics (tr1, tr2);
10461 else if (!context_msgStrictOps ())
10463 if (ctype_isPointer (tr1))
10465 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10469 else if (ctype_isInt (tr2))
10475 ret = ctype_unknown;
10478 else if (ctype_isPointer (tr2))
10480 if (ctype_isPointer (tr1))
10484 else if (ctype_isInt (tr1))
10490 ret = ctype_unknown;
10495 ret = ctype_resolveNumerics (tr1, tr2);
10500 int opid = lltok_getTok (op);
10501 bool comparop = (opid == EQ_OP || opid == NE_OP
10502 || opid == TLT || opid == TGT
10503 || opid == LE_OP || opid == GE_OP);
10505 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10508 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10509 || (ctype_isBool (tr1) && ctype_isBool (tr2))
10510 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10516 if (ctype_sameName (te1, te2))
10520 message ("Operands of %s are non-numeric (%t): %s %s %s",
10521 lltok_unparse (op), te1,
10522 exprNode_unparse (e1), lltok_unparse (op),
10523 exprNode_unparse (e2)),
10530 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10531 lltok_unparse (op), te1, te2,
10532 exprNode_unparse (e1), lltok_unparse (op),
10533 exprNode_unparse (e2)),
10538 else if (!ctype_isNumeric (tr1))
10542 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10543 lltok_unparse (op), te1,
10544 exprNode_unparse (e1), lltok_unparse (op),
10545 exprNode_unparse (e2)),
10550 if (!ctype_isNumeric (tr2))
10554 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10555 lltok_unparse (op), te2,
10556 exprNode_unparse (e1), lltok_unparse (op),
10557 exprNode_unparse (e2)),
10562 ret = ctype_unknown;
10570 abstractOpError (ctype tr1, ctype tr2, lltok op,
10571 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10572 fileloc loc1, fileloc loc2)
10574 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10576 if (ctype_match (tr1, tr2))
10580 message ("Operands of %s are abstract type (%t): %s %s %s",
10581 lltok_unparse (op), tr1,
10582 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10589 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10590 lltok_unparse (op), tr1, tr2,
10591 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10595 else if (ctype_isRealAbstract (tr1))
10599 message ("Left operand of %s is abstract type (%t): %s %s %s",
10600 lltok_unparse (op), tr1,
10601 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10606 if (ctype_isRealAbstract (tr2))
10610 message ("Right operand of %s is abstract type (%t): %s %s %s",
10611 lltok_unparse (op), tr2,
10612 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10621 ** requies e1 and e2 and not error exprNode's.
10625 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10626 ** the rep of the abstract type is exposed.
10628 ** The order is very important:
10630 ** check rep expose (move into check transfer)
10636 ** This isn't really a sensible procedure, but the indententation
10637 ** was getting too deep.
10641 checkOneRepExpose (sRef ysr, sRef base,
10642 /*@notnull@*/ exprNode e1,
10643 /*@notnull@*/ exprNode e2, ctype ct,
10646 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
10647 || sRef_isOwned (ysr)
10648 || sRef_isExposed (ysr)))
10650 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10651 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10654 if (sRef_isIReference (ysr))
10656 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10661 ("Assignment of mutable component of parameter %q "
10662 "to component of abstract "
10663 "type %s exposes rep: %s = %s",
10664 sRef_unparse (base),
10665 ctype_unparse (ct),
10666 exprNode_unparse (e1), exprNode_unparse (e2)),
10674 ("Assignment of mutable component of parameter %q "
10675 "(through alias %q) to component of abstract "
10676 "type %s exposes rep: %s = %s",
10677 sRef_unparse (base),
10678 sRef_unparse (e2->sref),
10679 ctype_unparse (ct),
10680 exprNode_unparse (e1), exprNode_unparse (e2)),
10686 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10690 message ("Assignment of mutable parameter %q "
10691 "to component of abstract type %s "
10692 "exposes rep: %s = %s",
10693 sRef_unparse (base),
10694 ctype_unparse (ct),
10695 exprNode_unparse (e1),
10696 exprNode_unparse (e2)),
10703 message ("Assignment of mutable parameter %q "
10704 "(through alias %q) to "
10705 "component of abstract type %s exposes "
10707 sRef_unparse (base),
10708 sRef_unparse (e2->sref),
10709 ctype_unparse (ct),
10710 exprNode_unparse (e1),
10711 exprNode_unparse (e2)),
10717 if (sRef_isFileOrGlobalScope (s2b))
10719 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10723 message ("Assignment of global %q "
10725 "abstract type %s exposes rep: %s = %s",
10726 sRef_unparse (base),
10727 ctype_unparse (ct),
10728 exprNode_unparse (e1), exprNode_unparse (e2)),
10735 message ("Assignment of global %q (through alias %q) "
10737 "abstract type %s exposes rep: %s = %s",
10738 sRef_unparse (base),
10739 sRef_unparse (e2->sref),
10740 ctype_unparse (ct),
10741 exprNode_unparse (e1), exprNode_unparse (e2)),
10749 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
10751 DPRINTF (("Do assign: %s <- %s",
10752 exprNode_unparse (e1), exprNode_unparse (e2)));
10753 DPRINTF (("Ctype: %s", ctype_unparse (exprNode_getType (e1))));
10755 if (ctype_isRealFunction (exprNode_getType (e1))
10756 && !ctype_isRealPointer (exprNode_getType (e1)))
10760 message ("Invalid left-hand side of assignment (function type %s): %s",
10761 ctype_unparse (exprNode_getType (e1)),
10762 exprNode_unparse (e1)),
10766 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
10768 ctype t2 = exprNode_getType (e2);
10769 sRef sr = sRef_getRootBase (e1->sref);
10770 ctype ct = sRef_getType (sr);
10772 if (ctype_isAbstract (t2)
10773 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
10775 /* it is immutable, okay to reference */
10776 goto donerepexpose;
10779 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
10781 sRef s2b = sRef_getRootBase (e2->sref);
10782 sRef s1 = e1->sref;
10783 sRef s1b = sRef_getRootBase (s1);
10786 aliases = usymtab_canAlias (e2->sref);
10788 if (!sRef_similar (s2b, s1b)
10789 && !sRef_isExposed (s1)
10790 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
10792 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
10793 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
10794 && !sRef_isExposed (s2b))
10796 if (sRef_isIReference (e2->sref))
10801 ("Assignment of mutable component of parameter %q "
10802 "to component of abstract type %s exposes rep: %s = %s",
10803 sRef_unparse (s2b),
10804 ctype_unparse (ct),
10805 exprNode_unparse (e1), exprNode_unparse (e2)),
10812 message ("Assignment of mutable parameter %q to "
10813 "component of abstract type %s exposes rep: %s = %s",
10814 sRef_unparse (s2b),
10815 ctype_unparse (ct),
10816 exprNode_unparse (e1), exprNode_unparse (e2)),
10821 if (sRef_isFileOrGlobalScope (s2b))
10825 message ("Assignment of global %q to component of "
10826 "abstract type %s exposes rep: %s = %s",
10827 sRef_unparse (s2b),
10828 ctype_unparse (ct),
10829 exprNode_unparse (e1), exprNode_unparse (e2)),
10833 sRefSet_realElements (aliases, ysr)
10835 sRef base = sRef_getRootBase (ysr);
10837 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
10838 || sRef_sameName (base, s1b))
10840 ; /* error already reported or same sref */
10844 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
10846 } end_sRefSet_realElements;
10848 sRefSet_free (aliases);
10855 ** function variables don't really work...
10858 if (!ctype_isFunction (ctype_realType (e2->typ)))
10862 DPRINTF (("Check init: %s / %s",
10863 exprNode_unparse (e1), exprNode_unparse (e2)));
10864 transferChecks_initialization (e1, e2);
10868 transferChecks_assign (e1, e2);
10873 sRef fref = e2->sref;
10875 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
10876 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
10878 /* Need to typecheck the annotation on the parameters */
10880 if (ctype_isRealFunction (e1->typ)) {
10881 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
10882 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
10884 if (!uentryList_isMissingParams (e1p)
10885 && !uentryList_isMissingParams (e2p)
10886 && uentryList_size (e1p) > 0) {
10887 if (uentryList_size (e1p) == uentryList_size (e2p)) {
10890 uentryList_elements (e1p, el1) {
10893 el2 = uentryList_getN (e2p, n);
10895 uentry_checkMatchParam (el1, el2, n, e2);
10896 } end_uentryList_elements;
10902 if (exprNode_isStringLiteral (e2))
10904 exprNode_checkStringLiteralLength (exprNode_getType (e1), e2);
10907 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
10913 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
10914 updateAliases (e1, e2);
10919 checkMacroParen (exprNode e)
10921 if (exprNode_isError (e) || e->kind == XPR_CAST)
10927 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
10931 message ("Macro parameter used without parentheses: %s",
10932 exprNode_unparse (e)),
10939 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
10943 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
10947 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
10954 ** if e2 is a parameter or global derived location which
10955 ** can be modified (that is, e2 is a mutable abstract type,
10956 ** or a derived pointer), then e1 can alias e2.
10958 ** e1 can alias everything which e2 can alias.
10960 ** Also, if e1 is guarded, remove from guard sets!
10963 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
10965 if (!context_inProtectVars ())
10968 ** depends on types of e1 and e2
10971 sRef s1 = e1->sref;
10972 sRef s2 = e2->sref;
10973 ctype t1 = exprNode_getType (e1);
10975 /* handle pointer sRefs, record fields, arrays, etc... */
10977 if (!ctype_isRealSU (t1))
10979 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
10980 sRef_copyRealDerivedComplete (s1, s2);
10985 ** Fields should alias
10988 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
10991 if (ctype_isMutable (t1) && sRef_isKnown (s1))
10993 usymtab_clearAlias (s1);
10994 usymtab_addMustAlias (s1, s2);
10995 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
10999 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
11002 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
11004 usymtab_unguard (s1);
11009 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
11011 if (exprNode_isDefined (e))
11013 e->loc = fileloc_update (e->loc, loc);
11017 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
11023 static void checkUniqueParams (exprNode fcn,
11024 /*@notnull@*/ exprNode current,
11026 int paramno, uentry ucurrent)
11029 sRef thisref = exprNode_getSref (current);
11032 ** Check if any argument could match this argument.
11035 exprNodeList_elements (args, icurrent)
11039 if (iparamno != paramno)
11041 sRef sr = exprNode_getSref (icurrent);
11043 if (sRef_similarRelaxed (thisref, sr))
11045 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
11050 ("Parameter %d (%s) to function %s is declared %s but "
11051 "is aliased by parameter %d (%s)",
11053 exprNode_unparse (current),
11054 exprNode_unparse (fcn),
11055 alkind_unparse (uentry_getAliasKind (ucurrent)),
11056 iparamno, exprNode_unparse (icurrent)),
11062 sRefSet aliases = usymtab_canAlias (sr);
11064 sRefSet_allElements (aliases, asr)
11066 if (ctype_isUnknown (sRef_getType (thisref)))
11068 sRef_setType (thisref, uentry_getType (ucurrent));
11071 if (sRef_similarRelaxed (thisref, asr))
11073 if (sRef_isExternal (asr))
11075 if (sRef_isLocalState (thisref))
11081 sRef base = sRef_getRootBase (asr);
11083 if (!sRef_similar (sRef_getBase (asr), thisref))
11085 if (sRef_isUnique (base) || sRef_isOnly (base)
11086 || sRef_isKept (base)
11087 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
11088 || (sRef_isAddress (thisref)
11089 && sRef_isLocalVar (sRef_getRootBase (thisref))))
11091 ; /* okay, no error */
11096 (FLG_MAYALIASUNIQUE,
11098 ("Parameter %d (%s) to function %s is declared %s but "
11099 "may be aliased externally by parameter %d (%s)",
11101 exprNode_unparse (current),
11102 exprNode_unparse (fcn),
11103 alkind_unparse (uentry_getAliasKind (ucurrent)),
11104 iparamno, exprNode_unparse (icurrent)),
11115 ("Parameter %d (%s) to function %s is declared %s but "
11116 "is aliased externally by parameter %d (%s) through "
11119 exprNode_unparse (current),
11120 exprNode_unparse (fcn),
11121 alkind_unparse (uentry_getAliasKind (ucurrent)),
11122 iparamno, exprNode_unparse (icurrent),
11123 sRef_unparse (asr)),
11127 } end_sRefSet_allElements;
11128 sRefSet_free (aliases);
11131 } end_exprNodeList_elements;
11134 long exprNode_getLongValue (exprNode e) {
11137 if (exprNode_hasValue (e)
11138 && multiVal_isInt (exprNode_getValue (e)))
11140 value = multiVal_forceInt (exprNode_getValue (e));
11151 /*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
11153 if (exprNode_isDefined (p_e) )
11154 return ( p_e->loc );
11156 return fileloc_undefined;
11159 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
11162 ** Returns the location of the sequence point following e.
11164 ** Only works for statements (for now).
11167 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
11168 lltok t = exprData_getUopTok (e->edata);
11169 return fileloc_copy(lltok_getLoc (t));
11171 /* drl possible problem : warning fix
11172 llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
11174 return fileloc_undefined;
11178 exprNode exprNode_createNew(ctype c)
11182 ret = exprNode_createPlain (c);
11187 bool exprNode_isInitBlock (exprNode e)
11189 return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);