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 e->typ = uentry_getType (c);
963 if (uentry_isFunction (c)
964 && !sRef_isLocalVar (uentry_getSref (c)))
966 e->sref = sRef_undefined;
970 e->sref = uentry_getSref (c);
973 if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
975 sRef_setDefined (e->sref, fileloc_undefined);
979 ** yoikes! leaving this out was a heinous bug...that would have been
980 ** caught if i had lclint working first. gag!
983 e->etext = cstring_undefined;
985 if (uentry_isEitherConstant (c))
988 e->val = multiVal_copy (uentry_getConstantValue (c));
993 e->val = multiVal_unknown ();
996 e->edata = exprData_makeId (c);
997 e->loc = context_getSaveLocation ();
999 if (fileloc_isUndefined (e->loc))
1001 fileloc_free (e->loc);
1002 e->loc = fileloc_copy (g_currentloc);
1005 e->guards = guardSet_new ();
1006 e->sets = sRefSet_new ();
1007 e->msets = sRefSet_new ();
1008 e->uses = sRefSet_new ();
1010 /*> missing fields, detected by lclint <*/
1011 e->exitCode = XK_NEVERESCAPE;
1012 e->isJumpPoint = FALSE;
1013 e->canBreak = FALSE;
1014 e->mustBreak = FALSE;
1016 exprNode_defineConstraints(e);
1022 return exprNode_createUnknown ();
1026 /*@notnull@*/ exprNode
1027 exprNode_fromIdentifier (/*@observer@*/ uentry c)
1031 if (context_justPopped ()) /* watch out! c could be dead */
1033 uentry ce = usymtab_lookupSafe (LastIdentifier ());
1035 if (uentry_isValid (ce))
1041 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
1045 ret = exprNode_fromIdentifierAux (c);
1050 static void exprNode_checkStringLiteralLength (ctype t1, exprNode e2)
1052 multiVal mval = exprNode_getValue (e2);
1056 if (ctype_isFixedArray (t1))
1058 int nelements = long_toInt (ctype_getArraySize (t1));
1060 llassert (multiVal_isString (mval));
1061 slit = multiVal_forceString (mval);
1062 len = cstring_length (slit);
1064 if (len == nelements)
1067 (FLG_STRINGLITNOROOM,
1068 message ("String literal with %d character%& "
1069 "is assigned to %s (no room for null terminator): %s",
1070 cstring_length (slit),
1072 exprNode_unparse (e2)),
1075 else if (len > nelements)
1078 (FLG_STRINGLITTOOLONG,
1079 message ("Stirng literal with %d character%& (counting null terminator) "
1080 "is assigned to %s (insufficient storage available): %s",
1081 cstring_length (slit),
1083 exprNode_unparse (e2)),
1086 else if (len < nelements - 1)
1089 (FLG_STRINGLITSMALLER,
1090 message ("String literal with %d character%& is assigned to %s (possible waste of storage): %s",
1091 cstring_length (slit),
1093 exprNode_unparse (e2)),
1103 static /*@only@*/ /*@notnull@*/ exprNode
1104 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
1106 exprNode e = exprNode_createId (c);
1109 uentry_setUsed (c, e->loc);
1111 if (uentry_isVar (c) && sRef_isFileOrGlobalScope (sr))
1113 checkGlobUse (c, FALSE, e);
1120 exprNode_isZero (exprNode e)
1122 if (exprNode_isDefined (e))
1124 multiVal m = exprNode_getValue (e);
1126 if (multiVal_isInt (m))
1128 return (multiVal_forceInt (m) == 0);
1136 exprNode_isNonNegative (exprNode e)
1138 if (exprNode_isDefined (e))
1140 multiVal m = exprNode_getValue (e);
1142 if (multiVal_isInt (m))
1144 return (multiVal_forceInt (m) >= 0);
1152 ** a[x] - uses a but NOT a[]
1153 ** result sref = a[] (set/use in assignment)
1155 ** The syntax x[a] is also legal in C, and has the same
1156 ** semantics. If ind is an array, and arr is an int, flip
1161 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
1164 ** error in arr, error propagates (no new messages)
1165 ** error in ind, assume valid and continue
1168 DPRINTF (("Array fetch: %s / %s",
1169 exprNode_unparse (e1), exprNode_unparse (e2)));
1171 if (exprNode_isError (e1))
1174 return (exprNode_makeError ());
1180 ctype carr = exprNode_getType (e1);
1181 ctype crarr = ctype_realType (carr);
1184 ** this sets up funny aliasing, that leads to spurious
1185 ** lclint errors. Hence, the i2 comments.
1188 /* evans 2001-09-09 added ctype_isKnown so there is no swap when e1 type is unknown */
1189 if (ctype_isKnown (crarr)
1190 && !ctype_isRealArray (crarr)
1191 && ctype_isRealNumeric (crarr)
1192 && !exprNode_isError (e2)
1193 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1198 carr = exprNode_getType (arr);
1199 crarr = ctype_realType (carr);
1207 DPRINTF (("arr: %s", exprNode_unparse (arr)));
1209 if (sRef_possiblyNull (arr->sref))
1211 if (!usymtab_isGuarded (arr->sref))
1213 if (optgenerror (FLG_NULLDEREF,
1214 message ("Index of %s pointer %q: %s",
1215 sRef_nullMessage (arr->sref),
1216 sRef_unparse (arr->sref),
1217 exprNode_unparse (arr)),
1220 DPRINTF (("ref: %s", sRef_unparseFull (arr->sref)));
1221 sRef_showNullInfo (arr->sref);
1223 /* suppress future messages */
1224 sRef_setNullError (arr->sref);
1229 if (exprNode_isError (ind))
1231 if ((ctype_isArrayPtr (crarr)
1232 && !ctype_isFunction (crarr))
1233 || ctype_isUnknown (carr))
1235 exprNode ret = exprNode_createPartialCopy (arr);
1237 if (ctype_isKnown (carr))
1239 ret->typ = ctype_baseArrayPtr (crarr);
1243 ret->typ = ctype_unknown;
1246 ret->sref = sRef_makeArrayFetch (arr->sref);
1248 ret->kind = XPR_FETCH;
1251 ** Because of funny aliasing (when arr and ind are
1252 ** flipped) spurious errors would be reported here.
1255 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1256 checkSafeUse (ret, arr->sref);
1261 voptgenerror (FLG_TYPE,
1262 message ("Array fetch from non-array (%t): %s[%s]", carr,
1263 exprNode_unparse (e1), exprNode_unparse (e2)),
1265 exprNode_free (arr);
1266 return (exprNode_makeError ());
1271 if (!ctype_isForceRealInt (&(ind->typ)))
1273 ctype rt = ctype_realType (ind->typ);
1275 if (ctype_isChar (rt))
1279 message ("Array fetch using non-integer, %t: %s[%s]",
1281 exprNode_unparse (e1), exprNode_unparse (e2)),
1284 else if (ctype_isEnum (rt))
1288 message ("Array fetch using non-integer, %t: %s[%s]",
1290 exprNode_unparse (e1), exprNode_unparse (e2)),
1297 message ("Array fetch using non-integer, %t: %s[%s]",
1299 exprNode_unparse (e1), exprNode_unparse (e2)),
1303 multiVal_free (ind->val);
1304 ind->val = multiVal_unknown ();
1307 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1309 exprNode ret = exprNode_createSemiCopy (arr);
1310 multiVal m = exprNode_getValue (ind);
1312 ret->typ = ctype_baseArrayPtr (crarr);
1313 ret->kind = XPR_FETCH;
1315 if (multiVal_isInt (m))
1317 int i = (int) multiVal_forceInt (m);
1319 if (sRef_isValid (arr->sref)) {
1320 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1322 ret->sref = sRef_undefined;
1327 ret->sref = sRef_makeArrayFetch (arr->sref);
1330 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1331 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1332 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1334 /* (see comment on spurious errors above) */
1335 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1337 exprNode_checkUse (ret, ind->sref, ind->loc);
1338 exprNode_checkUse (ret, arr->sref, arr->loc);
1344 if (ctype_isUnknown (carr))
1346 exprNode ret = exprNode_createPartialCopy (arr);
1348 ret->kind = XPR_FETCH;
1349 ret->typ = ctype_unknown;
1350 ret->sets = sRefSet_union (ret->sets, ind->sets);
1351 ret->msets = sRefSet_union (ret->msets, ind->msets);
1352 ret->uses = sRefSet_union (ret->uses, ind->uses);
1354 /* (see comment on spurious errors above) */
1355 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1357 exprNode_checkUse (ret, ind->sref, ind->loc);
1358 exprNode_checkUse (ret, arr->sref, arr->loc);
1365 message ("Array fetch from non-array (%t): %s[%s]", carr,
1366 exprNode_unparse (e1), exprNode_unparse (e2)),
1369 exprNode_free (arr);
1370 exprNode_free (ind);
1372 return (exprNode_makeError ());
1382 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1383 exprNodeList args, exprNode ret)
1385 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1389 ** checkPrintfArgs --- checks arguments for printf-like functions
1390 ** Arguments before ... have already been checked.
1391 ** The argument before the ... is a char *.
1392 ** argno is the format string argument.
1396 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1397 exprNodeList args, exprNode ret, int argno)
1400 ** the last argument before the elips is the format string
1405 int nargs = exprNodeList_size (args);
1406 uentryList params = uentry_getParams (fcn);
1410 ** These should be ensured by checkSpecialFunction
1413 llassert (uentryList_size (params) == argno + 1);
1414 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1416 a = exprNodeList_getN (args, argno - 1);
1417 formatloc = fileloc_copy (exprNode_loc (a));
1419 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1420 && exprNode_knownStringValue (a))
1422 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1423 char *code = format;
1426 nargs = exprNodeList_size (args);
1428 while ((code = strchr (code, '%')) != NULL)
1430 char *origcode = code;
1431 cstring codetext = cstring_newEmpty ();
1432 char key = *(++code);
1433 ctype modtype = ctype_int;
1434 bool modified = FALSE;
1436 fileloc_addColumn (formatloc, code - ocode);
1438 codetext = cstring_appendChar (codetext, key);
1441 while (isFlagKey (key))
1444 codetext = cstring_appendChar (codetext, key);
1445 fileloc_incColumn (formatloc);
1448 if (key == 'm') /* skipped in syslog */
1453 /* ignore field width */
1454 while (isdigit ((int) key) != 0)
1457 codetext = cstring_appendChar (codetext, key);
1458 fileloc_incColumn (formatloc);
1461 /* ignore precision */
1465 codetext = cstring_appendChar (codetext, key);
1466 fileloc_incColumn (formatloc);
1469 ** In printf, '*' means: read the next arg as an int for the
1470 ** field width. This seems to be missing from my copy of the
1471 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1472 ** later) but never does.
1477 ; /* don't do anything --- handle later */
1481 while (isdigit ((int) key) != 0)
1484 codetext = cstring_appendChar (codetext, key);
1485 fileloc_incColumn (formatloc);
1492 modtype = ctype_sint; /* short */
1494 codetext = cstring_appendChar (codetext, key);
1495 fileloc_incColumn (formatloc);
1497 else if (key == 'l' || key == 'L')
1499 modtype = ctype_lint; /* long */
1501 codetext = cstring_appendChar (codetext, key);
1502 fileloc_incColumn (formatloc);
1504 if (key == 'l' || key == 'L') {
1505 modtype = ctype_llint; /* long long */
1507 codetext = cstring_appendChar (codetext, key);
1508 fileloc_incColumn (formatloc);
1516 /* now, key = type of conversion to apply */
1518 fileloc_incColumn (formatloc);
1526 message ("No argument corresponding to %q format "
1527 "code %d (%%%s): \"%s\"",
1528 uentry_getName (fcn),
1530 cstring_fromChars (format)),
1533 if (fileloc_isDefined (formatloc)
1534 && context_getFlag (FLG_SHOWCOL))
1536 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1544 a = exprNodeList_getN (args, i);
1547 if (!exprNode_isError (a))
1553 case '*': /* int argument for fieldwidth */
1554 expecttype = ctype_int;
1555 *(--code) = '%'; /* convert it for next code */
1556 fileloc_subColumn (formatloc, 1);
1557 /*@switchbreak@*/ break;
1560 expecttype = ctype_combine (ctype_uint, modtype);
1561 /*@switchbreak@*/ break;
1563 case 'i': /* int argument */
1565 expecttype = ctype_combine (ctype_int, modtype);
1566 /*@switchbreak@*/ break;
1568 case 'x': /* unsigned int */
1570 expecttype = ctype_combine (ctype_uint, modtype);
1572 /*@switchbreak@*/ break;
1578 case 'f': /* double */
1579 expecttype = ctype_combine (ctype_double, modtype);
1580 /*@switchbreak@*/ break;
1582 case 'c': /* int converted to char (check its a char?) */
1583 expecttype = ctype_makeConj (ctype_int,
1584 ctype_makeConj (ctype_char,
1587 /* evans 2001-10-05 - changed to reflect correct ISO spec:
1588 int converted to char */
1590 /* expecttype = ctype_makeConj (ctype_char, ctype_uchar); */
1591 /*@switchbreak@*/ break;
1593 case 's': /* string */
1594 expecttype = ctype_string;
1595 /*@switchbreak@*/ break;
1598 while (((key = *(++code)) != ']')
1601 codetext = cstring_appendChar (codetext, key);
1602 fileloc_incColumn (formatloc);
1608 (message ("Bad character set format: %s",
1609 cstring_fromChars (origcode)));
1612 expecttype = ctype_string;
1613 /*@switchbreak@*/ break;
1615 case 'p': /* pointer */
1616 expecttype = ctype_makePointer (ctype_void);
1617 uentry_setDefState (regArg, SS_RELDEF); /* need not be defined */
1618 sRef_setPosNull (uentry_getSref (regArg), fileloc_undefined); /* could be null */
1619 /*@switchbreak@*/ break;
1621 case 'n': /* pointer to int, modified by call! */
1622 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1624 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1625 /*@switchbreak@*/ break;
1627 case 'm': /* in a syslog, it doesn't consume an argument */
1628 /* should check we're really doing syslog */
1630 /*@switchbreak@*/ break;
1634 expecttype = ctype_unknown;
1638 message ("Unrecognized format code: %s",
1639 cstring_fromChars (origcode)),
1640 fileloc_isDefined (formatloc)
1641 ? formatloc : g_currentloc);
1643 /*@switchbreak@*/ break;
1646 if (!(exprNode_matchArgType (expecttype, a)))
1648 if (ctype_isVoidPointer (expecttype)
1649 && ctype_isRealAbstract (a->typ)
1650 && (context_getFlag (FLG_ABSTVOIDP)))
1656 if (llgenformattypeerror
1657 (expecttype, exprNode_undefined,
1659 message ("Format argument %d to %q (%%%s) expects "
1662 uentry_getName (fcn),
1665 a->typ, exprNode_unparse (a)),
1668 if (fileloc_isDefined (formatloc)
1669 && context_getFlag (FLG_SHOWCOL))
1672 (cstring_makeLiteral
1673 ("Corresponding format code"),
1680 uentry_setType (regArg, expecttype);
1681 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1683 if (ctype_equal (expecttype, ctype_string))
1685 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1688 uentry_setType (regArg, ctype_unknown);
1689 uentry_fixupSref (regArg);
1693 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1704 cstring_free (codetext);
1709 voptgenerror (FLG_TYPE,
1710 message ("Format string for %q has %d arg%&, given %d",
1711 uentry_getName (fcn), i - argno, nargs - argno),
1717 /* no checking possible for compile-time unknown format strings */
1718 if (exprNode_isDefined (a))
1722 message ("Format string parameter to %s is not a compile-time constant: %s",
1723 exprNode_unparse (f),
1724 exprNode_unparse (a)),
1729 fileloc_free (formatloc);
1733 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1734 exprNodeList args, exprNode ret, int argno)
1738 int nargs = exprNodeList_size (args);
1739 uentryList params = uentry_getParams (fcn);
1743 ** These should be ensured by checkSpecialFunction
1746 llassert (uentryList_size (params) == argno + 1);
1747 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1749 a = exprNodeList_getN (args, argno - 1);
1750 formatloc = fileloc_copy (exprNode_loc (a));
1752 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1753 && exprNode_knownStringValue (a))
1755 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1756 char *code = format;
1759 nargs = exprNodeList_size (args);
1761 while ((code = strchr (code, '%')) != NULL)
1763 char *origcode = code;
1764 char key = *(++code);
1765 cstring codetext = cstring_newEmpty ();
1766 ctype modtype = ctype_int;
1767 char modifier = '\0';
1768 bool modified = TRUE;
1769 bool ignore = FALSE;
1771 codetext = cstring_appendChar (codetext, key);
1772 fileloc_addColumn (formatloc, code - ocode);
1775 ** this is based on ANSI standard library description of fscanf
1776 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1779 /* '*' suppresses assignment (does not need match argument) */
1784 codetext = cstring_appendChar (codetext, key);
1787 fileloc_incColumn (formatloc);
1790 /* ignore field width */
1791 while (isdigit ((int) key) != 0)
1794 codetext = cstring_appendChar (codetext, key);
1795 fileloc_incColumn (formatloc);
1800 modtype = ctype_sint; /* short */
1802 codetext = cstring_appendChar (codetext, key);
1803 fileloc_incColumn (formatloc);
1805 else if (key == 'l' || key == 'L')
1807 modtype = ctype_lint; /* long */
1811 codetext = cstring_appendChar (codetext, key);
1813 fileloc_incColumn (formatloc);
1815 if (key == 'l' || key == 'L') {
1816 modtype = ctype_llint; /* long long */
1818 codetext = cstring_appendChar (codetext, key);
1819 fileloc_incColumn (formatloc);
1827 /* now, key = type of conversion to apply */
1829 fileloc_incColumn (formatloc);
1843 message ("No argument corresponding to %q format "
1844 "code %d (%%%s): \"%s\"",
1845 uentry_getName (fcn),
1847 cstring_fromChars (format)),
1850 if (fileloc_isDefined (formatloc)
1851 && context_getFlag (FLG_SHOWCOL))
1854 (cstring_makeLiteral ("Corresponding format code"),
1862 a = exprNodeList_getN (args, i);
1865 if (!exprNode_isError (a))
1871 case '*': /* int argument for fieldwidth */
1872 expecttype = ctype_makePointer (ctype_int);
1873 *(--code) = '%'; /* convert it for next code */
1874 fileloc_subColumn (formatloc, 1);
1875 /*@switchbreak@*/ break;
1878 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1879 /*@switchbreak@*/ break;
1884 case 'X': /* unsigned int */
1885 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1886 /*@switchbreak@*/ break;
1893 /* printf is double, scanf is float! */
1895 if (modifier == 'l')
1897 expecttype = ctype_makePointer (ctype_double);
1899 else if (modifier == 'L')
1901 expecttype = ctype_makePointer (ctype_ldouble);
1905 llassert (modifier == '\0');
1906 expecttype = ctype_makePointer (ctype_float);
1908 /*@switchbreak@*/ break;
1910 case 'c': /* int converted to char (check its a char?) */
1911 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1912 /*@switchbreak@*/ break;
1914 case 's': /* string */
1915 expecttype = ctype_string;
1916 /*@switchbreak@*/ break;
1920 while (((key = *(++code)) != ']')
1923 codetext = cstring_appendChar (codetext, key);
1924 fileloc_incColumn (formatloc);
1930 (message ("Bad character set format: %s",
1931 cstring_fromChars (origcode)));
1934 expecttype = ctype_string;
1935 /*@switchbreak@*/ break;
1938 case 'p': /* pointer */
1941 message ("Format code should not be used in scanf: %s",
1942 cstring_fromChars (origcode)),
1943 fileloc_isDefined (formatloc)
1944 ? formatloc : g_currentloc);
1946 expecttype = ctype_unknown;
1947 /*@switchbreak@*/ break;
1949 case 'n': /* pointer to int, modified by call! */
1950 expecttype = ctype_makePointer (ctype_int);
1951 /*@switchbreak@*/ break;
1954 expecttype = ctype_unknown;
1958 message ("Unrecognized format code: %s",
1959 cstring_fromChars (origcode)),
1960 fileloc_isDefined (formatloc)
1961 ? formatloc : g_currentloc);
1963 /*@switchbreak@*/ break;
1966 if (!(exprNode_matchArgType (expecttype, a)))
1968 if (ctype_isVoidPointer (expecttype)
1969 && ctype_isRealAbstract (a->typ)
1970 && (context_getFlag (FLG_ABSTVOIDP)))
1976 if (llgenformattypeerror
1977 (expecttype, exprNode_undefined,
1979 message ("Format argument %d to %q (%%%s) expects "
1982 uentry_getName (fcn),
1983 codetext, expecttype,
1984 a->typ, exprNode_unparse (a)),
1987 if (fileloc_isDefined (formatloc)
1988 && context_getFlag (FLG_SHOWCOL))
1991 (cstring_makeLiteral
1992 ("Corresponding format code"),
1999 uentry_setType (outArg, expecttype);
2000 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
2001 uentry_setType (outArg, ctype_unknown);
2002 uentry_fixupSref (outArg);
2006 exprNode_checkCallModifyVal (a->sref, args, f, ret);
2011 /* a->sref = defref; */
2018 cstring_free (codetext);
2023 voptgenerror (FLG_TYPE,
2024 message ("Format string for %q has %d arg%&, given %d",
2025 uentry_getName (fcn), i - argno, nargs - argno),
2031 /* no checking possible for compile-time unknown format strings */
2034 fileloc_free (formatloc);
2038 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
2041 /*@unused@*/ int argno)
2044 ** the last argument before the elips is the format string
2047 int nargs = exprNodeList_size (args);
2052 a = exprNodeList_getN (args, argno - 1);
2053 formatloc = fileloc_copy (exprNode_loc (a));
2055 if (ctype_isUnknown (cstringType)) {
2056 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
2058 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
2062 if (ctype_isUnknown (ctypeType)) {
2063 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
2065 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
2069 if (ctype_isUnknown (filelocType)) {
2070 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
2072 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
2076 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
2077 && exprNode_knownStringValue (a))
2079 cstring format = multiVal_forceString (exprNode_getValue (a));
2080 char *code = cstring_toCharsSafe (format);
2083 nargs = exprNodeList_size (args);
2085 while ((code = strchr (code, '%')) != NULL)
2087 char *origcode = code;
2088 char key = *(++code);
2089 cstring codetext = cstring_newEmpty ();
2090 bool isOnly = FALSE;
2092 codetext = cstring_appendChar (codetext, key);
2094 fileloc_addColumn (formatloc, code - ocode);
2096 while (key >= '0' && key <= '9')
2099 codetext = cstring_appendChar (codetext, key);
2100 fileloc_incColumn (formatloc);
2104 fileloc_incColumn (formatloc);
2108 if (key == '&') /* plural marker */
2117 message ("Message missing format arg %d (%%%s): \"%s\"",
2118 i + 1, codetext, format),
2124 a = exprNodeList_getN (args, i);
2128 if (!exprNode_isError (a))
2132 /*@-loopswitchbreak@*/
2138 expecttype = ctype_char; break;
2140 expecttype = cstringType; break;
2142 expecttype = cstringType; isOnly = TRUE; break;
2144 expecttype = cstringType; isOnly = TRUE; break;
2145 case 'd': expecttype = ctype_int; break;
2146 case 'u': expecttype = ctype_uint; break;
2147 case 'w': expecttype = ctype_ulint; break;
2148 case 'f': expecttype = ctype_float; break;
2149 case 'b': expecttype = ctype_bool; break;
2150 case 't': expecttype = ctypeType; break;
2151 case 'l': expecttype = filelocType; break;
2152 case '&': /* a wee bit of a hack methinks */
2153 expecttype = ctype_int;
2155 case 'r': expecttype = ctype_bool; break;
2157 expecttype = ctype_unknown;
2160 message ("Unrecognized format code: %s",
2161 cstring_fromChars (origcode)),
2162 fileloc_isDefined (formatloc)
2163 ? formatloc : g_currentloc);
2166 /*@=loopswitchbreak@*/
2168 if (!(exprNode_matchArgType (expecttype, a)))
2170 if (ctype_isVoidPointer (expecttype)
2171 && ctype_isRealAbstract (a->typ)
2172 && (context_getFlag (FLG_ABSTVOIDP)))
2178 if (llgenformattypeerror
2179 (expecttype, exprNode_undefined,
2181 message ("Format argument %d to %q (%%%s) expects "
2184 uentry_getName (fcn),
2185 codetext, expecttype,
2186 a->typ, exprNode_unparse (a)),
2189 if (fileloc_isDefined (formatloc)
2190 && context_getFlag (FLG_SHOWCOL))
2193 (cstring_makeLiteral
2194 ("Corresponding format code"),
2201 if (ctype_equal (expecttype, cstringType))
2205 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2206 uentry_fixupSref (csOnlyArg);
2210 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2211 uentry_fixupSref (csArg);
2216 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2217 uentry_fixupSref (regArg);
2223 cstring_free (codetext);
2228 voptgenerror (FLG_TYPE,
2229 message ("Format string for %q has %d arg%&, given %d",
2230 uentry_getName (fcn), i - argno, nargs -argno),
2236 /* no checking possible for compile-time unknown format strings */
2239 fileloc_free (formatloc);
2243 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2244 /*@notnull@*/ exprNode e2,
2250 bool hadUncon = FALSE;
2252 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
2253 sRefSet_hasUnconstrained (sets2))
2256 (FLG_EVALORDERUNCON,
2258 ("Expression may have undefined behavior (%q used in right operand "
2259 "may set global variable %q used in left operand): %s %s %s",
2260 sRefSet_unparseUnconstrained (sets2),
2261 sRef_unparse (sRef_getRootBase (e1->sref)),
2262 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2266 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
2267 sRefSet_hasUnconstrained (sets1))
2270 (FLG_EVALORDERUNCON,
2272 ("Expression has undefined behavior (%q used in left operand "
2273 "may set global variable %q used in right operand): %s %s %s",
2274 sRefSet_unparseUnconstrained (sets1),
2275 sRef_unparse (e2->sref),
2276 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2280 sRefSet_realElements (e1->uses, sr)
2282 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2287 ("Expression has undefined behavior (left operand uses %q, "
2288 "modified by right operand): %s %s %s",
2290 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2293 } end_sRefSet_realElements;
2295 sRefSet_realElements (sets1, sr)
2297 if (sRef_isMeaningful (sr))
2299 if (sRef_same (sr, e2->sref))
2304 ("Expression has undefined behavior (value of right operand "
2305 "modified by left operand): %s %s %s",
2306 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2309 else if (sRefSet_member (e2->uses, sr))
2314 ("Expression has undefined behavior (left operand modifies %q, "
2315 "used by right operand): %s %s %s",
2317 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2322 if (sRefSet_member (sets2, sr))
2324 if (sRef_isUnconstrained (sr))
2332 hadUncon = optgenerror
2333 (FLG_EVALORDERUNCON,
2335 ("Expression may have undefined behavior. Left operand "
2336 "calls %q; right operand calls %q. The unconstrained "
2337 "functions may modify global state used by "
2338 "the other operand): %s %s %s",
2339 sRefSet_unparseUnconstrained (sets1),
2340 sRefSet_unparseUnconstrained (sets2),
2341 exprNode_unparse (e1), lltok_unparse (op),
2342 exprNode_unparse (e2)),
2351 ("Expression has undefined behavior (both "
2352 "operands modify %q): %s %s %s",
2354 exprNode_unparse (e1),
2355 lltok_unparse (op), exprNode_unparse (e2)),
2361 } end_sRefSet_realElements;
2364 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2366 bool hasError = FALSE;
2368 if (exprNode_isError (e1) || exprNode_isError (e2))
2373 if (sRefSet_member (e2->sets, e1->sref))
2375 if (e2->kind == XPR_CALL)
2381 hasError = optgenerror
2383 message ("Expression has undefined behavior "
2384 "(value of left operand %s is modified "
2385 "by right operand %s): %s %s %s",
2386 exprNode_unparse (e1),
2387 exprNode_unparse (e2),
2388 exprNode_unparse (e1), lltok_unparse (op),
2389 exprNode_unparse (e2)),
2394 if (context_getFlag (FLG_EVALORDERUNCON))
2396 if (sRefSet_member (e2->msets, e1->sref))
2398 if (e2->kind == XPR_CALL)
2404 hasError = optgenerror
2407 ("Expression has undefined behavior (value of left "
2408 "operand may be modified by right operand): %s %s %s",
2409 exprNode_unparse (e1), lltok_unparse (op),
2410 exprNode_unparse (e2)),
2418 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2420 if (context_maybeSet (FLG_EVALORDERUNCON))
2422 checkExpressionDefinedAux (e1, e2, e1->msets,
2423 e2->msets, op, FLG_EVALORDERUNCON);
2428 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2431 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2432 exprNodeList args, bool isIter, exprNode ret)
2436 if (!exprNode_isError (f))
2438 if (!uentryList_isMissingParams (cl))
2440 int nargs = exprNodeList_size (args);
2441 int expectargs = uentryList_size (cl);
2445 if (expectargs == 0)
2453 message ("Iter %q invoked with %d args, "
2455 uentry_getName (fcn),
2463 message ("Function %s called with %d args, "
2465 exprNode_unparse (f), nargs),
2472 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2474 exprNodeList_reset (args);
2476 uentryList_elements (cl, current)
2478 ctype ct = uentry_getType (current);
2481 if (ctype_isElips (ct))
2484 ** do special checking for printf/scanf library functions
2486 ** this is kludgey code, just for handling the special case
2490 if (uentry_isPrintfLike (fcn))
2492 checkPrintfArgs (f, fcn, args, ret, i);
2495 else if (uentry_isScanfLike (fcn))
2497 checkScanfArgs (f, fcn, args, ret, i);
2500 else if (uentry_isMessageLike (fcn))
2502 checkMessageArgs (f, fcn, args, i);
2507 llassert (!uentry_isSpecialFunction (fcn));
2510 nargs = expectargs; /* avoid errors */
2515 if (i >= nargs) break;
2517 a = exprNodeList_current (args);
2518 exprNodeList_advance (args);
2522 if (exprNode_isError (a))
2529 probably necessary? I'm not sure about this one
2530 checkMacroParen (a);
2533 f->guards = guardSet_union (f->guards, a->guards);
2535 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2537 if (!(exprNode_matchArgType (ct, a)))
2539 DPRINTF (("Args mismatch!"));
2541 if (ctype_isVoidPointer (ct)
2542 && (ctype_isPointer (a->typ)
2543 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2548 ("Pointer to abstract type (%t) used "
2550 "(arg %d to %q): %s",
2552 uentry_getName (fcn),
2553 exprNode_unparse (a)),
2561 (ct, exprNode_undefined,
2564 ("Iter %q expects arg %d to "
2565 "be %t gets %t: %s",
2566 uentry_getName (fcn),
2567 i, ct, a->typ, exprNode_unparse (a)),
2578 ("Function %q expects arg %d to be %t gets %t: %s",
2579 uentry_getName (fcn),
2580 i, ct, a->typ, exprNode_unparse (a)),
2583 DPRINTF (("Types: %s / %s",
2585 ctype_unparse (a->typ)));
2589 ** Clear null marker for abstract types.
2590 ** (It is not revealed, so suppress future messages.)
2593 if (ctype_isAbstract (a->typ))
2595 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2602 } end_uentryList_elements ;
2605 if (expectargs != nargs) /* note: not != since we may have ... */
2607 if (ctype_isElips (last))
2611 message ("Function %s called with %d args, expects at least %d",
2612 exprNode_unparse (f),
2613 nargs, expectargs - 1),
2622 message ("Iter %q invoked with %d args, expects %d",
2623 uentry_getName (fcn), nargs, expectargs),
2630 message ("Function %s called with %d args, expects %d",
2631 exprNode_unparse (f),
2644 ** Check for undefined code sequences in function arguments:
2646 ** one parameter sets something used by another parameter
2647 ** one parameter sets something set by another parameter
2651 checkSequencingOne (exprNode f, exprNodeList args,
2652 /*@notnull@*/ exprNode el, int argno)
2655 ** Do second loop, iff +undefunspec
2659 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2661 for (checkloop = 0; checkloop < numloops; checkloop++)
2667 thissets = el->sets;
2671 llassert (checkloop == 1);
2672 thissets = el->msets;
2675 sRefSet_realElements (thissets, thisset)
2679 /*@access exprNodeList@*/
2680 for (j = 0; j < args->nelements; j++)
2682 exprNode jl = args->elements[j];
2683 int thisargno = j + 1;
2685 if (thisargno != argno && exprNode_isDefined (jl))
2687 sRefSet otheruses = jl->uses;
2689 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
2690 sRefSet_hasUnconstrained (thissets))
2693 (FLG_EVALORDERUNCON,
2696 ("%q used in argument %d may set "
2697 "global variable %q used by argument %d: %s(%q)",
2698 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2701 sRef_unparse (sRef_getRootBase (jl->sref)),
2703 exprNode_unparse (f), exprNodeList_unparse (args)),
2707 if (sRefSet_member (otheruses, thisset))
2709 if (sRef_isUnconstrained (thisset))
2712 (FLG_EVALORDERUNCON,
2714 ("Unconstrained functions used in arguments %d (%q) "
2715 "and %d (%s) may modify "
2716 "or use global state in undefined way: %s(%q)",
2718 sRefSet_unparseUnconstrainedPlain (otheruses),
2720 sRef_unconstrainedName (thisset),
2721 exprNode_unparse (f),
2722 exprNodeList_unparse (args)),
2730 ("Argument %d modifies %q, used by argument %d "
2731 "(order of evaluation of actual parameters is "
2732 "undefined): %s(%q)",
2733 argno, sRef_unparse (thisset), thisargno,
2734 exprNode_unparse (f), exprNodeList_unparse (args)),
2740 sRefSet othersets = jl->sets;
2742 if (sRefSet_member (othersets, thisset))
2744 if (sRef_isUnconstrained (thisset))
2747 (FLG_EVALORDERUNCON,
2749 ("Unconstrained functions used in "
2750 "arguments %d (%q) and %d (%s) may modify "
2751 "or use global state in undefined way: %s(%q)",
2753 sRefSet_unparseUnconstrainedPlain (othersets),
2755 sRef_unconstrainedName (thisset),
2756 exprNode_unparse (f), exprNodeList_unparse (args)),
2764 ("Argument %d modifies %q, set by argument %d (order of"
2765 " evaluation of actual parameters is undefined): %s(%q)",
2766 argno, sRef_unparse (thisset), thisargno,
2767 exprNode_unparse (f), exprNodeList_unparse (args)),
2774 /*@noaccess exprNodeList@*/
2775 } end_sRefSet_realElements;
2780 checkSequencing (exprNode f, exprNodeList args)
2782 if (exprNodeList_size (args) > 1)
2787 /*@access exprNodeList*/
2789 for (i = 0; i < args->nelements; i++)
2791 el = args->elements[i];
2793 if (!exprNode_isError (el))
2795 checkSequencingOne (f, args, el, i + 1);
2798 /*@noaccess exprNodeList*/
2803 ** requires le = exprNode_getUentry (f)
2807 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2808 uentry le, exprNodeList args,
2809 /*@notnull@*/ exprNode ret, int specialArgs)
2811 bool isSpec = FALSE;
2812 bool hasMods = FALSE;
2814 globSet usesGlobs = globSet_undefined;
2815 sRefSet mods = sRefSet_undefined;
2816 bool freshMods = FALSE;
2817 uentryList params = uentryList_undefined;
2819 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2822 ** check globals and modifies
2827 if (!uentry_isValid (le))
2829 ctype fr = ctype_realType (f->typ);
2831 if (ctype_isFunction (fr))
2833 params = ctype_argsFunction (fr);
2837 params = uentryList_missingParams;
2840 if (!context_getFlag (FLG_MODNOMODS)
2841 && !context_getFlag (FLG_GLOBUNSPEC))
2843 checkUnspecCall (f, params, args);
2849 fname = uentry_rawName (le);
2853 if (uentry_isFunction (le))
2855 params = uentry_getParams (le);
2856 mods = uentry_getMods (le);
2857 hasMods = uentry_hasMods (le);
2858 usesGlobs = uentry_getGlobs (le);
2859 isSpec = uentry_isSpecified (le);
2861 else /* not a function */
2863 ctype ct = ctype_realType (uentry_getType (le));
2865 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2866 ("checkModGlobs: uentry not a function: %s",
2867 uentry_unparse (le)));
2869 params = ctype_argsFunction (ct);
2870 return; /*@32 ! remove this? */
2879 globSet_allElements (usesGlobs, el)
2881 if (sRef_isValid (el))
2883 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2885 context_usedGlobal (el);
2886 exprNode_checkUse (f, el, f->loc);
2888 if (context_checkInternalUse ())
2890 if (!context_globAccess (el))
2892 if (sRef_isSystemState (el)
2893 && !context_getFlag (FLG_MODFILESYSTEM))
2902 ("Called procedure %s may access %q, but "
2903 "globals list does not include globals %s",
2904 exprNode_unparse (f),
2906 cstring_makeLiteralTemp (sRef_isInternalState (el)
2914 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2920 uentry gle = sRef_getUentry (el);
2921 sRef sr = sRef_updateSref (el);
2923 if (sRef_isUndefGlob (el))
2925 sRef_setDefined (sr, f->loc);
2926 exprNode_checkSet (f, sr);
2934 if (sRef_isAllocated (el))
2936 exprNode_checkSet (f, sr);
2940 if (sRef_isStateUndefined (sr))
2945 ("%s %q used by function undefined before call: %s",
2946 sRef_getScopeName (sr),
2948 exprNode_unparse (f)),
2950 sRef_setDefined (sr, f->loc);
2952 exprNode_checkUse (f, sr, f->loc);
2955 checkGlobUse (gle, TRUE, f);
2958 if (sRef_isKilledGlob (el))
2960 sRef_kill (sr, f->loc);
2961 context_usedGlobal (sr);
2965 } end_globSet_allElements;
2971 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
2973 sRefSet smods = sRefSet_undefined;
2976 ** NEED to check for modifies anything
2980 ** check each sRef that called function modifies (ml), is
2986 sRefSet_allElements (mods, s) /* s is something which may be modified */
2988 DPRINTF (("Check modify: %s", sRef_unparse (s)));
2990 if (sRef_isKindSpecial (s))
2992 if (sRef_isSpecInternalState (s))
2994 if (context_getFlag (FLG_MODINTERNALSTRICT))
2996 exprNode_checkCallModifyVal (s, args, f, ret);
3000 sRefSet mmods = context_modList ();
3002 sRefSet_allElements (mmods, el)
3004 if (sRef_isInternalState (el))
3006 sRef_setModified (el);
3008 } end_sRefSet_allElements ;
3013 exprNode_checkCallModifyVal (s, args, f, ret);
3018 sRef rb = sRef_getRootBase (s);
3020 if (sRef_isFileOrGlobalScope (rb))
3022 context_usedGlobal (rb);
3025 if (sRef_isFileStatic (s)
3026 && !fileId_equal (fileloc_fileId (f->loc),
3027 fileloc_fileId (uentry_whereDefined (le))))
3029 smods = sRefSet_insert (smods, s);
3033 exprNode_checkCallModifyVal (s, args, f, ret);
3036 } end_sRefSet_allElements;
3041 ** Static elements in modifies set can have nasty consequences.
3042 ** (I think...have not been able to reproduce a possible bug.)
3045 if (!sRefSet_isDefined (smods))
3047 mods = sRefSet_newCopy (mods);
3050 sRefSet_allElements (smods, el)
3052 bool res = sRefSet_delete (mods, el);
3055 } end_sRefSet_allElements;
3057 sRefSet_free (smods);
3062 else if (sRefSet_isDefined (mods))
3063 { /* just check observers */
3066 sRefSet_allElements (mods, s) /* s is something which may be modified */
3068 sRef rb = sRef_getRootBase (s);
3072 if (sRef_isParam (rb))
3074 sRef b = sRef_fixBaseParam (s, args);
3076 if (sRef_isObserver (b))
3078 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
3082 message ("Function call may modify observer%q: %s",
3083 sRef_unparsePreOpt (b), exprNode_unparse (e)),
3086 sRef_showExpInfo (b);
3090 } end_sRefSet_allElements;
3094 if (!hasMods) /* no specified modifications */
3096 if (context_getFlag (FLG_MODOBSERVERUNCON))
3098 exprNodeList_elements (args, e)
3100 if (exprNode_isDefined (e))
3102 sRef s = exprNode_getSref (e);
3104 if (sRef_isObserver (s)
3105 && ctype_isMutable (sRef_getType (s)))
3108 (FLG_MODOBSERVERUNCON,
3110 ("Call to unconstrained function %s may modify observer%q: %s",
3111 exprNode_unparse (f),
3112 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3115 sRef_showExpInfo (s);
3119 } end_exprNodeList_elements;
3124 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3126 ret->uses = sRefSet_union (ret->uses, f->uses);
3127 ret->sets = sRefSet_union (ret->sets, f->sets);
3128 ret->msets = sRefSet_union (ret->msets, f->msets);
3133 ** Spurious errors reported, because lclint can't tell
3134 ** mods must be fresh if freshMods is true.
3137 /*@i@*/ sRefSet_free (mods);
3143 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3145 if (uentry_isVar (glob))
3147 if (context_inFunctionLike ())
3149 sRef sr = uentry_getSref (glob);
3151 context_usedGlobal (sr);
3153 if (context_checkGlobUse (glob))
3155 if (!context_globAccess (sr))
3161 message ("Called procedure %s may access %s %q",
3162 exprNode_unparse (e),
3163 sRef_unparseScope (sr),
3164 uentry_getName (glob)),
3171 message ("Undocumented use of %s %s",
3172 sRef_unparseScope (sr),
3173 exprNode_unparse (e)),
3182 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3187 reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
3189 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3190 exprNode_unparse (f), exprNodeList_unparse (args),
3191 uentry_unparseFull (le),
3192 stateClauseList_unparse (uentry_getStateClauseList (le))));
3194 if (uentry_isValid (le) && uentry_isFunction (le))
3196 stateClauseList sclauses = uentry_getStateClauseList (le);
3198 if (stateClauseList_isDefined (sclauses))
3200 DPRINTF (("Reflect ensures: %s / %s / %s",
3201 uentry_unparse (le),
3202 exprNode_unparse (f), exprNodeList_unparse (args)));
3204 stateClauseList_elements (sclauses, cl)
3206 if (stateClause_hasEnsures (cl))
3208 /* Same in usymtab.c:1904 */
3209 if (stateClause_setsMetaState (cl))
3211 qual q = stateClause_getMetaQual (cl);
3212 annotationInfo ainfo = qual_getAnnotationInfo (q);
3213 metaStateInfo minfo = annotationInfo_getState (ainfo);
3214 cstring key = metaStateInfo_getName (minfo);
3215 int mvalue = annotationInfo_getValue (ainfo);
3217 sRefSet osrs = sRefSet_undefined;
3220 if (stateClause_isGlobal (cl))
3222 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3227 srs = stateClause_getRefs (cl);
3230 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3233 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3235 sRefSet_elements (srs, sel)
3239 if (sRef_isResult (sRef_getRootBase (sel)))
3241 s = exprNode_getSref (ret);
3245 s = sRef_fixBaseParam (sel, args);
3248 DPRINTF (("Reflecting state clause on: %s / %s",
3249 sRef_unparse (sel), sRef_unparse (s)));
3251 sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3252 } end_sRefSet_elements;
3254 sRefSet_free (osrs);
3258 sRefSet srs = stateClause_getRefs (cl);
3259 sRefModVal modf = stateClause_getEnsuresFunction (cl);
3260 int eparam = stateClause_getStateParameter (cl);
3262 DPRINTF (("Reflect after clause: %s / %s",
3263 stateClause_unparse (cl),
3264 sRefSet_unparse (srs)));
3266 sRefSet_elements (srs, sel)
3270 DPRINTF (("elements: %s", sRef_unparse (sel)));
3271 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3273 if (sRef_isResult (sRef_getRootBase (sel)))
3275 DPRINTF (("Fix base: %s / %s",
3276 sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
3277 s = sRef_fixBase (sel, exprNode_getSref (ret));
3278 DPRINTF (("==> %s", sRef_unparseFull (s)));
3282 s = sRef_fixBaseParam (sel, args);
3285 DPRINTF (("elements: %s", sRef_unparse (s)));
3286 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3288 DPRINTF (("Reflecting state clause on: %s / %s",
3289 sRef_unparseFull (sel), sRef_unparseFull (s)));
3291 /* evans 2001-08-24 - added aliasSetCompleteParam */
3292 sRef_aliasSetCompleteParam (modf, s, eparam, exprNode_loc (f));
3294 DPRINTF (("After reflecting state clause on: %s / %s",
3295 sRef_unparseFull (sel), sRef_unparseFull (s)));
3296 } end_sRefSet_elements;
3299 } end_stateClauseList_elements ;
3302 DPRINTF (("Here: %s / %s",
3303 uentry_unparseFull (le),
3304 bool_unparse (uentry_hasMetaStateEnsures (le))));
3306 if (uentry_hasMetaStateEnsures (le))
3308 fileloc loc = exprNode_loc (f);
3310 metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3312 metaStateConstraintList_elements (mscl, msc)
3314 metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3315 metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3316 metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
3317 cstring key = metaStateInfo_getName (msinfo);
3318 sRef mlsr = metaStateSpecifier_getSref (msspec);
3320 sRef lastref = sRef_undefined;
3321 stateValue sval = stateValue_undefined;
3323 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3324 metaStateConstraint_unparse (msc)));
3325 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3327 if (sRef_isResult (sRef_getRootBase (mlsr)))
3329 s = exprNode_getSref (ret);
3333 s = sRef_fixBaseParam (mlsr, args);
3336 DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3338 while (metaStateExpression_isDefined (msexpr))
3340 metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
3341 metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
3344 DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3346 if (metaStateExpression_isMerge (msexpr))
3348 msexpr = metaStateExpression_getRest (msexpr);
3352 msexpr = metaStateExpression_undefined;
3355 if (metaStateInfo_isDefined (msi))
3357 /* Must match lhs state */
3358 llassert (metaStateInfo_equal (msinfo, msi));
3361 if (metaStateSpecifier_isElipsis (ms))
3364 ** For elipsis, we need to merge all the relevant elipsis parameters
3368 uentryList params = uentry_getParams (le);
3369 int paramno = uentryList_size (params) - 1;
3371 if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
3375 message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3376 uentry_getName (le)),
3377 uentry_whereLast (le));
3378 /*@innerbreak@*/ break;
3381 while (paramno < exprNodeList_size (args))
3383 exprNode arg = exprNodeList_getN (args, paramno);
3384 fs = exprNode_getSref (arg);
3385 DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3387 /* cut and pasted... gack*/
3388 if (stateValue_isDefined (sval))
3390 /* Use combination table to merge old state value with new one: */
3391 stateValue tval = sRef_getMetaStateValue (fs, key);
3393 if (stateValue_isDefined (tval))
3395 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3396 cstring msg = cstring_undefined;
3397 int nval = stateCombinationTable_lookup (sctable,
3398 stateValue_getValue (sval),
3399 stateValue_getValue (tval),
3401 DPRINTF (("Combining: %s + %s -> %d",
3402 stateValue_unparseValue (sval, msinfo),
3403 stateValue_unparseValue (tval, msinfo),
3406 if (nval == stateValue_error)
3411 ("Attributes merged in ensures clause in states that "
3412 "cannot be combined (%q is %q, %q is %q)%q",
3413 sRef_unparse (lastref),
3414 stateValue_unparseValue (sval, msinfo),
3416 stateValue_unparseValue (tval, msinfo),
3417 cstring_isDefined (msg) ?
3418 message (": %s", msg) : cstring_undefined),
3421 sRef_showMetaStateInfo (fs, key);
3425 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3426 loc = exprNode_loc (arg);
3430 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3435 sval = sRef_getMetaStateValue (fs, key);
3440 if (stateValue_isError (sval))
3442 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3451 msr = metaStateSpecifier_getSref (ms);
3454 llassert (sRef_isParam (sRef_getRootBase (msr)));
3455 fs = sRef_fixBaseParam (msr, args);
3457 if (stateValue_isDefined (sval))
3459 /* Use combination table to merge old state value with new one: */
3460 stateValue tval = sRef_getMetaStateValue (fs, key);
3462 if (stateValue_isDefined (tval))
3464 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3465 cstring msg = cstring_undefined;
3466 int nval = stateCombinationTable_lookup (sctable,
3467 stateValue_getValue (sval),
3468 stateValue_getValue (tval),
3470 DPRINTF (("Combining: %s + %s -> %d",
3471 stateValue_unparseValue (sval, msinfo),
3472 stateValue_unparseValue (tval, msinfo),
3475 if (nval == stateValue_error)
3480 ("Attributes merged in ensures clause in states that "
3481 "cannot be combined (%q is %q, %q is %q)%q",
3482 sRef_unparse (lastref),
3483 stateValue_unparseValue (sval, msinfo),
3485 stateValue_unparseValue (tval, msinfo),
3486 cstring_isDefined (msg)
3487 ? message (": %s", msg) : cstring_undefined),
3490 sRef_showMetaStateInfo (fs, key);
3494 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3498 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3503 sval = sRef_getMetaStateValue (fs, key);
3508 if (stateValue_isError (sval))
3510 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3515 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3517 if (stateValue_isDefined (sval))
3519 sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
3523 DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
3525 } end_metaStateConstraintList_elements ;
3527 metaStateConstraintList_free (mscl);
3533 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3535 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3536 exprNode_unparse (f), exprNodeList_unparse (args),
3537 uentry_unparseFull (le),
3538 stateClauseList_unparse (uentry_getStateClauseList (le))));
3540 if (uentry_isValid (le) && uentry_isFunction (le))
3542 stateClauseList sclauses = uentry_getStateClauseList (le);
3544 if (stateClauseList_isDefined (sclauses))
3546 DPRINTF (("Check requires: %s / %s / %s",
3547 uentry_unparse (le),
3548 exprNode_unparse (f), exprNodeList_unparse (args)));
3550 stateClauseList_elements (sclauses, cl)
3552 DPRINTF (("Check clause: %s / %s",
3553 stateClause_unparse (cl),
3554 bool_unparse (stateClause_hasRequires (cl))));
3556 if (stateClause_hasRequires (cl))
3558 sRefSet osrs = sRefSet_undefined;
3561 if (stateClause_isGlobal (cl))
3563 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3568 srs = stateClause_getRefs (cl);
3571 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3573 if (stateClause_setsMetaState (cl))
3575 qual q = stateClause_getMetaQual (cl);
3576 annotationInfo ainfo = qual_getAnnotationInfo (q);
3577 metaStateInfo minfo = annotationInfo_getState (ainfo);
3578 cstring key = metaStateInfo_getName (minfo);
3579 int mvalue = annotationInfo_getValue (ainfo);
3581 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3583 sRefSet_elements (srs, sel)
3585 sRef s = sRef_fixBaseParam (sel, args);
3587 if (sRef_isResult (sRef_getRootBase (sel)))
3593 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3594 sRef_unparseFull (sel), sRef_unparseFull (s),
3597 if (!sRef_checkMetaStateValue (s, key, mvalue))
3599 DPRINTF (("HERE: %s", sRef_unparse (s)));
3603 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3604 uentry_getName (le),
3605 sRef_isGlobalMarker (s)
3607 : message (" by %q", sRef_unparse (s)),
3608 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3610 stateClause_unparse (cl)),
3613 sRef_showAliasInfo (s);
3617 DPRINTF (("Error supressed!"));
3618 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3619 DPRINTF (("Context supress: %s",
3620 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3624 } end_sRefSet_elements;
3628 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3629 int eparam = stateClause_getStateParameter (cl);
3631 DPRINTF (("Reflect after clause: %s / %s",
3632 stateClause_unparse (cl),
3633 sRefSet_unparse (srs)));
3635 sRefSet_elements (srs, sel)
3639 DPRINTF (("elements: %s", sRef_unparse (sel)));
3640 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3642 s = sRef_fixBaseParam (sel, args);
3644 DPRINTF (("elements: %s", sRef_unparse (s)));
3645 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3647 if (sRef_isResult (sRef_getRootBase (sel)))
3649 ; /*@i423 what do we do about results */
3653 DPRINTF (("Reflecting state clause on: %s / %s",
3654 sRef_unparse (sel), sRef_unparse (s)));
3656 modf (s, eparam, exprNode_loc (f));
3658 } end_sRefSet_elements;
3661 sRefSet_free (osrs);
3663 } end_stateClauseList_elements ;
3668 static /*@only@*/ exprNode
3669 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3670 ctype t, /*@keep@*/ exprNodeList args)
3672 /* requires f is a non-error exprNode, with type function */
3673 cstring fname = exprNode_unparse (f);
3674 uentry le = exprNode_getUentry (f);
3675 exprNode ret = exprNode_createPartialCopy (f);
3680 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3682 ret->typ = ctype_getReturnType (t);
3683 ret->kind = XPR_CALL;
3685 ret->edata = exprData_makeCall (f, args);
3688 ** Order of these steps is very important!
3690 ** Must check for argument dependencies before messing up uses and sets.
3693 if (context_getFlag (FLG_EVALORDER))
3695 exprNodeList_elements (args, current)
3697 if (exprNode_isDefined (current))
3699 exprNode_addUse (current, current->sref);
3701 } end_exprNodeList_elements;
3703 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3705 checkSequencing (f, args);
3708 exprNodeList_elements (args, current)
3710 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3712 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3714 } end_exprNodeList_elements ;
3717 special = checkArgs (le, f, t, args, ret);
3718 checkGlobMods (f, le, args, ret, special);
3719 checkRequiresClause (le, f, args);
3722 if (uentry_isValid (le)
3723 && (uentry_isFunction (le)
3724 || (uentry_isVariable (le)
3725 && ctype_isFunction (uentry_getType (le)))))
3727 exitkind exk = uentry_getExitCode (le);
3729 /* f->typ is already set to the return type */
3731 DPRINTF (("Function: %s", uentry_unparseFull (le)));
3732 ret->sref = uentry_returnedRef (le, args);
3733 DPRINTF (("Returned: %s / %s",
3734 uentry_unparseFull (le),
3735 sRef_unparseFull (ret->sref)));
3737 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3739 qual nullPred = uentry_nullPred (le);
3741 if (qual_isTrueNull (nullPred))
3743 exprNode arg = exprNodeList_head (args);
3745 if (exprNode_isDefined (arg))
3747 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3750 else if (qual_isFalseNull (nullPred))
3752 exprNode arg = exprNodeList_head (args);
3754 if (exprNode_isDefined (arg))
3756 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3761 llassert (qual_isUnknown (nullPred));
3765 if (exitkind_isConditionalExit (exk))
3769 ** if (arg0) then { exit! } else { ; }
3771 ** if (arg0) then { ; } else { exit! }
3776 llassert (!exprNodeList_isEmpty (args));
3777 firstArg = exprNodeList_head (args);
3779 if (exprNode_isDefined (firstArg)
3780 && !guardSet_isEmpty (firstArg->guards))
3782 usymtab_trueBranch (guardSet_undefined);
3783 usymtab_altBranch (guardSet_undefined);
3785 if (exitkind_isTrueExit (exk))
3787 usymtab_popBranches (firstArg,
3788 exprNode_makeMustExit (),
3790 TRUE, TRUEEXITCLAUSE);
3794 usymtab_popBranches (firstArg,
3796 exprNode_makeMustExit (),
3797 TRUE, FALSEEXITCLAUSE);
3801 ret->exitCode = XK_MAYEXIT;
3803 else if (exitkind_mustExit (exk))
3805 ret->exitCode = XK_MUSTEXIT;
3807 else if (exitkind_couldExit (exk))
3809 ret->exitCode = XK_MAYEXIT;
3816 if (cstring_equalLit (fname, "exit"))
3818 if (exprNodeList_size (args) == 1)
3820 exprNode arg = exprNodeList_head (args);
3822 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3824 long int val = multiVal_forceInt (exprNode_getValue (arg));
3831 ("Argument to exit has implementation defined behavior: %s",
3832 exprNode_unparse (arg)),
3833 exprNode_loc (arg));
3842 exprNode_checkSetAny (ret, uentry_rawName (le));
3845 DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3846 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3847 reflectEnsuresClause (ret, le, f, args);
3854 ** this is yucky! should keep the uentry as part of exprNode!
3857 uentry exprNode_getUentry (exprNode e)
3859 if (exprNode_isError (e))
3861 return uentry_undefined;
3865 cstring s = exprNode_rootVarName (e);
3866 uentry ue = usymtab_lookupSafe (s);
3873 ** Returns true iff e1 and e2 are both exactly the same storage
3877 static bool exprNode_sameStorage (exprNode e1, exprNode e2)
3879 sRef s1 = exprNode_getSref (e1);
3880 sRef s2 = exprNode_getSref (e2);
3882 return (sRef_realSame (s1, s2));
3886 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3888 exprNode ret = exprNode_createPlain (ctype_unknown);
3890 ret->kind = XPR_INITBLOCK;
3891 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3892 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3898 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3904 if (exprNode_isUndefined (f))
3907 exprNodeList_free (args);
3908 return exprNode_undefined;
3911 t = exprNode_getType (f);
3913 if (sRef_isLocalVar (f->sref))
3915 exprNode_checkUse (f, f->sref, f->loc);
3917 if (sRef_possiblyNull (f->sref))
3919 if (!usymtab_isGuarded (f->sref))
3921 if (optgenerror (FLG_NULLDEREF,
3922 message ("Function call using %s pointer %q",
3923 sRef_nullMessage (f->sref),
3924 sRef_unparse (f->sref)),
3927 sRef_showNullInfo (f->sref);
3928 sRef_setNullError (f->sref);
3936 if (ctype_isRealFunction (t))
3938 exprNode ret = functionCallSafe (f, t, args);
3942 else if (ctype_isUnknown (t))
3944 exprNode ret = exprNode_createPartialCopy (f);
3950 exprNodeList_elements (args, current)
3952 if (exprNode_isDefined (current))
3954 exprNode_checkUse (ret, current->sref, ret->loc);
3957 ** also, anything derivable from current->sref may be used
3960 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3961 exprNode_mergeUSs (ret, current);
3963 } end_exprNodeList_elements;
3965 ret->edata = exprData_makeCall (f, args);
3966 ret->kind = XPR_CALL;
3968 tstring = cstring_copy (exprNode_unparse (f));
3970 cstring_markOwned (tstring);
3971 exprNode_checkSetAny (ret, tstring);
3977 voptgenerror (FLG_TYPE,
3978 message ("Call to non-function (type %t): %s", t,
3979 exprNode_unparse (f)),
3982 exprNodeList_free (args);
3984 return (exprNode_makeError ());
3989 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
3990 /*@only@*/ cstring f)
3992 exprNode ret = exprNode_createPartialCopy (s);
3994 ret->kind = XPR_FACCESS;
3996 if (exprNode_isError (s))
3998 ret->edata = exprData_makeField (s, f);
4003 ctype t = exprNode_getType (s);
4004 ctype tr = ctype_realType (t);
4006 checkMacroParen (s);
4008 ret->edata = exprData_makeField (s, f);
4010 if (ctype_isStructorUnion (tr))
4012 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
4014 if (uentry_isUndefined (tf))
4016 voptgenerror (FLG_TYPE,
4017 message ("Access non-existent field %s of %t: %s", f, t,
4018 exprNode_unparse (ret)),
4020 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
4025 uentry_setUsed (tf, exprNode_loc (ret));
4027 ret->typ = uentry_getType (tf);
4028 checkSafeUse (ret, s->sref);
4030 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
4031 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
4035 else /* isStructorUnion */
4037 if (ctype_isRealAbstract (tr))
4041 message ("Access field of abstract type (%t): %s.%s",
4042 t, exprNode_unparse (s), f),
4044 ret->typ = ctype_unknown;
4048 if (ctype_isKnown (tr))
4053 ("Access field of non-struct or union (%t): %s.%s",
4054 t, exprNode_unparse (s), f),
4057 ret->typ = ctype_unknown;
4061 cstring sn = cstring_copy (f);
4063 checkSafeUse (ret, s->sref);
4064 cstring_markOwned (sn);
4065 ret->sref = sRef_makeField (s->sref, sn);
4077 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
4078 /*@only@*/ cstring f)
4080 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
4081 lltok_release (dot);
4086 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
4088 exprNode ret = exprNode_createPartialCopy (e);
4090 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
4091 ret->kind = XPR_PARENS;
4092 ret->edata = exprData_makeUop (e, lpar);
4094 if (!exprNode_isError (e))
4096 ret->exitCode = e->exitCode;
4097 ret->canBreak = e->canBreak;
4098 ret->mustBreak = e->mustBreak;
4099 ret->isJumpPoint = e->isJumpPoint;
4100 ret->sref = e->sref;
4107 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4108 /*@only@*/ cstring f)
4110 exprNode ret = exprNode_createPartialCopy (s);
4112 ret->edata = exprData_makeField (s, f);
4113 ret->kind = XPR_ARROW;
4115 if (exprNode_isError (s))
4121 ctype t = exprNode_getType (s);
4122 ctype tr = ctype_realType (t);
4124 checkMacroParen (s);
4126 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4128 if (ctype_isRealPointer (tr))
4130 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4132 if (ctype_isStructorUnion (b))
4134 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4136 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4138 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4142 message ("Arrow access from %s pointer%q: %s",
4143 sRef_nullMessage (s->sref),
4144 sRef_unparsePreOpt (s->sref),
4145 exprNode_unparse (ret)),
4148 sRef_showNullInfo (s->sref);
4149 sRef_setNullError (s->sref);
4154 if (uentry_isUndefined (fentry))
4158 message ("Access non-existent field %s of %t: %s",
4159 f, t, exprNode_unparse (ret)),
4161 ret->typ = ctype_unknown;
4167 ** was safeUse: shouldn't be safe!
4170 ** rec must be defined,
4171 ** *rec must be allocated
4172 ** rec->field need only be defined it if is an rvalue
4175 uentry_setUsed (fentry, exprNode_loc (ret));
4176 ret->typ = uentry_getType (fentry);
4178 exprNode_checkUse (ret, s->sref, s->loc);
4180 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4181 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4185 else /* Pointer to something that is not a struct or union*/
4187 if (ctype_isRealAbstract (tr))
4189 ctype xrt = ctype_forceRealType (tr);
4193 message ("Arrow access field of abstract type (%t): %s->%s",
4194 t, exprNode_unparse (s), f),
4198 ** Set the state correctly, as if the abstraction is broken.
4201 if (ctype_isRealPointer (xrt) &&
4202 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4203 ctype_isStructorUnion (b)))
4205 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4206 ret->typ = uentry_getType (fentry);
4207 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4211 ret->typ = ctype_unknown;
4212 ret->sref = sRef_undefined;
4215 else /* not a struct, union or abstract */
4217 if (ctype_isUnknown (tr)) {
4218 cstring sn = cstring_copy (f);
4220 DPRINTF (("Here: %s", exprNode_unparse (s)));
4222 exprNode_checkUse (ret, s->sref, s->loc);
4223 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4225 cstring_markOwned (sn);
4226 ret->sref = sRef_makeArrow (s->sref, sn);
4228 ret->kind = XPR_ARROW;
4233 message ("Arrow access field of non-struct or union "
4234 "pointer (%t): %s->%s",
4235 t, exprNode_unparse (s), f),
4238 ret->typ = ctype_unknown;
4239 ret->sref = sRef_undefined;
4244 else /* its not a pointer */
4246 if (!ctype_isUnknown (tr))
4250 message ("Arrow access of non-pointer (%t): %s->%s",
4251 t, exprNode_unparse (s), f),
4254 ret->typ = ctype_unknown;
4255 ret->sref = sRef_undefined;
4259 cstring sn = cstring_copy (f);
4261 DPRINTF (("Here: %s", exprNode_unparse (s)));
4263 exprNode_checkUse (ret, s->sref, s->loc);
4264 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4266 cstring_markOwned (sn);
4267 ret->sref = sRef_makeArrow (s->sref, sn);
4269 ret->kind = XPR_ARROW;
4280 exprNode_arrowAccess (/*@only@*/ exprNode s,
4281 /*@only@*/ lltok arrow,
4282 /*@only@*/ cstring f)
4284 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4285 lltok_release (arrow);
4290 ** only postOp's in C: i++ and i--
4294 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4296 /* check modification also */
4297 /* cstring opname = lltok_unparse (op);*/
4299 exprNode ret = exprNode_createPartialCopy (e);
4301 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4302 ret->kind = XPR_POSTOP;
4303 ret->edata = exprData_makeUop (e, op);
4305 if (!exprNode_isDefined (e))
4310 checkMacroParen (e);
4312 exprNode_checkUse (ret, e->sref, e->loc);
4313 exprNode_checkSet (ret, e->sref);
4315 t = exprNode_getType (e);
4317 if (sRef_isUnsafe (e->sref))
4319 voptgenerror (FLG_MACROPARAMS,
4320 message ("Operand of %s is macro parameter (non-functional): %s%s",
4321 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4323 sRef_makeSafe (e->sref);
4324 sRef_makeSafe (ret->sref);
4327 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4333 if (ctype_isRealAbstract (t))
4337 message ("Operand of %s is abstract type (%t): %s",
4338 lltok_unparse (op), t, exprNode_unparse (e)),
4345 message ("Operand of %s is non-numeric (%t): %s",
4346 lltok_unparse (op), t, exprNode_unparse (e)),
4349 ret->typ = ctype_unknown;
4352 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4354 exprNode_checkModify (e, ret);
4356 /* added 7/11/2000 D.L */
4358 /*DRL 6/8/01 I decided to disable all Splint warnings here since the code
4359 probably needs a rewrite any way */
4364 /* updateEnvironmentForPostOp (e); */
4366 /* start modifications */
4367 /* added by Seejo on 4/16/2000 */
4369 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4371 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4373 ret->sref = sRef_copy (e->sref);
4376 if (lltok_getTok (op) == INC_OP) {
4377 if (sRef_getSize(e->sref) > 0) {
4379 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4381 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4382 /* Assumption: there is only 1 \0 in the buffer */
4383 /* This will not be correct if there are 2 \0's in the buffer */
4384 sRef_setNotNullTerminatedState(ret->sref);
4385 sRef_resetLen(ret->sref);
4387 sRef_setNullTerminatedState(ret->sref);
4388 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4390 if (sRef_isNullTerminated (ret->sref))
4391 printf ("ret->sref is Null Terminated\n");
4392 else if (sRef_isPossiblyNullTerminated (ret->sref))
4393 printf ("ret->sref is Possibly Null Terminated\n");
4394 else if (sRef_isNotNullTerminated (ret->sref))
4395 printf ("ret->sref is Not Null Terminated\n");
4400 if (lltok_getTok (op) == DEC_OP) {
4401 if (sRef_getSize(e->sref) >= 0) {
4402 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4403 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4408 /* end modifications */
4414 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4416 bool checkMod = FALSE;
4418 int opid = lltok_getTok (op);
4419 exprNode ret = exprNode_createSemiCopy (e);
4421 exprNode_copySets (ret, e);
4423 multiVal_free (ret->val);
4424 ret->val = multiVal_undefined;
4425 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4426 ret->kind = XPR_PREOP;
4427 ret->edata = exprData_makeUop (e, op);
4429 if (exprNode_isError (e))
4434 checkMacroParen (e);
4436 te = exprNode_getType (e);
4437 tr = ctype_realType (te);
4439 if (opid != TAMPERSAND)
4441 exprNode_checkUse (ret, e->sref, e->loc);
4443 if (ctype_isRealAbstract (tr)
4444 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4446 if (optgenerror (FLG_ABSTRACT,
4447 message ("Operand of %s is abstract type (%t): %s",
4448 lltok_unparse (op), tr,
4449 exprNode_unparse (ret)),
4452 tr = te = ctype_unknown;
4453 ret->typ = ctype_unknown;
4454 sRef_setNullError (e->sref);
4462 case DEC_OP: /* should also check modification! */
4463 if (sRef_isMacroParamRef (e->sref))
4467 message ("Operand of %s is macro parameter (non-functional): %s",
4468 lltok_unparse (op), exprNode_unparse (ret)),
4473 exprNode_checkSet (ret, e->sref);
4476 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4481 if (context_msgStrictOps ())
4485 message ("Operand of %s is non-numeric (%t): %s",
4486 lltok_unparse (op), te, exprNode_unparse (ret)),
4489 ret->typ = ctype_int;
4492 /* start modifications */
4493 /* added by Seejo on 4/16/2000 */
4495 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4497 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4499 ret->sref = sRef_copy (e->sref);
4502 if (lltok_getTok (op) == INC_OP) {
4503 if (sRef_getSize(e->sref) > 0) {
4505 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4507 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4508 /* Assumption: there is only 1 \0 in the buffer */
4509 /* This will not be correct if there are 2 \0's in the buffer */
4510 sRef_setNotNullTerminatedState(ret->sref);
4511 sRef_resetLen (ret->sref);
4513 sRef_setNullTerminatedState(ret->sref);
4514 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4520 if (lltok_getTok (op) == DEC_OP) {
4521 if (sRef_getSize(e->sref) >= 0) {
4522 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4523 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4528 /* end modifications */
4535 if (ctype_isForceRealNumeric (&tr))
4539 ret->val = multiVal_invert (exprNode_getValue (e));
4543 ret->val = multiVal_copy (exprNode_getValue (e));
4548 if (context_msgStrictOps ())
4552 message ("Operand of %s is non-numeric (%t): %s",
4553 lltok_unparse (op), te, exprNode_unparse (ret)),
4557 ret->typ = ctype_int;
4561 case TEXCL: /* maybe this should be restricted */
4562 guardSet_flip (ret->guards);
4564 if (ctype_isRealBool (te) || ctype_isUnknown (te))
4570 if (ctype_isRealPointer (tr))
4572 if (sRef_isKnown (e->sref))
4574 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4578 (FLG_BOOLOPS, FLG_PTRNEGATE,
4579 message ("Operand of %s is non-boolean (%t): %s",
4580 lltok_unparse (op), te, exprNode_unparse (ret)),
4587 message ("Operand of %s is non-boolean (%t): %s",
4588 lltok_unparse (op), te, exprNode_unparse (ret)),
4592 ret->typ = ctype_bool;
4597 if (ctype_isForceRealInt (&tr))
4602 if (context_msgStrictOps ())
4606 message ("Operand of %s is non-integer (%t): %s",
4607 lltok_unparse (op), te, exprNode_unparse (ret)),
4611 if (ctype_isInt (e->typ))
4617 ret->typ = ctype_int;
4623 ret->typ = ctype_makePointer (e->typ);
4625 if (sRef_isKnown (e->sref))
4627 ret->sref = sRef_makeAddress (e->sref);
4634 if (ctype_isAP (tr))
4636 ret->typ = ctype_baseArrayPtr (e->typ);
4640 if (ctype_isKnown (te))
4642 if (ctype_isFunction (te))
4648 message ("Dereference of function type (%t): %s",
4649 te, exprNode_unparse (ret)),
4654 voptgenerror (FLG_TYPE,
4655 message ("Dereference of non-pointer (%t): %s",
4656 te, exprNode_unparse (ret)),
4658 ret->typ = ctype_unknown;
4663 ret->typ = ctype_unknown;
4668 if (sRef_isKnown (e->sref))
4670 DPRINTF (("Checking possibly null: %s", sRef_unparseFull (e->sref)));
4672 if (sRef_possiblyNull (e->sref))
4674 DPRINTF (("Checking possibly null: %s", sRef_unparse (e->sref)));
4675 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4679 message ("Dereference of %s pointer %q: %s",
4680 sRef_nullMessage (e->sref),
4681 sRef_unparse (e->sref),
4682 exprNode_unparse (ret)),
4685 sRef_showNullInfo (e->sref);
4686 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4691 ret->sref = sRef_makePointer (e->sref);
4696 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4701 exprNode_checkModify (e, ret);
4708 ** any reason to disallow sizeof (abstract type) ?
4712 ** used by both sizeof
4716 ctype sizeof_resultType (void)
4718 static ctype sizet = ctype_unknown;
4720 if (ctype_isUnknown (sizet))
4722 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4724 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4728 sizet = ctype_ulint;
4735 exprNode_sizeofType (/*@only@*/ qtype qt)
4737 exprNode ret = exprNode_create (sizeof_resultType ());
4738 ctype ct = qtype_getType (qt);
4740 ret->kind = XPR_SIZEOFT;
4741 ret->edata = exprData_makeSizeofType (qt);
4743 voptgenerror (FLG_SIZEOFTYPE,
4744 message ("Parameter to sizeof is type %s: %s",
4746 exprNode_unparse (ret)),
4753 exprNode_alignofType (/*@only@*/ qtype qt)
4755 exprNode ret = exprNode_create (sizeof_resultType ());
4756 ctype ct = qtype_getType (qt);
4758 ret->kind = XPR_ALIGNOFT;
4759 ret->edata = exprData_makeSizeofType (qt);
4761 voptgenerror (FLG_SIZEOFTYPE,
4762 message ("Parameter to alignof is type %s: %s",
4764 exprNode_unparse (ret)),
4770 exprNode exprNode_offsetof (qtype qt, cstringList s)
4772 exprNode ret = exprNode_create (sizeof_resultType ());
4773 ctype ct = qtype_getType (qt);
4775 ret->kind = XPR_OFFSETOF;
4776 ret->edata = exprData_makeOffsetof (qt, s);
4778 if (!ctype_isRealSU (ct))
4780 voptgenerror (FLG_TYPE,
4781 message ("First parameter to offsetof is not a "
4782 "struct or union type (type %s): %s",
4784 exprNode_unparse (ret)),
4791 cstringList_elements (s, el) {
4795 if (ctype_isUndefined (lt))
4799 else if (!ctype_isRealSU (lt))
4801 voptgenerror (FLG_TYPE,
4802 message ("Inner offsetof type is not a "
4803 "struct or union type (type %s before field %s): %s",
4804 ctype_unparse (lt), el,
4805 exprNode_unparse (ret)),
4811 fields = ctype_getFields (ctype_realType (lt));
4812 fld = uentryList_lookupField (fields, el);
4813 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4815 if (uentry_isUndefined (fld))
4817 if (ctype_equal (lt, ct)) {
4818 voptgenerror (FLG_TYPE,
4819 message ("Field %s in offsetof is not the "
4820 "name of a field of %s: %s",
4823 exprNode_unparse (ret)),
4826 voptgenerror (FLG_TYPE,
4827 message ("Deep field %s in offsetof is not the "
4828 "name of a field of %s: %s",
4831 exprNode_unparse (ret)),
4837 lt = uentry_getType (fld);
4840 } end_cstringList_elements;
4842 /* Should report error if its a bit field - behavior is undefined! */
4849 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4853 if (exprNode_isUndefined (e))
4855 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4856 ret->edata = exprData_makeSingle (e);
4857 ret->typ = sizeof_resultType ();
4858 ret->kind = XPR_SIZEOF;
4862 uentry u = exprNode_getUentry (e);
4864 ret = exprNode_createPartialCopy (e);
4865 ret->edata = exprData_makeSingle (e);
4867 ret->typ = sizeof_resultType ();
4868 ret->kind = XPR_SIZEOF;
4870 if (uentry_isValid (u)
4871 && uentry_isRefParam (u)
4872 && ctype_isRealArray (uentry_getType (u)))
4875 (FLG_SIZEOFFORMALARRAY,
4876 message ("Parameter to sizeof is an array-type function parameter: %s",
4877 exprNode_unparse (ret)),
4883 ** sizeof (x) doesn't "really" use x
4890 exprNode_alignofExpr (/*@only@*/ exprNode e)
4894 if (exprNode_isUndefined (e))
4896 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4900 ret = exprNode_createPartialCopy (e);
4903 ret->edata = exprData_makeSingle (e);
4904 ret->typ = sizeof_resultType ();
4905 ret->kind = XPR_ALIGNOF;
4908 ** sizeof (x) doesn't "really" use x
4915 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4921 if (exprNode_isError (e))
4924 lltok_release (tok);
4925 return exprNode_undefined;
4928 checkMacroParen (e);
4930 c = qtype_getType (q);
4931 t = exprNode_getType (e);
4933 ret = exprNode_createPartialCopy (e);
4935 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4937 ret->kind = XPR_CAST;
4938 ret->edata = exprData_makeCast (tok, e, q);
4940 if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
4943 ** This is a bit of a hack to avoid a problem
4944 ** when the code does,
4945 ** (some other struct) x
4950 ret->sref = sRef_copy (e->sref);
4951 usymtab_addForceMustAlias (ret->sref, e->sref);
4952 sRef_setTypeFull (ret->sref, c);
4953 DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
4954 sRef_unparseFull (ret->sref)));
4958 ret->sref = e->sref;
4959 sRef_setTypeFull (ret->sref, c);
4960 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
4967 ** void * <-> abstract * (if FLG_ABSTVOIDP)
4968 ** abstract * <-> void * (if FLG_ABSTVOIDP)
4971 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
4975 else if (ctype_isRealAP (c)) /* casting to array or pointer */
4977 ctype bc = ctype_getBaseType (c);
4978 ctype bt = ctype_getBaseType (t);
4979 ctype rt = ctype_realType (t);
4981 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
4982 && (ctype_isArrayPtr (rt)
4983 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4987 message ("Cast from function pointer type (%t) to "
4988 "non-function pointer (%t): %s",
4989 c, t, exprNode_unparse (ret)),
4993 if (!ctype_isFunction (ctype_baseArrayPtr (c))
4994 && (ctype_isArrayPtr (rt)
4995 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4999 message ("Cast from non-function pointer type (%t) to "
5000 "function pointer (%t): %s",
5001 c, t, exprNode_unparse (ret)),
5005 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
5006 !(ctype_isRealAbstract (bc)
5007 && context_hasAccess (ctype_typeId (bc))))
5009 ; /* okay to cast zero */
5013 if (ctype_isRealAbstract (bc)
5014 && !context_hasAccess (ctype_typeId (bc)))
5016 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
5020 message ("Cast to underlying abstract type %t: %s",
5021 c, exprNode_unparse (ret)),
5028 message ("Cast to underlying abstract type %t: %s",
5029 c, exprNode_unparse (ret)),
5034 if (ctype_isRealAbstract (bt)
5035 && !context_hasAccess (ctype_typeId (bt)))
5037 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
5041 message ("Cast from underlying abstract type %t: %s",
5042 t, exprNode_unparse (ret)),
5049 message ("Cast from underlying abstract type %t: %s",
5050 t, exprNode_unparse (ret)),
5058 ctype bt = ctype_realType (ctype_getBaseType (t));
5059 ctype bc = ctype_realType (ctype_getBaseType (c));
5061 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
5063 if (ctype_match (c, t))
5065 if (ctype_equal (c, t))
5069 message ("Redundant cast involving abstract type %t: %s",
5070 bt, exprNode_unparse (ret)),
5078 message ("Cast from abstract type %t: %s",
5079 bt, exprNode_unparse (ret)),
5084 if (ctype_isAbstract (bc)
5085 && !context_hasAccess (ctype_typeId (bc)))
5087 if (ctype_match (c, t))
5093 DPRINTF (("No access to: %s / %d",
5094 ctype_unparse (bc), ctype_typeId (bc)));
5095 DPRINTF (("Context %s %s",
5096 bool_unparse (context_inFunctionLike ()),
5097 context_unparse ()));
5100 message ("Cast to abstract type %t: %s", bc,
5101 exprNode_unparse (ret)),
5107 if (ctype_isAbstract (c))
5109 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
5111 /* okay, cast exposed to abstract */
5112 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
5116 if (ctype_isVisiblySharable (t)
5117 && sRef_isExternallyVisible (e->sref)
5118 && !(ctype_isAbstract (t)
5119 && context_hasAccess (ctype_typeId (t))))
5123 message ("Cast to abstract type from externally visible "
5124 "mutable storage exposes rep of %s: %s",
5126 exprNode_unparse (e)),
5136 evaluationOrderUndefined (lltok op)
5138 int opid = lltok_getTok (op);
5140 return (opid != AND_OP && opid != OR_OP);
5143 static bool checkIntegral (/*@notnull@*/ exprNode e1,
5144 /*@notnull@*/ exprNode e2,
5145 /*@notnull@*/ exprNode ret,
5150 ctype te1 = exprNode_getType (e1);
5151 ctype te2 = exprNode_getType (e2);
5153 ctype tr1 = ctype_realishType (te1);
5154 ctype tr2 = ctype_realishType (te2);
5156 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5162 if (context_msgStrictOps ())
5164 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5166 if (ctype_sameName (te1, te2))
5170 message ("Operands of %s are non-integer (%t): %s",
5171 lltok_unparse (op), te1,
5172 exprNode_unparse (ret)),
5179 message ("Operands of %s are non-integers (%t, %t): %s",
5180 lltok_unparse (op), te1, te2,
5181 exprNode_unparse (ret)),
5185 else if (!ctype_isInt (tr1))
5189 message ("Left operand of %s is non-integer (%t): %s",
5190 lltok_unparse (op), te1, exprNode_unparse (ret)),
5194 /* !ctype_isInt (te2) */
5198 message ("Right operand of %s is non-integer (%t): %s",
5199 lltok_unparse (op), te2, exprNode_unparse (ret)),
5209 ** returns exprNode representing e1 op e2
5211 ** uses msg if there are errors
5212 ** can be used for both assignment ops and regular ops
5217 static /*@only@*/ /*@notnull@*/ exprNode
5218 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
5219 /*@keep@*/ lltok op)
5221 ctype te1, te2, tr1, tr2, tret;
5222 int opid = lltok_getTok (op);
5223 bool hasError = FALSE;
5226 if (exprNode_isError (e1))
5228 ret = exprNode_createPartialNVCopy (e2);
5232 ret = exprNode_createPartialNVCopy (e1);
5235 ret->val = multiVal_undefined;
5237 ret->edata = exprData_makeOp (e1, e2, op);
5239 if (exprNode_isError (e1) || exprNode_isError (e2))
5241 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5242 || opid == EQ_OP || opid == NE_OP
5243 || opid == AND_OP || opid == OR_OP)
5245 ret->typ = ctype_bool;
5248 if (exprNode_isDefined (e1))
5250 exprNode_checkUse (ret, e1->sref, e1->loc);
5253 if (exprNode_isDefined (e2))
5255 exprNode_mergeUSs (ret, e2);
5256 exprNode_checkUse (ret, e2->sref, e2->loc);
5262 tret = ctype_unknown;
5263 te1 = exprNode_getType (e1);
5265 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5267 te2 = exprNode_getType (e2);
5269 tr1 = ctype_realishType (te1);
5270 tr2 = ctype_realishType (te2);
5274 ret->guards = guardSet_or (ret->guards, e2->guards);
5276 else if (opid == AND_OP)
5278 ret->guards = guardSet_and (ret->guards, e2->guards);
5285 if (opid == EQ_OP || opid == NE_OP)
5287 exprNode temp1 = e1, temp2 = e2;
5289 /* could do NULL == x */
5291 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5293 temp1 = e2; temp2 = e1;
5296 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5298 reflectNullTest (temp1, (opid == NE_OP));
5299 guardSet_free (ret->guards);
5300 ret->guards = guardSet_copy (temp1->guards);
5304 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5305 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5310 if (anyAbstract (tr1, tr2) &&
5311 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
5312 (opid == AND_OP || opid == OR_OP
5313 || opid == EQ_OP || opid == NE_OP))))
5315 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
5317 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5319 /* unknown types, no comparisons possible */
5325 case TMULT: /* multiplication and division: */
5327 case MUL_ASSIGN: /* numeric, numeric -> numeric */
5328 case DIV_ASSIGN: /* */
5330 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5333 case TPLUS: /* addition and subtraction: */
5334 case TMINUS: /* pointer, int -> pointer */
5335 case SUB_ASSIGN: /* int, pointer -> pointer */
5336 case ADD_ASSIGN: /* numeric, numeric -> numeric */
5338 tr1 = ctype_fixArrayPtr (tr1);
5340 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5341 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5345 if (context_msgPointerArith ())
5349 message ("Pointer arithmetic (%t, %t): %s",
5350 te1, te2, exprNode_unparse (ret)),
5355 ** Swap terms so e1 is always the pointer
5358 if (ctype_isRealPointer (tr1))
5364 exprNode_swap (e1, e2);
5368 if (sRef_possiblyNull (e1->sref)
5369 && !usymtab_isGuarded (e1->sref))
5372 (FLG_NULLPOINTERARITH,
5373 message ("Pointer arithmetic involving possibly "
5374 "null pointer %s: %s",
5375 exprNode_unparse (e1),
5376 exprNode_unparse (ret)),
5380 ret->sref = sRef_copy (e1->sref);
5382 /* start modifications */
5383 /* added by Seejo on 4/16/2000 */
5385 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5387 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5390 added ugly fixed to stop
5391 program from crashing on point + int +int
5392 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5394 if (!multiVal_isInt (e2->val) )
5398 val = (int) multiVal_forceInt (e2->val);
5400 /* Operator : + or += */
5401 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5402 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5403 val should not result in a
5404 size < 0 (size = 0 is ok !) */
5406 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5408 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5409 sRef_setNotNullTerminatedState(ret->sref);
5410 sRef_resetLen (ret->sref);
5412 sRef_setNullTerminatedState(ret->sref);
5413 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5418 /* Operator : - or -= */
5419 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5420 if (sRef_getSize(e1->sref) >= 0) {
5421 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5422 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5427 /* end modifications */
5429 sRef_setNullError (ret->sref);
5432 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5433 ** since is points to storage that should not be deallocated
5434 ** through this pointer.
5437 if (sRef_isOnly (ret->sref)
5438 || sRef_isFresh (ret->sref))
5440 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5445 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5446 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5448 if (context_msgPointerArith ())
5452 message ("Pointer arithmetic (%t, %t): %s",
5453 te1, te2, exprNode_unparse (ret)),
5457 if (sRef_possiblyNull (e1->sref)
5458 && !usymtab_isGuarded (e1->sref))
5461 (FLG_NULLPOINTERARITH,
5462 message ("Pointer arithmetic involving possibly "
5463 "null pointer %s: %s",
5464 exprNode_unparse (e2),
5465 exprNode_unparse (ret)),
5469 ret->sref = sRef_copy (e2->sref);
5471 /* start modifications */
5472 /* added by Seejo on 4/16/2000 */
5474 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5477 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5478 int val = (int) multiVal_forceInt (e1->val);
5480 /* Operator : + or += */
5481 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5482 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5483 val should not result in a
5484 size < 0 (size = 0 is ok !) */
5486 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5488 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5489 sRef_setNotNullTerminatedState(ret->sref);
5490 sRef_resetLen (ret->sref);
5492 sRef_setNullTerminatedState(ret->sref);
5493 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5498 /* Operator : - or -= */
5499 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5500 if (sRef_getSize(e2->sref) >= 0) {
5501 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5502 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5506 /* end modifications */
5508 sRef_setNullError (ret->sref);
5511 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5512 ** since is points to storage that should not be deallocated
5513 ** through this pointer.
5516 if (sRef_isOnly (ret->sref)
5517 || sRef_isFresh (ret->sref)) {
5518 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5522 ret->sref = e2->sref;
5526 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5531 case LEFT_ASSIGN: /* Shifts: should be unsigned values */
5535 case TAMPERSAND: /* bitwise & */
5537 case TCIRC: /* ^ (XOR) */
5542 bool reported = FALSE;
5543 flagcode code = FLG_BITWISEOPS;
5545 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5546 || opid == RIGHT_OP || opid == RIGHT_ASSIGN) {
5547 code = FLG_SHIFTSIGNED;
5550 if (!ctype_isUnsigned (tr1))
5552 if (exprNode_isNonNegative (e1)) {
5555 reported = optgenerror
5557 message ("Left operand of %s is not unsigned value (%t): %s",
5558 lltok_unparse (op), te1,
5559 exprNode_unparse (ret)),
5569 /* right need not be signed for shifts */
5570 if (code != FLG_SHIFTSIGNED
5571 && !ctype_isUnsigned (tr2))
5573 if (!exprNode_isNonNegative (e2)) {
5574 reported = optgenerror
5576 message ("Right operand of %s is not unsigned value (%t): %s",
5577 lltok_unparse (op), te2,
5578 exprNode_unparse (ret)),
5586 if (!checkIntegral (e1, e2, ret, op)) {
5587 te1 = ctype_unknown;
5591 DPRINTF (("Set: %s", ctype_unparse (te1)));
5594 ** tret is the widest type of te1 and te2
5597 tret = ctype_widest (te1, te2);
5602 if (checkIntegral (e1, e2, ret, op)) {
5605 tret = ctype_unknown;
5610 case TLT: /* comparisons */
5611 case TGT: /* numeric, numeric -> bool */
5613 DPRINTF (("Here we go: %s / %s",
5614 ctype_unparse (tr1), ctype_unparse (tr2)));
5616 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5617 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5620 bool fepsilon = FALSE;
5622 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5627 if (opid == TLT || opid == TGT)
5629 uentry ue1 = exprNode_getUentry (e1);
5630 uentry ue2 = exprNode_getUentry (e2);
5633 ** FLT_EPSILON, etc. really is a variable, not
5637 if (uentry_isVariable (ue1))
5639 cstring uname = uentry_rawName (ue1);
5641 if (cstring_equalLit (uname, "FLT_EPSILON")
5642 || cstring_equalLit (uname, "DBL_EPSILON")
5643 || cstring_equalLit (uname, "LDBL_EPSILON"))
5649 if (uentry_isVariable (ue2))
5651 cstring uname = uentry_rawName (ue2);
5653 if (cstring_equalLit (uname, "FLT_EPSILON")
5654 || cstring_equalLit (uname, "DBL_EPSILON")
5655 || cstring_equalLit (uname, "LDBL_EPSILON"))
5664 ; /* Don't complain. */
5670 message ("Dangerous comparison involving %s types: %s",
5671 ctype_unparse (rtype),
5672 exprNode_unparse (ret)),
5681 ** Types should match.
5684 DPRINTF (("Match types: %s / %s", exprNode_unparse (e1),
5685 exprNode_unparse (e2)));
5687 if (!exprNode_matchTypes (e1, e2))
5689 hasError = gentypeerror
5691 message ("Operands of %s have incompatible types (%t, %t): %s",
5692 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5698 || (ctype_isForceRealNumeric (&tr1)
5699 && ctype_isForceRealNumeric (&tr2)) ||
5700 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5706 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5707 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5711 message ("Comparison of pointer and numeric (%t, %t): %s",
5712 te1, te2, exprNode_unparse (ret)),
5717 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5722 /* certain comparisons on unsigned's and zero look suspicious */
5724 if (opid == TLT || opid == LE_OP || opid == GE_OP)
5726 if ((ctype_isUnsigned (tr1) && exprNode_isZero (e2))
5727 || (ctype_isUnsigned (tr2) && exprNode_isZero (e1)))
5730 (FLG_UNSIGNEDCOMPARE,
5731 message ("Comparison of unsigned value involving zero: %s",
5732 exprNode_unparse (ret)),
5737 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5739 if ((opid == EQ_OP || opid == NE_OP) &&
5740 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5743 ** is one a variable?
5746 if (uentry_isVariable (exprNode_getUentry (e1))
5747 || uentry_isVariable (exprNode_getUentry (e2)))
5750 ** comparisons with FALSE are okay
5753 if (exprNode_isFalseConstant (e1)
5754 || exprNode_isFalseConstant (e2))
5763 ("Use of %q with %s variables (risks inconsistency because "
5764 "of multiple true values): %s",
5765 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5766 context_printBoolName (), exprNode_unparse (ret)),
5773 case AND_OP: /* bool, bool -> bool */
5776 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5782 if (context_maybeSet (FLG_BOOLOPS))
5784 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5786 if (ctype_sameName (te1, te2))
5790 message ("Operands of %s are non-boolean (%t): %s",
5791 lltok_unparse (op), te1,
5792 exprNode_unparse (ret)),
5800 ("Operands of %s are non-booleans (%t, %t): %s",
5801 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5805 else if (!ctype_isRealBool (te1))
5809 message ("Left operand of %s is non-boolean (%t): %s",
5810 lltok_unparse (op), te1, exprNode_unparse (ret)),
5813 else if (!ctype_isRealBool (te2))
5817 message ("Right operand of %s is non-boolean (%t): %s",
5818 lltok_unparse (op), te2, exprNode_unparse (ret)),
5831 (cstring_makeLiteral
5832 ("There has been a problem in the parser. This is believed to result "
5833 "from a problem with bison v. 1.25. Please try rebuidling Splint "
5834 "using the pre-compiled grammar files by commenting out the "
5835 "BISON= line in the top-level Makefile."));
5840 DPRINTF (("Return type: %s", ctype_unparse (tret)));
5843 exprNode_checkUse (ret, e1->sref, e1->loc);
5844 exprNode_mergeUSs (ret, e2);
5845 exprNode_checkUse (ret, e2->sref, e2->loc);
5851 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5852 /*@only@*/ lltok op)
5856 checkMacroParen (e1);
5857 checkMacroParen (e2);
5859 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5861 checkExpressionDefined (e1, e2, op);
5864 ret = exprNode_makeOp (e1, e2, op);
5869 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5872 ** This is somewhat bogus!
5874 ** Assigning to a nested observer in a non-observer datatype
5875 ** should not produce an error.
5878 sRef ref = exprNode_getSref (e1);
5880 DPRINTF (("Check assign mod: %s",
5881 sRef_unparseFull (ref)));
5883 if (sRef_isObserver (ref)
5884 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
5885 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5887 sRef base = sRef_getBase (ref);
5889 if (sRef_isValid (base) && sRef_isObserver (base))
5891 exprNode_checkModify (e1, ret);
5895 exprNode_checkModifyVal (e1, ret);
5900 exprNode_checkModify (e1, ret);
5905 exprNode_assign (/*@only@*/ exprNode e1,
5906 /*@only@*/ exprNode e2, /*@only@*/ lltok op)
5908 bool isalloc = FALSE;
5909 bool isjustalloc = FALSE;
5910 bool noalias = FALSE;
5913 DPRINTF (("%s [%s] <- %s [%s]",
5914 exprNode_unparse (e1),
5915 ctype_unparse (e1->typ),
5916 exprNode_unparse (e2),
5917 ctype_unparse (e2->typ)));
5919 if (lltok_getTok (op) != TASSIGN)
5921 ret = exprNode_makeOp (e1, e2, op);
5923 DPRINTF (("Here goes: %s %s",
5924 ctype_unparse (e1->typ),
5925 ctype_unparse (e2->typ)));
5927 if (ctype_isNumeric (e2->typ)
5928 || ctype_isNumeric (e1->typ))
5930 /* Its a pointer arithmetic expression like ptr += i */
5936 ret = exprNode_createPartialCopy (e1);
5937 ret->kind = XPR_ASSIGN;
5938 ret->edata = exprData_makeOp (e1, e2, op);
5940 if (!exprNode_isError (e2))
5942 ret->sets = sRefSet_union (ret->sets, e2->sets);
5943 ret->msets = sRefSet_union (ret->msets, e2->msets);
5944 ret->uses = sRefSet_union (ret->uses, e2->uses);
5948 checkExpressionDefined (e1, e2, op);
5950 if (exprNode_isError (e1))
5952 if (!exprNode_isError (e2))
5954 ret->loc = fileloc_update (ret->loc, e2->loc);
5958 ret->loc = fileloc_update (ret->loc, g_currentloc);
5962 if (!exprNode_isError (e2))
5964 checkMacroParen (e2);
5967 if (exprNode_isDefined (e1))
5969 if (sRef_isMacroParamRef (e1->sref))
5971 if (context_inIterDef ())
5973 uentry ue = sRef_getUentry (e1->sref);
5975 if (uentry_isYield (ue))
5981 if (fileloc_isDefined (e1->loc))
5985 message ("Assignment to non-yield iter parameter: %q",
5986 sRef_unparse (e1->sref)),
5993 message ("Assignment to non-yield iter parameter: %q",
5994 sRef_unparse (e1->sref)),
6001 if (fileloc_isDefined (e1->loc))
6005 message ("Assignment to macro parameter: %q",
6006 sRef_unparse (e1->sref)),
6013 message ("Assignment to macro parameter: %q",
6014 sRef_unparse (e1->sref)),
6018 exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
6023 exprNode_checkAssignMod (e1, ret);
6026 if (exprNode_isDefined (e2))
6028 if (lltok_getTok (op) == TASSIGN)
6030 ctype te1 = exprNode_getType (e1);
6031 ctype te2 = exprNode_getType (e2);
6033 if (!ctype_forceMatch (te1, te2))
6035 if (exprNode_matchLiteral (te1, e2))
6043 message ("Assignment of %t to %t: %s %s %s",
6044 te2, te1, exprNode_unparse (e1),
6046 exprNode_unparse (e2)),
6052 exprNode_mergeUSs (ret, e2);
6053 exprNode_checkUse (ret, e2->sref, e2->loc);
6055 DPRINTF (("Do assign! %s %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6062 doAssign (e1, e2, FALSE);
6065 ret->sref = e1->sref;
6069 if (exprNode_isDefined (e2))
6071 exprNode_mergeUSs (ret, e2);
6072 exprNode_checkUse (ret, e2->sref, e2->loc);
6076 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
6078 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
6081 isjustalloc = sRef_isJustAllocated (e1->sref);
6082 isalloc = sRef_isAllocated (e1->sref);
6084 if (sRef_isField (e1->sref))
6086 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
6088 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
6090 exprNode_checkUse (ret, root, e1->loc);
6096 ** be careful! this defines e1->sref.
6099 /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
6101 DPRINTF (("Setting: %s -> %s", exprNode_unparse (ret), sRef_unparse (e1->sref)));
6102 exprNode_checkSet (ret, e1->sref);
6106 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
6107 ? e2->loc : e1->loc);
6113 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
6122 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
6123 /*@keep@*/ exprNode elseclause)
6127 if (!exprNode_isError (pred))
6129 ret = exprNode_createPartialCopy (pred);
6130 checkMacroParen (pred);
6131 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
6133 if (!exprNode_isError (ifclause))
6135 checkMacroParen (ifclause); /* update macro counts! */
6137 if (!exprNode_isError (elseclause))
6139 checkMacroParen (elseclause);
6141 if (!exprNode_matchTypes (ifclause, elseclause))
6144 (exprNode_getType (ifclause),
6146 exprNode_getType (elseclause),
6148 message ("Conditional clauses are not of same type: "
6150 exprNode_unparse (ifclause),
6151 exprNode_getType (ifclause),
6152 exprNode_unparse (elseclause),
6153 exprNode_getType (elseclause)),
6156 ret->sref = sRef_undefined;
6157 ret->typ = ctype_unknown;
6162 /* for now...should merge the states */
6163 ret->sref = ifclause->sref;
6164 ret->typ = ifclause->typ;
6166 if (exprNode_isNullValue (ifclause))
6168 ret->typ = elseclause->typ;
6172 exprNode_checkUse (ret, pred->sref, pred->loc);
6173 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6174 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6176 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6181 ret->typ = ifclause->typ;
6183 exprNode_checkUse (pred, pred->sref, pred->loc);
6184 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6186 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6191 if (!exprNode_isError (elseclause))
6193 ret->typ = elseclause->typ;
6195 exprNode_checkUse (pred, pred->sref, pred->loc);
6196 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6198 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6202 else /* pred is error */
6204 if (!exprNode_isError (ifclause))
6206 ret = exprNode_createSemiCopy (ifclause);
6208 checkMacroParen (ifclause); /* update macro counts! */
6210 if (!exprNode_isError (elseclause))
6212 checkMacroParen (elseclause);
6214 ret->typ = ifclause->typ;
6216 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6219 (exprNode_getType (ifclause),
6221 exprNode_getType (elseclause),
6223 message ("Conditional clauses are not of same type: "
6225 exprNode_unparse (ifclause),
6226 exprNode_getType (ifclause),
6227 exprNode_unparse (elseclause),
6228 exprNode_getType (elseclause)),
6231 ret->typ = ctype_unknown;
6235 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6236 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6238 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6241 else if (!exprNode_isError (elseclause)) /* pred, if errors */
6243 ret = exprNode_createSemiCopy (ifclause);
6245 ret->typ = elseclause->typ;
6246 checkMacroParen (elseclause);
6248 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6249 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6251 else /* all errors! */
6253 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6257 ret->kind = XPR_COND;
6258 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
6260 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6262 exprNode_combineControl (ret, ifclause, elseclause);
6269 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6271 ctype totype = qtype_getType (qt);
6273 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6277 ** check use of va_arg : <valist>, type -> type
6280 if (exprNode_isError (arg))
6285 targ = exprNode_getType (arg);
6288 ** arg should have be a pointer
6291 if (!ctype_isUA (targ) ||
6292 (!usymId_equal (ctype_typeId (targ),
6293 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6297 message ("First argument to va_arg is not a va_list (type %t): %s",
6298 targ, exprNode_unparse (arg)),
6302 exprNode_checkSet (ret, arg->sref);
6306 ** return type is totype
6310 ret->kind = XPR_VAARG;
6311 ret->edata = exprData_makeCast (tok, arg, qt);
6316 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6318 exprNode ret = exprNode_createPlain (ctype_undefined);
6319 ret->kind = XPR_LABEL;
6320 ret->edata = exprData_makeLiteral (label);
6321 ret->isJumpPoint = TRUE;
6323 return (ret); /* for now, ignore label */
6326 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6328 if (exprNode_isDefined (stmt))
6330 stmt->isJumpPoint = TRUE;
6332 /* This prevent stray no return path errors, etc. */
6333 stmt->exitCode = XK_MUSTEXIT;
6339 bool exprNode_isDefaultMarker (exprNode e)
6341 if (exprNode_isDefined (e))
6343 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6349 bool exprNode_isCaseMarker (exprNode e)
6351 if (exprNode_isDefined (e))
6353 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6359 bool exprNode_isLabelMarker (exprNode e)
6361 if (exprNode_isDefined (e))
6363 return (e->kind == XPR_LABEL);
6369 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6371 exprNode ret = exprNode_createPartialCopy (test);
6373 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6375 if (exprNode_isError (test)) {
6379 exprNode_checkUse (ret, test->sref, test->loc);
6381 usymtab_setExitCode (ret->exitCode);
6385 usymtab_setMustBreak ();
6388 ret->edata = exprData_makeSingle (test);
6389 ret->isJumpPoint = TRUE;
6395 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6397 exprNode ret = exprNode_createPartialCopy (test);
6399 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6400 ret->edata = exprData_makePair (test, stmt);
6401 ret->isJumpPoint = TRUE;
6403 if (exprNode_isError (test))
6408 exprNode_checkUse (ret, test->sref, test->loc);
6410 if (exprNode_isError (stmt))
6415 exprNode_mergeUSs (ret, stmt);
6417 ret->exitCode = stmt->exitCode;
6418 ret->mustBreak = stmt->mustBreak;
6419 ret->canBreak = stmt->canBreak;
6421 usymtab_setExitCode (ret->exitCode);
6425 usymtab_setMustBreak ();
6432 /*@notnull@*/ /*@only@*/ exprNode
6433 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6435 exprNode ret = exprNode_createTok (def);
6437 ret->isJumpPoint = TRUE;
6438 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6443 exprNode_mayEscape (exprNode e)
6445 if (exprNode_isDefined (e))
6447 return exitkind_couldEscape (e->exitCode);
6453 exprNode_mustBreak (exprNode e)
6455 if (exprNode_isDefined (e))
6457 return e->mustBreak;
6464 exprNode_mustEscape (exprNode e)
6466 if (exprNode_isDefined (e))
6468 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6475 exprNode_errorEscape (exprNode e)
6477 if (exprNode_isDefined (e))
6479 return exitkind_isError (e->exitCode);
6485 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6487 exprNode ret = exprNode_createPartialCopy (e1);
6489 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6491 ret->edata = exprData_makePair (e1, e2);
6492 ret->kind = XPR_STMTLIST;
6494 if (exprNode_isDefined (e1))
6496 ret->isJumpPoint = e1->isJumpPoint;
6497 ret->canBreak = e1->canBreak;
6501 if (exprNode_isDefined (e2))
6503 ret->loc = fileloc_update (ret->loc, e2->loc);
6507 if (exprNode_isDefined (e2))
6509 ret->exitCode = e2->exitCode;
6510 ret->mustBreak = e2->mustBreak;
6511 if (e2->canBreak) ret->canBreak = TRUE;
6515 ** if e1 must return, then e2 is unreachable!
6518 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6520 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6521 && !(e2->isJumpPoint))
6523 if (context_getFlag (FLG_UNREACHABLE))
6527 if (e2->kind == XPR_STMT)
6529 nr = exprData_getUopNode (e2->edata);
6532 if ((nr->kind == XPR_TOK
6533 && lltok_isSemi (exprData_getTok (nr->edata))))
6535 /* okay to have unreachable ";" */
6536 ret->exitCode = XK_MUSTEXIT;
6537 ret->canBreak = TRUE;
6541 if (optgenerror (FLG_UNREACHABLE,
6542 message ("Unreachable code: %s",
6543 exprNode_unparseFirst (nr)),
6546 ret->isJumpPoint = TRUE;
6547 ret->mustBreak = FALSE;
6548 ret->exitCode = XK_ERROR;
6549 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6553 ret->exitCode = XK_MUSTEXIT;
6554 ret->canBreak = TRUE;
6562 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6565 ** We want a warning anytime we have:
6567 ** yyy; <<<- no break or return
6571 exprNode lastStmt = exprNode_lastStatement (e1);
6573 if (exprNode_isDefined (lastStmt)
6574 && !exprNode_mustEscape (lastStmt)
6575 && !exprNode_mustBreak (lastStmt)
6576 && !exprNode_isCaseMarker (lastStmt)
6577 && !exprNode_isDefaultMarker (lastStmt)
6578 && !exprNode_isLabelMarker (lastStmt))
6580 voptgenerror (FLG_CASEBREAK,
6582 ("Fall through case (no preceding break)"),
6589 exprNode_mergeUSs (ret, e2);
6591 usymtab_setExitCode (ret->exitCode);
6595 usymtab_setMustBreak ();
6601 exprNode exprNode_createTok (/*@only@*/ lltok t)
6603 exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6604 ret = exprNode_create (ctype_unknown);
6605 ret->kind = XPR_TOK;
6606 ret->edata = exprData_makeTok (t);
6610 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6612 if (!exprNode_isError (e))
6614 exprNode_checkStatement(e);
6617 return (exprNode_statementError (e, t));
6620 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6622 exprNode ret = exprNode_createPartialCopy (e);
6624 if (!exprNode_isError (e))
6626 if (e->kind != XPR_ASSIGN)
6628 exprNode_checkUse (ret, e->sref, e->loc);
6631 ret->exitCode = e->exitCode;
6632 ret->canBreak = e->canBreak;
6633 ret->mustBreak = e->mustBreak;
6636 ret->edata = exprData_makeUop (e, t);
6637 ret->kind = XPR_STMT;
6642 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6644 if (!exprNode_isError (e))
6646 if (e->kind != XPR_ASSIGN)
6648 exprNode_checkUse (e, e->sref, e->loc);
6655 void exprNode_produceGuards (exprNode pred)
6657 if (!exprNode_isError (pred))
6659 if (ctype_isRealPointer (pred->typ))
6661 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6664 exprNode_checkUse (pred, pred->sref, pred->loc);
6665 exprNode_resetSref (pred);
6669 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6671 exprNode ret = exprNode_createPartialCopy (e);
6673 if (!exprNode_isError (e))
6675 ret->exitCode = e->exitCode;
6676 ret->canBreak = e->canBreak;
6677 ret->mustBreak = e->mustBreak;
6680 ret->edata = exprData_makeSingle (e);
6681 ret->kind = XPR_BLOCK;
6685 bool exprNode_isBlock (exprNode e)
6687 return (exprNode_isDefined (e)
6688 && ((e)->kind == XPR_BLOCK));
6691 bool exprNode_isAssign (exprNode e)
6693 if (exprNode_isDefined (e))
6695 return (e->kind == XPR_ASSIGN);
6701 bool exprNode_isEmptyStatement (exprNode e)
6703 return (exprNode_isDefined (e)
6704 && (e->kind == XPR_TOK)
6705 && (lltok_isSemi (exprData_getTok (e->edata))));
6708 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6711 bool emptyErr = FALSE;
6713 if (context_maybeSet (FLG_IFEMPTY))
6715 if (exprNode_isEmptyStatement (tclause))
6717 emptyErr = optgenerror (FLG_IFEMPTY,
6719 ("Body of if statement is empty"),
6720 exprNode_loc (tclause));
6724 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6726 if (exprNode_isDefined (tclause)
6727 && !exprNode_isBlock (tclause))
6729 voptgenerror (FLG_IFBLOCK,
6731 ("Body of if statement is not a block: %s",
6732 exprNode_unparse (tclause)),
6733 exprNode_loc (tclause));
6737 if (exprNode_isError (pred))
6739 if (exprNode_isError (tclause))
6741 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6745 ret = exprNode_createPartialCopy (tclause);
6750 if (exprNode_mustEscape (pred))
6754 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6755 exprNode_loc (pred));
6758 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6759 exprNode_checkUse (pred, pred->sref, pred->loc);
6761 if (!exprNode_isError (tclause))
6763 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
6766 ret = exprNode_createPartialCopy (pred);
6770 ret->edata = exprData_makePair (pred, tclause);
6772 ret->exitCode = XK_UNKNOWN;
6774 if (exprNode_isDefined (tclause))
6776 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
6777 ret->canBreak = tclause->canBreak;
6778 ret->sets = sRefSet_union (ret->sets, tclause->sets);
6779 ret->msets = sRefSet_union (ret->msets, tclause->msets);
6780 ret->uses = sRefSet_union (ret->uses, tclause->uses);
6783 ret->mustBreak = FALSE;
6788 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
6789 /*@only@*/ exprNode tclause,
6790 /*@only@*/ exprNode eclause)
6793 bool tEmptyErr = FALSE;
6794 bool eEmptyErr = FALSE;
6796 if (context_maybeSet (FLG_IFEMPTY))
6798 if (exprNode_isEmptyStatement (tclause))
6800 tEmptyErr = optgenerror
6803 ("Body of if clause of if statement is empty"),
6804 exprNode_loc (tclause));
6807 if (exprNode_isEmptyStatement (eclause))
6809 eEmptyErr = optgenerror
6812 ("Body of else clause of if statement is empty"),
6813 exprNode_loc (eclause));
6817 if (context_maybeSet (FLG_IFBLOCK))
6820 && exprNode_isDefined (tclause)
6821 && !exprNode_isBlock (tclause))
6823 voptgenerror (FLG_IFBLOCK,
6825 ("Body of if clause of if statement is not a block: %s",
6826 exprNode_unparse (tclause)),
6827 exprNode_loc (tclause));
6831 && exprNode_isDefined (eclause)
6832 && !exprNode_isBlock (eclause)
6833 && !(eclause->kind == XPR_IF)
6834 && !(eclause->kind == XPR_IFELSE))
6839 ("Body of else clause of if statement is not a block: %s",
6840 exprNode_unparse (eclause)),
6841 exprNode_loc (eclause));
6845 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
6847 if (exprNode_isDefined (eclause)
6848 && (eclause->kind == XPR_IF))
6850 voptgenerror (FLG_ELSEIFCOMPLETE,
6851 message ("Incomplete else if logic (no final else): %s",
6852 exprNode_unparse (eclause)),
6853 exprNode_loc (eclause));
6857 if (exprNode_isError (pred))
6859 if (exprNode_isError (tclause))
6861 if (exprNode_isError (eclause))
6863 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6867 ret = exprNode_createPartialCopy (eclause);
6872 ret = exprNode_createPartialCopy (tclause);
6875 else /* pred is okay */
6877 ret = exprNode_createPartialCopy (pred);
6879 if (exprNode_mustEscape (pred))
6883 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6884 exprNode_loc (pred));
6887 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6888 exprNode_checkUse (ret, pred->sref, pred->loc);
6890 exprNode_mergeCondUSs (ret, tclause, eclause);
6893 ret->kind = XPR_IFELSE;
6894 ret->edata = exprData_makeCond (pred, tclause, eclause);
6896 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
6898 exprNode_combineControl (ret, tclause, eclause);
6899 ret->loc = fileloc_update (ret->loc, eclause->loc);
6906 ** *allpaths <- TRUE iff all executions paths must go through the switch
6910 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
6912 exprNodeSList el = exprNode_flatten (e);
6913 bool mustReturn = TRUE; /* find a branch that doesn't */
6914 bool thisReturn = FALSE;
6915 bool hasDefault = FALSE;
6916 bool hasAllMembers = FALSE;
6917 bool inSwitch = FALSE;
6918 bool isEnumSwitch = FALSE;
6919 bool canBreak = FALSE;
6920 bool fallThrough = FALSE;
6921 ctype ct = ctype_unknown;
6922 enumNameSList usedEnums;
6925 if (exprNode_isDefined (test))
6930 ttype = ctype_realType (ct);
6932 if (ctype_isEnum (ttype))
6934 isEnumSwitch = TRUE;
6935 enums = ctype_elist (ttype);
6936 usedEnums = enumNameSList_new ();
6940 exprNodeSList_elements (el, current)
6942 if (exprNode_isDefined (current))
6944 switch (current->kind)
6952 message ("Duplicate default cases in switch"),
6953 exprNode_loc (current));
6958 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
6966 exprNode st = exprData_getSingle (current->edata);
6967 uentry ue = exprNode_getUentry (st);
6969 if (uentry_isValid (ue))
6971 cstring cname = uentry_rawName (ue);
6973 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
6975 if (enumNameSList_member
6976 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
6980 message ("Duplicate case in switch: %s",
6986 enumNameSList_addh (usedEnums, cname);
6993 message ("Case in switch not %s member: %s",
6994 ctype_unparse (ct), cname),
7001 if (inSwitch && !fallThrough)
7003 if (!thisReturn || canBreak)
7013 /*@switchbreak@*/ break;
7015 thisReturn = thisReturn || exprNode_mustEscape (current);
7016 canBreak = canBreak || current->canBreak;
7017 if (canBreak) fallThrough = FALSE;
7020 } end_exprNodeSList_elements;
7022 if (inSwitch) /* check the last one! */
7024 if (!thisReturn || canBreak)
7033 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
7034 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
7036 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
7038 voptgenerror (FLG_MISSCASE,
7039 message ("Missing case%s in switch: %q",
7040 cstring_makeLiteralTemp
7041 ((enumNameSList_size (unused) > 1) ? "s" : ""),
7042 enumNameSList_unparse (unused)),
7045 enumNameSList_free (unused);
7046 *allpaths = FALSE; /* evans 2002-01-01 */
7050 hasAllMembers = TRUE;
7054 enumNameSList_free (usedEnums);
7058 *allpaths = hasDefault;
7061 exprNodeSList_free (el);
7062 return ((hasDefault || hasAllMembers) && mustReturn);
7065 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
7067 exprNode ret = exprNode_createPartialCopy (e);
7070 DPRINTF (("Switch: %s", exprNode_unparse (s)));
7072 ret->kind = XPR_SWITCH;
7073 ret->edata = exprData_makePair (e, s);
7075 if (!exprNode_isError (s))
7077 exprNode fs = exprNode_firstStatement (s);
7078 ret->loc = fileloc_update (ret->loc, s->loc);
7080 if (exprNode_isUndefined (fs)
7081 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
7082 || exprNode_isDefaultMarker (fs)) {
7085 voptgenerror (FLG_FIRSTCASE,
7087 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
7092 if (!exprNode_isError (e))
7094 if (checkSwitchExpr (e, s, &allpaths))
7096 ret->exitCode = XK_MUSTRETURN;
7100 ret->exitCode = e->exitCode;
7103 ret->canBreak = e->canBreak;
7104 ret->mustBreak = e->mustBreak;
7108 ** exprNode.c:3883,32: Variable allpaths used before definition
7115 DPRINTF (("Context exit switch!"));
7116 context_exitSwitch (ret, allpaths);
7117 DPRINTF (("Context exit switch done!"));
7122 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
7123 /*@notnull@*/ exprNode body)
7125 sRefSet tuses = test->uses;
7127 if (!sRefSet_isEmpty (test->uses))
7129 sRefSet sets = sRefSet_newCopy (body->sets);
7130 bool hasError = TRUE;
7131 bool innerState = FALSE;
7132 sRefSet tuncon = sRefSet_undefined;
7134 sets = sRefSet_union (sets, test->sets);
7135 sets = sRefSet_union (sets, body->msets);
7136 sets = sRefSet_union (sets, test->msets);
7138 sRefSet_allElements (tuses, el)
7140 if (sRef_isUnconstrained (el))
7142 tuncon = sRefSet_insert (tuncon, el);
7146 if (sRefSet_member (sets, el))
7153 if (sRef_isInternalState (el)
7154 || sRef_isFileStatic (sRef_getRootBase (el)))
7158 } end_sRefSet_allElements ;
7162 sRefSet suncon = sRefSet_undefined;
7163 bool sinner = FALSE;
7165 sRefSet_allElements (sets, el)
7167 if (sRef_isUnconstrained (el))
7169 suncon = sRefSet_insert (suncon, el);
7171 else if (sRef_isInternalState (el))
7179 } end_sRefSet_allElements ;
7181 if (sinner && innerState)
7185 else if (sRefSet_isEmpty (tuncon)
7186 && sRefSet_isEmpty (suncon))
7191 ("Suspected infinite loop. No value used in loop test (%q) "
7192 "is modified by test or loop body.",
7193 sRefSet_unparsePlain (tuses)),
7198 if (sRefSet_isEmpty (tuncon))
7202 message ("Suspected infinite loop. No condition values "
7203 "modified. Modification possible through "
7204 "unconstrained calls: %q",
7205 sRefSet_unparsePlain (suncon)),
7212 message ("Suspected infinite loop. No condition values "
7213 "modified. Possible undetected dependency through "
7214 "unconstrained calls in loop test: %q",
7215 sRefSet_unparsePlain (tuncon)),
7221 sRefSet_free (sets);
7225 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7228 bool emptyErr = FALSE;
7230 if (context_maybeSet (FLG_WHILEEMPTY))
7232 if (exprNode_isEmptyStatement (b))
7234 emptyErr = optgenerror
7237 ("Body of while statement is empty"),
7242 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7244 if (exprNode_isDefined (b)
7245 && !exprNode_isBlock (b))
7247 if (context_inIterDef ()
7248 && (b->kind == XPR_STMTLIST
7249 || b->kind == XPR_TOK))
7255 voptgenerror (FLG_WHILEBLOCK,
7257 ("Body of while statement is not a block: %s",
7258 exprNode_unparse (b)),
7264 if (exprNode_isError (t))
7266 if (exprNode_isError (b))
7268 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7272 ret = exprNode_createPartialCopy (b);
7279 ret = exprNode_createPartialCopy (t);
7281 llassert (t->kind == XPR_WHILEPRED);
7283 test = exprData_getSingle (t->edata);
7285 if (!exprNode_isError (b) && exprNode_isDefined (test))
7287 if (context_maybeSet (FLG_INFLOOPS)
7288 || context_maybeSet (FLG_INFLOOPSUNCON))
7291 ** check that some variable in the predicate is set by the body
7292 ** if the predicate uses any variables
7295 checkInfiniteLoop (test, b);
7298 exprNode_mergeUSs (ret, b);
7300 if (exprNode_isDefined (b))
7302 ret->exitCode = exitkind_makeConditional (b->exitCode);
7307 ret->edata = exprData_makePair (t, b);
7308 ret->kind = XPR_WHILE;
7310 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7314 message ("Predicate always exits: %s", exprNode_unparse (t)),
7318 ret->exitCode = XK_NEVERESCAPE;
7321 ** If loop is infinite, and there is no break inside,
7322 ** exit code is never reach.
7325 if (exprNode_knownIntValue (t))
7327 if (!exprNode_isZero (t))
7329 if (exprNode_isDefined (b))
7333 /* Really, it means never reached. */
7334 ret->exitCode = XK_MUSTEXIT;
7344 ret->canBreak = FALSE;
7345 ret->mustBreak = FALSE;
7351 ** do { b } while (t);
7353 ** note: body passed as first argument
7356 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7360 DPRINTF (("Do while: %s / %s",
7361 exprNode_unparse (b), exprNode_unparse (t)));
7363 if (exprNode_isError (t))
7365 if (exprNode_isError (b))
7367 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7371 ret = exprNode_createPartialCopy (b);
7373 ret->exitCode = exitkind_makeConditional (b->exitCode);
7374 exprNode_checkUse (ret, b->sref, b->loc);
7375 ret->exitCode = b->exitCode;
7376 ret->canBreak = b->canBreak;
7377 ret->mustBreak = FALSE;
7382 DPRINTF (("Do while: %s / %s",
7383 exitkind_unparse (t->exitCode),
7384 exitkind_unparse (b->exitCode)));
7386 ret = exprNode_createPartialCopy (t);
7387 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7389 if (!exprNode_isError (b))
7392 ** forgot the copy's --- why wasn't this detected??
7395 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7396 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7397 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
7399 /* left this out --- causes and aliasing bug (infinite loop)
7400 should be detected?? */
7402 exprNode_checkUse (ret, b->sref, b->loc);
7403 exprNode_mergeUSs (ret, t);
7404 exprNode_checkUse (ret, t->sref, t->loc);
7406 /* evans 2001-10-05: while loop can break */
7407 ret->exitCode = exitkind_makeConditional (b->exitCode);
7409 DPRINTF (("Do while: %s",
7410 exitkind_unparse (ret->exitCode)));
7412 ret->canBreak = b->canBreak;
7414 /* Always FALSE for doWhile loops - break's when test is false */
7415 ret->mustBreak = FALSE; /* b->mustBreak; */
7419 context_exitDoWhileClause (t);
7421 ret->kind = XPR_DOWHILE;
7422 ret->edata = exprData_makePair (t, b);
7426 bool exprNode_loopMustExec (exprNode forPred)
7429 ** Returns true if it is obvious that the loop always executes at least once
7431 ** For now, we only identify the most obvious cases. Should be true anytime
7432 ** we can prove init => !test.
7435 if (exprNode_isDefined (forPred))
7437 exprNode init, test, inc;
7440 llassert (forPred->kind == XPR_FORPRED);
7442 edata = forPred->edata;
7443 init = exprData_getTripleInit (edata);
7444 test = exprData_getTripleTest (edata);
7445 inc = exprData_getTripleInc (edata);
7447 if (exprNode_isAssign (init))
7449 exprNode loopVar = exprData_getOpA (init->edata);
7450 exprNode loopInit = exprData_getOpB (init->edata);
7452 if (exprNode_isDefined (test) && test->kind == XPR_OP)
7454 exprNode testVar = exprData_getOpA (test->edata);
7455 exprNode testVal = exprData_getOpB (test->edata);
7456 lltok comp = exprData_getOpTok (test->edata);
7457 int opid = lltok_getTok (comp);
7459 DPRINTF (("Same storage: %s / %s", exprNode_unparse (loopVar),
7460 exprNode_unparse (testVar)));
7462 if (exprNode_sameStorage (loopVar, testVar))
7464 multiVal valinit = exprNode_getValue (loopInit);
7465 multiVal valtest = exprNode_getValue (testVal);
7467 DPRINTF (("Values: %s / %s", multiVal_unparse (valinit),
7468 multiVal_unparse (valtest)));
7470 if (multiVal_isInt (valinit) && multiVal_isInt (valtest))
7472 long v1 = multiVal_forceInt (valinit);
7473 long v2 = multiVal_forceInt (valtest);
7475 DPRINTF (("Here: %ld %ld", v1, v2));
7477 if ((opid == EQ_OP && v1 < v2)
7478 || (opid == NE_OP && v1 != v2)
7479 || (opid == TLT && v1 <= v2)
7480 || (opid == TGT && v1 >= v2)
7481 || (opid == LE_OP && v1 < v2)
7482 || (opid == GE_OP && v1 > v2))
7484 DPRINTF (("mustexec if inc"));
7493 DPRINTF (("loop must exec: FALSE"));
7497 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7500 bool emptyErr = FALSE;
7502 if (context_maybeSet (FLG_FOREMPTY))
7504 if (exprNode_isEmptyStatement (body))
7506 emptyErr = optgenerror
7509 ("Body of for statement is empty"),
7510 exprNode_loc (body));
7514 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7516 if (exprNode_isDefined (body)
7517 && !exprNode_isBlock (body))
7519 if (context_inIterDef ()
7520 && (body->kind == XPR_STMTLIST
7521 || body->kind == XPR_TOK))
7527 voptgenerror (FLG_FORBLOCK,
7529 ("Body of for statement is not a block: %s",
7530 exprNode_unparse (body)),
7531 exprNode_loc (body));
7537 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7540 if (exprNode_isError (body))
7542 ret = exprNode_createPartialCopy (inc);
7546 ret = exprNode_createPartialCopy (body);
7548 ret->exitCode = exitkind_makeConditional (body->exitCode);
7550 exprNode_mergeUSs (inc, body);
7552 if (exprNode_isDefined (inc))
7556 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7558 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7559 exprNode_freeShallow (tmp);
7561 context_clearMessageAnnote ();
7562 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7564 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7565 exprNode_freeShallow (tmp);
7567 context_clearMessageAnnote ();
7569 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7570 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7571 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7575 ret->kind = XPR_FOR;
7576 ret->edata = exprData_makePair (inc, body);
7578 if (exprNode_isDefined (inc)) {
7579 exprNode test = exprData_getTripleTest (inc->edata);
7581 if (exprNode_isUndefined (test)) {
7582 if (exprNode_isDefined (body)) {
7583 if (!body->canBreak) {
7584 /* Really, it means never reached. */
7585 ret->exitCode = XK_MUSTEXIT;
7595 ** for (init; test; inc)
7598 ** while (test) { body; inc; }
7600 ** Now: check use of init (may set vars for test)
7601 ** check use of test
7605 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7609 if (exprNode_isError (pred)) return guardSet_undefined;
7611 llassert (pred->kind == XPR_FORPRED);
7613 test = exprData_getTripleTest (pred->edata);
7615 if (!exprNode_isError (test))
7617 return (test->guards);
7620 return guardSet_undefined;
7623 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7625 exprNode ret = exprNode_createSemiCopy (test);
7627 if (exprNode_isDefined (test))
7629 exprNode_copySets (ret, test);
7630 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7631 exprNode_checkUse (ret, test->sref, test->loc);
7633 exprNode_produceGuards (test);
7635 ret->guards = guardSet_copy (test->guards);
7638 ret->edata = exprData_makeSingle (test);
7639 ret->kind = XPR_WHILEPRED;
7643 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7644 /*@only@*/ exprNode inc)
7649 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7652 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7654 if (!exprNode_isError (inc))
7656 ret = exprNode_createPartialCopy (inc);
7660 if (!exprNode_isError (init))
7662 ret = exprNode_createPartialCopy (init);
7664 else if (!exprNode_isError (test))
7666 ret = exprNode_createPartialCopy (test);
7670 ret = exprNode_createUnknown ();
7674 exprNode_mergeUSs (ret, init);
7676 if (exprNode_isDefined (init))
7678 exprNode_checkUse (ret, init->sref, init->loc);
7681 exprNode_mergeUSs (ret, test);
7683 if (exprNode_isDefined (test))
7685 exprNode_checkUse (ret, test->sref, test->loc);
7688 ret->kind = XPR_FORPRED;
7689 ret->edata = exprData_makeFor (init, test, inc);
7693 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7695 exprNode ret = exprNode_createUnknown ();
7697 if (context_inMacro ())
7699 voptgenerror (FLG_MACROSTMT,
7700 message ("Macro %s uses goto (not functional)",
7701 context_inFunctionName ()),
7705 ret->kind = XPR_GOTO;
7706 ret->edata = exprData_makeLiteral (label);
7707 ret->mustBreak = TRUE;
7708 ret->exitCode = XK_GOTO;
7709 ret->canBreak = TRUE;
7713 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7715 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7717 ret->kind = XPR_CONTINUE;
7718 ret->edata = exprData_makeTok (l);
7719 ret->canBreak = TRUE;
7720 ret->mustBreak = TRUE;
7722 if (qcontinue == QSAFEBREAK)
7726 else if (qcontinue == QINNERCONTINUE)
7728 if (!context_inDeepLoop ())
7731 (FLG_LOOPLOOPCONTINUE,
7732 cstring_makeLiteral ("Continue statement marked with innercontinue "
7733 "is not inside a nested loop"),
7734 exprNode_loc (ret));
7737 else if (qcontinue == BADTOK)
7739 if (context_inDeepLoop ())
7742 (FLG_LOOPLOOPCONTINUE,
7743 cstring_makeLiteral ("Continue statement in nested loop"),
7744 exprNode_loc (ret));
7749 llbuglit ("exprNode_continue: bad qcontinue");
7755 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
7757 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7758 clause breakClause = context_breakClause ();
7760 ret->kind = XPR_BREAK;
7761 ret->edata = exprData_makeTok (l);
7762 ret->canBreak = TRUE;
7763 ret->mustBreak = TRUE;
7765 if (breakClause == NOCLAUSE)
7769 cstring_makeLiteral ("Break not inside while, for or switch statement"),
7770 exprNode_loc (ret));
7774 if (bqual != BADTOK)
7781 if (breakClause == SWITCHCLAUSE)
7783 if (!context_inDeepSwitch ())
7785 voptgenerror (FLG_SYNTAX,
7787 ("Break preceded by innerbreak is not in a deep switch"),
7788 exprNode_loc (ret));
7793 if (!context_inDeepLoop ())
7795 voptgenerror (FLG_SYNTAX,
7797 ("Break preceded by innerbreak is not in a deep loop"),
7798 exprNode_loc (ret));
7803 if (breakClause == SWITCHCLAUSE)
7805 voptgenerror (FLG_SYNTAX,
7807 ("Break preceded by loopbreak is breaking a switch"),
7808 exprNode_loc (ret));
7812 if (breakClause != SWITCHCLAUSE)
7816 message ("Break preceded by switchbreak is breaking %s",
7817 cstring_makeLiteralTemp
7818 ((breakClause == WHILECLAUSE
7819 || breakClause == DOWHILECLAUSE) ? "a while loop"
7820 : (breakClause == FORCLAUSE) ? "a for loop"
7821 : (breakClause == ITERCLAUSE) ? "an iterator"
7823 exprNode_loc (ret));
7831 if (breakClause == SWITCHCLAUSE)
7833 clause nextBreakClause = context_nextBreakClause ();
7835 switch (nextBreakClause)
7837 case NOCLAUSE: break;
7843 (FLG_LOOPSWITCHBREAK,
7844 cstring_makeLiteral ("Break statement in switch inside loop"),
7845 exprNode_loc (ret));
7849 (FLG_SWITCHSWITCHBREAK,
7850 cstring_makeLiteral ("Break statement in switch inside switch"),
7851 exprNode_loc (ret));
7858 if (context_inDeepLoop ())
7862 cstring_makeLiteral ("Break statement in nested loop"),
7863 exprNode_loc (ret));
7867 if (context_inDeepLoopSwitch ())
7870 (FLG_SWITCHLOOPBREAK,
7871 cstring_makeLiteral ("Break statement in loop inside switch"),
7872 exprNode_loc (ret));
7882 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
7884 fileloc loc = lltok_getLoc (t);
7885 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
7887 context_returnFunction ();
7888 exprChecks_checkNullReturn (loc);
7890 ret->kind = XPR_NULLRETURN;
7891 ret->edata = exprData_makeTok (t);
7892 ret->exitCode = XK_MUSTRETURN;
7896 exprNode exprNode_return (/*@only@*/ exprNode e)
7900 if (exprNode_isError (e))
7902 ret = exprNode_createUnknown ();
7906 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
7908 exprNode_checkUse (ret, e->sref, e->loc);
7909 exprNode_checkReturn (e);
7912 context_returnFunction ();
7913 ret->kind = XPR_RETURN;
7914 ret->edata = exprData_makeSingle (e);
7915 ret->exitCode = XK_MUSTRETURN;
7920 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
7924 if (exprNode_isError (e1))
7926 if (exprNode_isError (e2))
7928 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7932 ret = exprNode_createPartialCopy (e2);
7933 exprNode_checkUse (ret, e2->sref, e2->loc);
7934 ret->sref = e2->sref;
7939 ret = exprNode_createPartialCopy (e1);
7941 exprNode_checkUse (ret, e1->sref, e1->loc);
7943 if (!exprNode_isError (e2))
7945 exprNode_mergeUSs (ret, e2);
7946 exprNode_checkUse (ret, e2->sref, e2->loc);
7947 ret->sref = e2->sref;
7951 ret->kind = XPR_COMMA;
7952 ret->edata = exprData_makePair (e1, e2);
7954 if (exprNode_isDefined (e1))
7956 if (exprNode_isDefined (e2))
7960 if (exprNode_mustEscape (e1) || e1->mustBreak)
7964 message ("Second clause of comma expression is unreachable: %s",
7965 exprNode_unparse (e2)),
7969 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
7970 ret->mustBreak = e1->mustBreak || e2->mustBreak;
7971 ret->canBreak = e1->canBreak || e2->canBreak;
7975 if (exprNode_mustEscape (e1) || e1->mustBreak)
7979 message ("Second clause of comma expression is unreachable: %s",
7980 exprNode_unparse (e2)),
7984 ret->exitCode = e1->exitCode;
7985 ret->canBreak = e1->canBreak;
7990 if (exprNode_isDefined (e2))
7992 ret->exitCode = e2->exitCode;
7993 ret->mustBreak = e2->mustBreak;
7994 ret->canBreak = e2->canBreak;
8001 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
8003 ctype t1 = exprNode_getType (el);
8004 ctype t2 = exprNode_getType (val);
8005 bool hasError = FALSE;
8007 DPRINTF (("Check one init: %s / %s",
8008 exprNode_unparse (el),
8009 exprNode_unparse (val)));
8011 if (ctype_isUnknown (t1))
8013 voptgenerror (FLG_IMPTYPE,
8014 message ("Variable has unknown (implicitly int) type: %s",
8015 exprNode_unparse (el)),
8019 el->typ = ctype_int;
8022 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
8024 exprNodeList vals = exprData_getArgs (val->edata);
8026 DPRINTF (("Check one init: %s", exprNodeList_unparse (vals)));
8027 DPRINTF (("Type: %s", ctype_unparse (t1)));
8029 if (ctype_isRealAP (t1))
8034 if (ctype_isFixedArray (t1))
8036 int nelements = long_toInt (ctype_getArraySize (t1));
8038 if (exprNode_isStringLiteral (val))
8040 exprNode_checkStringLiteralLength (t1, val);
8044 if (exprNodeList_size (vals) != nelements)
8046 hasError = optgenerror
8047 (exprNodeList_size (vals) > nelements ? FLG_INITSIZE : FLG_INITALLELEMENTS,
8048 message ("Initializer block for "
8049 "%s has %d element%&, but declared as %s: %q",
8050 exprNode_unparse (el),
8051 exprNodeList_size (vals),
8053 exprNodeList_unparse (vals)),
8059 exprNodeList_elements (vals, oneval)
8061 cstring istring = message ("%d", i);
8064 (exprNode_fakeCopy (el),
8065 exprNode_numLiteral (ctype_int, istring,
8066 fileloc_copy (el->loc), i));
8068 if (exprNode_isDefined (newel))
8070 if (exprNodeList_size (vals) == 1
8071 && ctype_isString (exprNode_getType (oneval))
8072 && ctype_isChar (exprNode_getType (newel)))
8074 exprNode_freeIniter (newel);
8078 if (exprNode_checkOneInit (newel, oneval))
8083 if (nerrors > 3 && exprNodeList_size (vals) > 6)
8086 (message ("Additional initialization errors "
8087 "for %s not reported",
8088 exprNode_unparse (el)),
8090 exprNode_freeIniter (newel);
8095 exprNode_freeIniter (newel);
8100 exprNode_freeIniter (newel);
8105 cstring_free (istring);
8108 } end_exprNodeList_elements;
8111 else if (ctype_isStruct (ctype_realType (t1)))
8113 uentryList fields = ctype_getFields (t1);
8116 if (uentryList_size (fields) != exprNodeList_size (vals))
8118 if (uentryList_size (fields) > exprNodeList_size (vals))
8120 hasError = optgenerror
8122 message ("Initializer block for "
8123 "%s has %d field%&, but %s has %d field%&: %q",
8124 exprNode_unparse (el),
8125 exprNodeList_size (vals),
8127 uentryList_size (fields),
8128 exprNodeList_unparse (vals)),
8133 hasError = optgenerror
8135 message ("Initializer block for "
8136 "%s has %d field%&, but %s has %d field%&: %q",
8137 exprNode_unparse (el),
8138 exprNodeList_size (vals),
8140 uentryList_size (fields),
8141 exprNodeList_unparse (vals)),
8147 exprNodeList_elements (vals, oneval)
8149 uentry thisfield = uentryList_getN (fields, i);
8151 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8153 uentry_getName (thisfield));
8155 if (exprNode_isDefined (newel))
8157 if (exprNode_checkOneInit (newel, oneval))
8162 exprNode_freeIniter (newel);
8166 } end_exprNodeList_elements;
8169 /* evans 2001-12-30: added to fix bug reported by Jim Zelenka */
8170 else if (ctype_isUnion (ctype_realType (t1)))
8172 uentryList fields = ctype_getFields (t1);
8176 ** Union initializers set the first member always.
8179 DPRINTF (("Union initializer: %s / %s",
8180 exprNode_unparse (el), ctype_unparse (ctype_realType (t1))));
8182 if (exprNodeList_size (vals) != 1)
8184 hasError = optgenerror
8186 message ("Initializer block for union "
8187 "%s has %d elements, union initializers should have one element: %q",
8188 exprNode_unparse (el),
8189 exprNodeList_size (vals),
8190 exprNodeList_unparse (vals)),
8195 exprNode oneval = exprNodeList_head (vals);
8196 uentry thisfield = uentryList_getN (fields, i);
8198 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8200 uentry_getName (thisfield));
8202 if (exprNode_isDefined (newel))
8204 if (exprNode_checkOneInit (newel, oneval))
8209 exprNode_freeIniter (newel);
8215 hasError = optgenerror
8217 message ("Initializer block used for "
8218 "%s where %t is expected: %s",
8219 exprNode_unparse (el), t1, exprNode_unparse (val)),
8225 if (exprNode_isDefined (val))
8227 doAssign (el, val, TRUE);
8229 if (!exprNode_matchType (t1, val))
8231 hasError = gentypeerror
8233 message ("Initial value of %s is type %t, "
8235 exprNode_unparse (el),
8236 t2, t1, exprNode_unparse (val)),
8246 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
8250 DPRINTF (("Initialization: %s", idDecl_unparse (t)));
8252 if (usymtab_exists (idDecl_observeId (t)))
8254 uentry ue = usymtab_lookup (idDecl_observeId (t));
8255 ret = exprNode_createId (ue);
8257 /*@i723 don't do this...but why? */
8259 ct = ctype_realishType (ret->typ);
8261 DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
8263 if (ctype_isUnknown (ct))
8265 if (uentry_isAnyTag (ue))
8269 message ("%s used but not previously declared: %s",
8270 uentry_ekindName (ue),
8271 idDecl_getName (t)),
8279 message ("Variable has unknown (implicitly int) type: %s",
8280 idDecl_getName (t)),
8292 DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
8294 ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
8295 /*!! fileloc_copy (g_currentloc)); */
8296 /*@i32!!! should get error without this */
8298 ret = exprNode_fromIdentifierAux (ue);
8301 ** No error - this happens in old style declarations:
8305 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8312 exprData_free (ret->edata, ret->kind);
8313 ret->edata = exprData_undefined;
8315 ret->exitCode = XK_NEVERESCAPE;
8316 ret->mustBreak = FALSE;
8317 ret->kind = XPR_INIT;
8321 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8323 exprNode ret = exprNode_makeInitializationAux (t);
8324 llassert (ret->edata == exprData_undefined);
8325 ret->edata = exprData_makeInit (t, exprNode_undefined);
8329 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8330 /*@only@*/ exprNode e)
8332 uentry ue = usymtab_lookup (idDecl_observeId (t));
8333 exprNode ret = exprNode_makeInitializationAux (t);
8334 fileloc loc = exprNode_loc (e);
8336 if (exprNode_isError (e))
8338 e = exprNode_createUnknown ();
8341 /* error: assume initializer is defined */
8342 sRef_setDefined (ret->sref, g_currentloc);
8346 ctype ct = ctype_realishType (ret->typ);
8351 ** was addSafeUse --- what's the problem?
8353 ** int x = 3, y = x ?
8356 exprData_free (ret->edata, ret->kind);
8357 ret->edata = exprData_makeInit (t, e);
8359 exprNode_checkUse (ret, e->sref, e->loc);
8361 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8363 exprNode lhs = exprNode_createId (ue);
8366 ** static storage should be undefined before initializing
8369 if (uentry_isStatic (ue))
8371 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8374 (void) exprNode_checkOneInit (lhs, e);
8376 if (uentry_isStatic (ue))
8378 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8381 exprNode_free (lhs);
8385 if (!exprNode_matchType (ct, e))
8387 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
8394 (exprNode_getType (e), e, exprNode_getType (ret), ret,
8396 ("Variable %q initialized to type %t, expects %t: %s",
8397 uentry_getName (ue), exprNode_getType (e),
8398 exprNode_getType (ret),
8399 exprNode_unparse (e)),
8405 if (uentry_isStatic (ue))
8407 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8410 doAssign (ret, e, TRUE);
8412 if (uentry_isStatic (ue))
8414 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8418 if (context_inIterDef ())
8420 /* should check if it is yield */
8421 uentry_setUsed (ue, loc);
8428 exprNode_mergeUSs (ret, e);
8432 exprNode exprNode_iter (/*@observer@*/ uentry name,
8433 /*@only@*/ exprNodeList alist,
8434 /*@only@*/ exprNode body,
8435 /*@observer@*/ uentry end)
8440 llassert (uentry_isValid (name));
8442 uentry_setUsed (name, exprNode_loc (body));
8444 ret = exprNode_createPartialCopy (body);
8445 iname = uentry_getName (name);
8447 if (uentry_isInvalid (end))
8450 message ("Iter %s not balanced with end_%s", iname, iname));
8454 cstring ename = uentry_getName (end);
8456 if (!cstring_equalPrefixLit (ename, "end_"))
8458 llerror (FLG_ITER, message ("Iter %s not balanced with end_%s: %s",
8459 iname, iname, ename));
8463 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8466 message ("Iter %s not balanced with end_%s: %s",
8467 iname, iname, ename));
8471 cstring_free (ename);
8474 context_exitIterClause (body);
8476 ret->kind = XPR_ITER;
8477 ret->edata = exprData_makeIter (name, alist, body, end);
8479 if (uentry_isIter (name))
8481 (void) checkArgsReal (name, body,
8482 uentry_getParams (name), alist, TRUE, ret);
8485 cstring_free (iname);
8491 exprNode_iterNewId (/*@only@*/ cstring s)
8493 exprNode e = exprNode_new ();
8494 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8496 llassert (processingIterVars ());
8498 e->loc = context_getSaveLocation ();
8500 if (fileloc_isUndefined (e->loc))
8502 fileloc_free (e->loc);
8503 e->loc = fileloc_copy (g_currentloc);
8506 e->uses = sRefSet_new ();
8507 e->sets = sRefSet_new ();
8508 e->msets = sRefSet_new ();
8510 e->val = multiVal_unknown ();
8511 e->guards = guardSet_new ();
8513 e->isJumpPoint = FALSE;
8514 e->exitCode = XK_NEVERESCAPE;
8516 /*> missing fields, detected by lclint <*/
8517 e->canBreak = FALSE;
8518 e->mustBreak = FALSE;
8519 e->etext = cstring_undefined;
8521 if (uentry_isYield (ue))
8523 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8524 fileloc_copy (e->loc),
8528 uue = usymtab_supEntrySrefReturn (uue);
8530 sr = uentry_getSref (uue);
8531 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8532 sr = uentry_getSref (uue);
8533 sRef_setDefined (sr, e->loc);
8535 e->typ = uentry_getType (uue);
8537 e->edata = exprData_makeId (uue);
8538 uentry_setUsed (uue, g_currentloc);
8544 sRef_setGlobalScope ();
8545 uue = uentry_makeVariableLoc (s, ctype_unknown);
8547 e->typ = ctype_unknown;
8548 e->edata = exprData_makeId (uue);
8550 uentry_setUsed (uue, e->loc);
8551 uentry_setHasNameError (uue);
8553 if (context_getFlag (FLG_REPEATUNRECOG))
8555 uentry_markOwned (uue);
8559 usymtab_supGlobalEntry (uue);
8562 sRef_clearGlobalScope ();
8564 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8571 exprNode_defineConstraints(e);
8576 exprNode_iterExpr (/*@returned@*/ exprNode e)
8578 if (!processingIterVars ())
8580 llcontbuglit ("checkIterParam: not in iter");
8584 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8587 if (exprNode_isDefined (e))
8589 if (fileloc_isDefined (e->loc))
8593 message ("Yield parameter is not simple identifier: %s",
8594 exprNode_unparse (e)),
8601 message ("Yield parameter is not simple identifier: %s",
8602 exprNode_unparse (e)),
8612 exprNode_iterId (/*@observer@*/ uentry c)
8616 llassert (processingIterVars ());
8618 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8621 if (uentry_isYield (ue))
8623 ctype ct = uentry_getType (ue);
8624 exprNode e = exprNode_createPlain (ct);
8625 cstring name = uentry_getName (c);
8626 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8628 uentry_setUsed (ue, g_currentloc);
8629 uentry_setHasNameError (ue);
8631 cstring_free (name);
8634 e->edata = exprData_makeId (le);
8635 e->loc = context_getSaveLocation ();
8636 e->sref = uentry_getSref (le);
8638 usymtab_supEntrySref (le);
8640 if (!context_inHeader ())
8644 message ("Yield parameter shadows local declaration: %q",
8645 uentry_getName (c)),
8646 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8648 uentry_showWhereDeclared (c);
8655 return (exprNode_fromIdentifierAux (c));
8658 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8660 exprNode ret = exprNode_create (ctype_unknown);
8662 ret->kind = XPR_ITERCALL;
8663 ret->edata = exprData_makeIterCall (name, alist);
8665 if (uentry_isIter (name))
8667 uentryList params = uentry_getParams (name);
8669 if (context_inIterDef ()
8670 && uentryList_size (params) == exprNodeList_size (alist))
8674 exprNodeList_elements (alist, arg)
8676 uentry parg = uentryList_getN (params, i);
8678 if (uentry_isYield (parg))
8680 uentry ue = exprNode_getUentry (arg);
8682 if (uentry_isValid (ue))
8689 } end_exprNodeList_elements;
8692 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8693 checkUnspecCall (ret, params, alist);
8699 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8701 if (exprNode_isDefined (e))
8704 if (e->sref == defref) /*@noaccess sRef@*/
8707 e->sref = sRef_makeUnknown ();
8708 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8719 return sRef_undefined;
8723 /*@observer@*/ cstring
8724 exprNode_unparseFirst (exprNode e)
8726 if (exprNode_isDefined (e))
8730 if (e->kind == XPR_STMTLIST
8731 || e->kind == XPR_COMMA || e->kind == XPR_COND)
8733 exprNode first = exprData_getPairA (e->edata);
8735 if (exprNode_isDefined (first))
8737 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8741 return (cstring_makeLiteralTemp ("..."));
8745 ret = cstring_elide (exprNode_unparse (e), 20);
8746 cstring_markOwned (ret);
8752 return cstring_makeLiteralTemp ("<error>");
8756 /*@observer@*/ cstring
8757 exprNode_unparse (/*@temp@*/ exprNode e)
8759 if (exprNode_isError (e))
8761 return cstring_makeLiteralTemp ("<error>");
8764 if (cstring_isDefined (e->etext))
8770 cstring ret = exprNode_doUnparse (e);
8772 /*@-modifies@*/ /* benevolent */
8779 /*@observer@*/ fileloc
8780 exprNode_loc (exprNode e)
8782 if (exprNode_isError (e))
8784 return (g_currentloc);
8793 ** executes exprNode e
8794 ** recursively rexecutes as though in original parse using
8795 ** information in e->edata
8798 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
8800 exprNodeList ret = exprNodeList_new ();
8802 exprNodeList_elements (e, current)
8804 exprNodeList_addh (ret, exprNode_effect (current));
8805 } end_exprNodeList_elements;
8810 static /*@only@*/ exprNode exprNode_effect (exprNode e)
8811 /*@globals internalState@*/
8813 bool innerEffect = inEffect;
8819 context_clearJustPopped ();
8821 if (exprNode_isError (e))
8823 ret = exprNode_undefined;
8828 ** Turn off expose and dependent transfer checking.
8829 ** Need to pass exposed internal nodes,
8830 ** [ copying would be a waste! ]
8831 ** [ Actually, I think I wasted a lot more time than its worth ]
8832 ** [ trying to do this. ]
8836 /*@-observertrans@*/
8837 /*@-dependenttrans@*/
8844 ret = exprNode_addParens (exprData_getUopTok (data),
8845 exprNode_effect (exprData_getUopNode (data)));
8848 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
8849 exprNode_effect (exprData_getOpB (data)),
8850 exprData_getOpTok (data));
8853 ret = exprNode_undefined;
8856 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
8857 exprNodeList_effect (exprData_getArgs (data)));
8870 cstring id = exprData_getId (data);
8871 uentry ue = usymtab_lookupSafe (id);
8873 ret = exprNode_fromIdentifierAux (ue);
8874 ret->loc = fileloc_update (ret->loc, e->loc);
8881 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
8882 exprNode_effect (exprData_getPairB (data)));
8885 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
8886 exprNode_effect (exprData_getOpB (data)),
8887 exprData_getOpTok (data));
8891 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
8892 exprData_getUopTok (data));
8895 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
8896 exprData_getUopTok (data));
8908 ret = exprNode_vaArg (exprData_getCastTok (data),
8909 exprNode_effect (exprData_getCastNode (data)),
8910 exprData_getCastType (data));
8914 ret = exprNode_cast (exprData_getCastTok (data),
8915 exprNode_effect (exprData_getCastNode (data)),
8916 exprData_getCastType (data));
8919 ret = exprNode_iterStart (exprData_getIterCallIter (data),
8921 (exprData_getIterCallArgs (data)));
8925 ret = exprNode_iter (exprData_getIterSname (data),
8926 exprNodeList_effect (exprData_getIterAlist (data)),
8927 exprNode_effect (exprData_getIterBody (data)),
8928 exprData_getIterEname (data));
8932 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
8933 exprNode_effect (exprData_getPairB (data)));
8937 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
8938 exprNode_effect (exprData_getTripleTest (data)),
8939 exprNode_effect (exprData_getTripleInc (data)));
8943 ret = exprNode_createTok (exprData_getTok (data));
8947 ret = exprNode_goto (exprData_getLiteral (data));
8948 ret->loc = fileloc_update (ret->loc, e->loc);
8952 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
8956 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
8960 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
8963 case XPR_NULLRETURN:
8964 ret = exprNode_nullReturn (exprData_getTok (data));
8968 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
8969 exprNode_effect (exprData_getPairB (data)));
8973 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
8974 exprNode_effect (exprData_getTripleTrue (data)),
8975 exprNode_effect (exprData_getTripleFalse (data)));
8978 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
8979 exprNode_effect (exprData_getPairB (data)));
8983 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
8984 exprNode_effect (exprData_getTripleTrue (data)),
8985 exprNode_effect (exprData_getTripleFalse (data)));
8988 ret = exprNode_whilePred (exprData_getSingle (data));
8992 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
8993 exprNode_effect (exprData_getPairB (data)));
8997 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
8998 exprNode_effect (exprData_getPairB (data)));
9002 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
9006 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
9007 exprData_getUopTok (data));
9011 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
9012 exprNode_effect (exprData_getPairB (data)));
9017 ret = exprNode_caseMarker
9018 (exprNode_effect (exprData_getSingle (data)),
9024 ret = exprNode_createTok (exprData_getTok (data));
9028 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
9029 exprNode_effect (exprData_getPairB (data)));
9033 ret = exprNode_makeInitialization
9034 (exprData_getInitId (data),
9035 exprNode_effect (exprData_getInitNode (data)));
9039 ret = exprNode_fieldAccessAux
9040 (exprNode_effect (exprData_getFieldNode (data)),
9041 exprNode_loc (exprData_getFieldNode (data)),
9042 cstring_copy (exprData_getFieldName (data)));
9046 ret = exprNode_arrowAccessAux
9047 (exprNode_effect (exprData_getFieldNode (data)),
9048 exprNode_loc (exprData_getFieldNode (data)),
9049 cstring_copy (exprData_getFieldName (data)));
9052 case XPR_STRINGLITERAL:
9066 /*@=observertrans@*/
9068 /*@=dependenttrans@*/
9079 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
9084 if (exprNode_isError (e))
9086 return cstring_undefined;
9094 ret = exprNode_rootVarName (exprData_getUopNode (data));
9097 ret = exprNode_rootVarName (exprData_getOpA (data));
9101 ret = exprData_getId (data);
9104 ret = idDecl_getName (exprData_getInitId (data));
9129 case XPR_NULLRETURN:
9151 case XPR_STRINGLITERAL:
9152 ret = cstring_undefined;
9159 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
9164 if (exprNode_isError (e))
9166 static /*@only@*/ cstring error = cstring_undefined;
9168 if (!cstring_isDefined (error))
9170 error = cstring_makeLiteral ("<error>");
9181 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
9184 ret = message ("%s %s %s",
9185 exprNode_unparse (exprData_getOpA (data)),
9186 lltok_unparse (exprData_getOpTok (data)),
9187 exprNode_unparse (exprData_getOpB (data)));
9190 ret = message ("%s(%q)",
9191 exprNode_unparse (exprData_getFcn (data)),
9192 exprNodeList_unparse (exprData_getArgs (data)));
9195 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
9198 ret = cstring_undefined;
9201 ret = message ("%s:", exprData_getId (data));
9205 ret = cstring_copy (exprData_getId (data));
9208 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
9209 exprNode_unparse (exprData_getPairB (data)));
9212 ret = message ("<body>");
9215 ret = message ("%s %s %s",
9216 exprNode_unparse (exprData_getOpA (data)),
9217 lltok_unparse (exprData_getOpTok (data)),
9218 exprNode_unparse (exprData_getOpB (data)));
9222 ret = message ("%s%s",
9223 lltok_unparse (exprData_getUopTok (data)),
9224 exprNode_unparse (exprData_getUopNode (data)));
9228 ret = message ("%s%s",
9229 exprNode_unparse (exprData_getUopNode (data)),
9230 lltok_unparse (exprData_getUopTok (data)));
9234 ret = message ("offsetof(%s,%q)",
9235 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
9236 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
9240 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9244 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
9248 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9252 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
9256 ret = message ("va_arg(%s, %q)",
9257 exprNode_unparse (exprData_getCastNode (data)),
9258 qtype_unparse (exprData_getCastType (data)));
9262 ret = message ("%q(%q)",
9263 uentry_getName (exprData_getIterCallIter (data)),
9264 exprNodeList_unparse (exprData_getIterCallArgs (data)));
9267 ret = message ("%q(%q) %s %q",
9268 uentry_getName (exprData_getIterSname (data)),
9269 exprNodeList_unparse (exprData_getIterAlist (data)),
9270 exprNode_unparse (exprData_getIterBody (data)),
9271 uentry_getName (exprData_getIterEname (data)));
9274 ret = message ("(%q)%s",
9275 qtype_unparse (exprData_getCastType (data)),
9276 exprNode_unparse (exprData_getCastNode (data)));
9280 ret = message ("%s %s",
9281 exprNode_unparse (exprData_getPairA (data)),
9282 exprNode_unparse (exprData_getPairB (data)));
9286 ret = message ("for (%s; %s; %s)",
9287 exprNode_unparse (exprData_getTripleInit (data)),
9288 exprNode_unparse (exprData_getTripleTest (data)),
9289 exprNode_unparse (exprData_getTripleInc (data)));
9293 ret = message ("goto %s", exprData_getLiteral (data));
9297 ret = cstring_makeLiteral ("continue");
9301 ret = cstring_makeLiteral ("break");
9305 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
9308 case XPR_NULLRETURN:
9309 ret = cstring_makeLiteral ("return");
9313 ret = message ("%s, %s",
9314 exprNode_unparse (exprData_getPairA (data)),
9315 exprNode_unparse (exprData_getPairB (data)));
9319 ret = message ("%s ? %s : %s",
9320 exprNode_unparse (exprData_getTriplePred (data)),
9321 exprNode_unparse (exprData_getTripleTrue (data)),
9322 exprNode_unparse (exprData_getTripleFalse (data)));
9325 ret = message ("if (%s) %s",
9326 exprNode_unparse (exprData_getPairA (data)),
9327 exprNode_unparse (exprData_getPairB (data)));
9331 ret = message ("if (%s) %s else %s",
9332 exprNode_unparse (exprData_getTriplePred (data)),
9333 exprNode_unparse (exprData_getTripleTrue (data)),
9334 exprNode_unparse (exprData_getTripleFalse (data)));
9337 ret = message ("while (%s) %s",
9338 exprNode_unparse (exprData_getPairA (data)),
9339 exprNode_unparse (exprData_getPairB (data)));
9343 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9347 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9351 ret = message ("do { %s } while (%s)",
9352 exprNode_unparse (exprData_getPairB (data)),
9353 exprNode_unparse (exprData_getPairA (data)));
9357 ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
9361 ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
9365 ret = message ("%s; %s",
9366 exprNode_unparse (exprData_getPairA (data)),
9367 exprNode_unparse (exprData_getPairB (data)));
9372 ret = cstring_makeLiteral ("default:");
9376 ret = message ("switch (%s) %s",
9377 exprNode_unparse (exprData_getPairA (data)),
9378 exprNode_unparse (exprData_getPairB (data)));
9383 ret = message ("case %s:",
9384 exprNode_unparse (exprData_getSingle (data)));
9388 if (exprNode_isError (exprData_getInitNode (data)))
9390 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9394 ret = message ("%q = %s",
9395 idDecl_unparseC (exprData_getInitId (data)),
9396 exprNode_unparse (exprData_getInitNode (data)));
9401 ret = message ("%s.%s",
9402 exprNode_unparse (exprData_getFieldNode (data)),
9403 exprData_getFieldName (data));
9407 ret = message ("%s->%s",
9408 exprNode_unparse (exprData_getFieldNode (data)),
9409 exprData_getFieldName (data));
9412 case XPR_STRINGLITERAL:
9413 if (ctype_isWideString (e->typ))
9415 ret = message ("L\"%s\"", exprData_getLiteral (data));
9419 ret = message ("\"%s\"", exprData_getLiteral (data));
9424 ret = cstring_copy (exprData_getLiteral (data));
9428 ret = cstring_makeLiteral ("<node>");
9436 exprNode_isInitializer (exprNode e)
9438 return (exprNode_isDefined (e)
9439 && e->kind == XPR_INIT);
9443 exprNode_isCharLit (exprNode e)
9445 if (exprNode_isDefined (e))
9447 return (multiVal_isChar (exprNode_getValue (e)));
9456 exprNode_isNumLit (exprNode e)
9458 if (exprNode_isDefined (e))
9460 return (multiVal_isInt (exprNode_getValue (e)));
9469 exprNode_isFalseConstant (exprNode e)
9471 if (exprNode_isDefined (e))
9473 cstring s = exprNode_rootVarName (e);
9475 if (cstring_equal (s, context_getFalseName ()))
9485 exprNode_matchLiteral (ctype expected, exprNode e)
9487 if (exprNode_isDefined (e))
9489 multiVal m = exprNode_getValue (e);
9491 if (multiVal_isDefined (m))
9493 if (multiVal_isInt (m))
9495 long int val = multiVal_forceInt (m);
9497 if (ctype_isDirectBool (ctype_realishType (expected)))
9501 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9509 if (ctype_isRealInt (expected))
9512 ** unsigned <- [ constant >= 0 is okay ]
9515 if (ctype_isUnsigned (expected))
9524 ** No checks on sizes of integers...maybe add
9528 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9529 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9530 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9532 if (context_getFlag (FLG_NUMLITERAL)
9533 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9539 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9543 else if (ctype_isChar (expected))
9547 else if (ctype_isArrayPtr (expected))
9550 ** evans 2001-10-14: We allow 0 to match any pointer, but only if the type matches or is void *.
9555 if (ctype_match (exprNode_getType (e), expected)
9556 || ctype_isVoidPointer (exprNode_getType (e)))
9566 else if (ctype_isAnyFloat (expected))
9568 return (context_getFlag (FLG_NUMLITERAL));
9575 else if (multiVal_isDouble (m))
9577 if (ctype_isAnyFloat (expected))
9582 else if (multiVal_isChar (m))
9584 char val = multiVal_forceChar (m);
9586 if (ctype_isChar (expected))
9588 if (ctype_isUnsigned (expected) && ((int)val) < 0)
9609 exprNode_matchType (ctype expected, exprNode e)
9613 if (!exprNode_isDefined (e)) return TRUE;
9615 actual = ctype_realishType (exprNode_getType (e));
9617 if (ctype_match (ctype_realishType (expected), actual))
9622 llassert (!exprNode_isError (e));
9623 return (exprNode_matchLiteral (expected, e));
9627 exprNode_matchTypes (exprNode e1, exprNode e2)
9632 if (!exprNode_isDefined (e1)) return TRUE;
9633 if (!exprNode_isDefined (e2)) return TRUE;
9636 ** realish type --- keep bools, bools
9639 t1 = ctype_realishType (exprNode_getType (e1));
9640 t2 = ctype_realishType (exprNode_getType (e2));
9642 if (ctype_match (t1, t2))
9647 DPRINTF (("Matching literal! %s %s %s %s",
9648 ctype_unparse (t1), exprNode_unparse (e2),
9649 ctype_unparse (t2), exprNode_unparse (e1)));
9651 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9659 exprNode_matchArgType (ctype ct, exprNode e)
9663 if (!exprNode_isDefined (e))
9668 et = ctype_realType (exprNode_getType (e));
9670 if (ctype_matchArg (ct, et)) return TRUE;
9672 llassert (!exprNode_isError (e));
9673 return (exprNode_matchLiteral (ct, e));
9676 static /*@only@*/ exprNodeSList
9677 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9679 if (exprNode_isDefined (e))
9681 if (e->kind == XPR_STMTLIST)
9683 return (exprNodeSList_append
9684 (exprNode_flatten (exprData_getPairA (e->edata)),
9685 exprNode_flatten (exprData_getPairB (e->edata))));
9687 else if (e->kind == XPR_BLOCK)
9689 return (exprNode_flatten (exprData_getSingle (e->edata)));
9693 return (exprNodeSList_singleton (e));
9697 return exprNodeSList_new ();
9700 static /*@exposed@*/ exprNode
9701 exprNode_lastStatement (/*@returned@*/ exprNode e)
9703 if (exprNode_isDefined (e))
9705 if (e->kind == XPR_STMTLIST)
9707 exprNode b = exprData_getPairB (e->edata);
9709 if (exprNode_isDefined (b))
9711 return exprNode_lastStatement (b);
9715 return exprNode_lastStatement (exprData_getPairA (e->edata));
9718 else if (e->kind == XPR_BLOCK)
9720 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
9728 return exprNode_undefined;
9731 static /*@exposed@*/ exprNode
9732 exprNode_firstStatement (/*@returned@*/ exprNode e)
9734 if (exprNode_isDefined (e))
9736 if (e->kind == XPR_STMTLIST)
9738 exprNode b = exprData_getPairA (e->edata);
9740 if (exprNode_isDefined (b))
9742 return exprNode_firstStatement (b);
9746 return exprNode_firstStatement (exprData_getPairB (e->edata));
9749 else if (e->kind == XPR_BLOCK)
9751 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
9759 return exprNode_undefined;
9763 exprNode_mergeUSs (exprNode res, exprNode other)
9765 if (exprNode_isDefined (res) && exprNode_isDefined (other))
9767 res->msets = sRefSet_union (res->msets, other->msets);
9768 res->sets = sRefSet_union (res->sets, other->sets);
9769 res->uses = sRefSet_union (res->uses, other->uses);
9774 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
9776 if (exprNode_isDefined (res))
9778 if (exprNode_isDefined (other1))
9780 res->sets = sRefSet_union (res->sets, other1->sets);
9781 res->msets = sRefSet_union (res->msets, other1->msets);
9782 res->uses = sRefSet_union (res->uses, other1->uses);
9784 if (exprNode_isDefined (other2))
9786 res->sets = sRefSet_union (res->sets, other2->sets);
9787 res->msets = sRefSet_union (res->msets, other2->msets);
9788 res->uses = sRefSet_union (res->uses, other2->uses);
9796 ** Reports errors is s is not defined.
9800 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
9802 if (exprNode_isDefined (e))
9804 e->uses = sRefSet_insert (e->uses, s);
9809 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
9811 if (sRef_isKnown (s) && !sRef_isConst (s))
9814 ** need to check all outer types are useable
9817 DPRINTF (("Check use: %s / %s",
9818 exprNode_unparse (e), sRef_unparse (s)));
9820 exprNode_addUse (e, s);
9822 if (!context_inProtectVars ())
9825 ** only report the deepest error
9828 sRef errorRef = sRef_undefined;
9829 sRef lastRef = sRef_undefined;
9830 bool deadRef = FALSE;
9831 bool unuseable = FALSE;
9832 bool errorMaybe = FALSE;
9834 while (sRef_isValid (s) && sRef_isKnown (s))
9836 ynm readable = sRef_isValidLvalue (s);
9838 DPRINTF (("Readable: %s / %s",
9839 sRef_unparseFull (s), ynm_unparse (readable)));
9841 if (!(ynm_toBoolStrict (readable)))
9843 if (ynm_isMaybe (readable))
9847 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
9848 deadRef = sRef_isPossiblyDead (errorRef);
9849 unuseable = sRef_isUnuseable (errorRef);
9856 deadRef = sRef_isDead (errorRef);
9857 unuseable = sRef_isUnuseable (errorRef);
9861 if (!sRef_isPartial (s))
9863 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
9864 sRef_setDefined (s, fileloc_undefined);
9868 s = sRef_getBaseSafe (s);
9871 if (sRef_isValid (errorRef))
9873 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
9874 && sRef_isPointer (errorRef))
9881 if (sRef_isThroughArrayFetch (errorRef))
9884 (FLG_STRICTUSERELEASED,
9885 message ("%q %q may be used after being released",
9886 sRef_unparseKindNamePlain (errorRef),
9887 sRef_unparse (errorRef)),
9890 sRef_showRefKilled (errorRef);
9892 if (sRef_isKept (errorRef))
9894 sRef_clearAliasState (errorRef, loc);
9900 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
9904 message ("%q %q %qused after being released",
9905 sRef_unparseKindNamePlain (errorRef),
9906 sRef_unparse (errorRef),
9907 cstring_makeLiteral (errorMaybe
9911 sRef_showRefKilled (errorRef);
9913 if (sRef_isKept (errorRef))
9915 sRef_clearAliasState (errorRef, loc);
9924 message ("%q %q%qused in inconsistent state",
9925 sRef_unparseKindName (errorRef),
9926 sRef_unparseOpt (errorRef),
9927 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9930 sRef_showStateInconsistent (errorRef);
9935 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
9939 message ("%q %q%qused before definition",
9940 sRef_unparseKindName (errorRef),
9941 sRef_unparseOpt (errorRef),
9942 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9945 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
9948 sRef_setDefined (errorRef, loc);
9950 if (sRef_isAddress (errorRef))
9952 sRef_setDefined (sRef_getRootBase (errorRef), loc);
9954 } /* end is error */
9962 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
9964 if (exprNode_isDefined (e) && sRef_isKnown (s))
9966 e->uses = sRefSet_insert (e->uses, s);
9971 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
9973 if (exprNode_isDefined (e))
9975 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
9980 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
9982 sRef defines = sRef_undefined;
9984 if (sRef_isValid (s) && !sRef_isNothing (s))
9986 uentry ue = sRef_getBaseUentry (s);
9988 if (uentry_isValid (ue))
9990 uentry_setLset (ue);
9993 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9995 voptgenerror (FLG_USEDEF,
9996 message ("Attempt to set unuseable storage: %q",
10001 if (sRef_isMeaningful (s))
10003 if (sRef_isDead (s))
10005 sRef base = sRef_getBaseSafe (s);
10007 if (sRef_isValid (base)
10008 && sRef_isDead (base))
10010 sRef_setPartial (s, exprNode_loc (e));
10013 defines = s; /* okay - modifies for only param */
10015 else if (sRef_isPartial (s))
10017 sRef eref = exprNode_getSref (e);
10019 if (!sRef_isPartial (eref))
10022 ** should do something different here???
10025 sRef_setDefinedComplete (eref, exprNode_loc (e));
10029 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
10032 if (sRef_isMeaningful (eref))
10041 else if (sRef_isAllocated (s))
10043 sRef eref = exprNode_getSref (e);
10046 if (!sRef_isAllocated (eref))
10048 sRef_setDefinedComplete (eref, exprNode_loc (e));
10052 sRef base = sRef_getBaseSafe (eref);
10054 if (sRef_isValid (base))
10056 sRef_setPdefined (base, exprNode_loc (e));
10064 sRef_setDefinedNCComplete (s, exprNode_loc (e));
10069 else /* not meaningful...but still need to insert it */
10075 if (exprNode_isDefined (e) && sRef_isValid (defines))
10077 e->sets = sRefSet_insert (e->sets, defines);
10082 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
10084 if (sRef_isValid (s) && !sRef_isNothing (s))
10086 uentry ue = sRef_getBaseUentry (s);
10088 if (uentry_isValid (ue))
10090 uentry_setLset (ue);
10093 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10095 voptgenerror (FLG_USEDEF,
10096 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
10100 if (sRef_isMeaningful (s))
10102 sRef_setDefinedComplete (s, exprNode_loc (e));
10105 if (exprNode_isDefined (e))
10107 e->msets = sRefSet_insert (e->msets, s);
10113 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
10115 checkAnyCall (fcn, cstring_undefined, params, args,
10116 FALSE, sRefSet_undefined, FALSE, 0);
10120 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
10121 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
10125 if (uentry_isYield (ucurrent))
10127 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
10128 exprNode_checkSet (current, current->sref);
10132 if (uentry_isSefParam (ucurrent))
10134 sRefSet sets = current->sets;
10135 sRef ref = exprNode_getSref (current);
10137 if (sRef_isMacroParamRef (ref))
10139 uentry ue = sRef_getUentry (ref);
10141 if (!uentry_isSefParam (ue))
10146 ("Parameter %d to %s is declared sef, but "
10147 "the argument is a macro parameter declared "
10149 argno, exprNode_unparse (fcn),
10150 exprNode_unparse (current)),
10151 exprNode_loc (current));
10155 if (!sRefSet_isEmpty (sets))
10157 sRefSet reported = sRefSet_undefined;
10159 sRefSet_realElements (current->sets, el)
10161 if (sRefSet_isSameNameMember (reported, el))
10163 ; /* don't report again */
10167 if (sRef_isUnconstrained (el))
10172 ("Parameter %d to %s is declared sef, but "
10173 "the argument calls unconstrained function %s "
10174 "(no guarantee it will not modify something): %s",
10175 argno, exprNode_unparse (fcn),
10176 sRef_unconstrainedName (el),
10177 exprNode_unparse (current)),
10178 exprNode_loc (current));
10185 ("Parameter %d to %s is declared sef, but "
10186 "the argument may modify %q: %s",
10187 argno, exprNode_unparse (fcn),
10189 exprNode_unparse (current)),
10190 exprNode_loc (current));
10193 } end_sRefSet_realElements;
10197 checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs);
10198 exprNode_mergeUSs (fcn, current);
10203 checkAnyCall (/*@dependent@*/ exprNode fcn,
10204 /*@dependent@*/ cstring fname,
10207 bool hasMods, sRefSet mods,
10212 int nargs = exprNodeList_size (args);
10217 ** concat all args ud's to f, add each arg sref as a use unless
10218 ** it was specified as "out", in which case it is a def.
10221 uentryList_reset (pn);
10224 ** aliasing checks:
10226 ** if paramn is only or unique, no other arg may alias argn
10229 exprNodeList_elements (args, current)
10233 if (exprNode_isDefined (current))
10235 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
10237 uentry ucurrent = uentryList_current (pn);
10239 if (specialArgs == 0
10240 || (paramno < specialArgs))
10242 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
10244 if (context_maybeSet (FLG_ALIASUNIQUE))
10246 if (uentry_isOnly (ucurrent)
10247 || uentry_isUnique (ucurrent))
10249 checkUniqueParams (fcn, current, args,
10250 paramno, ucurrent);
10255 else /* uentry is undefined */
10257 if (specialArgs == 0)
10259 exprNode_checkUseParam (current);
10262 exprNode_mergeUSs (fcn, current);
10265 uentryList_advanceSafe (pn);
10266 } end_exprNodeList_elements;
10272 sRefSet_allElements (mods, s)
10275 sRef rb = sRef_getRootBase (s);
10277 if (sRef_isFileOrGlobalScope (rb))
10279 context_usedGlobal (rb);
10282 fb = sRef_fixBaseParam (s, args);
10284 if (!sRef_isMacroParamRef (fb))
10286 if (sRef_isNothing (fb))
10292 if (sRef_isValid (fb))
10294 uentry ue = sRef_getBaseUentry (s);
10296 if (uentry_isValid (ue))
10298 uentry_setLset (ue);
10302 fcn->sets = sRefSet_insert (fcn->sets, fb);
10305 sRef_clearDerivedComplete (s);
10306 } end_sRefSet_allElements;
10312 if (context_hasMods ())
10314 if (context_maybeSet (FLG_MODUNCON))
10318 message ("Undetected modification possible "
10319 "from call to unconstrained function %s: %s",
10321 exprNode_unparse (fcn)),
10322 exprNode_loc (fcn));
10327 if (context_maybeSet (FLG_MODUNCONNOMODS)
10328 && !(context_inIterDef () || context_inIterEnd ()))
10331 (FLG_MODUNCONNOMODS,
10332 message ("Undetected modification possible "
10333 "from call to unconstrained function %s: %s",
10335 exprNode_unparse (fcn)),
10336 exprNode_loc (fcn));
10340 exprNode_checkSetAny (fcn, fname);
10344 void exprNode_checkUseParam (exprNode current)
10346 if (exprNode_isDefined (current))
10348 exprNode_checkUse (current, current->sref, current->loc);
10353 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10354 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10359 if (!ctype_match (tr1, tr2))
10361 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10362 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10364 DPRINTF (("No error: [%s] %s / [%s] %s",
10365 exprNode_unparse (e1), ctype_unparse (tr1),
10366 exprNode_unparse (e2), ctype_unparse (tr2)));
10370 (void) gentypeerror
10372 message ("Incompatible types for %s (%s, %s): %s %s %s",
10373 lltok_unparse (op),
10374 ctype_unparse (te1),
10375 ctype_unparse (te2),
10376 exprNode_unparse (e1), lltok_unparse (op),
10377 exprNode_unparse (e2)),
10380 ret = ctype_unknown;
10384 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
10386 ret = ctype_resolveNumerics (tr1, tr2);
10388 else if (!context_msgStrictOps ())
10390 if (ctype_isPointer (tr1))
10392 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10396 else if (ctype_isInt (tr2))
10402 ret = ctype_unknown;
10405 else if (ctype_isPointer (tr2))
10407 if (ctype_isPointer (tr1))
10411 else if (ctype_isInt (tr1))
10417 ret = ctype_unknown;
10422 ret = ctype_resolveNumerics (tr1, tr2);
10427 int opid = lltok_getTok (op);
10428 bool comparop = (opid == EQ_OP || opid == NE_OP
10429 || opid == TLT || opid == TGT
10430 || opid == LE_OP || opid == GE_OP);
10432 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10435 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10436 || (ctype_isBool (tr1) && ctype_isBool (tr2))
10437 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10443 if (ctype_sameName (te1, te2))
10447 message ("Operands of %s are non-numeric (%t): %s %s %s",
10448 lltok_unparse (op), te1,
10449 exprNode_unparse (e1), lltok_unparse (op),
10450 exprNode_unparse (e2)),
10457 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10458 lltok_unparse (op), te1, te2,
10459 exprNode_unparse (e1), lltok_unparse (op),
10460 exprNode_unparse (e2)),
10465 else if (!ctype_isNumeric (tr1))
10469 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10470 lltok_unparse (op), te1,
10471 exprNode_unparse (e1), lltok_unparse (op),
10472 exprNode_unparse (e2)),
10477 if (!ctype_isNumeric (tr2))
10481 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10482 lltok_unparse (op), te2,
10483 exprNode_unparse (e1), lltok_unparse (op),
10484 exprNode_unparse (e2)),
10489 ret = ctype_unknown;
10497 abstractOpError (ctype tr1, ctype tr2, lltok op,
10498 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10499 fileloc loc1, fileloc loc2)
10501 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10503 if (ctype_match (tr1, tr2))
10507 message ("Operands of %s are abstract type (%t): %s %s %s",
10508 lltok_unparse (op), tr1,
10509 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10516 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10517 lltok_unparse (op), tr1, tr2,
10518 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10522 else if (ctype_isRealAbstract (tr1))
10526 message ("Left operand of %s is abstract type (%t): %s %s %s",
10527 lltok_unparse (op), tr1,
10528 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10533 if (ctype_isRealAbstract (tr2))
10537 message ("Right operand of %s is abstract type (%t): %s %s %s",
10538 lltok_unparse (op), tr2,
10539 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10548 ** requies e1 and e2 and not error exprNode's.
10552 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10553 ** the rep of the abstract type is exposed.
10555 ** The order is very important:
10557 ** check rep expose (move into check transfer)
10563 ** This isn't really a sensible procedure, but the indententation
10564 ** was getting too deep.
10568 checkOneRepExpose (sRef ysr, sRef base,
10569 /*@notnull@*/ exprNode e1,
10570 /*@notnull@*/ exprNode e2, ctype ct,
10573 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
10574 || sRef_isOwned (ysr)
10575 || sRef_isExposed (ysr)))
10577 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10578 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10581 if (sRef_isIReference (ysr))
10583 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10588 ("Assignment of mutable component of parameter %q "
10589 "to component of abstract "
10590 "type %s exposes rep: %s = %s",
10591 sRef_unparse (base),
10592 ctype_unparse (ct),
10593 exprNode_unparse (e1), exprNode_unparse (e2)),
10601 ("Assignment of mutable component of parameter %q "
10602 "(through alias %q) to component of abstract "
10603 "type %s exposes rep: %s = %s",
10604 sRef_unparse (base),
10605 sRef_unparse (e2->sref),
10606 ctype_unparse (ct),
10607 exprNode_unparse (e1), exprNode_unparse (e2)),
10613 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10617 message ("Assignment of mutable parameter %q "
10618 "to component of abstract type %s "
10619 "exposes rep: %s = %s",
10620 sRef_unparse (base),
10621 ctype_unparse (ct),
10622 exprNode_unparse (e1),
10623 exprNode_unparse (e2)),
10630 message ("Assignment of mutable parameter %q "
10631 "(through alias %q) to "
10632 "component of abstract type %s exposes "
10634 sRef_unparse (base),
10635 sRef_unparse (e2->sref),
10636 ctype_unparse (ct),
10637 exprNode_unparse (e1),
10638 exprNode_unparse (e2)),
10644 if (sRef_isFileOrGlobalScope (s2b))
10646 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10650 message ("Assignment of global %q "
10652 "abstract type %s exposes rep: %s = %s",
10653 sRef_unparse (base),
10654 ctype_unparse (ct),
10655 exprNode_unparse (e1), exprNode_unparse (e2)),
10662 message ("Assignment of global %q (through alias %q) "
10664 "abstract type %s exposes rep: %s = %s",
10665 sRef_unparse (base),
10666 sRef_unparse (e2->sref),
10667 ctype_unparse (ct),
10668 exprNode_unparse (e1), exprNode_unparse (e2)),
10676 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
10678 DPRINTF (("Do assign: %s <- %s",
10679 exprNode_unparse (e1), exprNode_unparse (e2)));
10680 DPRINTF (("Ctype: %s", ctype_unparse (exprNode_getType (e1))));
10682 if (ctype_isRealFunction (exprNode_getType (e1))
10683 && !ctype_isRealPointer (exprNode_getType (e1)))
10687 message ("Invalid left-hand side of assignment (function type %s): %s",
10688 ctype_unparse (exprNode_getType (e1)),
10689 exprNode_unparse (e1)),
10693 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
10695 ctype t2 = exprNode_getType (e2);
10696 sRef sr = sRef_getRootBase (e1->sref);
10697 ctype ct = sRef_getType (sr);
10699 if (ctype_isAbstract (t2)
10700 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
10702 /* it is immutable, okay to reference */
10703 goto donerepexpose;
10706 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
10708 sRef s2b = sRef_getRootBase (e2->sref);
10709 sRef s1 = e1->sref;
10710 sRef s1b = sRef_getRootBase (s1);
10713 aliases = usymtab_canAlias (e2->sref);
10715 if (!sRef_similar (s2b, s1b)
10716 && !sRef_isExposed (s1)
10717 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
10719 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
10720 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
10721 && !sRef_isExposed (s2b))
10723 if (sRef_isIReference (e2->sref))
10728 ("Assignment of mutable component of parameter %q "
10729 "to component of abstract type %s exposes rep: %s = %s",
10730 sRef_unparse (s2b),
10731 ctype_unparse (ct),
10732 exprNode_unparse (e1), exprNode_unparse (e2)),
10739 message ("Assignment of mutable parameter %q to "
10740 "component of abstract type %s exposes rep: %s = %s",
10741 sRef_unparse (s2b),
10742 ctype_unparse (ct),
10743 exprNode_unparse (e1), exprNode_unparse (e2)),
10748 if (sRef_isFileOrGlobalScope (s2b))
10752 message ("Assignment of global %q to component of "
10753 "abstract type %s exposes rep: %s = %s",
10754 sRef_unparse (s2b),
10755 ctype_unparse (ct),
10756 exprNode_unparse (e1), exprNode_unparse (e2)),
10760 sRefSet_realElements (aliases, ysr)
10762 sRef base = sRef_getRootBase (ysr);
10764 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
10765 || sRef_sameName (base, s1b))
10767 ; /* error already reported or same sref */
10771 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
10773 } end_sRefSet_realElements;
10775 sRefSet_free (aliases);
10782 ** function variables don't really work...
10785 if (!ctype_isFunction (ctype_realType (e2->typ)))
10789 DPRINTF (("Check init: %s / %s",
10790 exprNode_unparse (e1), exprNode_unparse (e2)));
10791 checkInitTransfer (e1, e2);
10795 checkAssignTransfer (e1, e2);
10800 sRef fref = e2->sref;
10802 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
10803 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
10805 /* Need to typecheck the annotation on the parameters */
10807 if (ctype_isRealFunction (e1->typ)) {
10808 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
10809 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
10811 if (!uentryList_isMissingParams (e1p)
10812 && !uentryList_isMissingParams (e2p)
10813 && uentryList_size (e1p) > 0) {
10814 if (uentryList_size (e1p) == uentryList_size (e2p)) {
10817 uentryList_elements (e1p, el1) {
10820 el2 = uentryList_getN (e2p, n);
10822 uentry_checkMatchParam (el1, el2, n, e2);
10823 } end_uentryList_elements;
10829 if (exprNode_isStringLiteral (e2))
10831 exprNode_checkStringLiteralLength (exprNode_getType (e1), e2);
10834 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
10840 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
10841 updateAliases (e1, e2);
10846 checkMacroParen (exprNode e)
10848 if (exprNode_isError (e) || e->kind == XPR_CAST)
10854 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
10858 message ("Macro parameter used without parentheses: %s",
10859 exprNode_unparse (e)),
10866 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
10870 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
10874 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
10881 ** if e2 is a parameter or global derived location which
10882 ** can be modified (that is, e2 is a mutable abstract type,
10883 ** or a derived pointer), then e1 can alias e2.
10885 ** e1 can alias everything which e2 can alias.
10887 ** Also, if e1 is guarded, remove from guard sets!
10890 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
10892 if (!context_inProtectVars ())
10895 ** depends on types of e1 and e2
10898 sRef s1 = e1->sref;
10899 sRef s2 = e2->sref;
10900 ctype t1 = exprNode_getType (e1);
10902 /* handle pointer sRefs, record fields, arrays, etc... */
10904 if (!ctype_isRealSU (t1))
10906 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
10907 sRef_copyRealDerivedComplete (s1, s2);
10912 ** Fields should alias
10915 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
10918 if (ctype_isMutable (t1) && sRef_isKnown (s1))
10920 usymtab_clearAlias (s1);
10921 usymtab_addMustAlias (s1, s2);
10922 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
10926 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
10929 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
10931 usymtab_unguard (s1);
10936 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
10938 if (exprNode_isDefined (e))
10940 e->loc = fileloc_update (e->loc, loc);
10944 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
10950 static void checkUniqueParams (exprNode fcn,
10951 /*@notnull@*/ exprNode current,
10953 int paramno, uentry ucurrent)
10956 sRef thisref = exprNode_getSref (current);
10959 ** Check if any argument could match this argument.
10962 exprNodeList_elements (args, icurrent)
10966 if (iparamno != paramno)
10968 sRef sr = exprNode_getSref (icurrent);
10970 if (sRef_similarRelaxed (thisref, sr))
10972 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
10977 ("Parameter %d (%s) to function %s is declared %s but "
10978 "is aliased by parameter %d (%s)",
10980 exprNode_unparse (current),
10981 exprNode_unparse (fcn),
10982 alkind_unparse (uentry_getAliasKind (ucurrent)),
10983 iparamno, exprNode_unparse (icurrent)),
10989 sRefSet aliases = usymtab_canAlias (sr);
10991 sRefSet_allElements (aliases, asr)
10993 if (ctype_isUnknown (sRef_getType (thisref)))
10995 sRef_setType (thisref, uentry_getType (ucurrent));
10998 if (sRef_similarRelaxed (thisref, asr))
11000 if (sRef_isExternal (asr))
11002 if (sRef_isLocalState (thisref))
11008 sRef base = sRef_getRootBase (asr);
11010 if (!sRef_similar (sRef_getBase (asr), thisref))
11012 if (sRef_isUnique (base) || sRef_isOnly (base)
11013 || sRef_isKept (base)
11014 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
11015 || (sRef_isAddress (thisref)
11016 && sRef_isLocalVar (sRef_getRootBase (thisref))))
11018 ; /* okay, no error */
11023 (FLG_MAYALIASUNIQUE,
11025 ("Parameter %d (%s) to function %s is declared %s but "
11026 "may be aliased externally by parameter %d (%s)",
11028 exprNode_unparse (current),
11029 exprNode_unparse (fcn),
11030 alkind_unparse (uentry_getAliasKind (ucurrent)),
11031 iparamno, exprNode_unparse (icurrent)),
11042 ("Parameter %d (%s) to function %s is declared %s but "
11043 "is aliased externally by parameter %d (%s) through "
11046 exprNode_unparse (current),
11047 exprNode_unparse (fcn),
11048 alkind_unparse (uentry_getAliasKind (ucurrent)),
11049 iparamno, exprNode_unparse (icurrent),
11050 sRef_unparse (asr)),
11054 } end_sRefSet_allElements;
11055 sRefSet_free (aliases);
11058 } end_exprNodeList_elements;
11061 long exprNode_getLongValue (exprNode e) {
11064 if (exprNode_hasValue (e)
11065 && multiVal_isInt (exprNode_getValue (e)))
11067 value = multiVal_forceInt (exprNode_getValue (e));
11078 /*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
11080 if (exprNode_isDefined (p_e) )
11081 return ( p_e->loc );
11083 return fileloc_undefined;
11086 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
11089 ** Returns the location of the sequence point following e.
11091 ** Only works for statements (for now).
11094 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
11095 lltok t = exprData_getUopTok (e->edata);
11096 return fileloc_copy(lltok_getLoc (t));
11098 /* drl possible problem : warning fix
11099 llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
11101 return fileloc_undefined;
11105 exprNode exprNode_createNew(ctype c)
11109 ret = exprNode_createPlain (c);
11114 bool exprNode_isInitBlock (exprNode e)
11116 return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);