2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
28 # include <ctype.h> /* for isdigit */
29 # include "splintMacros.nf"
31 # include "cgrammar.h"
32 # include "cgrammar_tokens.h"
34 # include "exprChecks.h"
35 # include "transferChecks.h"
36 # include "exprNodeSList.h"
38 static bool exprNode_sameStorage (exprNode p_e1, exprNode p_e2) /*@*/ ;
39 static bool exprNode_isEmptyStatement (exprNode p_e);
40 static /*@exposed@*/ exprNode exprNode_firstStatement (/*@returned@*/ exprNode p_e);
41 static bool exprNode_isFalseConstant (exprNode p_e) /*@*/ ;
42 static bool exprNode_isStatement (exprNode p_e);
43 static void checkGlobUse (uentry p_glob, bool p_isCall, /*@notnull@*/ exprNode p_e);
44 static void exprNode_addUse (exprNode p_e, /*@exposed@*/ sRef p_s);
45 static bool exprNode_matchArgType (ctype p_ct, exprNode p_e);
46 static exprNode exprNode_fakeCopy (exprNode p_e) /*@*/ ;
47 static exprNode exprNode_statementError (/*@only@*/ exprNode p_e, /*@only@*/ lltok p_t);
48 static bool exprNode_matchTypes (exprNode p_e1, exprNode p_e2);
49 static void checkUniqueParams (exprNode p_fcn,
50 /*@notnull@*/ exprNode p_current, exprNodeList p_args,
51 int p_paramno, uentry p_ucurrent);
52 static void updateAliases (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2);
53 static void abstractOpError (ctype p_tr1, ctype p_tr2, lltok p_op,
54 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2,
55 fileloc p_loc1, fileloc p_loc2);
56 static ctype checkNumerics (ctype p_tr1, ctype p_tr2, ctype p_te1, ctype p_te2,
57 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, lltok p_op);
58 static void doAssign (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, bool p_isInit);
59 static void checkSafeUse (exprNode p_e, /*@exposed@*/ sRef p_s);
60 static void reflectNullTest (/*@notnull@*/ exprNode p_e, bool p_isnull);
61 static void checkMacroParen (exprNode p_e);
62 static exprNodeSList exprNode_flatten (/*@dependent@*/ exprNode p_e);
63 static void exprNode_checkSetAny (exprNode p_e, /*@dependent@*/ cstring p_name);
64 static void exprNode_checkUse (exprNode p_e, /*@exposed@*/ sRef p_s, fileloc p_loc);
65 static void exprNode_mergeUSs (exprNode p_res, exprNode p_other);
66 static void exprNode_mergeCondUSs (exprNode p_res, exprNode p_other1, exprNode p_other2);
67 static /*@only@*/ /*@notnull@*/ exprNode exprNode_fromIdentifierAux (/*@observer@*/ uentry p_c);
68 static void checkAnyCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn,
69 /*@dependent@*/ cstring p_fname,
70 uentryList p_pn, exprNodeList p_args,
71 bool p_hasMods, sRefSet p_mods, bool p_isSpec,
73 static void checkOneArg (uentry p_ucurrent, /*@notnull@*/ exprNode p_current,
74 /*@dependent@*/ exprNode p_fcn, bool p_isSpec, int p_argno, int p_totargs);
76 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn, uentryList p_params, exprNodeList p_args);
78 static /*@only@*/ exprNode exprNode_effect (exprNode p_e)
79 /*@globals internalState@*/ ;
80 static /*@only@*/ cstring exprNode_doUnparse (exprNode p_e);
81 static /*@observer@*/ cstring exprNode_rootVarName (exprNode p_e);
82 static /*@exposed@*/ exprNode
83 exprNode_lastStatement (/*@returned@*/ exprNode p_e);
85 static /*@only@*/ exprNode s_mustExitNode = exprNode_undefined;
87 static int checkArgsReal (uentry p_fcn, /*@dependent@*/ exprNode p_f,
89 exprNodeList p_args, bool p_isIter, exprNode p_ret);
91 static bool inEffect = FALSE;
92 static int nowalloc = 0;
93 static int totalloc = 0;
94 static int maxalloc = 0;
96 static /*@only@*/ uentry regArg;
97 static /*@only@*/ uentry outArg;
98 static /*@only@*/ uentry outStringArg;
99 static /*@exposed@*/ sRef stdinRef;
100 static /*@exposed@*/ sRef stdoutRef;
101 static /*@only@*/ uentry csArg;
102 static /*@only@*/ uentry csOnlyArg;
103 static ctype cstringType;
104 static ctype ctypeType;
105 static ctype filelocType;
106 static bool initMod = FALSE;
108 /*@function void exprNode_swap (sef exprNode, sef exprNode)@*/
110 # define exprNode_swap(e1,e2) do { exprNode m_tmp = (e1); (e1) = (e2); (e2) = m_tmp; } while (FALSE)
113 static void exprNode_defineConstraints(/*@sef@*/ /*@special@*/ /*@notnull@*/ exprNode e)
114 /*@defines e->requiresConstraints, e->ensuresConstraints,
115 e->trueEnsuresConstraints, e->falseEnsuresConstraints @*/
117 e->requiresConstraints = constraintList_makeNew ();
118 e->ensuresConstraints = constraintList_makeNew ();
119 e->trueEnsuresConstraints = constraintList_makeNew ();
120 e->falseEnsuresConstraints = constraintList_makeNew ();
124 ** must occur after library has been read
127 void exprNode_initMod (void)
128 /*@globals undef regArg, undef outArg, undef outStringArg,
129 undef csOnlyArg, undef csArg;
136 cstringType = ctype_unknown;
137 ctypeType = ctype_unknown;
138 filelocType = ctype_unknown;
140 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
142 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
145 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
147 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
150 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
152 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
155 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdin")))
157 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdin"));
159 else /* define stdin */
161 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdin"),
163 fileloc_getBuiltin (),
165 uentry_setHasNameError (ue);
166 ue = usymtab_supGlobalEntryReturn (ue);
169 stdinRef = sRef_makePointer (uentry_getSref (ue));
171 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdout")))
173 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdout"));
177 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdout"),
179 fileloc_getBuiltin (),
181 uentry_setHasNameError (ue);
182 ue = usymtab_supGlobalEntryReturn (ue);
185 stdoutRef = sRef_makePointer (uentry_getSref (ue));
187 tmp = idDecl_create (cstring_undefined, qtype_create (ctype_unknown));
189 regArg = uentry_makeParam (tmp, PARAMUNKNOWN);
192 qtype_addQual (qtype_create (ctype_makePointer (ctype_unknown)),
195 outArg = uentry_makeParam (tmp, PARAMUNKNOWN);
197 idDecl_setTyp (tmp, qtype_addQual (qtype_create (ctype_string),
200 outStringArg = uentry_makeParam (tmp, PARAMUNKNOWN);
202 idDecl_setTyp (tmp, qtype_addQual (qtype_addQual (qtype_create (cstringType),
204 qual_createNull ()));
206 csOnlyArg = uentry_makeParam (tmp, PARAMUNKNOWN);
208 idDecl_setTyp (tmp, qtype_addQual (qtype_create (cstringType), qual_createNull ()));
209 csArg = uentry_makeParam (tmp, PARAMUNKNOWN);
215 exprNode_destroyMod (void)
216 /*@globals killed regArg, killed outArg, killed outStringArg,
217 killed s_mustExitNode, initMod @*/
221 uentry_free (regArg);
222 uentry_free (outArg);
223 uentry_free (outStringArg);
225 exprNode_free (s_mustExitNode);
232 static void exprNode_resetSref (/*@notnull@*/ exprNode e)
234 e->sref = sRef_undefined;
237 exprNode exprNode_fakeCopy (exprNode e)
239 /*@-temptrans@*/ /*@-retalias@*/
241 /*@=temptrans@*/ /*@=retalias@*/
244 static bool isFlagKey (char key)
246 return (key == '-' || key == '+' || key == ' ' || key == '#');
249 static void exprNode_combineControl (/*@notnull@*/ exprNode ret,
250 /*@notnull@*/ exprNode ifclause,
251 /*@notnull@*/ exprNode elseclause)
253 ret->canBreak = ifclause->canBreak || elseclause->canBreak;
256 (ifclause->mustBreak || exprNode_mustEscape (ifclause))
257 && (elseclause->mustBreak || exprNode_mustEscape (elseclause));
259 ret->exitCode = exitkind_combine (ifclause->exitCode,
260 elseclause->exitCode);
265 ** For exprNode's returned by exprNode_effect.
268 static bool shallowKind (exprKind kind)
270 return (kind == XPR_STRINGLITERAL
271 || kind == XPR_NUMLIT
274 || kind == XPR_NODE);
278 exprNode_freeIniter (/*@only@*/ exprNode e)
280 if (!exprNode_isError (e))
286 ** Its a fake copy, don't free the field->rec and field->field
291 sfree (e->edata->field);
297 exprNode_free (e->edata->op->b);
298 /*@-compdestroy@*/ sfree (e->edata->op); /*@=compdestroy@*/
302 llbug (message ("other: %s", exprNode_unparse (e)));
305 multiVal_free (e->val);
306 cstring_free (e->etext);
307 fileloc_free (e->loc);
308 sRefSet_free (e->uses);
309 sRefSet_free (e->sets);
310 sRefSet_free (e->msets);
311 guardSet_free (e->guards);
313 constraintList_free(e->requiresConstraints);
314 constraintList_free(e->ensuresConstraints);
315 constraintList_free(e->trueEnsuresConstraints);
316 constraintList_free(e->falseEnsuresConstraints);
318 e->requiresConstraints = NULL;
319 e->ensuresConstraints = NULL;
320 e->trueEnsuresConstraints = NULL;
321 e->falseEnsuresConstraints = NULL;
328 exprNode_freeShallow (/*@only@*/ exprNode e)
330 if (!exprNode_isError (e))
332 if (shallowKind (e->kind))
339 if (e->kind == XPR_EMPTY
340 || e->kind == XPR_BODY
341 || e->kind == XPR_STRINGLITERAL
342 || e->kind == XPR_NUMLIT
343 || e->kind == XPR_NODE
344 || e->kind == XPR_OFFSETOF
345 || e->kind == XPR_ALIGNOFT
346 || e->kind == XPR_ALIGNOF
347 || e->kind == XPR_SIZEOFT
348 || e->kind == XPR_SIZEOF)
350 /* don't free anything */
354 /* multiVal_free (e->val); */
355 cstring_free (e->etext);
356 fileloc_free (e->loc);
357 sRefSet_free (e->uses);
358 sRefSet_free (e->sets);
359 sRefSet_free (e->msets);
360 guardSet_free (e->guards);
361 exprData_freeShallow (e->edata, e->kind);
363 /*@-compdestroy@*/ sfree (e); /*@=compdestroy@*/
372 exprNode_free (exprNode e)
374 if (!exprNode_isError (e))
378 multiVal_free (e->val);
379 cstring_free (e->etext);
380 fileloc_free (e->loc);
381 sRefSet_free (e->uses);
382 sRefSet_free (e->sets);
383 sRefSet_free (e->msets);
384 guardSet_free (e->guards);
385 exprData_free (e->edata, e->kind);
387 constraintList_free(e->requiresConstraints);
388 constraintList_free(e->ensuresConstraints);
389 constraintList_free(e->trueEnsuresConstraints);
390 constraintList_free(e->falseEnsuresConstraints);
392 e->requiresConstraints = NULL;
393 e->ensuresConstraints = NULL;
394 e->trueEnsuresConstraints = NULL;
395 e->falseEnsuresConstraints = NULL;
405 exprNode_makeError ()
407 return exprNode_undefined;
410 static /*@out@*/ /*@only@*/ /*@notnull@*/ exprNode
413 exprNode ret = (exprNode) dmalloc (sizeof (*ret));
414 /* static int lastexpnodes = 0; */
419 if (nowalloc > maxalloc)
427 static /*@notnull@*/ /*@special@*/ exprNode
428 exprNode_createPlain (ctype c)
430 /*@ensures isnull result->edata, result->loc, result->val, result->guards,
431 result->uses, result->sets, result->msets, result->etext @*/
434 exprNode e = exprNode_new ();
438 e->val = multiVal_undefined;
439 e->sref = sRef_undefined;
440 e->etext = cstring_undefined;
441 e->loc = fileloc_undefined;
442 e->guards = guardSet_undefined;
443 e->uses = sRefSet_undefined;
444 e->sets = sRefSet_undefined;
445 e->msets = sRefSet_undefined;
446 e->edata = exprData_undefined;
447 e->exitCode = XK_NEVERESCAPE;
449 e->mustBreak = FALSE;
450 e->isJumpPoint = FALSE;
452 exprNode_defineConstraints(e);
457 /*@observer@*/ exprNode exprNode_makeMustExit (void)
459 if (exprNode_isUndefined (s_mustExitNode))
461 s_mustExitNode = exprNode_createPlain (ctype_unknown);
462 s_mustExitNode->exitCode = XK_MUSTEXIT;
465 return s_mustExitNode;
469 static /*@notnull@*/ /*@special@*/ exprNode exprNode_create (ctype c)
471 /*@post:isnull result->edata, result->guards, result->val,
472 result->uses, result->sets, result->msets@*/
475 exprNode e = exprNode_createPlain (c);
476 e->loc = fileloc_copy (g_currentloc);
480 static /*@notnull@*/ /*@special@*/ exprNode exprNode_createUnknown (void)
482 /*@post:isnull result->edata, result->guards,
483 result->uses, result->sets, result->msets@*/
486 return (exprNode_create (ctype_unknown));
489 static /*@notnull@*/ /*@special@*/ exprNode
490 exprNode_createLoc (ctype c, /*@keep@*/ fileloc loc)
492 /*@post:isnull result->edata, result->guards, result->val,
493 result->uses, result->sets, result->msets@*/
496 exprNode e = exprNode_createPlain (c);
502 exprNode_copySets (/*@special@*/ /*@notnull@*/ exprNode ret, exprNode e)
503 /*@defines ret->guards, ret->uses, ret->sets, ret->msets@*/
505 if (exprNode_isDefined (e))
507 ret->guards = guardSet_copy (e->guards);
508 ret->uses = sRefSet_newCopy (e->uses);
509 ret->sets = sRefSet_newCopy (e->sets);
510 ret->msets = sRefSet_newCopy (e->msets);
514 ret->guards = guardSet_undefined;
515 ret->uses = sRefSet_undefined;
516 ret->sets = sRefSet_undefined;
517 ret->msets = sRefSet_undefined;
521 static /*@notnull@*/ /*@special@*/ exprNode
522 exprNode_createPartialLocCopy (exprNode e, /*@only@*/ fileloc loc)
524 /*@post:isnull result->edata, result->etext@*/
527 exprNode ret = exprNode_new ();
529 if (exprNode_isError (e))
531 ret->typ = ctype_unknown;
532 ret->val = multiVal_undefined;
534 ret->guards = guardSet_undefined;
535 ret->uses = sRefSet_undefined;
536 ret->sets = sRefSet_undefined;
537 ret->msets = sRefSet_undefined;
542 ret->val = multiVal_copy (e->val);
544 ret->guards = guardSet_copy (e->guards);
545 ret->uses = sRefSet_newCopy (e->uses);
546 ret->sets = sRefSet_newCopy (e->sets);
547 ret->msets = sRefSet_newCopy (e->msets);
550 ret->kind = XPR_EMPTY;
551 ret->sref = sRef_undefined;
552 ret->etext = cstring_undefined;
553 ret->exitCode = XK_NEVERESCAPE;
554 ret->canBreak = FALSE;
555 ret->mustBreak = FALSE;
556 ret->isJumpPoint = FALSE;
557 ret->edata = exprData_undefined;
559 exprNode_defineConstraints(ret);
565 static /*@notnull@*/ /*@special@*/ exprNode
566 exprNode_createPartialCopy (exprNode e)
568 /*@post:isnull result->edata, result->etext@*/
571 return (exprNode_createPartialLocCopy (e, fileloc_copy (exprNode_loc (e))));
574 static /*@notnull@*/ /*@special@*/ exprNode
575 exprNode_createPartialNVCopy (exprNode e)
577 /*@post:isnull result->edata, result->etext, result->val @*/
580 exprNode ret = exprNode_new ();
582 if (exprNode_isError (e))
584 ret->typ = ctype_unknown;
585 ret->loc = fileloc_undefined;
586 ret->guards = guardSet_undefined;
587 ret->uses = sRefSet_undefined;
588 ret->sets = sRefSet_undefined;
589 ret->msets = sRefSet_undefined;
594 ret->loc = fileloc_copy (e->loc);
595 ret->guards = guardSet_copy (e->guards);
596 ret->uses = sRefSet_newCopy (e->uses);
597 ret->sets = sRefSet_newCopy (e->sets);
598 ret->msets = sRefSet_newCopy (e->msets);
601 ret->val = multiVal_undefined;
602 ret->kind = XPR_EMPTY;
603 ret->sref = sRef_undefined;
604 ret->etext = cstring_undefined;
605 ret->exitCode = XK_NEVERESCAPE;
606 ret->canBreak = FALSE;
607 ret->mustBreak = FALSE;
608 ret->isJumpPoint = FALSE;
609 ret->edata = exprData_undefined;
611 exprNode_defineConstraints(ret);
616 static /*@notnull@*/ /*@special@*/ exprNode
617 exprNode_createSemiCopy (exprNode e)
619 /*@post:isnull result->edata, result->etext, result->sets,
620 result->msets, result->uses, result->guards@*/
623 if (exprNode_isError (e))
625 return exprNode_createPlain (ctype_unknown);
629 exprNode ret = exprNode_new ();
632 ret->val = multiVal_copy (e->val);
633 ret->loc = fileloc_copy (e->loc);
634 ret->guards = guardSet_undefined;
635 ret->uses = sRefSet_undefined;
636 ret->sets = sRefSet_undefined;
637 ret->msets = sRefSet_undefined;
639 ret->kind = XPR_EMPTY;
640 ret->sref = sRef_undefined;
641 ret->etext = cstring_undefined;
642 ret->exitCode = XK_NEVERESCAPE;
643 ret->canBreak = FALSE;
644 ret->mustBreak = FALSE;
645 ret->isJumpPoint = FALSE;
646 ret->edata = exprData_undefined;
648 exprNode_defineConstraints(ret);
655 exprNode_isNullValue (exprNode e)
657 if (exprNode_isDefined (e))
659 multiVal m = exprNode_getValue (e);
661 if (multiVal_isInt (m))
663 return (multiVal_forceInt (m) == 0);
671 exprNode_isUnknownConstant (/*@notnull@*/ exprNode e)
673 while (e->kind == XPR_PARENS)
675 e = exprData_getUopNode (e->edata);
677 if (!exprNode_isDefined (e))
682 /* evans 2002-02-05: was llassert (exprNode_isDefined (e)); but this can fail */
685 if (e->kind == XPR_CONST)
687 multiVal m = exprNode_getValue (e);
689 if (multiVal_isUnknown (m))
699 exprNode_numLiteral (ctype c, /*@temp@*/ cstring t,
700 /*@only@*/ fileloc loc, long val)
702 exprNode e = exprNode_createLoc (c, loc);
704 e->kind = XPR_NUMLIT;
706 llassert (multiVal_isUndefined (e->val));
707 e->val = multiVal_makeInt (val);
708 e->edata = exprData_makeLiteral (cstring_copy (t));
712 e->sref = sRef_makeUnknown ();
713 sRef_setDefNull (e->sref, e->loc);
716 DPRINTF (("Num lit: %s / %s", exprNode_unparse (e), ctype_unparse (exprNode_getType (e))));
721 exprNode_charLiteral (char c, cstring text, /*@only@*/ fileloc loc)
723 exprNode e = exprNode_createLoc (ctype_char, loc);
725 if (context_getFlag (FLG_CHARINTLITERAL))
727 e->typ = ctype_makeConj (ctype_char, ctype_int);
730 e->kind = XPR_NUMLIT;
731 e->val = multiVal_makeChar (c);
733 e->edata = exprData_makeLiteral (cstring_copy (text));
738 exprNode_floatLiteral (double d, ctype ct, cstring text, /*@only@*/ fileloc loc)
740 exprNode e = exprNode_createLoc (ct, loc);
742 e->kind = XPR_NUMLIT;
743 e->val = multiVal_makeDouble (d);
744 e->edata = exprData_makeLiteral (cstring_copy (text));
748 multiVal exprNode_getValue (exprNode e)
750 while (exprNode_isInParens (e)) {
751 if (e->edata != NULL) {
752 e = exprData_getUopNode (e->edata);
758 if (exprNode_isDefined (e)) {
761 return multiVal_undefined;
766 exprNode_combineLiterals (exprNode e, exprNode rest)
770 /* Both must be string literals. */
772 if (exprNode_isUndefined (rest) || exprNode_isUndefined (e))
774 exprNode_free (rest);
778 if (!exprNode_isStringLiteral (e))
782 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e),
783 exprNode_unparse (rest)),
785 exprNode_free (rest);
789 if (!exprNode_isStringLiteral (rest))
793 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e), exprNode_unparse (rest)),
796 exprNode_free (rest);
800 ns = cstring_concat (multiVal_forceString (exprNode_getValue (e)),
801 multiVal_forceString (exprNode_getValue (rest)));
803 multiVal_free (e->val);
804 exprData_free (e->edata, e->kind);
805 e->edata = exprData_makeLiteral (cstring_copy (ns));
806 e->val = multiVal_makeString (ns);
807 exprNode_free (rest);
812 exprNode_rawStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
814 exprNode e = exprNode_createLoc (ctype_string, loc);
815 size_t len = cstring_length (t);
817 if (context_getFlag (FLG_STRINGLITERALLEN))
819 if (len > size_fromInt (context_getValue (FLG_STRINGLITERALLEN)))
821 voptgenerror (FLG_STRINGLITERALLEN,
823 ("String literal length (%d) exceeds maximum "
824 "length (%d): \"%s\"",
826 context_getValue (FLG_STRINGLITERALLEN),
832 e->kind = XPR_STRINGLITERAL;
833 e->val = multiVal_makeString (cstring_copy (t));
834 e->edata = exprData_makeLiteral (t);
835 e->sref = sRef_makeConst (ctype_string);
837 if (context_getFlag (FLG_READONLYSTRINGS))
839 sRef_setAliasKind (e->sref, AK_STATIC, fileloc_undefined);
840 sRef_setExKind (e->sref, XO_OBSERVER, loc);
844 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
847 return (e); /* s released */
851 exprNode_wideStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
853 exprNode res = exprNode_stringLiteral (t, loc);
854 res->typ = ctype_makeWideString ();
859 exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
861 size_t len = size_fromInt (cstring_length (t) - 2);
862 char *ts = cstring_toCharsSafe (t);
863 char *s = cstring_toCharsSafe (cstring_create (len + 1));
865 llassert (*ts == '\"' && *(ts + len + 1) == '\"');
866 strncpy (s, ts+1, len);
869 return exprNode_rawStringLiteral (cstring_fromCharsO (s), loc);
872 exprNode exprNode_fromUIO (cstring c)
874 fileloc loc = context_getSaveLocation ();
875 exprNode e = exprNode_createPlain (ctype_unknown);
879 if (fileloc_isUndefined (loc))
881 loc = fileloc_copy (g_currentloc);
884 e->loc = loc; /* save loc was mangled */
885 e->sref = sRef_undefined;
887 if (usymtab_exists (c))
889 uentry ue = usymtab_lookupEither (c);
891 if (uentry_isDatatype (ue)
892 && uentry_isSpecified (ue))
895 (message ("%q: Specified datatype %s used in code, but not defined. "
896 "(Cannot continue reasonably from this error.)",
897 fileloc_unparse (e->loc), c));
905 llassertprint (!usymtab_exists (c), ("Entry exists: %s", c));
908 ** was supercedeGlobalEntry...is this better?
911 if (!context_inIterEnd ())
913 if (context_inMacro ())
915 if (context_getFlag (FLG_UNRECOG))
919 message ("Unrecognized identifier in macro definition: %s", c), e->loc);
923 flagcode_recordSuppressed (FLG_UNRECOG);
929 (FLG_UNRECOG, message ("Unrecognized identifier: %s", c), e->loc);
933 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
935 /* No alias errors for unrecognized identifiers */
936 sRef_setAliasKind (e->sref, AK_ERROR, loc);
941 exprNode exprNode_makeConstantString (cstring c, /*@only@*/ fileloc loc)
943 exprNode e = exprNode_createPlain (ctype_unknown);
946 e->sref = sRef_makeConst (ctype_string);
947 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
948 e->typ = ctype_string;
950 /* No alias errors for unrecognized identifiers */
951 sRef_setAliasKind (e->sref, AK_STATIC, loc);
952 sRef_setExKind (e->sref, XO_OBSERVER, loc);
957 exprNode exprNode_createId (/*@observer@*/ uentry c)
959 if (uentry_isValid (c))
961 exprNode e = exprNode_new ();
963 DPRINTF (("create id: %s", uentry_unparse (c)));
965 e->typ = uentry_getType (c);
967 if (uentry_isFunction (c)
968 && !sRef_isLocalVar (uentry_getSref (c)))
970 e->sref = sRef_undefined;
974 e->sref = uentry_getSref (c);
977 if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
979 sRef_setDefined (e->sref, fileloc_undefined);
983 ** yoikes! leaving this out was a heinous bug...that would have been
984 ** caught if i had splint working first. gag!
987 e->etext = cstring_undefined;
989 if (uentry_isEitherConstant (c))
992 e->val = multiVal_copy (uentry_getConstantValue (c));
997 e->val = multiVal_unknown ();
1000 e->edata = exprData_makeId (c);
1001 e->loc = context_getSaveLocation ();
1003 if (fileloc_isUndefined (e->loc))
1005 fileloc_free (e->loc);
1006 e->loc = fileloc_copy (g_currentloc);
1009 e->guards = guardSet_new ();
1010 e->sets = sRefSet_new ();
1011 e->msets = sRefSet_new ();
1012 e->uses = sRefSet_new ();
1014 /*> missing fields, detected by splint <*/
1015 e->exitCode = XK_NEVERESCAPE;
1016 e->isJumpPoint = FALSE;
1017 e->canBreak = FALSE;
1018 e->mustBreak = FALSE;
1020 exprNode_defineConstraints (e);
1025 return exprNode_createUnknown ();
1029 /*@notnull@*/ exprNode
1030 exprNode_fromIdentifier (/*@observer@*/ uentry c)
1034 if (context_justPopped ()) /* watch out! c could be dead */
1036 uentry ce = usymtab_lookupSafe (LastIdentifier ());
1038 if (uentry_isValid (ce))
1044 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
1048 ret = exprNode_fromIdentifierAux (c);
1053 static void exprNode_checkStringLiteralLength (ctype t1, exprNode e2)
1055 multiVal mval = exprNode_getValue (e2);
1059 if (ctype_isFixedArray (t1))
1061 int nelements = long_toInt (ctype_getArraySize (t1));
1063 llassert (multiVal_isString (mval));
1064 slit = multiVal_forceString (mval);
1066 len = cstring_lengthExpandEscapes (slit);
1068 llassert (exprNode_isDefined (e2));
1070 if (len == nelements)
1074 temp = cstring_expandEscapes (slit);
1076 if (temp[len-1] == '\0')
1079 (FLG_STRINGLITNOROOMFINALNULL,
1080 message ("String literal with %d character%& "
1081 "is assigned to %s (no room for final null terminator): %s",
1084 exprNode_unparse (e2)),
1090 (FLG_STRINGLITNOROOM,
1091 message ("String literal with %d character%& "
1092 "is assigned to %s (no room for null terminator): %s",
1095 exprNode_unparse (e2)),
1099 else if (len > nelements)
1102 (FLG_STRINGLITTOOLONG,
1103 message ("String literal with %d character%& (counting null terminator) "
1104 "is assigned to %s (insufficient storage available): %s",
1107 exprNode_unparse (e2)),
1110 else if (len < nelements - 1)
1113 (FLG_STRINGLITSMALLER,
1114 message ("String literal with %d character%& is assigned to %s (possible waste of storage): %s",
1117 exprNode_unparse (e2)),
1127 static /*@only@*/ /*@notnull@*/ exprNode
1128 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
1130 exprNode e = exprNode_createId (c);
1133 uentry_setUsed (c, e->loc);
1135 if (uentry_isVar (c) && sRef_isFileOrGlobalScope (sr))
1137 checkGlobUse (c, FALSE, e);
1144 exprNode_isZero (exprNode e)
1146 if (exprNode_isDefined (e))
1148 multiVal m = exprNode_getValue (e);
1150 if (multiVal_isInt (m))
1152 return (multiVal_forceInt (m) == 0);
1160 exprNode_isNonNegative (exprNode e)
1162 if (exprNode_isDefined (e))
1164 multiVal m = exprNode_getValue (e);
1166 if (multiVal_isInt (m))
1168 return (multiVal_forceInt (m) >= 0);
1172 ** This is not always true if programmer defines enum
1173 ** values, but then the constant should be known.
1176 if (ctype_isEnum (ctype_realType (e->typ)))
1186 ** a[x] - uses a but NOT a[]
1187 ** result sref = a[] (set/use in assignment)
1189 ** The syntax x[a] is also legal in C, and has the same
1190 ** semantics. If ind is an array, and arr is an int, flip
1195 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
1198 ** error in arr, error propagates (no new messages)
1199 ** error in ind, assume valid and continue
1202 DPRINTF (("Array fetch: %s / %s",
1203 exprNode_unparse (e1), exprNode_unparse (e2)));
1205 if (exprNode_isError (e1))
1208 return (exprNode_makeError ());
1214 ctype carr = exprNode_getType (e1);
1215 ctype crarr = ctype_realType (carr);
1218 ** this sets up funny aliasing, that leads to spurious
1219 ** splint errors. Hence, the i2 comments.
1222 /* evans 2001-09-09 added ctype_isKnown so there is no swap when e1 type is unknown */
1223 if (ctype_isKnown (crarr)
1224 && !ctype_isRealArray (crarr)
1225 && ctype_isRealNumeric (crarr)
1226 && !exprNode_isError (e2)
1227 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1232 carr = exprNode_getType (arr);
1233 crarr = ctype_realType (carr);
1241 DPRINTF (("arr: %s", exprNode_unparse (arr)));
1243 if (sRef_possiblyNull (arr->sref))
1245 if (!usymtab_isGuarded (arr->sref))
1247 if (optgenerror (FLG_NULLDEREF,
1248 message ("Index of %s pointer %q: %s",
1249 sRef_nullMessage (arr->sref),
1250 sRef_unparse (arr->sref),
1251 exprNode_unparse (arr)),
1254 DPRINTF (("ref: %s", sRef_unparseFull (arr->sref)));
1255 sRef_showNullInfo (arr->sref);
1257 /* suppress future messages */
1258 sRef_setNullError (arr->sref);
1263 if (exprNode_isError (ind))
1265 if ((ctype_isArrayPtr (crarr)
1266 && !ctype_isFunction (crarr))
1267 || ctype_isUnknown (carr))
1269 exprNode ret = exprNode_createPartialCopy (arr);
1271 if (ctype_isKnown (carr))
1273 ret->typ = ctype_baseArrayPtr (crarr);
1277 ret->typ = ctype_unknown;
1280 ret->sref = sRef_makeArrayFetch (arr->sref);
1282 ret->kind = XPR_FETCH;
1285 ** Because of funny aliasing (when arr and ind are
1286 ** flipped) spurious errors would be reported here.
1289 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1290 checkSafeUse (ret, arr->sref);
1295 voptgenerror (FLG_TYPE,
1296 message ("Array fetch from non-array (%t): %s[%s]", carr,
1297 exprNode_unparse (e1), exprNode_unparse (e2)),
1299 exprNode_free (arr);
1300 return (exprNode_makeError ());
1305 if (!ctype_isForceRealInt (&(ind->typ)))
1307 ctype rt = ctype_realType (ind->typ);
1309 if (ctype_isChar (rt))
1313 message ("Array fetch using non-integer, %t: %s[%s]",
1315 exprNode_unparse (e1), exprNode_unparse (e2)),
1318 else if (ctype_isEnum (rt))
1322 message ("Array fetch using non-integer, %t: %s[%s]",
1324 exprNode_unparse (e1), exprNode_unparse (e2)),
1331 message ("Array fetch using non-integer, %t: %s[%s]",
1333 exprNode_unparse (e1), exprNode_unparse (e2)),
1337 multiVal_free (ind->val);
1338 ind->val = multiVal_unknown ();
1341 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1343 exprNode ret = exprNode_createSemiCopy (arr);
1344 multiVal m = exprNode_getValue (ind);
1346 ret->typ = ctype_baseArrayPtr (crarr);
1347 ret->kind = XPR_FETCH;
1349 if (multiVal_isInt (m))
1351 int i = (int) multiVal_forceInt (m);
1353 if (sRef_isValid (arr->sref)) {
1354 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1356 ret->sref = sRef_undefined;
1361 ret->sref = sRef_makeArrayFetch (arr->sref);
1364 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1365 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1366 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1368 /* (see comment on spurious errors above) */
1369 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1371 exprNode_checkUse (ret, ind->sref, ind->loc);
1372 exprNode_checkUse (ret, arr->sref, arr->loc);
1378 if (ctype_isUnknown (carr))
1380 exprNode ret = exprNode_createPartialCopy (arr);
1382 ret->kind = XPR_FETCH;
1383 ret->typ = ctype_unknown;
1384 ret->sets = sRefSet_union (ret->sets, ind->sets);
1385 ret->msets = sRefSet_union (ret->msets, ind->msets);
1386 ret->uses = sRefSet_union (ret->uses, ind->uses);
1388 /* (see comment on spurious errors above) */
1389 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1391 exprNode_checkUse (ret, ind->sref, ind->loc);
1392 exprNode_checkUse (ret, arr->sref, arr->loc);
1399 message ("Array fetch from non-array (%t): %s[%s]", carr,
1400 exprNode_unparse (e1), exprNode_unparse (e2)),
1403 exprNode_free (arr);
1404 exprNode_free (ind);
1406 return (exprNode_makeError ());
1416 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1417 exprNodeList args, exprNode ret)
1419 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1423 ** checkPrintfArgs --- checks arguments for printf-like functions
1424 ** Arguments before ... have already been checked.
1425 ** The argument before the ... is a char *.
1426 ** argno is the format string argument.
1430 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1431 exprNodeList args, exprNode ret, int argno)
1434 ** the last argument before the elips is the format string
1439 int nargs = exprNodeList_size (args);
1440 uentryList params = uentry_getParams (fcn);
1444 ** These should be ensured by checkSpecialFunction
1447 llassert (uentryList_size (params) == argno + 1);
1448 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1450 a = exprNodeList_getN (args, argno - 1);
1451 formatloc = fileloc_copy (exprNode_loc (a));
1453 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1454 && exprNode_knownStringValue (a))
1456 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1457 char *code = format;
1460 nargs = exprNodeList_size (args);
1462 while ((code = strchr (code, '%')) != NULL)
1464 char *origcode = code;
1465 cstring codetext = cstring_newEmpty ();
1466 char key = *(++code);
1467 ctype modtype = ctype_int;
1468 bool modified = FALSE;
1470 fileloc_addColumn (formatloc, code - ocode);
1472 codetext = cstring_appendChar (codetext, key);
1475 while (isFlagKey (key))
1478 codetext = cstring_appendChar (codetext, key);
1479 fileloc_incColumn (formatloc);
1482 if (key == 'm') /* skipped in syslog */
1487 /* ignore field width */
1488 while (isdigit ((int) key) != 0)
1491 codetext = cstring_appendChar (codetext, key);
1492 fileloc_incColumn (formatloc);
1495 /* ignore precision */
1499 codetext = cstring_appendChar (codetext, key);
1500 fileloc_incColumn (formatloc);
1503 ** In printf, '*' means: read the next arg as an int for the
1504 ** field width. This seems to be missing from my copy of the
1505 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1506 ** later) but never does.
1511 ; /* don't do anything --- handle later */
1515 while (isdigit ((int) key) != 0)
1518 codetext = cstring_appendChar (codetext, key);
1519 fileloc_incColumn (formatloc);
1526 modtype = ctype_sint; /* short */
1528 codetext = cstring_appendChar (codetext, key);
1529 fileloc_incColumn (formatloc);
1531 else if (key == 'l' || key == 'L')
1533 modtype = ctype_lint; /* long */
1535 codetext = cstring_appendChar (codetext, key);
1536 fileloc_incColumn (formatloc);
1538 if (key == 'l' || key == 'L') {
1539 modtype = ctype_llint; /* long long */
1541 codetext = cstring_appendChar (codetext, key);
1542 fileloc_incColumn (formatloc);
1550 /* now, key = type of conversion to apply */
1552 fileloc_incColumn (formatloc);
1560 message ("No argument corresponding to %q format "
1561 "code %d (%%%s): \"%s\"",
1562 uentry_getName (fcn),
1564 cstring_fromChars (format)),
1567 if (fileloc_isDefined (formatloc)
1568 && context_getFlag (FLG_SHOWCOL))
1570 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1578 a = exprNodeList_getN (args, i);
1581 if (!exprNode_isError (a))
1587 case '*': /* int argument for fieldwidth */
1588 expecttype = ctype_int;
1589 *(--code) = '%'; /* convert it for next code */
1590 fileloc_subColumn (formatloc, 1);
1591 /*@switchbreak@*/ break;
1594 expecttype = ctype_combine (ctype_uint, modtype);
1595 /*@switchbreak@*/ break;
1597 case 'i': /* int argument */
1599 expecttype = ctype_combine (ctype_int, modtype);
1600 /*@switchbreak@*/ break;
1602 case 'x': /* unsigned int */
1604 expecttype = ctype_combine (ctype_uint, modtype);
1606 /*@switchbreak@*/ break;
1612 case 'f': /* double */
1613 expecttype = ctype_combine (ctype_double, modtype);
1614 /*@switchbreak@*/ break;
1616 case 'c': /* int converted to char (check its a char?) */
1617 expecttype = ctype_makeConj (ctype_int,
1618 ctype_makeConj (ctype_char,
1621 /* evans 2001-10-05 - changed to reflect correct ISO spec:
1622 int converted to char */
1624 /* expecttype = ctype_makeConj (ctype_char, ctype_uchar); */
1625 /*@switchbreak@*/ break;
1627 case 's': /* string */
1628 expecttype = ctype_string;
1629 /*@switchbreak@*/ break;
1632 while (((key = *(++code)) != ']')
1635 codetext = cstring_appendChar (codetext, key);
1636 fileloc_incColumn (formatloc);
1642 (message ("Bad character set format: %s",
1643 cstring_fromChars (origcode)));
1646 expecttype = ctype_string;
1647 /*@switchbreak@*/ break;
1649 case 'p': /* pointer */
1650 expecttype = ctype_makePointer (ctype_void);
1651 /* need not be defined */
1652 uentry_setDefState (regArg, SS_RELDEF);
1653 sRef_setPosNull (uentry_getSref (regArg),
1656 /*@switchbreak@*/ break;
1658 case 'n': /* pointer to int, modified by call! */
1659 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1661 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1662 /*@switchbreak@*/ break;
1664 case 'm': /* in a syslog, it doesn't consume an argument */
1665 /* should check we're really doing syslog */
1667 /*@switchbreak@*/ break;
1671 expecttype = ctype_unknown;
1675 message ("Unrecognized format code: %s",
1676 cstring_fromChars (origcode)),
1677 fileloc_isDefined (formatloc)
1678 ? formatloc : g_currentloc);
1680 /*@switchbreak@*/ break;
1683 if (!(exprNode_matchArgType (expecttype, a)))
1685 if (ctype_isVoidPointer (expecttype)
1686 && ctype_isRealAbstract (a->typ)
1687 && (context_getFlag (FLG_ABSTVOIDP)))
1693 if (llgenformattypeerror
1694 (expecttype, exprNode_undefined,
1696 message ("Format argument %d to %q (%%%s) expects "
1699 uentry_getName (fcn),
1702 a->typ, exprNode_unparse (a)),
1705 if (fileloc_isDefined (formatloc)
1706 && context_getFlag (FLG_SHOWCOL))
1709 (cstring_makeLiteral
1710 ("Corresponding format code"),
1717 uentry_setType (regArg, expecttype);
1718 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1720 if (ctype_equal (expecttype, ctype_string))
1722 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1725 uentry_setType (regArg, ctype_unknown);
1726 uentry_fixupSref (regArg);
1730 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1741 cstring_free (codetext);
1746 voptgenerror (FLG_TYPE,
1747 message ("Format string for %q has %d arg%&, given %d",
1748 uentry_getName (fcn), i - argno, nargs - argno),
1754 /* no checking possible for compile-time unknown format strings */
1755 if (exprNode_isDefined (a))
1759 message ("Format string parameter to %s is not a compile-time constant: %s",
1760 exprNode_unparse (f),
1761 exprNode_unparse (a)),
1766 fileloc_free (formatloc);
1770 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1771 exprNodeList args, exprNode ret, int argno)
1775 int nargs = exprNodeList_size (args);
1776 uentryList params = uentry_getParams (fcn);
1780 ** These should be ensured by checkSpecialFunction
1783 llassert (uentryList_size (params) == argno + 1);
1784 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1786 a = exprNodeList_getN (args, argno - 1);
1787 formatloc = fileloc_copy (exprNode_loc (a));
1789 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1790 && exprNode_knownStringValue (a))
1792 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1793 char *code = format;
1796 nargs = exprNodeList_size (args);
1798 while ((code = strchr (code, '%')) != NULL)
1800 char *origcode = code;
1801 char key = *(++code);
1802 cstring codetext = cstring_newEmpty ();
1803 ctype modtype = ctype_int;
1804 char modifier = '\0';
1805 bool modified = TRUE;
1806 bool ignore = FALSE;
1808 codetext = cstring_appendChar (codetext, key);
1809 fileloc_addColumn (formatloc, code - ocode);
1812 ** this is based on ANSI standard library description of fscanf
1813 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1816 /* '*' suppresses assignment (does not need match argument) */
1821 codetext = cstring_appendChar (codetext, key);
1824 fileloc_incColumn (formatloc);
1827 /* ignore field width */
1828 while (isdigit ((int) key) != 0)
1831 codetext = cstring_appendChar (codetext, key);
1832 fileloc_incColumn (formatloc);
1837 modtype = ctype_sint; /* short */
1839 codetext = cstring_appendChar (codetext, key);
1840 fileloc_incColumn (formatloc);
1842 else if (key == 'l' || key == 'L')
1844 modtype = ctype_lint; /* long */
1848 codetext = cstring_appendChar (codetext, key);
1850 fileloc_incColumn (formatloc);
1852 if (key == 'l' || key == 'L') {
1853 modtype = ctype_llint; /* long long */
1855 codetext = cstring_appendChar (codetext, key);
1856 fileloc_incColumn (formatloc);
1864 /* now, key = type of conversion to apply */
1866 fileloc_incColumn (formatloc);
1880 message ("No argument corresponding to %q format "
1881 "code %d (%%%s): \"%s\"",
1882 uentry_getName (fcn),
1884 cstring_fromChars (format)),
1887 if (fileloc_isDefined (formatloc)
1888 && context_getFlag (FLG_SHOWCOL))
1891 (cstring_makeLiteral ("Corresponding format code"),
1899 a = exprNodeList_getN (args, i);
1902 if (!exprNode_isError (a))
1908 case '*': /* int argument for fieldwidth */
1909 expecttype = ctype_makePointer (ctype_int);
1910 *(--code) = '%'; /* convert it for next code */
1911 fileloc_subColumn (formatloc, 1);
1912 /*@switchbreak@*/ break;
1915 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1916 /*@switchbreak@*/ break;
1921 case 'X': /* unsigned int */
1922 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1923 /*@switchbreak@*/ break;
1930 /* printf is double, scanf is float! */
1932 if (modifier == 'l')
1934 expecttype = ctype_makePointer (ctype_double);
1936 else if (modifier == 'L')
1938 expecttype = ctype_makePointer (ctype_ldouble);
1942 llassert (modifier == '\0');
1943 expecttype = ctype_makePointer (ctype_float);
1945 /*@switchbreak@*/ break;
1947 case 'c': /* int converted to char (check its a char?) */
1948 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1949 /*@switchbreak@*/ break;
1951 case 's': /* string */
1952 expecttype = ctype_string;
1953 /*@switchbreak@*/ break;
1957 while (((key = *(++code)) != ']')
1960 codetext = cstring_appendChar (codetext, key);
1961 fileloc_incColumn (formatloc);
1967 (message ("Bad character set format: %s",
1968 cstring_fromChars (origcode)));
1971 expecttype = ctype_string;
1972 /*@switchbreak@*/ break;
1975 case 'p': /* pointer */
1978 message ("Format code should not be used in scanf: %s",
1979 cstring_fromChars (origcode)),
1980 fileloc_isDefined (formatloc)
1981 ? formatloc : g_currentloc);
1983 expecttype = ctype_unknown;
1984 /*@switchbreak@*/ break;
1986 case 'n': /* pointer to int, modified by call! */
1987 expecttype = ctype_makePointer (ctype_int);
1988 /*@switchbreak@*/ break;
1991 expecttype = ctype_unknown;
1995 message ("Unrecognized format code: %s",
1996 cstring_fromChars (origcode)),
1997 fileloc_isDefined (formatloc)
1998 ? formatloc : g_currentloc);
2000 /*@switchbreak@*/ break;
2003 if (!(exprNode_matchArgType (expecttype, a)))
2005 if (ctype_isVoidPointer (expecttype)
2006 && ctype_isRealAbstract (a->typ)
2007 && (context_getFlag (FLG_ABSTVOIDP)))
2013 if (llgenformattypeerror
2014 (expecttype, exprNode_undefined,
2016 message ("Format argument %d to %q (%%%s) expects "
2019 uentry_getName (fcn),
2020 codetext, expecttype,
2021 a->typ, exprNode_unparse (a)),
2024 if (fileloc_isDefined (formatloc)
2025 && context_getFlag (FLG_SHOWCOL))
2028 (cstring_makeLiteral
2029 ("Corresponding format code"),
2036 uentry_setType (outArg, expecttype);
2037 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
2038 uentry_setType (outArg, ctype_unknown);
2039 uentry_fixupSref (outArg);
2043 exprNode_checkCallModifyVal (a->sref, args, f, ret);
2048 /* a->sref = sRef_undefined; */
2055 cstring_free (codetext);
2060 voptgenerror (FLG_TYPE,
2061 message ("Format string for %q has %d arg%&, given %d",
2062 uentry_getName (fcn), i - argno, nargs - argno),
2068 /* no checking possible for compile-time unknown format strings */
2071 fileloc_free (formatloc);
2075 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
2078 /*@unused@*/ int argno)
2081 ** the last argument before the elips is the format string
2084 int nargs = exprNodeList_size (args);
2089 a = exprNodeList_getN (args, argno - 1);
2090 formatloc = fileloc_copy (exprNode_loc (a));
2092 if (ctype_isUnknown (cstringType)) {
2093 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
2095 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
2099 if (ctype_isUnknown (ctypeType)) {
2100 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
2102 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
2106 if (ctype_isUnknown (filelocType)) {
2107 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
2109 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
2113 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
2114 && exprNode_knownStringValue (a))
2116 cstring format = multiVal_forceString (exprNode_getValue (a));
2117 char *code = cstring_toCharsSafe (format);
2120 nargs = exprNodeList_size (args);
2122 while ((code = strchr (code, '%')) != NULL)
2124 char *origcode = code;
2125 char key = *(++code);
2126 cstring codetext = cstring_newEmpty ();
2127 bool isOnly = FALSE;
2129 codetext = cstring_appendChar (codetext, key);
2131 fileloc_addColumn (formatloc, code - ocode);
2133 while (key >= '0' && key <= '9')
2136 codetext = cstring_appendChar (codetext, key);
2137 fileloc_incColumn (formatloc);
2141 fileloc_incColumn (formatloc);
2145 if (key == '&') /* plural marker */
2154 message ("Message missing format arg %d (%%%s): \"%s\"",
2155 i + 1, codetext, format),
2161 a = exprNodeList_getN (args, i);
2165 if (!exprNode_isError (a))
2169 /*@-loopswitchbreak@*/
2175 expecttype = ctype_char; break;
2177 expecttype = cstringType; break;
2179 expecttype = cstringType; isOnly = TRUE; break;
2181 expecttype = cstringType; isOnly = TRUE; break;
2182 case 'd': expecttype = ctype_int; break;
2183 case 'u': expecttype = ctype_uint; break;
2184 case 'w': expecttype = ctype_ulint; break;
2185 case 'f': expecttype = ctype_float; break;
2186 case 'b': expecttype = ctype_bool; break;
2187 case 't': expecttype = ctypeType; break;
2189 expecttype = ctype_makePointer (ctype_void);
2190 /* need not be defined */
2191 uentry_setDefState (regArg, SS_RELDEF);
2192 sRef_setPosNull (uentry_getSref (regArg),
2195 /*@switchbreak@*/ break;
2196 case 'l': expecttype = filelocType; break;
2197 case '&': /* a wee bit of a hack methinks */
2198 expecttype = ctype_int;
2200 case 'r': expecttype = ctype_bool; break;
2202 expecttype = ctype_unknown;
2205 message ("Unrecognized format code: %s",
2206 cstring_fromChars (origcode)),
2207 fileloc_isDefined (formatloc)
2208 ? formatloc : g_currentloc);
2211 /*@=loopswitchbreak@*/
2213 if (!(exprNode_matchArgType (expecttype, a)))
2215 if (ctype_isVoidPointer (expecttype)
2216 && ctype_isRealAbstract (a->typ)
2217 && (context_getFlag (FLG_ABSTVOIDP)))
2223 if (llgenformattypeerror
2224 (expecttype, exprNode_undefined,
2226 message ("Format argument %d to %q (%%%s) expects "
2229 uentry_getName (fcn),
2230 codetext, expecttype,
2231 a->typ, exprNode_unparse (a)),
2234 if (fileloc_isDefined (formatloc)
2235 && context_getFlag (FLG_SHOWCOL))
2238 (cstring_makeLiteral
2239 ("Corresponding format code"),
2246 if (ctype_equal (expecttype, cstringType))
2250 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2251 uentry_fixupSref (csOnlyArg);
2255 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2256 uentry_fixupSref (csArg);
2261 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2262 uentry_fixupSref (regArg);
2268 cstring_free (codetext);
2273 voptgenerror (FLG_TYPE,
2274 message ("Format string for %q has %d arg%&, given %d",
2275 uentry_getName (fcn), i - argno, nargs -argno),
2281 /* no checking possible for compile-time unknown format strings */
2284 fileloc_free (formatloc);
2288 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2289 /*@notnull@*/ exprNode e2,
2295 bool hadUncon = FALSE;
2297 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
2298 sRefSet_hasUnconstrained (sets2))
2301 (FLG_EVALORDERUNCON,
2303 ("Expression may have undefined behavior (%q used in right operand "
2304 "may set global variable %q used in left operand): %s %s %s",
2305 sRefSet_unparseUnconstrained (sets2),
2306 sRef_unparse (sRef_getRootBase (e1->sref)),
2307 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2311 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
2312 sRefSet_hasUnconstrained (sets1))
2315 (FLG_EVALORDERUNCON,
2317 ("Expression has undefined behavior (%q used in left operand "
2318 "may set global variable %q used in right operand): %s %s %s",
2319 sRefSet_unparseUnconstrained (sets1),
2320 sRef_unparse (e2->sref),
2321 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2325 sRefSet_realElements (e1->uses, sr)
2327 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2332 ("Expression has undefined behavior (left operand uses %q, "
2333 "modified by right operand): %s %s %s",
2335 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2338 } end_sRefSet_realElements;
2340 sRefSet_realElements (sets1, sr)
2342 if (sRef_isMeaningful (sr))
2344 if (sRef_same (sr, e2->sref))
2349 ("Expression has undefined behavior (value of right operand "
2350 "modified by left operand): %s %s %s",
2351 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2354 else if (sRefSet_member (e2->uses, sr))
2359 ("Expression has undefined behavior (left operand modifies %q, "
2360 "used by right operand): %s %s %s",
2362 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2367 if (sRefSet_member (sets2, sr))
2369 if (sRef_isUnconstrained (sr))
2377 hadUncon = optgenerror
2378 (FLG_EVALORDERUNCON,
2380 ("Expression may have undefined behavior. Left operand "
2381 "calls %q; right operand calls %q. The unconstrained "
2382 "functions may modify global state used by "
2383 "the other operand): %s %s %s",
2384 sRefSet_unparseUnconstrained (sets1),
2385 sRefSet_unparseUnconstrained (sets2),
2386 exprNode_unparse (e1), lltok_unparse (op),
2387 exprNode_unparse (e2)),
2396 ("Expression has undefined behavior (both "
2397 "operands modify %q): %s %s %s",
2399 exprNode_unparse (e1),
2400 lltok_unparse (op), exprNode_unparse (e2)),
2406 } end_sRefSet_realElements;
2409 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2411 bool hasError = FALSE;
2413 if (exprNode_isError (e1) || exprNode_isError (e2))
2418 if (sRefSet_member (e2->sets, e1->sref))
2420 if (e2->kind == XPR_CALL)
2426 hasError = optgenerror
2428 message ("Expression has undefined behavior "
2429 "(value of left operand %s is modified "
2430 "by right operand %s): %s %s %s",
2431 exprNode_unparse (e1),
2432 exprNode_unparse (e2),
2433 exprNode_unparse (e1), lltok_unparse (op),
2434 exprNode_unparse (e2)),
2439 if (context_getFlag (FLG_EVALORDERUNCON))
2441 if (sRefSet_member (e2->msets, e1->sref))
2443 if (e2->kind == XPR_CALL)
2449 hasError = optgenerror
2452 ("Expression has undefined behavior (value of left "
2453 "operand may be modified by right operand): %s %s %s",
2454 exprNode_unparse (e1), lltok_unparse (op),
2455 exprNode_unparse (e2)),
2463 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2465 if (context_maybeSet (FLG_EVALORDERUNCON))
2467 checkExpressionDefinedAux (e1, e2, e1->msets,
2468 e2->msets, op, FLG_EVALORDERUNCON);
2473 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2476 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2477 exprNodeList args, bool isIter, exprNode ret)
2481 if (!exprNode_isError (f))
2483 if (!uentryList_isMissingParams (cl))
2485 int nargs = exprNodeList_size (args);
2486 int expectargs = uentryList_size (cl);
2490 if (expectargs == 0)
2498 message ("Iter %q invoked with %d args, "
2500 uentry_getName (fcn),
2508 message ("Function %s called with %d args, "
2510 exprNode_unparse (f), nargs),
2517 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2519 exprNodeList_reset (args);
2521 uentryList_elements (cl, current)
2523 ctype ct = uentry_getType (current);
2526 if (ctype_isElips (ct))
2529 ** do special checking for printf/scanf library functions
2531 ** this is kludgey code, just for handling the special case
2535 if (uentry_isPrintfLike (fcn))
2537 checkPrintfArgs (f, fcn, args, ret, i);
2540 else if (uentry_isScanfLike (fcn))
2542 checkScanfArgs (f, fcn, args, ret, i);
2545 else if (uentry_isMessageLike (fcn))
2547 checkMessageArgs (f, fcn, args, i);
2552 llassert (!uentry_isSpecialFunction (fcn));
2555 nargs = expectargs; /* avoid errors */
2560 if (i >= nargs) break;
2562 a = exprNodeList_current (args);
2563 exprNodeList_advance (args);
2567 if (exprNode_isError (a))
2574 probably necessary? I'm not sure about this one
2575 checkMacroParen (a);
2578 f->guards = guardSet_union (f->guards, a->guards);
2580 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2582 if (!(exprNode_matchArgType (ct, a)))
2584 DPRINTF (("Args mismatch!"));
2586 if (ctype_isVoidPointer (ct)
2587 && (ctype_isPointer (a->typ)
2588 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2593 ("Pointer to abstract type (%t) used "
2595 "(arg %d to %q): %s",
2597 uentry_getName (fcn),
2598 exprNode_unparse (a)),
2606 (ct, exprNode_undefined,
2609 ("Iter %q expects arg %d to "
2610 "be %t gets %t: %s",
2611 uentry_getName (fcn),
2612 i, ct, a->typ, exprNode_unparse (a)),
2623 ("Function %q expects arg %d to be %t gets %t: %s",
2624 uentry_getName (fcn),
2625 i, ct, a->typ, exprNode_unparse (a)),
2628 DPRINTF (("Types: %s / %s",
2630 ctype_unparse (a->typ)));
2634 ** Clear null marker for abstract types.
2635 ** (It is not revealed, so suppress future messages.)
2638 if (ctype_isAbstract (a->typ))
2640 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2647 } end_uentryList_elements ;
2650 if (expectargs != nargs) /* note: not != since we may have ... */
2652 if (ctype_isElips (last))
2656 message ("Function %s called with %d args, expects at least %d",
2657 exprNode_unparse (f),
2658 nargs, expectargs - 1),
2667 message ("Iter %q invoked with %d args, expects %d",
2668 uentry_getName (fcn), nargs, expectargs),
2675 message ("Function %s called with %d args, expects %d",
2676 exprNode_unparse (f),
2689 ** Check for undefined code sequences in function arguments:
2691 ** one parameter sets something used by another parameter
2692 ** one parameter sets something set by another parameter
2696 checkSequencingOne (exprNode f, exprNodeList args,
2697 /*@notnull@*/ exprNode el, int argno)
2700 ** Do second loop, iff +undefunspec
2704 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2706 for (checkloop = 0; checkloop < numloops; checkloop++)
2712 thissets = el->sets;
2716 llassert (checkloop == 1);
2717 thissets = el->msets;
2720 sRefSet_realElements (thissets, thisset)
2724 /*@access exprNodeList@*/
2725 for (j = 0; j < args->nelements; j++)
2727 exprNode jl = args->elements[j];
2728 int thisargno = j + 1;
2730 if (thisargno != argno && exprNode_isDefined (jl))
2732 sRefSet otheruses = jl->uses;
2734 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
2735 sRefSet_hasUnconstrained (thissets))
2738 (FLG_EVALORDERUNCON,
2741 ("%q used in argument %d may set "
2742 "global variable %q used by argument %d: %s(%q)",
2743 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2746 sRef_unparse (sRef_getRootBase (jl->sref)),
2748 exprNode_unparse (f), exprNodeList_unparse (args)),
2752 if (sRefSet_member (otheruses, thisset))
2754 if (sRef_isUnconstrained (thisset))
2757 (FLG_EVALORDERUNCON,
2759 ("Unconstrained functions used in arguments %d (%q) "
2760 "and %d (%s) may modify "
2761 "or use global state in undefined way: %s(%q)",
2763 sRefSet_unparseUnconstrainedPlain (otheruses),
2765 sRef_unconstrainedName (thisset),
2766 exprNode_unparse (f),
2767 exprNodeList_unparse (args)),
2775 ("Argument %d modifies %q, used by argument %d "
2776 "(order of evaluation of actual parameters is "
2777 "undefined): %s(%q)",
2778 argno, sRef_unparse (thisset), thisargno,
2779 exprNode_unparse (f), exprNodeList_unparse (args)),
2785 sRefSet othersets = jl->sets;
2787 if (sRefSet_member (othersets, thisset))
2789 if (sRef_isUnconstrained (thisset))
2792 (FLG_EVALORDERUNCON,
2794 ("Unconstrained functions used in "
2795 "arguments %d (%q) and %d (%s) may modify "
2796 "or use global state in undefined way: %s(%q)",
2798 sRefSet_unparseUnconstrainedPlain (othersets),
2800 sRef_unconstrainedName (thisset),
2801 exprNode_unparse (f), exprNodeList_unparse (args)),
2809 ("Argument %d modifies %q, set by argument %d (order of"
2810 " evaluation of actual parameters is undefined): %s(%q)",
2811 argno, sRef_unparse (thisset), thisargno,
2812 exprNode_unparse (f), exprNodeList_unparse (args)),
2819 /*@noaccess exprNodeList@*/
2820 } end_sRefSet_realElements;
2825 checkSequencing (exprNode f, exprNodeList args)
2827 if (exprNodeList_size (args) > 1)
2832 /*@access exprNodeList*/
2834 for (i = 0; i < args->nelements; i++)
2836 el = args->elements[i];
2838 if (!exprNode_isError (el))
2840 checkSequencingOne (f, args, el, i + 1);
2843 /*@noaccess exprNodeList*/
2848 ** requires le = exprNode_getUentry (f)
2852 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2853 uentry le, exprNodeList args,
2854 /*@notnull@*/ exprNode ret, int specialArgs)
2856 bool isSpec = FALSE;
2857 bool hasMods = FALSE;
2859 globSet usesGlobs = globSet_undefined;
2860 sRefSet mods = sRefSet_undefined;
2861 bool freshMods = FALSE;
2862 uentryList params = uentryList_undefined;
2864 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2867 ** check globals and modifies
2872 if (!uentry_isValid (le))
2874 ctype fr = ctype_realType (f->typ);
2876 if (ctype_isFunction (fr))
2878 params = ctype_argsFunction (fr);
2882 params = uentryList_missingParams;
2885 if (!context_getFlag (FLG_MODNOMODS)
2886 && !context_getFlag (FLG_GLOBUNSPEC))
2888 checkUnspecCall (f, params, args);
2894 fname = uentry_rawName (le);
2898 if (uentry_isFunction (le))
2900 params = uentry_getParams (le);
2901 mods = uentry_getMods (le);
2902 hasMods = uentry_hasMods (le);
2903 usesGlobs = uentry_getGlobs (le);
2904 isSpec = uentry_isSpecified (le);
2906 else /* not a function */
2908 ctype ct = ctype_realType (uentry_getType (le));
2910 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2911 ("checkModGlobs: uentry not a function: %s",
2912 uentry_unparse (le)));
2914 params = ctype_argsFunction (ct);
2915 return; /*@32 ! remove this? */
2924 globSet_allElements (usesGlobs, el)
2926 if (sRef_isValid (el))
2928 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2930 context_usedGlobal (el);
2931 exprNode_checkUse (f, el, f->loc);
2933 if (context_checkInternalUse ())
2935 if (!context_globAccess (el))
2937 if (sRef_isSystemState (el)
2938 && !context_getFlag (FLG_MODFILESYSTEM))
2947 ("Called procedure %s may access %q, but "
2948 "globals list does not include globals %s",
2949 exprNode_unparse (f),
2951 cstring_makeLiteralTemp (sRef_isInternalState (el)
2959 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2965 uentry gle = sRef_getUentry (el);
2966 sRef sr = sRef_updateSref (el);
2968 if (sRef_isUndefGlob (el))
2970 sRef_setDefined (sr, f->loc);
2971 exprNode_checkSet (f, sr);
2979 if (sRef_isAllocated (el))
2981 exprNode_checkSet (f, sr);
2985 if (sRef_isStateUndefined (sr))
2990 ("%s %q used by function undefined before call: %s",
2991 sRef_getScopeName (sr),
2993 exprNode_unparse (f)),
2995 sRef_setDefined (sr, f->loc);
2997 exprNode_checkUse (f, sr, f->loc);
3000 checkGlobUse (gle, TRUE, f);
3003 if (sRef_isKilledGlob (el))
3005 sRef_kill (sr, f->loc);
3006 context_usedGlobal (sr);
3010 } end_globSet_allElements;
3016 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
3018 sRefSet smods = sRefSet_undefined;
3021 ** NEED to check for modifies anything
3025 ** check each sRef that called function modifies (ml), is
3031 sRefSet_allElements (mods, s) /* s is something which may be modified */
3033 DPRINTF (("Check modify: %s", sRef_unparse (s)));
3035 if (sRef_isKindSpecial (s))
3037 if (sRef_isSpecInternalState (s))
3039 if (context_getFlag (FLG_MODINTERNALSTRICT))
3041 exprNode_checkCallModifyVal (s, args, f, ret);
3045 sRefSet mmods = context_modList ();
3047 sRefSet_allElements (mmods, el)
3049 if (sRef_isInternalState (el))
3051 sRef_setModified (el);
3053 } end_sRefSet_allElements ;
3058 exprNode_checkCallModifyVal (s, args, f, ret);
3063 sRef rb = sRef_getRootBase (s);
3065 if (sRef_isFileOrGlobalScope (rb))
3067 context_usedGlobal (rb);
3070 if (sRef_isFileStatic (s)
3071 && !fileId_equal (fileloc_fileId (f->loc),
3072 fileloc_fileId (uentry_whereDefined (le))))
3074 smods = sRefSet_insert (smods, s);
3078 exprNode_checkCallModifyVal (s, args, f, ret);
3081 } end_sRefSet_allElements;
3086 ** Static elements in modifies set can have nasty consequences.
3087 ** (I think...have not been able to reproduce a possible bug.)
3090 if (!sRefSet_isDefined (smods))
3092 mods = sRefSet_newCopy (mods);
3095 sRefSet_allElements (smods, el)
3097 bool res = sRefSet_delete (mods, el);
3100 } end_sRefSet_allElements;
3102 sRefSet_free (smods);
3107 else if (sRefSet_isDefined (mods))
3108 { /* just check observers */
3111 sRefSet_allElements (mods, s) /* s is something which may be modified */
3113 sRef rb = sRef_getRootBase (s);
3117 if (sRef_isParam (rb))
3119 sRef b = sRef_fixBaseParam (s, args);
3121 if (sRef_isObserver (b))
3123 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
3127 message ("Function call may modify observer%q: %s",
3128 sRef_unparsePreOpt (b), exprNode_unparse (e)),
3131 sRef_showExpInfo (b);
3135 } end_sRefSet_allElements;
3139 if (!hasMods) /* no specified modifications */
3141 if (context_getFlag (FLG_MODOBSERVERUNCON))
3143 exprNodeList_elements (args, e)
3145 if (exprNode_isDefined (e))
3147 sRef s = exprNode_getSref (e);
3149 if (sRef_isObserver (s)
3150 && ctype_isMutable (sRef_getType (s)))
3153 (FLG_MODOBSERVERUNCON,
3155 ("Call to unconstrained function %s may modify observer%q: %s",
3156 exprNode_unparse (f),
3157 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3160 sRef_showExpInfo (s);
3164 } end_exprNodeList_elements;
3169 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3171 ret->uses = sRefSet_union (ret->uses, f->uses);
3172 ret->sets = sRefSet_union (ret->sets, f->sets);
3173 ret->msets = sRefSet_union (ret->msets, f->msets);
3178 ** Spurious errors reported, because splint can't tell
3179 ** mods must be fresh if freshMods is true.
3182 /*@i@*/ sRefSet_free (mods);
3188 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3190 if (uentry_isVar (glob))
3192 if (context_inFunctionLike ())
3194 sRef sr = uentry_getSref (glob);
3196 context_usedGlobal (sr);
3198 if (context_checkGlobUse (glob))
3200 if (!context_globAccess (sr))
3206 message ("Called procedure %s may access %s %q",
3207 exprNode_unparse (e),
3208 sRef_unparseScope (sr),
3209 uentry_getName (glob)),
3216 message ("Undocumented use of %s %s",
3217 sRef_unparseScope (sr),
3218 exprNode_unparse (e)),
3227 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3232 reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
3234 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3235 exprNode_unparse (f), exprNodeList_unparse (args),
3236 uentry_unparseFull (le),
3237 stateClauseList_unparse (uentry_getStateClauseList (le))));
3239 if (uentry_isValid (le) && uentry_isFunction (le))
3241 stateClauseList sclauses = uentry_getStateClauseList (le);
3243 if (stateClauseList_isDefined (sclauses))
3245 DPRINTF (("Reflect ensures: %s / %s / %s",
3246 uentry_unparse (le),
3247 exprNode_unparse (f), exprNodeList_unparse (args)));
3249 stateClauseList_elements (sclauses, cl)
3251 if (stateClause_hasEnsures (cl))
3253 /* Same in usymtab.c:1904 */
3254 if (stateClause_setsMetaState (cl))
3256 qual q = stateClause_getMetaQual (cl);
3257 annotationInfo ainfo = qual_getAnnotationInfo (q);
3258 metaStateInfo minfo = annotationInfo_getState (ainfo);
3259 cstring key = metaStateInfo_getName (minfo);
3260 int mvalue = annotationInfo_getValue (ainfo);
3262 sRefSet osrs = sRefSet_undefined;
3265 if (stateClause_isGlobal (cl))
3267 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3272 srs = stateClause_getRefs (cl);
3275 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3278 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3280 sRefSet_elements (srs, sel)
3284 if (sRef_isResult (sRef_getRootBase (sel)))
3286 s = exprNode_getSref (ret);
3290 s = sRef_fixBaseParam (sel, args);
3293 DPRINTF (("Reflecting state clause on: %s / %s",
3294 sRef_unparse (sel), sRef_unparse (s)));
3296 sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3297 } end_sRefSet_elements;
3299 sRefSet_free (osrs);
3303 sRefSet srs = stateClause_getRefs (cl);
3304 sRefModVal modf = stateClause_getEnsuresFunction (cl);
3305 int eparam = stateClause_getStateParameter (cl);
3307 llassert (modf != NULL);
3309 DPRINTF (("Reflect after clause: %s / %s",
3310 stateClause_unparse (cl),
3311 sRefSet_unparse (srs)));
3313 sRefSet_elements (srs, sel)
3317 DPRINTF (("elements: %s", sRef_unparse (sel)));
3318 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3320 if (sRef_isResult (sRef_getRootBase (sel)))
3322 DPRINTF (("Fix base: %s / %s",
3323 sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
3324 s = sRef_fixBase (sel, exprNode_getSref (ret));
3325 DPRINTF (("==> %s", sRef_unparseFull (s)));
3329 s = sRef_fixBaseParam (sel, args);
3332 DPRINTF (("elements: %s", sRef_unparse (s)));
3333 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3335 DPRINTF (("Reflecting state clause on: %s / %s",
3336 sRef_unparseFull (sel), sRef_unparseFull (s)));
3338 /* evans 2001-08-24 - added aliasSetCompleteParam */
3339 sRef_aliasSetCompleteParam (modf, s, eparam, exprNode_loc (f));
3341 DPRINTF (("After reflecting state clause on: %s / %s",
3342 sRef_unparseFull (sel), sRef_unparseFull (s)));
3343 } end_sRefSet_elements;
3346 } end_stateClauseList_elements ;
3349 DPRINTF (("Here: %s / %s",
3350 uentry_unparseFull (le),
3351 bool_unparse (uentry_hasMetaStateEnsures (le))));
3353 if (uentry_hasMetaStateEnsures (le))
3355 fileloc loc = exprNode_loc (f);
3357 metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3359 metaStateConstraintList_elements (mscl, msc)
3361 metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3362 metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3363 metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
3364 cstring key = metaStateInfo_getName (msinfo);
3365 sRef mlsr = metaStateSpecifier_getSref (msspec);
3367 sRef lastref = sRef_undefined;
3368 stateValue sval = stateValue_undefined;
3370 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3371 metaStateConstraint_unparse (msc)));
3372 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3374 if (sRef_isResult (sRef_getRootBase (mlsr)))
3376 s = exprNode_getSref (ret);
3380 s = sRef_fixBaseParam (mlsr, args);
3383 DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3385 while (metaStateExpression_isDefined (msexpr))
3387 metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
3388 metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
3391 DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3393 if (metaStateExpression_isMerge (msexpr))
3395 msexpr = metaStateExpression_getRest (msexpr);
3399 msexpr = metaStateExpression_undefined;
3402 if (metaStateInfo_isDefined (msi))
3404 /* Must match lhs state */
3405 llassert (metaStateInfo_equal (msinfo, msi));
3408 if (metaStateSpecifier_isElipsis (ms))
3411 ** For elipsis, we need to merge all the relevant elipsis parameters
3415 uentryList params = uentry_getParams (le);
3416 int paramno = uentryList_size (params) - 1;
3418 if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
3422 message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3423 uentry_getName (le)),
3424 uentry_whereLast (le));
3425 /*@innerbreak@*/ break;
3428 while (paramno < exprNodeList_size (args))
3430 exprNode arg = exprNodeList_getN (args, paramno);
3431 fs = exprNode_getSref (arg);
3432 DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3434 /* cut and pasted... gack*/
3435 if (stateValue_isDefined (sval))
3437 /* Use combination table to merge old state value with new one: */
3438 stateValue tval = sRef_getMetaStateValue (fs, key);
3440 if (stateValue_isDefined (tval))
3442 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3443 cstring msg = cstring_undefined;
3444 int nval = stateCombinationTable_lookup (sctable,
3445 stateValue_getValue (sval),
3446 stateValue_getValue (tval),
3448 DPRINTF (("Combining: %s + %s -> %d",
3449 stateValue_unparseValue (sval, msinfo),
3450 stateValue_unparseValue (tval, msinfo),
3453 if (nval == stateValue_error)
3458 ("Attributes merged in ensures clause in states that "
3459 "cannot be combined (%q is %q, %q is %q)%q",
3460 sRef_unparse (lastref),
3461 stateValue_unparseValue (sval, msinfo),
3463 stateValue_unparseValue (tval, msinfo),
3464 cstring_isDefined (msg) ?
3465 message (": %s", msg) : cstring_undefined),
3468 sRef_showMetaStateInfo (fs, key);
3472 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3473 loc = exprNode_loc (arg);
3477 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3482 sval = sRef_getMetaStateValue (fs, key);
3487 if (stateValue_isError (sval))
3489 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3498 msr = metaStateSpecifier_getSref (ms);
3501 llassert (sRef_isParam (sRef_getRootBase (msr)));
3502 fs = sRef_fixBaseParam (msr, args);
3504 if (stateValue_isDefined (sval))
3506 /* Use combination table to merge old state value with new one: */
3507 stateValue tval = sRef_getMetaStateValue (fs, key);
3509 if (stateValue_isDefined (tval))
3511 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3512 cstring msg = cstring_undefined;
3513 int nval = stateCombinationTable_lookup (sctable,
3514 stateValue_getValue (sval),
3515 stateValue_getValue (tval),
3517 DPRINTF (("Combining: %s + %s -> %d",
3518 stateValue_unparseValue (sval, msinfo),
3519 stateValue_unparseValue (tval, msinfo),
3522 if (nval == stateValue_error)
3527 ("Attributes merged in ensures clause in states that "
3528 "cannot be combined (%q is %q, %q is %q)%q",
3529 sRef_unparse (lastref),
3530 stateValue_unparseValue (sval, msinfo),
3532 stateValue_unparseValue (tval, msinfo),
3533 cstring_isDefined (msg)
3534 ? message (": %s", msg) : cstring_undefined),
3537 sRef_showMetaStateInfo (fs, key);
3541 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3545 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3550 sval = sRef_getMetaStateValue (fs, key);
3555 if (stateValue_isError (sval))
3557 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3562 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3564 if (stateValue_isDefined (sval))
3566 sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
3570 DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
3572 } end_metaStateConstraintList_elements ;
3574 metaStateConstraintList_free (mscl);
3580 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3582 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3583 exprNode_unparse (f), exprNodeList_unparse (args),
3584 uentry_unparseFull (le),
3585 stateClauseList_unparse (uentry_getStateClauseList (le))));
3587 if (uentry_isValid (le) && uentry_isFunction (le))
3589 stateClauseList sclauses = uentry_getStateClauseList (le);
3591 if (stateClauseList_isDefined (sclauses))
3593 DPRINTF (("Check requires: %s / %s / %s",
3594 uentry_unparse (le),
3595 exprNode_unparse (f), exprNodeList_unparse (args)));
3597 stateClauseList_elements (sclauses, cl)
3599 DPRINTF (("Check clause: %s / %s",
3600 stateClause_unparse (cl),
3601 bool_unparse (stateClause_hasRequires (cl))));
3603 if (stateClause_hasRequires (cl))
3605 sRefSet osrs = sRefSet_undefined;
3608 if (stateClause_isGlobal (cl))
3610 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3615 srs = stateClause_getRefs (cl);
3618 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3620 if (stateClause_setsMetaState (cl))
3622 qual q = stateClause_getMetaQual (cl);
3623 annotationInfo ainfo = qual_getAnnotationInfo (q);
3624 metaStateInfo minfo = annotationInfo_getState (ainfo);
3625 cstring key = metaStateInfo_getName (minfo);
3626 int mvalue = annotationInfo_getValue (ainfo);
3628 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3630 sRefSet_elements (srs, sel)
3632 sRef s = sRef_fixBaseParam (sel, args);
3634 if (sRef_isResult (sRef_getRootBase (sel)))
3640 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3641 sRef_unparseFull (sel), sRef_unparseFull (s),
3644 if (!sRef_checkMetaStateValue (s, key, mvalue))
3646 DPRINTF (("HERE: %s", sRef_unparse (s)));
3650 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3651 uentry_getName (le),
3652 sRef_isGlobalMarker (s)
3654 : message (" by %q", sRef_unparse (s)),
3655 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3657 stateClause_unparse (cl)),
3660 sRef_showAliasInfo (s);
3664 DPRINTF (("Error supressed!"));
3665 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3666 DPRINTF (("Context supress: %s",
3667 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3671 } end_sRefSet_elements;
3675 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3676 int eparam = stateClause_getStateParameter (cl);
3678 DPRINTF (("Reflect after clause: %s / %s",
3679 stateClause_unparse (cl),
3680 sRefSet_unparse (srs)));
3682 llassert (modf != NULL);
3684 sRefSet_elements (srs, sel)
3688 DPRINTF (("elements: %s", sRef_unparse (sel)));
3689 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3691 s = sRef_fixBaseParam (sel, args);
3693 DPRINTF (("elements: %s", sRef_unparse (s)));
3694 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3696 if (sRef_isResult (sRef_getRootBase (sel)))
3698 ; /*@i423 what do we do about results */
3702 DPRINTF (("Reflecting state clause on: %s / %s",
3703 sRef_unparse (sel), sRef_unparse (s)));
3705 modf (s, eparam, exprNode_loc (f));
3707 } end_sRefSet_elements;
3710 sRefSet_free (osrs);
3712 } end_stateClauseList_elements ;
3717 static /*@only@*/ exprNode
3718 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3719 ctype t, /*@keep@*/ exprNodeList args)
3721 /* requires f is a non-error exprNode, with type function */
3722 cstring fname = exprNode_unparse (f);
3723 uentry le = exprNode_getUentry (f);
3724 exprNode ret = exprNode_createPartialCopy (f);
3729 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3731 ret->typ = ctype_getReturnType (t);
3732 ret->kind = XPR_CALL;
3734 ret->edata = exprData_makeCall (f, args);
3737 ** Order of these steps is very important!
3739 ** Must check for argument dependencies before messing up uses and sets.
3742 if (context_getFlag (FLG_EVALORDER))
3744 exprNodeList_elements (args, current)
3746 if (exprNode_isDefined (current))
3748 exprNode_addUse (current, current->sref);
3750 } end_exprNodeList_elements;
3752 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3754 checkSequencing (f, args);
3757 exprNodeList_elements (args, current)
3759 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3761 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3763 } end_exprNodeList_elements ;
3766 special = checkArgs (le, f, t, args, ret);
3767 checkGlobMods (f, le, args, ret, special);
3768 checkRequiresClause (le, f, args);
3771 if (uentry_isValid (le)
3772 && (uentry_isFunction (le)
3773 || (uentry_isVariable (le)
3774 && ctype_isFunction (uentry_getType (le)))))
3776 exitkind exk = uentry_getExitCode (le);
3778 /* f->typ is already set to the return type */
3780 DPRINTF (("Function: %s", uentry_unparseFull (le)));
3781 ret->sref = uentry_returnedRef (le, args);
3782 DPRINTF (("Returned: %s / %s",
3783 uentry_unparseFull (le),
3784 sRef_unparseFull (ret->sref)));
3786 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3788 qual nullPred = uentry_nullPred (le);
3790 if (qual_isTrueNull (nullPred))
3792 exprNode arg = exprNodeList_head (args);
3794 if (exprNode_isDefined (arg))
3796 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3799 else if (qual_isFalseNull (nullPred))
3801 exprNode arg = exprNodeList_head (args);
3803 if (exprNode_isDefined (arg))
3805 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3810 llassert (qual_isUnknown (nullPred));
3814 if (exitkind_isConditionalExit (exk))
3818 ** if (arg0) then { exit! } else { ; }
3820 ** if (arg0) then { ; } else { exit! }
3825 llassert (!exprNodeList_isEmpty (args));
3826 firstArg = exprNodeList_head (args);
3828 if (exprNode_isDefined (firstArg)
3829 && !guardSet_isEmpty (firstArg->guards))
3831 usymtab_trueBranch (guardSet_undefined);
3832 usymtab_altBranch (guardSet_undefined);
3834 if (exitkind_isTrueExit (exk))
3836 usymtab_popBranches (firstArg,
3837 exprNode_makeMustExit (),
3839 TRUE, TRUEEXITCLAUSE);
3843 usymtab_popBranches (firstArg,
3845 exprNode_makeMustExit (),
3846 TRUE, FALSEEXITCLAUSE);
3850 ret->exitCode = XK_MAYEXIT;
3852 else if (exitkind_mustExit (exk))
3854 ret->exitCode = XK_MUSTEXIT;
3856 else if (exitkind_couldExit (exk))
3858 ret->exitCode = XK_MAYEXIT;
3865 if (cstring_equalLit (fname, "exit"))
3867 if (exprNodeList_size (args) == 1)
3869 exprNode arg = exprNodeList_head (args);
3871 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3873 long int val = multiVal_forceInt (exprNode_getValue (arg));
3880 ("Argument to exit has implementation defined behavior: %s",
3881 exprNode_unparse (arg)),
3882 exprNode_loc (arg));
3890 ret->sref = sRef_undefined;
3891 exprNode_checkSetAny (ret, uentry_rawName (le));
3894 DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3895 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3896 reflectEnsuresClause (ret, le, f, args);
3903 ** this is yucky! should keep the uentry as part of exprNode!
3906 uentry exprNode_getUentry (exprNode e)
3908 if (exprNode_isError (e))
3910 return uentry_undefined;
3914 cstring s = exprNode_rootVarName (e);
3915 uentry ue = usymtab_lookupSafe (s);
3922 ** Returns true iff e1 and e2 are both exactly the same storage
3926 static bool exprNode_sameStorage (exprNode e1, exprNode e2)
3928 sRef s1 = exprNode_getSref (e1);
3929 sRef s2 = exprNode_getSref (e2);
3931 return (sRef_realSame (s1, s2));
3935 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3937 exprNode ret = exprNode_createPlain (ctype_unknown);
3939 ret->kind = XPR_INITBLOCK;
3940 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3941 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3947 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3952 usymtab_checkAllValid ();
3955 if (exprNode_isUndefined (f))
3958 exprNodeList_free (args);
3959 return exprNode_undefined;
3962 t = exprNode_getType (f);
3964 if (sRef_isLocalVar (f->sref))
3966 exprNode_checkUse (f, f->sref, f->loc);
3968 if (sRef_possiblyNull (f->sref))
3970 if (!usymtab_isGuarded (f->sref))
3972 if (optgenerror (FLG_NULLDEREF,
3973 message ("Function call using %s pointer %q",
3974 sRef_nullMessage (f->sref),
3975 sRef_unparse (f->sref)),
3978 sRef_showNullInfo (f->sref);
3979 sRef_setNullError (f->sref);
3987 if (ctype_isRealFunction (t))
3989 exprNode ret = functionCallSafe (f, t, args);
3993 else if (ctype_isUnknown (t))
3995 exprNode ret = exprNode_createPartialCopy (f);
4001 exprNodeList_elements (args, current)
4003 if (exprNode_isDefined (current))
4005 exprNode_checkUse (ret, current->sref, ret->loc);
4008 ** also, anything derivable from current->sref may be used
4011 exprNode_addUse (ret, sRef_makeDerived (current->sref));
4012 exprNode_mergeUSs (ret, current);
4014 } end_exprNodeList_elements;
4016 ret->edata = exprData_makeCall (f, args);
4017 ret->kind = XPR_CALL;
4019 tstring = cstring_copy (exprNode_unparse (f));
4021 cstring_markOwned (tstring);
4022 exprNode_checkSetAny (ret, tstring);
4028 voptgenerror (FLG_TYPE,
4029 message ("Call to non-function (type %t): %s", t,
4030 exprNode_unparse (f)),
4033 exprNodeList_free (args);
4035 return (exprNode_makeError ());
4040 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4041 /*@only@*/ cstring f)
4043 exprNode ret = exprNode_createPartialCopy (s);
4045 ret->kind = XPR_FACCESS;
4047 if (exprNode_isError (s))
4049 ret->edata = exprData_makeField (s, f);
4054 ctype t = exprNode_getType (s);
4055 ctype tr = ctype_realType (t);
4057 checkMacroParen (s);
4059 ret->edata = exprData_makeField (s, f);
4061 if (ctype_isStructorUnion (tr))
4063 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
4065 if (uentry_isUndefined (tf))
4067 voptgenerror (FLG_TYPE,
4068 message ("Access non-existent field %s of %t: %s", f, t,
4069 exprNode_unparse (ret)),
4071 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
4076 uentry_setUsed (tf, exprNode_loc (ret));
4078 ret->typ = uentry_getType (tf);
4079 checkSafeUse (ret, s->sref);
4081 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
4082 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
4086 else /* isStructorUnion */
4088 if (ctype_isRealAbstract (tr))
4092 message ("Access field of abstract type (%t): %s.%s",
4093 t, exprNode_unparse (s), f),
4095 ret->typ = ctype_unknown;
4099 if (ctype_isKnown (tr))
4104 ("Access field of non-struct or union (%t): %s.%s",
4105 t, exprNode_unparse (s), f),
4108 ret->typ = ctype_unknown;
4112 cstring sn = cstring_copy (f);
4114 checkSafeUse (ret, s->sref);
4115 cstring_markOwned (sn);
4116 ret->sref = sRef_makeField (s->sref, sn);
4128 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
4129 /*@only@*/ cstring f)
4131 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
4137 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
4139 exprNode ret = exprNode_createPartialCopy (e);
4141 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
4142 ret->kind = XPR_PARENS;
4143 ret->edata = exprData_makeUop (e, lpar);
4145 if (!exprNode_isError (e))
4147 ret->exitCode = e->exitCode;
4148 ret->canBreak = e->canBreak;
4149 ret->mustBreak = e->mustBreak;
4150 ret->isJumpPoint = e->isJumpPoint;
4151 ret->sref = e->sref;
4158 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4159 /*@only@*/ cstring f)
4161 exprNode ret = exprNode_createPartialCopy (s);
4163 ret->edata = exprData_makeField (s, f);
4164 ret->kind = XPR_ARROW;
4166 if (exprNode_isError (s))
4172 ctype t = exprNode_getType (s);
4173 ctype tr = ctype_realType (t);
4175 checkMacroParen (s);
4177 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4179 if (ctype_isRealPointer (tr))
4181 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4183 if (ctype_isStructorUnion (b))
4185 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4187 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4189 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4193 message ("Arrow access from %s pointer%q: %s",
4194 sRef_nullMessage (s->sref),
4195 sRef_unparsePreOpt (s->sref),
4196 exprNode_unparse (ret)),
4199 sRef_showNullInfo (s->sref);
4200 sRef_setNullError (s->sref);
4205 if (uentry_isUndefined (fentry))
4209 message ("Access non-existent field %s of %t: %s",
4210 f, t, exprNode_unparse (ret)),
4212 ret->typ = ctype_unknown;
4218 ** was safeUse: shouldn't be safe!
4221 ** rec must be defined,
4222 ** *rec must be allocated
4223 ** rec->field need only be defined it if is an rvalue
4226 uentry_setUsed (fentry, exprNode_loc (ret));
4227 ret->typ = uentry_getType (fentry);
4229 exprNode_checkUse (ret, s->sref, s->loc);
4231 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4232 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4236 else /* Pointer to something that is not a struct or union*/
4238 if (ctype_isRealAbstract (tr))
4240 ctype xrt = ctype_forceRealType (tr);
4244 message ("Arrow access field of abstract type (%t): %s->%s",
4245 t, exprNode_unparse (s), f),
4249 ** Set the state correctly, as if the abstraction is broken.
4252 if (ctype_isRealPointer (xrt) &&
4253 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4254 ctype_isStructorUnion (b)))
4256 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4257 ret->typ = uentry_getType (fentry);
4258 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4262 ret->typ = ctype_unknown;
4263 ret->sref = sRef_undefined;
4266 else /* not a struct, union or abstract */
4268 if (ctype_isUnknown (tr)) {
4269 cstring sn = cstring_copy (f);
4271 DPRINTF (("Here: %s", exprNode_unparse (s)));
4273 exprNode_checkUse (ret, s->sref, s->loc);
4274 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4276 cstring_markOwned (sn);
4277 ret->sref = sRef_makeArrow (s->sref, sn);
4279 ret->kind = XPR_ARROW;
4284 message ("Arrow access field of non-struct or union "
4285 "pointer (%t): %s->%s",
4286 t, exprNode_unparse (s), f),
4289 ret->typ = ctype_unknown;
4290 ret->sref = sRef_undefined;
4295 else /* its not a pointer */
4297 if (!ctype_isUnknown (tr))
4301 message ("Arrow access of non-pointer (%t): %s->%s",
4302 t, exprNode_unparse (s), f),
4305 ret->typ = ctype_unknown;
4306 ret->sref = sRef_undefined;
4310 cstring sn = cstring_copy (f);
4312 DPRINTF (("Here: %s", exprNode_unparse (s)));
4314 exprNode_checkUse (ret, s->sref, s->loc);
4315 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4317 cstring_markOwned (sn);
4318 ret->sref = sRef_makeArrow (s->sref, sn);
4320 ret->kind = XPR_ARROW;
4331 exprNode_arrowAccess (/*@only@*/ exprNode s,
4332 /*@only@*/ lltok arrow,
4333 /*@only@*/ cstring f)
4335 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4341 ** only postOp's in C: i++ and i--
4345 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4347 /* check modification also */
4348 /* cstring opname = lltok_unparse (op);*/
4350 exprNode ret = exprNode_createPartialCopy (e);
4352 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4353 ret->kind = XPR_POSTOP;
4354 ret->edata = exprData_makeUop (e, op);
4356 if (!exprNode_isDefined (e))
4361 checkMacroParen (e);
4363 exprNode_checkUse (ret, e->sref, e->loc);
4364 exprNode_checkSet (ret, e->sref);
4366 t = exprNode_getType (e);
4368 if (sRef_isUnsafe (e->sref))
4370 voptgenerror (FLG_MACROPARAMS,
4371 message ("Operand of %s is macro parameter (non-functional): %s%s",
4372 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4374 sRef_makeSafe (e->sref);
4375 sRef_makeSafe (ret->sref);
4378 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4384 if (ctype_isRealAbstract (t))
4388 message ("Operand of %s is abstract type (%t): %s",
4389 lltok_unparse (op), t, exprNode_unparse (e)),
4396 message ("Operand of %s is non-numeric (%t): %s",
4397 lltok_unparse (op), t, exprNode_unparse (e)),
4400 ret->typ = ctype_unknown;
4403 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4405 exprNode_checkModify (e, ret);
4407 /* added 7/11/2000 D.L */
4409 /*DRL 6/8/01 I decided to disable all Splint warnings here since the code
4410 probably needs a rewrite any way */
4415 /* updateEnvironmentForPostOp (e); */
4417 /* start modifications */
4418 /* added by Seejo on 4/16/2000 */
4420 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4422 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4424 ret->sref = sRef_copy (e->sref);
4427 if (lltok_getTok (op) == INC_OP) {
4428 if (sRef_getSize(e->sref) > 0) {
4430 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4432 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4433 /* Assumption: there is only 1 \0 in the buffer */
4434 /* This will not be correct if there are 2 \0's in the buffer */
4435 sRef_setNotNullTerminatedState(ret->sref);
4436 sRef_resetLen(ret->sref);
4438 sRef_setNullTerminatedState(ret->sref);
4439 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4441 if (sRef_isNullTerminated (ret->sref))
4442 printf ("ret->sref is Null Terminated\n");
4443 else if (sRef_isPossiblyNullTerminated (ret->sref))
4444 printf ("ret->sref is Possibly Null Terminated\n");
4445 else if (sRef_isNotNullTerminated (ret->sref))
4446 printf ("ret->sref is Not Null Terminated\n");
4451 if (lltok_getTok (op) == DEC_OP) {
4452 if (sRef_getSize(e->sref) >= 0) {
4453 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4454 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4459 /* end modifications */
4465 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4467 bool checkMod = FALSE;
4469 int opid = lltok_getTok (op);
4470 exprNode ret = exprNode_createSemiCopy (e);
4472 exprNode_copySets (ret, e);
4474 multiVal_free (ret->val);
4475 ret->val = multiVal_undefined;
4476 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4477 ret->kind = XPR_PREOP;
4478 ret->edata = exprData_makeUop (e, op);
4480 if (exprNode_isError (e))
4485 checkMacroParen (e);
4487 te = exprNode_getType (e);
4488 tr = ctype_realType (te);
4490 if (opid != TAMPERSAND)
4492 exprNode_checkUse (ret, e->sref, e->loc);
4494 if (ctype_isRealAbstract (tr)
4495 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4497 if (optgenerror (FLG_ABSTRACT,
4498 message ("Operand of %s is abstract type (%t): %s",
4499 lltok_unparse (op), tr,
4500 exprNode_unparse (ret)),
4503 tr = te = ctype_unknown;
4504 ret->typ = ctype_unknown;
4505 sRef_setNullError (e->sref);
4513 case DEC_OP: /* should also check modification! */
4514 if (sRef_isMacroParamRef (e->sref))
4518 message ("Operand of %s is macro parameter (non-functional): %s",
4519 lltok_unparse (op), exprNode_unparse (ret)),
4524 exprNode_checkSet (ret, e->sref);
4527 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4532 if (context_msgStrictOps ())
4536 message ("Operand of %s is non-numeric (%t): %s",
4537 lltok_unparse (op), te, exprNode_unparse (ret)),
4540 ret->typ = ctype_int;
4543 /* start modifications */
4544 /* added by Seejo on 4/16/2000 */
4546 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4548 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4550 ret->sref = sRef_copy (e->sref);
4553 if (lltok_getTok (op) == INC_OP) {
4554 if (sRef_getSize(e->sref) > 0) {
4556 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4558 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4559 /* Assumption: there is only 1 \0 in the buffer */
4560 /* This will not be correct if there are 2 \0's in the buffer */
4561 sRef_setNotNullTerminatedState(ret->sref);
4562 sRef_resetLen (ret->sref);
4564 sRef_setNullTerminatedState(ret->sref);
4565 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4571 if (lltok_getTok (op) == DEC_OP) {
4572 if (sRef_getSize(e->sref) >= 0) {
4573 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4574 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4579 /* end modifications */
4586 if (ctype_isForceRealNumeric (&tr))
4590 ret->val = multiVal_invert (exprNode_getValue (e));
4594 ret->val = multiVal_copy (exprNode_getValue (e));
4599 if (context_msgStrictOps ())
4603 message ("Operand of %s is non-numeric (%t): %s",
4604 lltok_unparse (op), te, exprNode_unparse (ret)),
4608 ret->typ = ctype_int;
4612 case TEXCL: /* maybe this should be restricted */
4613 guardSet_flip (ret->guards);
4615 if (ctype_isRealBool (te) || ctype_isUnknown (te))
4621 if (ctype_isRealPointer (tr))
4623 if (sRef_isKnown (e->sref))
4625 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4629 (FLG_BOOLOPS, FLG_PTRNEGATE,
4630 message ("Operand of %s is non-boolean (%t): %s",
4631 lltok_unparse (op), te, exprNode_unparse (ret)),
4638 message ("Operand of %s is non-boolean (%t): %s",
4639 lltok_unparse (op), te, exprNode_unparse (ret)),
4643 ret->typ = ctype_bool;
4648 if (ctype_isForceRealInt (&tr))
4653 if (context_msgStrictOps ())
4657 message ("Operand of %s is non-integer (%t): %s",
4658 lltok_unparse (op), te, exprNode_unparse (ret)),
4662 if (ctype_isInt (e->typ))
4668 ret->typ = ctype_int;
4674 ret->typ = ctype_makePointer (e->typ);
4676 if (sRef_isKnown (e->sref))
4678 ret->sref = sRef_makeAddress (e->sref);
4685 if (ctype_isAP (tr))
4687 ret->typ = ctype_baseArrayPtr (e->typ);
4691 if (ctype_isKnown (te))
4693 if (ctype_isFunction (te))
4699 message ("Dereference of function type (%t): %s",
4700 te, exprNode_unparse (ret)),
4705 voptgenerror (FLG_TYPE,
4706 message ("Dereference of non-pointer (%t): %s",
4707 te, exprNode_unparse (ret)),
4709 ret->typ = ctype_unknown;
4714 ret->typ = ctype_unknown;
4719 if (sRef_isKnown (e->sref))
4721 DPRINTF (("Checking possibly null: %s", sRef_unparseFull (e->sref)));
4723 if (sRef_possiblyNull (e->sref))
4725 DPRINTF (("Checking possibly null: %s", sRef_unparse (e->sref)));
4726 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4730 message ("Dereference of %s pointer %q: %s",
4731 sRef_nullMessage (e->sref),
4732 sRef_unparse (e->sref),
4733 exprNode_unparse (ret)),
4736 sRef_showNullInfo (e->sref);
4737 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4742 ret->sref = sRef_makePointer (e->sref);
4747 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4752 exprNode_checkModify (e, ret);
4759 ** any reason to disallow sizeof (abstract type) ?
4763 ** used by both sizeof
4767 ctype sizeof_resultType (void)
4769 static ctype sizet = ctype_unknown;
4771 if (ctype_isUnknown (sizet))
4773 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4775 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4779 sizet = ctype_ulint;
4786 exprNode_sizeofType (/*@only@*/ qtype qt)
4788 exprNode ret = exprNode_create (sizeof_resultType ());
4789 ctype ct = qtype_getType (qt);
4791 ret->kind = XPR_SIZEOFT;
4792 ret->edata = exprData_makeSizeofType (qt);
4794 voptgenerror (FLG_SIZEOFTYPE,
4795 message ("Parameter to sizeof is type %s: %s",
4797 exprNode_unparse (ret)),
4804 exprNode_alignofType (/*@only@*/ qtype qt)
4806 exprNode ret = exprNode_create (sizeof_resultType ());
4807 ctype ct = qtype_getType (qt);
4809 ret->kind = XPR_ALIGNOFT;
4810 ret->edata = exprData_makeSizeofType (qt);
4812 voptgenerror (FLG_SIZEOFTYPE,
4813 message ("Parameter to alignof is type %s: %s",
4815 exprNode_unparse (ret)),
4821 exprNode exprNode_offsetof (qtype qt, cstringList s)
4823 exprNode ret = exprNode_create (sizeof_resultType ());
4824 ctype ct = qtype_getType (qt);
4826 ret->kind = XPR_OFFSETOF;
4827 ret->edata = exprData_makeOffsetof (qt, s);
4829 if (!ctype_isRealSU (ct))
4831 voptgenerror (FLG_TYPE,
4832 message ("First parameter to offsetof is not a "
4833 "struct or union type (type %s): %s",
4835 exprNode_unparse (ret)),
4842 cstringList_elements (s, el) {
4846 if (ctype_isUndefined (lt))
4850 else if (!ctype_isRealSU (lt))
4852 voptgenerror (FLG_TYPE,
4853 message ("Inner offsetof type is not a "
4854 "struct or union type (type %s before field %s): %s",
4855 ctype_unparse (lt), el,
4856 exprNode_unparse (ret)),
4862 fields = ctype_getFields (ctype_realType (lt));
4863 fld = uentryList_lookupField (fields, el);
4864 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4866 if (uentry_isUndefined (fld))
4868 if (ctype_equal (lt, ct)) {
4869 voptgenerror (FLG_TYPE,
4870 message ("Field %s in offsetof is not the "
4871 "name of a field of %s: %s",
4874 exprNode_unparse (ret)),
4877 voptgenerror (FLG_TYPE,
4878 message ("Deep field %s in offsetof is not the "
4879 "name of a field of %s: %s",
4882 exprNode_unparse (ret)),
4888 lt = uentry_getType (fld);
4891 } end_cstringList_elements;
4893 /* Should report error if its a bit field - behavior is undefined! */
4900 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4904 if (exprNode_isUndefined (e))
4906 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4907 ret->edata = exprData_makeSingle (e);
4908 ret->typ = sizeof_resultType ();
4909 ret->kind = XPR_SIZEOF;
4913 uentry u = exprNode_getUentry (e);
4915 ret = exprNode_createPartialCopy (e);
4916 ret->edata = exprData_makeSingle (e);
4918 ret->typ = sizeof_resultType ();
4919 ret->kind = XPR_SIZEOF;
4921 if (uentry_isValid (u)
4922 && uentry_isRefParam (u)
4923 && ctype_isRealArray (uentry_getType (u)))
4926 (FLG_SIZEOFFORMALARRAY,
4927 message ("Parameter to sizeof is an array-type function parameter: %s",
4928 exprNode_unparse (ret)),
4934 ** sizeof (x) doesn't "really" use x
4941 exprNode_alignofExpr (/*@only@*/ exprNode e)
4945 if (exprNode_isUndefined (e))
4947 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4951 ret = exprNode_createPartialCopy (e);
4954 ret->edata = exprData_makeSingle (e);
4955 ret->typ = sizeof_resultType ();
4956 ret->kind = XPR_ALIGNOF;
4959 ** sizeof (x) doesn't "really" use x
4966 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4972 if (exprNode_isError (e))
4976 return exprNode_undefined;
4979 checkMacroParen (e);
4981 c = qtype_getType (q);
4982 t = exprNode_getType (e);
4984 ret = exprNode_createPartialCopy (e);
4986 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4988 ret->kind = XPR_CAST;
4989 ret->edata = exprData_makeCast (tok, e, q);
4991 ret->sref = sRef_copy (e->sref);
4993 if (!sRef_isConst (e->sref))
4995 usymtab_addForceMustAlias (ret->sref, e->sref);
4998 sRef_setTypeFull (ret->sref, c);
4999 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
5005 ** void * <-> abstract * (if FLG_ABSTVOIDP)
5006 ** abstract * <-> void * (if FLG_ABSTVOIDP)
5009 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
5013 else if (ctype_isRealAP (c)) /* casting to array or pointer */
5015 ctype bc = ctype_getBaseType (c);
5016 ctype bt = ctype_getBaseType (t);
5017 ctype rt = ctype_realType (t);
5019 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
5020 && (ctype_isArrayPtr (rt)
5021 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5025 message ("Cast from function pointer type (%t) to "
5026 "non-function pointer (%t): %s",
5027 c, t, exprNode_unparse (ret)),
5031 if (!ctype_isFunction (ctype_baseArrayPtr (c))
5032 && (ctype_isArrayPtr (rt)
5033 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5037 message ("Cast from non-function pointer type (%t) to "
5038 "function pointer (%t): %s",
5039 c, t, exprNode_unparse (ret)),
5043 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
5044 !(ctype_isRealAbstract (bc)
5045 && context_hasAccess (ctype_typeId (bc))))
5047 ; /* okay to cast zero */
5051 if (ctype_isRealAbstract (bc)
5052 && !context_hasAccess (ctype_typeId (bc)))
5054 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
5058 message ("Cast to underlying abstract type %t: %s",
5059 c, exprNode_unparse (ret)),
5066 message ("Cast to underlying abstract type %t: %s",
5067 c, exprNode_unparse (ret)),
5072 if (ctype_isRealAbstract (bt)
5073 && !context_hasAccess (ctype_typeId (bt)))
5075 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
5079 message ("Cast from underlying abstract type %t: %s",
5080 t, exprNode_unparse (ret)),
5087 message ("Cast from underlying abstract type %t: %s",
5088 t, exprNode_unparse (ret)),
5096 ctype bt = ctype_realType (ctype_getBaseType (t));
5097 ctype bc = ctype_realType (ctype_getBaseType (c));
5099 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
5101 if (ctype_match (c, t))
5103 if (ctype_equal (c, t))
5107 message ("Redundant cast involving abstract type %t: %s",
5108 bt, exprNode_unparse (ret)),
5116 message ("Cast from abstract type %t: %s",
5117 bt, exprNode_unparse (ret)),
5122 if (ctype_isAbstract (bc)
5123 && !context_hasAccess (ctype_typeId (bc)))
5125 if (ctype_match (c, t))
5131 DPRINTF (("No access to: %s / %d",
5132 ctype_unparse (bc), ctype_typeId (bc)));
5133 DPRINTF (("Context %s %s",
5134 bool_unparse (context_inFunctionLike ()),
5135 context_unparse ()));
5138 message ("Cast to abstract type %t: %s", bc,
5139 exprNode_unparse (ret)),
5145 if (ctype_isAbstract (c))
5147 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
5149 /* okay, cast exposed to abstract */
5150 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
5154 if (ctype_isVisiblySharable (t)
5155 && sRef_isExternallyVisible (e->sref)
5156 && !(ctype_isAbstract (t)
5157 && context_hasAccess (ctype_typeId (t))))
5161 message ("Cast to abstract type from externally visible "
5162 "mutable storage exposes rep of %s: %s",
5164 exprNode_unparse (e)),
5174 evaluationOrderUndefined (lltok op)
5176 int opid = lltok_getTok (op);
5178 return (opid != AND_OP && opid != OR_OP);
5181 static bool checkIntegral (/*@notnull@*/ exprNode e1,
5182 /*@notnull@*/ exprNode e2,
5183 /*@notnull@*/ exprNode ret,
5188 ctype te1 = exprNode_getType (e1);
5189 ctype te2 = exprNode_getType (e2);
5191 ctype tr1 = ctype_realishType (te1);
5192 ctype tr2 = ctype_realishType (te2);
5194 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5200 if (context_msgStrictOps ())
5202 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5204 if (ctype_sameName (te1, te2))
5208 message ("Operands of %s are non-integer (%t): %s",
5209 lltok_unparse (op), te1,
5210 exprNode_unparse (ret)),
5217 message ("Operands of %s are non-integers (%t, %t): %s",
5218 lltok_unparse (op), te1, te2,
5219 exprNode_unparse (ret)),
5223 else if (!ctype_isInt (tr1))
5227 message ("Left operand of %s is non-integer (%t): %s",
5228 lltok_unparse (op), te1, exprNode_unparse (ret)),
5232 /* !ctype_isInt (te2) */
5236 message ("Right operand of %s is non-integer (%t): %s",
5237 lltok_unparse (op), te2, exprNode_unparse (ret)),
5247 ** returns exprNode representing e1 op e2
5249 ** uses msg if there are errors
5250 ** can be used for both assignment ops and regular ops
5255 static /*@only@*/ /*@notnull@*/ exprNode
5256 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
5257 /*@keep@*/ lltok op)
5259 ctype te1, te2, tr1, tr2, tret;
5260 int opid = lltok_getTok (op);
5261 bool hasError = FALSE;
5264 if (exprNode_isError (e1))
5266 ret = exprNode_createPartialNVCopy (e2);
5270 ret = exprNode_createPartialNVCopy (e1);
5273 ret->val = multiVal_undefined;
5276 ret->edata = exprData_makeOp (e1, e2, op);
5278 if (exprNode_isError (e1) || exprNode_isError (e2))
5280 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5281 || opid == EQ_OP || opid == NE_OP
5282 || opid == AND_OP || opid == OR_OP)
5284 ret->typ = ctype_bool;
5287 if (exprNode_isDefined (e1))
5289 exprNode_checkUse (ret, e1->sref, e1->loc);
5292 if (exprNode_isDefined (e2))
5294 exprNode_mergeUSs (ret, e2);
5295 exprNode_checkUse (ret, e2->sref, e2->loc);
5301 tret = ctype_unknown;
5302 te1 = exprNode_getType (e1);
5304 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5306 te2 = exprNode_getType (e2);
5308 tr1 = ctype_realishType (te1);
5309 tr2 = ctype_realishType (te2);
5313 ret->guards = guardSet_or (ret->guards, e2->guards);
5315 else if (opid == AND_OP)
5317 ret->guards = guardSet_and (ret->guards, e2->guards);
5324 if (opid == EQ_OP || opid == NE_OP)
5326 exprNode temp1 = e1, temp2 = e2;
5328 /* could do NULL == x */
5330 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5332 temp1 = e2; temp2 = e1;
5335 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5337 reflectNullTest (temp1, (opid == NE_OP));
5338 guardSet_free (ret->guards);
5339 ret->guards = guardSet_copy (temp1->guards);
5343 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5344 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5349 if (anyAbstract (tr1, tr2) &&
5350 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
5351 (opid == AND_OP || opid == OR_OP
5352 || opid == EQ_OP || opid == NE_OP))))
5354 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
5356 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5358 /* unknown types, no comparisons possible */
5364 case TMULT: /* multiplication and division: */
5366 case MUL_ASSIGN: /* numeric, numeric -> numeric */
5367 case DIV_ASSIGN: /* */
5369 if (opid == TMULT || opid == MUL_ASSIGN)
5371 ret->val = multiVal_multiply (exprNode_getValue (e1),
5372 exprNode_getValue (e2));
5376 ret->val = multiVal_divide (exprNode_getValue (e1),
5377 exprNode_getValue (e2));
5380 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5383 case TPLUS: /* addition and subtraction: */
5384 case TMINUS: /* pointer, int -> pointer */
5385 case SUB_ASSIGN: /* int, pointer -> pointer */
5386 case ADD_ASSIGN: /* numeric, numeric -> numeric */
5388 if (opid == TPLUS || opid == ADD_ASSIGN)
5390 ret->val = multiVal_add (exprNode_getValue (e1),
5391 exprNode_getValue (e2));
5395 ret->val = multiVal_subtract (exprNode_getValue (e1),
5396 exprNode_getValue (e2));
5399 tr1 = ctype_fixArrayPtr (tr1);
5401 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5402 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5406 if (context_msgPointerArith ())
5410 message ("Pointer arithmetic (%t, %t): %s",
5411 te1, te2, exprNode_unparse (ret)),
5416 ** Swap terms so e1 is always the pointer
5419 if (ctype_isRealPointer (tr1))
5425 exprNode_swap (e1, e2);
5429 if (sRef_possiblyNull (e1->sref)
5430 && !usymtab_isGuarded (e1->sref))
5433 (FLG_NULLPOINTERARITH,
5434 message ("Pointer arithmetic involving possibly "
5435 "null pointer %s: %s",
5436 exprNode_unparse (e1),
5437 exprNode_unparse (ret)),
5441 ret->sref = sRef_copy (e1->sref);
5443 /* start modifications */
5444 /* added by Seejo on 4/16/2000 */
5446 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5448 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5451 added ugly fixed to stop
5452 program from crashing on point + int +int
5453 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5455 if (!multiVal_isInt (e2->val) )
5459 val = (int) multiVal_forceInt (e2->val);
5461 /* Operator : + or += */
5462 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5463 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5464 val should not result in a
5465 size < 0 (size = 0 is ok !) */
5467 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5469 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5470 sRef_setNotNullTerminatedState(ret->sref);
5471 sRef_resetLen (ret->sref);
5473 sRef_setNullTerminatedState(ret->sref);
5474 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5479 /* Operator : - or -= */
5480 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5481 if (sRef_getSize(e1->sref) >= 0) {
5482 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5483 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5488 /* end modifications */
5490 sRef_setNullError (ret->sref);
5493 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5494 ** since is points to storage that should not be deallocated
5495 ** through this pointer.
5498 if (sRef_isOnly (ret->sref)
5499 || sRef_isFresh (ret->sref))
5501 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5506 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5507 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5509 if (context_msgPointerArith ())
5513 message ("Pointer arithmetic (%t, %t): %s",
5514 te1, te2, exprNode_unparse (ret)),
5518 if (sRef_possiblyNull (e1->sref)
5519 && !usymtab_isGuarded (e1->sref))
5522 (FLG_NULLPOINTERARITH,
5523 message ("Pointer arithmetic involving possibly "
5524 "null pointer %s: %s",
5525 exprNode_unparse (e2),
5526 exprNode_unparse (ret)),
5530 ret->sref = sRef_copy (e2->sref);
5532 /* start modifications */
5533 /* added by Seejo on 4/16/2000 */
5535 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5538 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5539 int val = (int) multiVal_forceInt (e1->val);
5541 /* Operator : + or += */
5542 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5543 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5544 val should not result in a
5545 size < 0 (size = 0 is ok !) */
5547 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5549 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5550 sRef_setNotNullTerminatedState(ret->sref);
5551 sRef_resetLen (ret->sref);
5553 sRef_setNullTerminatedState(ret->sref);
5554 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5559 /* Operator : - or -= */
5560 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5561 if (sRef_getSize(e2->sref) >= 0) {
5562 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5563 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5567 /* end modifications */
5569 sRef_setNullError (ret->sref);
5572 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5573 ** since is points to storage that should not be deallocated
5574 ** through this pointer.
5577 if (sRef_isOnly (ret->sref)
5578 || sRef_isFresh (ret->sref)) {
5579 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5583 ret->sref = e2->sref;
5587 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5596 case TAMPERSAND: /* bitwise & */
5598 case TCIRC: /* ^ (XOR) */
5603 bool reported = FALSE;
5609 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5610 || opid == RIGHT_OP || opid == RIGHT_ASSIGN)
5613 ** evans 2002-01-01: fixed this to follow ISO 6.5.7.
5616 if (!ctype_isUnsigned (tr2)
5617 && !exprNode_isNonNegative (e2))
5619 reported = optgenerror
5621 message ("Right operand of %s may be negative (%t): %s",
5622 lltok_unparse (op), te2,
5623 exprNode_unparse (ret)),
5627 if (!ctype_isUnsigned (tr1)
5628 && !exprNode_isNonNegative (e1))
5630 reported = optgenerror
5631 (FLG_SHIFTIMPLEMENTATION,
5632 message ("Left operand of %s may be negative (%t): %s",
5633 lltok_unparse (op), te1,
5634 exprNode_unparse (ret)),
5639 ** Should check size of right operand also...
5645 if (!ctype_isUnsigned (tr1))
5647 if (exprNode_isNonNegative (e1)) {
5650 reported = optgenerror
5652 message ("Left operand of %s is not unsigned value (%t): %s",
5653 lltok_unparse (op), te1,
5654 exprNode_unparse (ret)),
5664 if (!ctype_isUnsigned (tr2))
5666 if (!exprNode_isNonNegative (e2)) {
5667 reported = optgenerror
5669 message ("Right operand of %s is not unsigned value (%t): %s",
5670 lltok_unparse (op), te2,
5671 exprNode_unparse (ret)),
5680 if (!checkIntegral (e1, e2, ret, op)) {
5681 te1 = ctype_unknown;
5685 DPRINTF (("Set: %s", ctype_unparse (te1)));
5688 ** tret is the widest type of te1 and te2
5691 tret = ctype_widest (te1, te2);
5696 if (checkIntegral (e1, e2, ret, op)) {
5699 tret = ctype_unknown;
5704 case TLT: /* comparisons */
5705 case TGT: /* numeric, numeric -> bool */
5707 DPRINTF (("Here we go: %s / %s",
5708 ctype_unparse (tr1), ctype_unparse (tr2)));
5710 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5711 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5714 bool fepsilon = FALSE;
5716 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5721 if (opid == TLT || opid == TGT)
5723 uentry ue1 = exprNode_getUentry (e1);
5724 uentry ue2 = exprNode_getUentry (e2);
5727 ** FLT_EPSILON, etc. really is a variable, not
5731 if (uentry_isVariable (ue1))
5733 cstring uname = uentry_rawName (ue1);
5735 if (cstring_equalLit (uname, "FLT_EPSILON")
5736 || cstring_equalLit (uname, "DBL_EPSILON")
5737 || cstring_equalLit (uname, "LDBL_EPSILON"))
5743 if (uentry_isVariable (ue2))
5745 cstring uname = uentry_rawName (ue2);
5747 if (cstring_equalLit (uname, "FLT_EPSILON")
5748 || cstring_equalLit (uname, "DBL_EPSILON")
5749 || cstring_equalLit (uname, "LDBL_EPSILON"))
5758 ; /* Don't complain. */
5764 message ("Dangerous comparison involving %s types: %s",
5765 ctype_unparse (rtype),
5766 exprNode_unparse (ret)),
5775 ** Types should match.
5778 DPRINTF (("Match types: %s / %s", exprNode_unparse (e1),
5779 exprNode_unparse (e2)));
5781 if (!exprNode_matchTypes (e1, e2))
5783 hasError = gentypeerror
5785 message ("Operands of %s have incompatible types (%t, %t): %s",
5786 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5792 || (ctype_isForceRealNumeric (&tr1)
5793 && ctype_isForceRealNumeric (&tr2)) ||
5794 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5800 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5801 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5805 message ("Comparison of pointer and numeric (%t, %t): %s",
5806 te1, te2, exprNode_unparse (ret)),
5811 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5816 /* certain comparisons on unsigned's and zero look suspicious */
5818 if (opid == TLT || opid == LE_OP || opid == GE_OP)
5820 if ((ctype_isUnsigned (tr1) && exprNode_isZero (e2))
5821 || (ctype_isUnsigned (tr2) && exprNode_isZero (e1)))
5824 (FLG_UNSIGNEDCOMPARE,
5825 message ("Comparison of unsigned value involving zero: %s",
5826 exprNode_unparse (ret)),
5831 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5833 if ((opid == EQ_OP || opid == NE_OP) &&
5834 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5837 ** is one a variable?
5840 if (uentry_isVariable (exprNode_getUentry (e1))
5841 || uentry_isVariable (exprNode_getUentry (e2)))
5844 ** comparisons with FALSE are okay
5847 if (exprNode_isFalseConstant (e1)
5848 || exprNode_isFalseConstant (e2))
5857 ("Use of %q with %s variables (risks inconsistency because "
5858 "of multiple true values): %s",
5859 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5860 context_printBoolName (), exprNode_unparse (ret)),
5867 case AND_OP: /* bool, bool -> bool */
5870 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5876 if (context_maybeSet (FLG_BOOLOPS))
5878 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5880 if (ctype_sameName (te1, te2))
5884 message ("Operands of %s are non-boolean (%t): %s",
5885 lltok_unparse (op), te1,
5886 exprNode_unparse (ret)),
5894 ("Operands of %s are non-booleans (%t, %t): %s",
5895 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5899 else if (!ctype_isRealBool (te1))
5903 message ("Left operand of %s is non-boolean (%t): %s",
5904 lltok_unparse (op), te1, exprNode_unparse (ret)),
5907 else if (!ctype_isRealBool (te2))
5911 message ("Right operand of %s is non-boolean (%t): %s",
5912 lltok_unparse (op), te2, exprNode_unparse (ret)),
5925 (cstring_makeLiteral
5926 ("There has been a problem in the parser. This is believed to result "
5927 "from a problem with bison v. 1.25. Please try rebuidling Splint "
5928 "using the pre-compiled grammar files by commenting out the "
5929 "BISON= line in the top-level Makefile."));
5934 DPRINTF (("Return type: %s", ctype_unparse (tret)));
5937 exprNode_checkUse (ret, e1->sref, e1->loc);
5938 exprNode_mergeUSs (ret, e2);
5939 exprNode_checkUse (ret, e2->sref, e2->loc);
5945 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5946 /*@only@*/ lltok op)
5950 checkMacroParen (e1);
5951 checkMacroParen (e2);
5953 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5955 checkExpressionDefined (e1, e2, op);
5958 ret = exprNode_makeOp (e1, e2, op);
5963 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5966 ** This is somewhat bogus!
5968 ** Assigning to a nested observer in a non-observer datatype
5969 ** should not produce an error.
5972 sRef ref = exprNode_getSref (e1);
5974 DPRINTF (("Check assign mod: %s",
5975 sRef_unparseFull (ref)));
5977 if (sRef_isObserver (ref)
5978 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
5979 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5981 sRef base = sRef_getBase (ref);
5983 if (sRef_isValid (base) && sRef_isObserver (base))
5985 exprNode_checkModify (e1, ret);
5989 exprNode_checkModifyVal (e1, ret);
5994 exprNode_checkModify (e1, ret);
5999 exprNode_assign (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2, /*@only@*/ lltok op)
6001 bool isalloc = FALSE;
6002 bool isjustalloc = FALSE;
6003 bool noalias = FALSE;
6006 DPRINTF (("%s [%s] <- %s [%s]",
6007 exprNode_unparse (e1),
6008 ctype_unparse (e1->typ),
6009 exprNode_unparse (e2),
6010 ctype_unparse (e2->typ)));
6012 if (lltok_getTok (op) != TASSIGN)
6014 ret = exprNode_makeOp (e1, e2, op);
6016 DPRINTF (("Here goes: %s %s",
6017 ctype_unparse (e1->typ),
6018 ctype_unparse (e2->typ)));
6020 if (exprNode_isDefined (e1)
6021 && exprNode_isDefined (e2))
6023 if (ctype_isNumeric (e2->typ)
6024 || ctype_isNumeric (e1->typ))
6026 /* Its a pointer arithmetic expression like ptr += i */
6033 ret = exprNode_createPartialCopy (e1);
6034 ret->kind = XPR_ASSIGN;
6035 ret->edata = exprData_makeOp (e1, e2, op);
6037 if (!exprNode_isError (e2))
6039 ret->sets = sRefSet_union (ret->sets, e2->sets);
6040 ret->msets = sRefSet_union (ret->msets, e2->msets);
6041 ret->uses = sRefSet_union (ret->uses, e2->uses);
6045 checkExpressionDefined (e1, e2, op);
6047 if (exprNode_isError (e1))
6049 if (!exprNode_isError (e2))
6051 ret->loc = fileloc_update (ret->loc, e2->loc);
6055 ret->loc = fileloc_update (ret->loc, g_currentloc);
6059 if (!exprNode_isError (e2))
6061 checkMacroParen (e2);
6064 if (exprNode_isDefined (e1))
6066 if (sRef_isMacroParamRef (e1->sref))
6068 if (context_inIterDef ())
6070 uentry ue = sRef_getUentry (e1->sref);
6072 if (uentry_isYield (ue))
6078 if (fileloc_isDefined (e1->loc))
6082 message ("Assignment to non-yield iter parameter: %q",
6083 sRef_unparse (e1->sref)),
6090 message ("Assignment to non-yield iter parameter: %q",
6091 sRef_unparse (e1->sref)),
6098 if (fileloc_isDefined (e1->loc))
6102 message ("Assignment to macro parameter: %q",
6103 sRef_unparse (e1->sref)),
6110 message ("Assignment to macro parameter: %q",
6111 sRef_unparse (e1->sref)),
6115 exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
6120 exprNode_checkAssignMod (e1, ret);
6123 if (exprNode_isDefined (e2))
6125 if (lltok_getTok (op) == TASSIGN)
6127 ctype te1 = exprNode_getType (e1);
6128 ctype te2 = exprNode_getType (e2);
6130 if (ctype_isVoid (te2))
6134 message ("Assignment of void value to %t: %s %s %s",
6135 te1, exprNode_unparse (e1),
6137 exprNode_unparse (e2)),
6140 else if (!ctype_forceMatch (te1, te2))
6142 if (exprNode_matchLiteral (te1, e2))
6150 message ("Assignment of %t to %t: %s %s %s",
6151 te2, te1, exprNode_unparse (e1),
6153 exprNode_unparse (e2)),
6159 /* Type checks okay */
6163 exprNode_mergeUSs (ret, e2);
6164 exprNode_checkUse (ret, e2->sref, e2->loc);
6166 DPRINTF (("Do assign! %s %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6173 doAssign (e1, e2, FALSE);
6176 ret->sref = e1->sref;
6180 if (exprNode_isDefined (e2))
6182 exprNode_mergeUSs (ret, e2);
6183 exprNode_checkUse (ret, e2->sref, e2->loc);
6187 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
6189 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
6192 isjustalloc = sRef_isJustAllocated (e1->sref);
6193 isalloc = sRef_isAllocated (e1->sref);
6195 if (sRef_isField (e1->sref))
6197 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
6199 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
6201 exprNode_checkUse (ret, root, e1->loc);
6207 ** be careful! this defines e1->sref.
6210 /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
6212 DPRINTF (("Setting: %s -> %s", exprNode_unparse (ret), sRef_unparse (e1->sref)));
6213 exprNode_checkSet (ret, e1->sref);
6217 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
6218 ? e2->loc : e1->loc);
6224 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
6233 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
6234 /*@keep@*/ exprNode elseclause)
6238 if (!exprNode_isError (pred))
6240 ret = exprNode_createPartialCopy (pred);
6241 checkMacroParen (pred);
6242 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
6244 if (!exprNode_isError (ifclause))
6246 checkMacroParen (ifclause); /* update macro counts! */
6248 if (!exprNode_isError (elseclause))
6250 checkMacroParen (elseclause);
6252 if (!exprNode_matchTypes (ifclause, elseclause))
6255 (exprNode_getType (ifclause),
6257 exprNode_getType (elseclause),
6259 message ("Conditional clauses are not of same type: "
6261 exprNode_unparse (ifclause),
6262 exprNode_getType (ifclause),
6263 exprNode_unparse (elseclause),
6264 exprNode_getType (elseclause)),
6267 ret->sref = sRef_undefined;
6268 ret->typ = ctype_unknown;
6273 /* for now...should merge the states */
6274 ret->sref = ifclause->sref;
6275 ret->typ = ifclause->typ;
6277 if (exprNode_isNullValue (ifclause))
6279 ret->typ = elseclause->typ;
6283 exprNode_checkUse (ret, pred->sref, pred->loc);
6284 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6285 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6287 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6292 ret->typ = ifclause->typ;
6294 exprNode_checkUse (pred, pred->sref, pred->loc);
6295 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6297 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6302 if (!exprNode_isError (elseclause))
6304 ret->typ = elseclause->typ;
6306 exprNode_checkUse (pred, pred->sref, pred->loc);
6307 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6309 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6313 else /* pred is error */
6315 if (!exprNode_isError (ifclause))
6317 ret = exprNode_createSemiCopy (ifclause);
6319 checkMacroParen (ifclause); /* update macro counts! */
6321 if (!exprNode_isError (elseclause))
6323 checkMacroParen (elseclause);
6325 ret->typ = ifclause->typ;
6327 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6330 (exprNode_getType (ifclause),
6332 exprNode_getType (elseclause),
6334 message ("Conditional clauses are not of same type: "
6336 exprNode_unparse (ifclause),
6337 exprNode_getType (ifclause),
6338 exprNode_unparse (elseclause),
6339 exprNode_getType (elseclause)),
6342 ret->typ = ctype_unknown;
6346 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6347 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6349 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6352 else if (!exprNode_isError (elseclause)) /* pred, if errors */
6354 ret = exprNode_createSemiCopy (ifclause);
6356 ret->typ = elseclause->typ;
6357 checkMacroParen (elseclause);
6359 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6360 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6362 else /* all errors! */
6364 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6368 ret->kind = XPR_COND;
6369 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
6371 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6373 exprNode_combineControl (ret, ifclause, elseclause);
6380 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6382 ctype totype = qtype_getType (qt);
6384 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6388 ** check use of va_arg : <valist>, type -> type
6391 if (exprNode_isError (arg))
6396 targ = exprNode_getType (arg);
6399 ** arg should have be a pointer
6402 if (!ctype_isUA (targ) ||
6403 (!usymId_equal (ctype_typeId (targ),
6404 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6408 message ("First argument to va_arg is not a va_list (type %t): %s",
6409 targ, exprNode_unparse (arg)),
6413 exprNode_checkSet (ret, arg->sref);
6417 ** return type is totype
6421 ret->kind = XPR_VAARG;
6422 ret->edata = exprData_makeCast (tok, arg, qt);
6427 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6429 exprNode ret = exprNode_createPlain (ctype_undefined);
6430 ret->kind = XPR_LABEL;
6431 ret->edata = exprData_makeLiteral (label);
6432 ret->isJumpPoint = TRUE;
6434 return (ret); /* for now, ignore label */
6437 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6439 if (exprNode_isDefined (stmt))
6441 stmt->isJumpPoint = TRUE;
6443 /* This prevent stray no return path errors, etc. */
6444 stmt->exitCode = XK_MUSTEXIT;
6450 bool exprNode_isDefaultMarker (exprNode e)
6452 if (exprNode_isDefined (e))
6454 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6460 bool exprNode_isCaseMarker (exprNode e)
6462 if (exprNode_isDefined (e))
6464 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6470 bool exprNode_isLabelMarker (exprNode e)
6472 if (exprNode_isDefined (e))
6474 return (e->kind == XPR_LABEL);
6480 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6482 exprNode ret = exprNode_createPartialCopy (test);
6484 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6486 if (exprNode_isError (test)) {
6490 exprNode_checkUse (ret, test->sref, test->loc);
6492 usymtab_setExitCode (ret->exitCode);
6496 usymtab_setMustBreak ();
6499 ret->edata = exprData_makeSingle (test);
6500 ret->isJumpPoint = TRUE;
6506 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6508 exprNode ret = exprNode_createPartialCopy (test);
6510 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6511 ret->edata = exprData_makePair (test, stmt);
6512 ret->isJumpPoint = TRUE;
6514 if (exprNode_isError (test))
6519 exprNode_checkUse (ret, test->sref, test->loc);
6521 if (exprNode_isError (stmt))
6526 exprNode_mergeUSs (ret, stmt);
6528 ret->exitCode = stmt->exitCode;
6529 ret->mustBreak = stmt->mustBreak;
6530 ret->canBreak = stmt->canBreak;
6532 usymtab_setExitCode (ret->exitCode);
6536 usymtab_setMustBreak ();
6543 /*@notnull@*/ /*@only@*/ exprNode
6544 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6546 exprNode ret = exprNode_createTok (def);
6548 ret->isJumpPoint = TRUE;
6549 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6554 exprNode_mayEscape (exprNode e)
6556 if (exprNode_isDefined (e))
6558 return exitkind_couldEscape (e->exitCode);
6564 exprNode_mustBreak (exprNode e)
6566 if (exprNode_isDefined (e))
6568 return e->mustBreak;
6575 exprNode_mustEscape (exprNode e)
6577 if (exprNode_isDefined (e))
6579 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6586 exprNode_errorEscape (exprNode e)
6588 if (exprNode_isDefined (e))
6590 return exitkind_isError (e->exitCode);
6596 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6598 exprNode ret = exprNode_createPartialCopy (e1);
6600 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6602 ret->edata = exprData_makePair (e1, e2);
6603 ret->kind = XPR_STMTLIST;
6605 if (exprNode_isDefined (e1))
6607 ret->isJumpPoint = e1->isJumpPoint;
6608 ret->canBreak = e1->canBreak;
6612 if (exprNode_isDefined (e2))
6614 ret->loc = fileloc_update (ret->loc, e2->loc);
6618 if (exprNode_isDefined (e2))
6620 ret->exitCode = e2->exitCode;
6621 ret->mustBreak = e2->mustBreak;
6622 if (e2->canBreak) ret->canBreak = TRUE;
6626 ** if e1 must return, then e2 is unreachable!
6629 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6631 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6632 && !(e2->isJumpPoint))
6634 if (context_getFlag (FLG_UNREACHABLE))
6638 if (e2->kind == XPR_STMT)
6640 nr = exprData_getUopNode (e2->edata);
6643 if ((nr->kind == XPR_TOK
6644 && lltok_isSemi (exprData_getTok (nr->edata))))
6646 /* okay to have unreachable ";" */
6647 ret->exitCode = XK_MUSTEXIT;
6648 ret->canBreak = TRUE;
6652 if (optgenerror (FLG_UNREACHABLE,
6653 message ("Unreachable code: %s",
6654 exprNode_unparseFirst (nr)),
6657 ret->isJumpPoint = TRUE;
6658 ret->mustBreak = FALSE;
6659 ret->exitCode = XK_ERROR;
6660 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6664 ret->exitCode = XK_MUSTEXIT;
6665 ret->canBreak = TRUE;
6673 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6676 ** We want a warning anytime we have:
6678 ** yyy; <<<- no break or return
6682 exprNode lastStmt = exprNode_lastStatement (e1);
6684 if (exprNode_isDefined (lastStmt)
6685 && !exprNode_mustEscape (lastStmt)
6686 && !exprNode_mustBreak (lastStmt)
6687 && !exprNode_isCaseMarker (lastStmt)
6688 && !exprNode_isDefaultMarker (lastStmt)
6689 && !exprNode_isLabelMarker (lastStmt))
6691 voptgenerror (FLG_CASEBREAK,
6693 ("Fall through case (no preceding break)"),
6700 exprNode_mergeUSs (ret, e2);
6702 usymtab_setExitCode (ret->exitCode);
6706 usymtab_setMustBreak ();
6709 DPRINTF (("==> %s", exprNode_unparse (ret)));
6713 exprNode exprNode_createTok (/*@only@*/ lltok t)
6715 exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6716 ret = exprNode_create (ctype_unknown);
6717 ret->kind = XPR_TOK;
6718 ret->edata = exprData_makeTok (t);
6722 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6724 if (!exprNode_isError (e))
6726 exprChecks_checkStatementEffect(e);
6729 return (exprNode_statementError (e, t));
6732 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6734 exprNode ret = exprNode_createPartialCopy (e);
6736 if (!exprNode_isError (e))
6738 if (e->kind != XPR_ASSIGN)
6740 exprNode_checkUse (ret, e->sref, e->loc);
6743 ret->exitCode = e->exitCode;
6744 ret->canBreak = e->canBreak;
6745 ret->mustBreak = e->mustBreak;
6748 ret->edata = exprData_makeUop (e, t);
6749 ret->kind = XPR_STMT;
6754 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6756 if (!exprNode_isError (e))
6758 if (e->kind != XPR_ASSIGN)
6760 exprNode_checkUse (e, e->sref, e->loc);
6767 void exprNode_produceGuards (exprNode pred)
6769 if (!exprNode_isError (pred))
6771 if (ctype_isRealPointer (pred->typ))
6773 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6776 exprNode_checkUse (pred, pred->sref, pred->loc);
6777 exprNode_resetSref (pred);
6781 exprNode exprNode_compoundStatementExpression (/*@only@*/ lltok tlparen, /*@only@*/ exprNode e)
6785 DPRINTF (("Compound: %s", exprNode_unparse (e)));
6787 if (!context_flagOn (FLG_GNUEXTENSIONS, exprNode_loc (e)))
6789 (void) llgenhinterror
6791 message ("Compound statement expressions is not supported by ISO C99"),
6792 message ("Use +gnuextensions to allow compound statement expressions (and other GNU language extensions) "
6793 "without this warning"),
6798 ** The type of a compoundStatementExpression is the type of the last statement
6801 llassert (exprNode_isBlock (e));
6802 laststmt = exprNode_lastStatement (e);
6804 DPRINTF (("Last statement: %s / %s", exprNode_unparse (laststmt), ctype_unparse (exprNode_getType (laststmt))));
6805 DPRINTF (("e: %s", exprNode_unparse (e)));
6806 e->typ = exprNode_getType (laststmt);
6807 return exprNode_addParens (tlparen, e);
6811 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6813 exprNode ret = exprNode_createPartialCopy (e);
6815 if (!exprNode_isError (e))
6817 ret->exitCode = e->exitCode;
6818 ret->canBreak = e->canBreak;
6819 ret->mustBreak = e->mustBreak;
6822 DPRINTF (("Block e: %s", exprNode_unparse (e)));
6823 ret->edata = exprData_makeSingle (e);
6824 ret->kind = XPR_BLOCK;
6825 DPRINTF (("Block: %s", exprNode_unparse (ret)));
6829 bool exprNode_isBlock (exprNode e)
6831 return (exprNode_isDefined (e)
6832 && ((e)->kind == XPR_BLOCK));
6835 bool exprNode_isStatement (exprNode e)
6837 return (exprNode_isDefined (e)
6838 && ((e)->kind == XPR_STMT));
6841 bool exprNode_isAssign (exprNode e)
6843 if (exprNode_isDefined (e))
6845 return (e->kind == XPR_ASSIGN);
6851 bool exprNode_isEmptyStatement (exprNode e)
6853 return (exprNode_isDefined (e)
6854 && (e->kind == XPR_TOK)
6855 && (lltok_isSemi (exprData_getTok (e->edata))));
6858 bool exprNode_isMultiStatement (exprNode e)
6860 return (exprNode_isDefined (e)
6861 && ((e->kind == XPR_FOR)
6862 || (e->kind == XPR_FORPRED)
6863 || (e->kind == XPR_IF)
6864 || (e->kind == XPR_IFELSE)
6865 || (e->kind == XPR_WHILE)
6866 || (e->kind == XPR_WHILEPRED)
6867 || (e->kind == XPR_DOWHILE)
6868 || (e->kind == XPR_BLOCK)
6869 || (e->kind == XPR_STMT)
6870 || (e->kind == XPR_STMTLIST)
6871 || (e->kind == XPR_SWITCH)));
6874 void exprNode_checkIfPred (exprNode pred)
6876 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6879 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6882 bool emptyErr = FALSE;
6884 if (context_maybeSet (FLG_IFEMPTY))
6886 if (exprNode_isEmptyStatement (tclause))
6888 emptyErr = optgenerror (FLG_IFEMPTY,
6890 ("Body of if statement is empty"),
6891 exprNode_loc (tclause));
6895 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6897 if (exprNode_isDefined (tclause)
6898 && !exprNode_isBlock (tclause))
6900 voptgenerror (FLG_IFBLOCK,
6902 ("Body of if statement is not a block: %s",
6903 exprNode_unparse (tclause)),
6904 exprNode_loc (tclause));
6908 if (exprNode_isError (pred))
6910 if (exprNode_isError (tclause))
6912 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6916 ret = exprNode_createPartialCopy (tclause);
6921 if (exprNode_mustEscape (pred))
6925 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6926 exprNode_loc (pred));
6929 /*! exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred); */ /*@i523@*/
6930 exprNode_checkUse (pred, pred->sref, pred->loc);
6932 if (!exprNode_isError (tclause))
6934 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
6937 ret = exprNode_createPartialCopy (pred);
6941 ret->edata = exprData_makePair (pred, tclause);
6943 ret->exitCode = XK_UNKNOWN;
6945 if (exprNode_isDefined (tclause))
6947 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
6948 ret->canBreak = tclause->canBreak;
6949 ret->sets = sRefSet_union (ret->sets, tclause->sets);
6950 ret->msets = sRefSet_union (ret->msets, tclause->msets);
6951 ret->uses = sRefSet_union (ret->uses, tclause->uses);
6954 ret->mustBreak = FALSE;
6959 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
6960 /*@only@*/ exprNode tclause,
6961 /*@only@*/ exprNode eclause)
6964 bool tEmptyErr = FALSE;
6965 bool eEmptyErr = FALSE;
6967 if (context_maybeSet (FLG_IFEMPTY))
6969 if (exprNode_isEmptyStatement (tclause))
6971 tEmptyErr = optgenerror
6974 ("Body of if clause of if statement is empty"),
6975 exprNode_loc (tclause));
6978 if (exprNode_isEmptyStatement (eclause))
6980 eEmptyErr = optgenerror
6983 ("Body of else clause of if statement is empty"),
6984 exprNode_loc (eclause));
6988 if (context_maybeSet (FLG_IFBLOCK))
6991 && exprNode_isDefined (tclause)
6992 && !exprNode_isBlock (tclause))
6994 voptgenerror (FLG_IFBLOCK,
6996 ("Body of if clause of if statement is not a block: %s",
6997 exprNode_unparse (tclause)),
6998 exprNode_loc (tclause));
7002 && exprNode_isDefined (eclause)
7003 && !exprNode_isBlock (eclause)
7004 && !(eclause->kind == XPR_IF)
7005 && !(eclause->kind == XPR_IFELSE))
7010 ("Body of else clause of if statement is not a block: %s",
7011 exprNode_unparse (eclause)),
7012 exprNode_loc (eclause));
7016 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
7018 if (exprNode_isDefined (eclause)
7019 && (eclause->kind == XPR_IF))
7021 voptgenerror (FLG_ELSEIFCOMPLETE,
7022 message ("Incomplete else if logic (no final else): %s",
7023 exprNode_unparse (eclause)),
7024 exprNode_loc (eclause));
7028 if (exprNode_isError (pred))
7030 if (exprNode_isError (tclause))
7032 if (exprNode_isError (eclause))
7034 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7038 ret = exprNode_createPartialCopy (eclause);
7043 ret = exprNode_createPartialCopy (tclause);
7046 else /* pred is okay */
7048 ret = exprNode_createPartialCopy (pred);
7050 if (exprNode_mustEscape (pred))
7054 message ("Predicate always exits: %s", exprNode_unparse (pred)),
7055 exprNode_loc (pred));
7058 /*@i3423 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);*/
7059 exprNode_checkUse (ret, pred->sref, pred->loc);
7061 exprNode_mergeCondUSs (ret, tclause, eclause);
7064 ret->kind = XPR_IFELSE;
7065 ret->edata = exprData_makeCond (pred, tclause, eclause);
7067 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
7069 exprNode_combineControl (ret, tclause, eclause);
7070 ret->loc = fileloc_update (ret->loc, eclause->loc);
7077 ** *allpaths <- TRUE iff all executions paths must go through the switch
7081 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
7083 exprNodeSList el = exprNode_flatten (e);
7084 bool mustReturn = TRUE; /* find a branch that doesn't */
7085 bool thisReturn = FALSE;
7086 bool hasDefault = FALSE;
7087 bool hasAllMembers = FALSE;
7088 bool inSwitch = FALSE;
7089 bool isEnumSwitch = FALSE;
7090 bool canBreak = FALSE;
7091 bool fallThrough = FALSE;
7092 ctype ct = ctype_unknown;
7093 enumNameSList usedEnums;
7096 if (exprNode_isDefined (test))
7101 ttype = ctype_realType (ct);
7103 if (ctype_isEnum (ttype))
7105 isEnumSwitch = TRUE;
7106 enums = ctype_elist (ttype);
7107 usedEnums = enumNameSList_new ();
7111 exprNodeSList_elements (el, current)
7114 DPRINTF ((message("checkSwitchExpr current = %s ", exprNode_unparse(current) ) ));
7116 if (exprNode_isDefined (current))
7118 switch (current->kind)
7125 (FLG_DUPLICATECASES,
7126 message ("Duplicate default cases in switch"),
7127 exprNode_loc (current));
7132 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
7140 exprNode st = exprData_getSingle (current->edata);
7141 uentry ue = exprNode_getUentry (st);
7143 if (uentry_isValid (ue))
7145 cstring cname = uentry_rawName (ue);
7147 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
7149 if (enumNameSList_member
7150 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
7153 (FLG_DUPLICATECASES,
7154 message ("Duplicate case in switch: %s",
7160 enumNameSList_addh (usedEnums, cname);
7167 message ("Case in switch not %s member: %s",
7168 ctype_unparse (ct), cname),
7175 if (inSwitch && !fallThrough)
7177 if (!thisReturn || canBreak)
7187 /*@switchbreak@*/ break;
7189 thisReturn = thisReturn || exprNode_mustEscape (current);
7190 canBreak = canBreak || current->canBreak;
7191 if (canBreak) fallThrough = FALSE;
7194 } end_exprNodeSList_elements;
7196 if (inSwitch) /* check the last one! */
7198 if (!thisReturn || canBreak)
7207 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
7208 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
7210 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
7212 voptgenerror (FLG_MISSCASE,
7213 message ("Missing case%s in switch: %q",
7214 cstring_makeLiteralTemp
7215 ((enumNameSList_size (unused) > 1) ? "s" : ""),
7216 enumNameSList_unparse (unused)),
7219 enumNameSList_free (unused);
7220 *allpaths = FALSE; /* evans 2002-01-01 */
7224 hasAllMembers = TRUE;
7228 enumNameSList_free (usedEnums);
7232 *allpaths = hasDefault;
7235 exprNodeSList_free (el);
7236 return ((hasDefault || hasAllMembers) && mustReturn);
7239 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
7241 exprNode ret = exprNode_createPartialCopy (e);
7244 DPRINTF (("Switch: %s", exprNode_unparse (s)));
7246 ret->kind = XPR_SWITCH;
7247 ret->edata = exprData_makePair (e, s);
7249 if (!exprNode_isError (s))
7251 exprNode fs = exprNode_firstStatement (s);
7252 ret->loc = fileloc_update (ret->loc, s->loc);
7254 if (exprNode_isUndefined (fs)
7255 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
7256 || exprNode_isDefaultMarker (fs)) {
7259 voptgenerror (FLG_FIRSTCASE,
7261 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
7266 if (!exprNode_isError (e))
7268 if (checkSwitchExpr (e, s, &allpaths))
7270 ret->exitCode = XK_MUSTRETURN;
7274 ret->exitCode = e->exitCode;
7277 ret->canBreak = e->canBreak;
7278 ret->mustBreak = e->mustBreak;
7282 ** exprNode.c:3883,32: Variable allpaths used before definition
7289 DPRINTF (("Context exit switch!"));
7290 context_exitSwitch (ret, allpaths);
7291 DPRINTF (("Context exit switch done!"));
7296 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
7297 /*@notnull@*/ exprNode body)
7299 sRefSet tuses = test->uses;
7301 if (!sRefSet_isEmpty (test->uses))
7303 sRefSet sets = sRefSet_newCopy (body->sets);
7304 bool hasError = TRUE;
7305 bool innerState = FALSE;
7306 sRefSet tuncon = sRefSet_undefined;
7308 sets = sRefSet_union (sets, test->sets);
7309 sets = sRefSet_union (sets, body->msets);
7310 sets = sRefSet_union (sets, test->msets);
7312 sRefSet_allElements (tuses, el)
7314 if (sRef_isUnconstrained (el))
7316 tuncon = sRefSet_insert (tuncon, el);
7320 if (sRefSet_member (sets, el))
7327 if (sRef_isInternalState (el)
7328 || sRef_isFileStatic (sRef_getRootBase (el)))
7332 } end_sRefSet_allElements ;
7336 sRefSet suncon = sRefSet_undefined;
7337 bool sinner = FALSE;
7339 sRefSet_allElements (sets, el)
7341 if (sRef_isUnconstrained (el))
7343 suncon = sRefSet_insert (suncon, el);
7345 else if (sRef_isInternalState (el))
7353 } end_sRefSet_allElements ;
7355 if (sinner && innerState)
7359 else if (sRefSet_isEmpty (tuncon)
7360 && sRefSet_isEmpty (suncon))
7365 ("Suspected infinite loop. No value used in loop test (%q) "
7366 "is modified by test or loop body.",
7367 sRefSet_unparsePlain (tuses)),
7372 if (sRefSet_isEmpty (tuncon))
7376 message ("Suspected infinite loop. No condition values "
7377 "modified. Modification possible through "
7378 "unconstrained calls: %q",
7379 sRefSet_unparsePlain (suncon)),
7386 message ("Suspected infinite loop. No condition values "
7387 "modified. Possible undetected dependency through "
7388 "unconstrained calls in loop test: %q",
7389 sRefSet_unparsePlain (tuncon)),
7395 sRefSet_free (sets);
7399 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7402 bool emptyErr = FALSE;
7404 if (context_maybeSet (FLG_WHILEEMPTY))
7406 if (exprNode_isEmptyStatement (b))
7408 emptyErr = optgenerror
7411 ("Body of while statement is empty"),
7416 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7418 if (exprNode_isDefined (b)
7419 && !exprNode_isBlock (b))
7421 if (context_inIterDef ()
7422 && (b->kind == XPR_STMTLIST
7423 || b->kind == XPR_TOK))
7429 voptgenerror (FLG_WHILEBLOCK,
7431 ("Body of while statement is not a block: %s",
7432 exprNode_unparse (b)),
7438 if (exprNode_isError (t))
7440 if (exprNode_isError (b))
7442 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7446 ret = exprNode_createPartialCopy (b);
7453 ret = exprNode_createPartialCopy (t);
7455 llassert (t->kind == XPR_WHILEPRED);
7457 test = exprData_getSingle (t->edata);
7459 if (!exprNode_isError (b) && exprNode_isDefined (test))
7461 if (context_maybeSet (FLG_INFLOOPS)
7462 || context_maybeSet (FLG_INFLOOPSUNCON))
7465 ** check that some variable in the predicate is set by the body
7466 ** if the predicate uses any variables
7469 checkInfiniteLoop (test, b);
7472 exprNode_mergeUSs (ret, b);
7474 if (exprNode_isDefined (b))
7476 ret->exitCode = exitkind_makeConditional (b->exitCode);
7481 ret->edata = exprData_makePair (t, b);
7482 ret->kind = XPR_WHILE;
7484 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7488 message ("Predicate always exits: %s", exprNode_unparse (t)),
7492 ret->exitCode = XK_NEVERESCAPE;
7495 ** If loop is infinite, and there is no break inside,
7496 ** exit code is never reach.
7499 if (exprNode_knownIntValue (t))
7501 if (!exprNode_isZero (t))
7503 if (exprNode_isDefined (b))
7507 /* Really, it means never reached. */
7508 ret->exitCode = XK_MUSTEXIT;
7518 ret->canBreak = FALSE;
7519 ret->mustBreak = FALSE;
7525 ** do { b } while (t);
7527 ** note: body passed as first argument
7530 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7534 DPRINTF (("Do while: %s / %s",
7535 exprNode_unparse (b), exprNode_unparse (t)));
7537 if (exprNode_isError (t))
7539 if (exprNode_isError (b))
7541 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7545 ret = exprNode_createPartialCopy (b);
7547 ret->exitCode = exitkind_makeConditional (b->exitCode);
7548 exprNode_checkUse (ret, b->sref, b->loc);
7549 ret->exitCode = b->exitCode;
7550 ret->canBreak = b->canBreak;
7551 ret->mustBreak = FALSE;
7556 DPRINTF (("Do while: %s / %s",
7557 exitkind_unparse (t->exitCode),
7558 exitkind_unparse (b->exitCode)));
7560 ret = exprNode_createPartialCopy (t);
7561 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7563 if (!exprNode_isError (b))
7566 ** forgot the copy's --- why wasn't this detected??
7569 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7570 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7571 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
7573 /* left this out --- causes and aliasing bug (infinite loop)
7574 should be detected?? */
7576 exprNode_checkUse (ret, b->sref, b->loc);
7577 exprNode_mergeUSs (ret, t);
7578 exprNode_checkUse (ret, t->sref, t->loc);
7580 /* evans 2001-10-05: while loop can break */
7581 ret->exitCode = exitkind_makeConditional (b->exitCode);
7583 DPRINTF (("Do while: %s",
7584 exitkind_unparse (ret->exitCode)));
7586 ret->canBreak = b->canBreak;
7588 /* Always FALSE for doWhile loops - break's when test is false */
7589 ret->mustBreak = FALSE; /* b->mustBreak; */
7593 context_exitDoWhileClause (t);
7595 ret->kind = XPR_DOWHILE;
7596 ret->edata = exprData_makePair (t, b);
7600 bool exprNode_loopMustExec (exprNode forPred)
7603 ** Returns true if it is obvious that the loop always executes at least once
7605 ** For now, we only identify the most obvious cases. Should be true anytime
7606 ** we can prove init => !test.
7609 if (exprNode_isDefined (forPred))
7611 exprNode init, test, inc;
7614 llassert (forPred->kind == XPR_FORPRED);
7616 edata = forPred->edata;
7617 init = exprData_getTripleInit (edata);
7618 test = exprData_getTripleTest (edata);
7619 inc = exprData_getTripleInc (edata);
7621 if (exprNode_isAssign (init))
7623 exprNode loopVar = exprData_getOpA (init->edata);
7624 exprNode loopInit = exprData_getOpB (init->edata);
7626 if (exprNode_isDefined (test) && test->kind == XPR_OP)
7628 exprNode testVar = exprData_getOpA (test->edata);
7629 exprNode testVal = exprData_getOpB (test->edata);
7630 lltok comp = exprData_getOpTok (test->edata);
7631 int opid = lltok_getTok (comp);
7633 DPRINTF (("Same storage: %s / %s", exprNode_unparse (loopVar),
7634 exprNode_unparse (testVar)));
7636 if (exprNode_sameStorage (loopVar, testVar))
7638 multiVal valinit = exprNode_getValue (loopInit);
7639 multiVal valtest = exprNode_getValue (testVal);
7641 DPRINTF (("Values: %s / %s", multiVal_unparse (valinit),
7642 multiVal_unparse (valtest)));
7644 if (multiVal_isInt (valinit) && multiVal_isInt (valtest))
7646 long v1 = multiVal_forceInt (valinit);
7647 long v2 = multiVal_forceInt (valtest);
7649 DPRINTF (("Here: %ld %ld", v1, v2));
7651 if ((opid == EQ_OP && v1 < v2)
7652 || (opid == NE_OP && v1 != v2)
7653 || (opid == TLT && v1 <= v2)
7654 || (opid == TGT && v1 >= v2)
7655 || (opid == LE_OP && v1 < v2)
7656 || (opid == GE_OP && v1 > v2))
7658 DPRINTF (("mustexec if inc"));
7667 DPRINTF (("loop must exec: FALSE"));
7671 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7674 bool emptyErr = FALSE;
7676 if (context_maybeSet (FLG_FOREMPTY))
7678 if (exprNode_isEmptyStatement (body))
7680 emptyErr = optgenerror
7683 ("Body of for statement is empty"),
7684 exprNode_loc (body));
7688 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7690 if (exprNode_isDefined (body)
7691 && !exprNode_isBlock (body))
7693 if (context_inIterDef ()
7694 && (body->kind == XPR_STMTLIST
7695 || body->kind == XPR_TOK))
7701 voptgenerror (FLG_FORBLOCK,
7703 ("Body of for statement is not a block: %s",
7704 exprNode_unparse (body)),
7705 exprNode_loc (body));
7711 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7714 if (exprNode_isError (body))
7716 ret = exprNode_createPartialCopy (inc);
7720 ret = exprNode_createPartialCopy (body);
7722 ret->exitCode = exitkind_makeConditional (body->exitCode);
7724 exprNode_mergeUSs (inc, body);
7726 if (exprNode_isDefined (inc))
7730 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7732 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7733 exprNode_freeShallow (tmp);
7735 context_clearMessageAnnote ();
7736 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7738 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7739 exprNode_freeShallow (tmp);
7741 context_clearMessageAnnote ();
7743 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7744 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7745 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7749 ret->kind = XPR_FOR;
7750 ret->edata = exprData_makePair (inc, body);
7752 if (exprNode_isDefined (inc)) {
7753 exprNode test = exprData_getTripleTest (inc->edata);
7755 if (exprNode_isUndefined (test)) {
7756 if (exprNode_isDefined (body)) {
7757 if (!body->canBreak) {
7758 /* Really, it means never reached. */
7759 ret->exitCode = XK_MUSTEXIT;
7769 ** for (init; test; inc)
7772 ** while (test) { body; inc; }
7774 ** Now: check use of init (may set vars for test)
7775 ** check use of test
7779 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7783 if (exprNode_isError (pred)) return guardSet_undefined;
7785 llassert (pred->kind == XPR_FORPRED);
7787 test = exprData_getTripleTest (pred->edata);
7789 if (!exprNode_isError (test))
7791 return (test->guards);
7794 return guardSet_undefined;
7797 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7799 exprNode ret = exprNode_createSemiCopy (test);
7801 if (exprNode_isDefined (test))
7803 exprNode_copySets (ret, test);
7804 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7805 exprNode_checkUse (ret, test->sref, test->loc);
7807 exprNode_produceGuards (test);
7809 ret->guards = guardSet_copy (test->guards);
7812 ret->edata = exprData_makeSingle (test);
7813 ret->kind = XPR_WHILEPRED;
7817 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7818 /*@only@*/ exprNode inc)
7823 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7826 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7828 if (!exprNode_isError (inc))
7830 ret = exprNode_createPartialCopy (inc);
7834 if (!exprNode_isError (init))
7836 ret = exprNode_createPartialCopy (init);
7838 else if (!exprNode_isError (test))
7840 ret = exprNode_createPartialCopy (test);
7844 ret = exprNode_createUnknown ();
7848 exprNode_mergeUSs (ret, init);
7850 if (exprNode_isDefined (init))
7852 exprNode_checkUse (ret, init->sref, init->loc);
7855 exprNode_mergeUSs (ret, test);
7857 if (exprNode_isDefined (test))
7859 exprNode_checkUse (ret, test->sref, test->loc);
7862 ret->kind = XPR_FORPRED;
7863 ret->edata = exprData_makeFor (init, test, inc);
7867 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7869 exprNode ret = exprNode_createUnknown ();
7871 if (context_inMacro ())
7873 voptgenerror (FLG_MACROSTMT,
7874 message ("Macro %s uses goto (not functional)",
7875 context_inFunctionName ()),
7879 ret->kind = XPR_GOTO;
7880 ret->edata = exprData_makeLiteral (label);
7881 ret->mustBreak = TRUE;
7882 ret->exitCode = XK_GOTO;
7883 ret->canBreak = TRUE;
7887 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7889 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7891 ret->kind = XPR_CONTINUE;
7892 ret->edata = exprData_makeTok (l);
7893 ret->canBreak = TRUE;
7894 ret->mustBreak = TRUE;
7896 if (qcontinue == QSAFEBREAK)
7900 else if (qcontinue == QINNERCONTINUE)
7902 if (!context_inDeepLoop ())
7905 (FLG_LOOPLOOPCONTINUE,
7906 cstring_makeLiteral ("Continue statement marked with innercontinue "
7907 "is not inside a nested loop"),
7908 exprNode_loc (ret));
7911 else if (qcontinue == BADTOK)
7913 if (context_inDeepLoop ())
7916 (FLG_LOOPLOOPCONTINUE,
7917 cstring_makeLiteral ("Continue statement in nested loop"),
7918 exprNode_loc (ret));
7923 llbuglit ("exprNode_continue: bad qcontinue");
7929 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
7931 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7932 clause breakClause = context_breakClause ();
7934 ret->kind = XPR_BREAK;
7935 ret->edata = exprData_makeTok (l);
7936 ret->canBreak = TRUE;
7937 ret->mustBreak = TRUE;
7939 if (breakClause == NOCLAUSE)
7943 cstring_makeLiteral ("Break not inside while, for or switch statement"),
7944 exprNode_loc (ret));
7948 if (bqual != BADTOK)
7955 if (breakClause == SWITCHCLAUSE)
7957 if (!context_inDeepSwitch ())
7959 voptgenerror (FLG_SYNTAX,
7961 ("Break preceded by innerbreak is not in a deep switch"),
7962 exprNode_loc (ret));
7967 if (!context_inDeepLoop ())
7969 voptgenerror (FLG_SYNTAX,
7971 ("Break preceded by innerbreak is not in a deep loop"),
7972 exprNode_loc (ret));
7977 if (breakClause == SWITCHCLAUSE)
7979 voptgenerror (FLG_SYNTAX,
7981 ("Break preceded by loopbreak is breaking a switch"),
7982 exprNode_loc (ret));
7986 if (breakClause != SWITCHCLAUSE)
7990 message ("Break preceded by switchbreak is breaking %s",
7991 cstring_makeLiteralTemp
7992 ((breakClause == WHILECLAUSE
7993 || breakClause == DOWHILECLAUSE) ? "a while loop"
7994 : (breakClause == FORCLAUSE) ? "a for loop"
7995 : (breakClause == ITERCLAUSE) ? "an iterator"
7997 exprNode_loc (ret));
8005 if (breakClause == SWITCHCLAUSE)
8007 clause nextBreakClause = context_nextBreakClause ();
8009 switch (nextBreakClause)
8011 case NOCLAUSE: break;
8017 (FLG_LOOPSWITCHBREAK,
8018 cstring_makeLiteral ("Break statement in switch inside loop"),
8019 exprNode_loc (ret));
8023 (FLG_SWITCHSWITCHBREAK,
8024 cstring_makeLiteral ("Break statement in switch inside switch"),
8025 exprNode_loc (ret));
8032 if (context_inDeepLoop ())
8036 cstring_makeLiteral ("Break statement in nested loop"),
8037 exprNode_loc (ret));
8041 if (context_inDeepLoopSwitch ())
8044 (FLG_SWITCHLOOPBREAK,
8045 cstring_makeLiteral ("Break statement in loop inside switch"),
8046 exprNode_loc (ret));
8056 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
8058 fileloc loc = lltok_getLoc (t);
8059 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
8061 context_returnFunction ();
8062 exprChecks_checkNullReturn (loc);
8064 ret->kind = XPR_NULLRETURN;
8065 ret->edata = exprData_makeTok (t);
8066 ret->exitCode = XK_MUSTRETURN;
8070 exprNode exprNode_return (/*@only@*/ exprNode e)
8074 if (exprNode_isError (e))
8076 ret = exprNode_createUnknown ();
8080 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
8082 exprNode_checkUse (ret, e->sref, e->loc);
8083 exprNode_checkReturn (e);
8086 context_returnFunction ();
8087 ret->kind = XPR_RETURN;
8088 ret->edata = exprData_makeSingle (e);
8089 ret->exitCode = XK_MUSTRETURN;
8094 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
8098 if (exprNode_isError (e1))
8100 if (exprNode_isError (e2))
8102 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
8106 ret = exprNode_createPartialCopy (e2);
8107 exprNode_checkUse (ret, e2->sref, e2->loc);
8108 ret->sref = e2->sref;
8113 ret = exprNode_createPartialCopy (e1);
8115 exprNode_checkUse (ret, e1->sref, e1->loc);
8117 if (!exprNode_isError (e2))
8119 exprNode_mergeUSs (ret, e2);
8120 exprNode_checkUse (ret, e2->sref, e2->loc);
8121 ret->sref = e2->sref;
8125 ret->kind = XPR_COMMA;
8126 ret->edata = exprData_makePair (e1, e2);
8128 if (exprNode_isDefined (e1))
8130 if (exprNode_isDefined (e2))
8134 if (exprNode_mustEscape (e1) || e1->mustBreak)
8138 message ("Second clause of comma expression is unreachable: %s",
8139 exprNode_unparse (e2)),
8143 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
8144 ret->mustBreak = e1->mustBreak || e2->mustBreak;
8145 ret->canBreak = e1->canBreak || e2->canBreak;
8149 if (exprNode_mustEscape (e1) || e1->mustBreak)
8153 message ("Second clause of comma expression is unreachable: %s",
8154 exprNode_unparse (e2)),
8158 ret->exitCode = e1->exitCode;
8159 ret->canBreak = e1->canBreak;
8164 if (exprNode_isDefined (e2))
8166 ret->exitCode = e2->exitCode;
8167 ret->mustBreak = e2->mustBreak;
8168 ret->canBreak = e2->canBreak;
8175 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
8177 ctype t1 = exprNode_getType (el);
8178 ctype t2 = exprNode_getType (val);
8179 bool hasError = FALSE;
8181 DPRINTF (("Check one init: %s / %s",
8182 exprNode_unparse (el),
8183 exprNode_unparse (val)));
8185 if (ctype_isUnknown (t1))
8187 voptgenerror (FLG_IMPTYPE,
8188 message ("Variable has unknown (implicitly int) type: %s",
8189 exprNode_unparse (el)),
8193 el->typ = ctype_int;
8196 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
8198 exprNodeList vals = exprData_getArgs (val->edata);
8200 DPRINTF (("Check one init: %s", exprNodeList_unparse (vals)));
8201 DPRINTF (("Type: %s", ctype_unparse (t1)));
8203 if (ctype_isRealAP (t1))
8208 if (ctype_isFixedArray (t1))
8210 int nelements = long_toInt (ctype_getArraySize (t1));
8212 DPRINTF (("Checked array: %s / %d",
8213 ctype_unparse (t1), nelements));
8215 if (exprNode_isStringLiteral (val))
8217 exprNode_checkStringLiteralLength (t1, val);
8221 if (exprNodeList_size (vals) != nelements)
8223 hasError = optgenerror
8224 (exprNodeList_size (vals) > nelements ? FLG_INITSIZE : FLG_INITALLELEMENTS,
8225 message ("Initializer block for "
8226 "%s has %d element%&, but declared as %s: %q",
8227 exprNode_unparse (el),
8228 exprNodeList_size (vals),
8230 exprNodeList_unparse (vals)),
8236 exprNodeList_elements (vals, oneval)
8238 cstring istring = message ("%d", i);
8241 (exprNode_fakeCopy (el),
8242 exprNode_numLiteral (ctype_int, istring,
8243 fileloc_copy (el->loc), i));
8245 if (exprNode_isDefined (newel))
8247 if (exprNodeList_size (vals) == 1
8248 && ctype_isString (exprNode_getType (oneval))
8249 && ctype_isChar (exprNode_getType (newel)))
8251 exprNode_freeIniter (newel);
8255 if (exprNode_checkOneInit (newel, oneval))
8260 if (nerrors > 3 && exprNodeList_size (vals) > 6)
8263 (message ("Additional initialization errors "
8264 "for %s not reported",
8265 exprNode_unparse (el)),
8267 exprNode_freeIniter (newel);
8272 exprNode_freeIniter (newel);
8277 exprNode_freeIniter (newel);
8282 cstring_free (istring);
8285 } end_exprNodeList_elements;
8288 else if (ctype_isStruct (ctype_realType (t1)))
8290 uentryList fields = ctype_getFields (t1);
8293 if (uentryList_size (fields) != exprNodeList_size (vals))
8295 if (uentryList_size (fields) > exprNodeList_size (vals))
8297 hasError = optgenerror
8299 message ("Initializer block for "
8300 "%s has %d field%&, but %s has %d field%&: %q",
8301 exprNode_unparse (el),
8302 exprNodeList_size (vals),
8304 uentryList_size (fields),
8305 exprNodeList_unparse (vals)),
8310 hasError = optgenerror
8312 message ("Initializer block for "
8313 "%s has %d field%&, but %s has %d field%&: %q",
8314 exprNode_unparse (el),
8315 exprNodeList_size (vals),
8317 uentryList_size (fields),
8318 exprNodeList_unparse (vals)),
8324 exprNodeList_elements (vals, oneval)
8326 uentry thisfield = uentryList_getN (fields, i);
8328 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8330 uentry_getName (thisfield));
8332 if (exprNode_isDefined (newel))
8334 if (exprNode_checkOneInit (newel, oneval))
8339 exprNode_freeIniter (newel);
8343 } end_exprNodeList_elements;
8346 /* evans 2001-12-30: added to fix bug reported by Jim Zelenka */
8347 else if (ctype_isUnion (ctype_realType (t1)))
8349 uentryList fields = ctype_getFields (t1);
8353 ** Union initializers set the first member always.
8356 DPRINTF (("Union initializer: %s / %s",
8357 exprNode_unparse (el), ctype_unparse (ctype_realType (t1))));
8359 if (exprNodeList_size (vals) != 1)
8361 hasError = optgenerror
8363 message ("Initializer block for union "
8364 "%s has %d elements, union initializers should have one element: %q",
8365 exprNode_unparse (el),
8366 exprNodeList_size (vals),
8367 exprNodeList_unparse (vals)),
8372 exprNode oneval = exprNodeList_head (vals);
8373 uentry thisfield = uentryList_getN (fields, i);
8375 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8377 uentry_getName (thisfield));
8379 if (exprNode_isDefined (newel))
8381 if (exprNode_checkOneInit (newel, oneval))
8386 exprNode_freeIniter (newel);
8392 hasError = optgenerror
8394 message ("Initializer block used for "
8395 "%s where %t is expected: %s",
8396 exprNode_unparse (el), t1, exprNode_unparse (val)),
8402 if (exprNode_isDefined (val))
8404 doAssign (el, val, TRUE);
8406 if (!exprNode_matchType (t1, val))
8408 hasError = gentypeerror
8410 message ("Initial value of %s is type %t, "
8412 exprNode_unparse (el),
8413 t2, t1, exprNode_unparse (val)),
8422 static /*@notnull@*/ exprNode
8423 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
8427 DPRINTF (("Initialization: %s", idDecl_unparse (t)));
8429 if (usymtab_exists (idDecl_observeId (t)))
8431 uentry ue = usymtab_lookup (idDecl_observeId (t));
8432 ret = exprNode_createId (ue);
8434 /*@i723 don't do this...but why? */
8436 ct = ctype_realishType (ret->typ);
8438 DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
8440 if (ctype_isUnknown (ct))
8442 if (uentry_isAnyTag (ue))
8446 message ("%s used but not previously declared: %s",
8447 uentry_ekindName (ue),
8448 idDecl_getName (t)),
8456 message ("Variable has unknown (implicitly int) type: %s",
8457 idDecl_getName (t)),
8469 DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
8471 ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
8472 /*!! fileloc_copy (g_currentloc)); */
8473 /*@i32!!! should get error without this */
8475 ret = exprNode_fromIdentifierAux (ue);
8478 ** No error - this happens in old style declarations:
8482 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8489 exprData_free (ret->edata, ret->kind);
8490 ret->edata = exprData_undefined;
8491 ret->exitCode = XK_NEVERESCAPE;
8492 ret->mustBreak = FALSE;
8493 ret->kind = XPR_INIT;
8497 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8499 exprNode ret = exprNode_makeInitializationAux (t);
8500 llassert (ret->edata == exprData_undefined);
8501 ret->edata = exprData_makeInit (t, exprNode_undefined);
8505 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8506 /*@only@*/ exprNode e)
8508 uentry ue = usymtab_lookup (idDecl_observeId (t));
8509 exprNode ret = exprNode_makeInitializationAux (t);
8510 fileloc loc = exprNode_loc (e);
8512 DPRINTF (("initialization: %s = %s", idDecl_unparse (t), exprNode_unparse (e)));
8514 if (exprNode_isError (e))
8516 e = exprNode_createUnknown ();
8517 /* error: assume initializer is defined */
8518 sRef_setDefined (ret->sref, g_currentloc);
8519 ret->edata = exprData_makeInit (t, e);
8523 ctype ct = ctype_realishType (ret->typ);
8528 ** was addSafeUse --- what's the problem?
8530 ** int x = 3, y = x ?
8533 exprData_free (ret->edata, ret->kind);
8534 ret->edata = exprData_makeInit (t, e);
8535 DPRINTF (("ret: %s", exprNode_unparse (ret)));
8537 exprNode_checkUse (ret, e->sref, e->loc);
8539 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8541 exprNode lhs = exprNode_createId (ue);
8544 ** static storage should be undefined before initializing
8547 if (uentry_isStatic (ue))
8549 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8552 (void) exprNode_checkOneInit (lhs, e);
8554 if (uentry_isStatic (ue))
8556 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8559 exprNode_free (lhs);
8563 if (!exprNode_matchType (ct, e))
8565 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
8572 (exprNode_getType (e), e, exprNode_getType (ret), ret,
8574 ("Variable %q initialized to type %t, expects %t: %s",
8575 uentry_getName (ue), exprNode_getType (e),
8576 exprNode_getType (ret),
8577 exprNode_unparse (e)),
8583 if (uentry_isStatic (ue))
8585 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8588 if (exprNode_isStringLiteral (e)
8589 && (ctype_isArray (ct))
8590 && (ctype_isChar (ctype_realType (ctype_baseArrayPtr (ct)))))
8593 ** If t is a char [], the literal is copied.
8598 if (multiVal_isDefined (e->val))
8600 slit = multiVal_forceString (e->val);
8604 slit = cstring_undefined;
8607 sRef_setDefState (ret->sref, SS_DEFINED, e->loc);
8608 ret->val = multiVal_copy (e->val);
8610 if (cstring_isDefined (slit))
8612 if (ctype_isFixedArray (ct))
8614 long int alength = ctype_getArraySize (ct);
8616 if (alength < cstring_length (slit) + 1)
8619 (FLG_LITERALOVERSIZE,
8620 ("Array initialized to string literal bigger than allocated size (literal is %d chars long (plus one for nul terminator), array size is %d): %s",
8621 cstring_length (slit),
8623 exprNode_unparse (e)),
8626 else if (alength > cstring_length (slit))
8629 (FLG_LITERALUNDERSIZE,
8630 ("Array initialized to string literal smaller than allocated size (literal is %d chars long (plus one for nul terminator), array size is %d), could waste storage: %s",
8631 cstring_length (slit),
8633 exprNode_unparse (e)),
8643 sRef_setNullTerminatedState (ret->sref);
8644 sRef_setSize (ret->sref, cstring_length (slit) + 1);
8645 sRef_setLen (ret->sref, cstring_length (slit) + 1);
8652 doAssign (ret, e, TRUE);
8655 if (uentry_isStatic (ue))
8657 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8661 if (context_inIterDef ())
8663 /* should check if it is yield */
8664 uentry_setUsed (ue, loc);
8671 exprNode_mergeUSs (ret, e);
8672 DPRINTF (("Ret: %s %p %p",
8673 exprNode_unparse (ret),
8674 ret->requiresConstraints,
8675 ret->ensuresConstraints));
8677 DPRINTF (("Ret: %s %s %s",
8678 exprNode_unparse (ret),
8679 constraintList_unparse (ret->requiresConstraints),
8680 constraintList_unparse (ret->ensuresConstraints)));
8684 exprNode exprNode_iter (/*@observer@*/ uentry name,
8685 /*@only@*/ exprNodeList alist,
8686 /*@only@*/ exprNode body,
8687 /*@observer@*/ uentry end)
8692 llassert (uentry_isValid (name));
8694 uentry_setUsed (name, exprNode_loc (body));
8696 ret = exprNode_createPartialCopy (body);
8697 iname = uentry_getName (name);
8699 if (uentry_isInvalid (end))
8701 llerror (FLG_ITERBALANCE,
8702 message ("Iter %s not balanced with end_%s", iname, iname));
8706 cstring ename = uentry_getName (end);
8708 if (!cstring_equalPrefixLit (ename, "end_"))
8710 llerror (FLG_ITERBALANCE, message ("Iter %s not balanced with end_%s: %s",
8711 iname, iname, ename));
8715 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8717 llerror (FLG_ITERBALANCE,
8718 message ("Iter %s not balanced with end_%s: %s",
8719 iname, iname, ename));
8723 cstring_free (ename);
8726 context_exitIterClause (body);
8728 ret->kind = XPR_ITER;
8729 ret->edata = exprData_makeIter (name, alist, body, end);
8731 if (uentry_isIter (name))
8733 (void) checkArgsReal (name, body,
8734 uentry_getParams (name), alist, TRUE, ret);
8737 cstring_free (iname);
8743 exprNode_iterNewId (/*@only@*/ cstring s)
8745 exprNode e = exprNode_new ();
8746 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8748 llassert (processingIterVars ());
8750 e->loc = context_getSaveLocation ();
8752 if (fileloc_isUndefined (e->loc))
8754 fileloc_free (e->loc);
8755 e->loc = fileloc_copy (g_currentloc);
8758 e->uses = sRefSet_new ();
8759 e->sets = sRefSet_new ();
8760 e->msets = sRefSet_new ();
8762 e->val = multiVal_unknown ();
8763 e->guards = guardSet_new ();
8764 e->sref = sRef_undefined;
8765 e->isJumpPoint = FALSE;
8766 e->exitCode = XK_NEVERESCAPE;
8768 /*> missing fields, detected by splint <*/
8769 e->canBreak = FALSE;
8770 e->mustBreak = FALSE;
8771 e->etext = cstring_undefined;
8773 if (uentry_isYield (ue))
8775 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8776 fileloc_copy (e->loc),
8780 uue = usymtab_supEntrySrefReturn (uue);
8782 sr = uentry_getSref (uue);
8783 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8784 sr = uentry_getSref (uue);
8785 sRef_setDefined (sr, e->loc);
8787 e->typ = uentry_getType (uue);
8789 e->edata = exprData_makeId (uue);
8790 uentry_setUsed (uue, g_currentloc);
8796 sRef_setGlobalScope ();
8797 uue = uentry_makeVariableLoc (s, ctype_unknown);
8799 e->typ = ctype_unknown;
8800 e->edata = exprData_makeId (uue);
8802 uentry_setUsed (uue, e->loc);
8803 uentry_setHasNameError (uue);
8805 if (context_getFlag (FLG_REPEATUNRECOG))
8807 uentry_markOwned (uue);
8811 usymtab_supGlobalEntry (uue);
8814 sRef_clearGlobalScope ();
8816 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8823 exprNode_defineConstraints(e);
8828 exprNode_iterExpr (/*@returned@*/ exprNode e)
8830 if (!processingIterVars ())
8832 llcontbuglit ("checkIterParam: not in iter");
8836 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8839 if (exprNode_isDefined (e))
8841 if (fileloc_isDefined (e->loc))
8845 message ("Yield parameter is not simple identifier: %s",
8846 exprNode_unparse (e)),
8853 message ("Yield parameter is not simple identifier: %s",
8854 exprNode_unparse (e)),
8864 exprNode_iterId (/*@observer@*/ uentry c)
8868 llassert (processingIterVars ());
8870 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8873 if (uentry_isYield (ue))
8875 ctype ct = uentry_getType (ue);
8876 exprNode e = exprNode_createPlain (ct);
8877 cstring name = uentry_getName (c);
8878 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8880 uentry_setUsed (ue, g_currentloc);
8881 uentry_setHasNameError (ue);
8883 cstring_free (name);
8886 e->edata = exprData_makeId (le);
8887 e->loc = context_getSaveLocation ();
8888 e->sref = uentry_getSref (le);
8890 usymtab_supEntrySref (le);
8892 if (!context_inHeader ())
8896 message ("Yield parameter shadows local declaration: %q",
8897 uentry_getName (c)),
8898 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8900 uentry_showWhereDeclared (c);
8907 return (exprNode_fromIdentifierAux (c));
8910 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8912 exprNode ret = exprNode_create (ctype_unknown);
8914 ret->kind = XPR_ITERCALL;
8915 ret->edata = exprData_makeIterCall (name, alist);
8917 if (uentry_isIter (name))
8919 uentryList params = uentry_getParams (name);
8921 if (context_inIterDef ()
8922 && uentryList_size (params) == exprNodeList_size (alist))
8926 exprNodeList_elements (alist, arg)
8928 uentry parg = uentryList_getN (params, i);
8930 if (uentry_isYield (parg))
8932 uentry ue = exprNode_getUentry (arg);
8934 if (uentry_isValid (ue))
8941 } end_exprNodeList_elements;
8944 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8945 checkUnspecCall (ret, params, alist);
8951 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8953 if (exprNode_isDefined (e))
8955 if (sRef_isInvalid (e->sref))
8958 e->sref = sRef_makeUnknown ();
8959 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8970 return sRef_undefined;
8974 /*@observer@*/ cstring
8975 exprNode_unparseFirst (exprNode e)
8977 if (exprNode_isDefined (e))
8981 if (e->kind == XPR_STMTLIST
8982 || e->kind == XPR_COMMA || e->kind == XPR_COND)
8984 exprNode first = exprData_getPairA (e->edata);
8986 if (exprNode_isDefined (first))
8988 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8992 return (cstring_makeLiteralTemp ("..."));
8996 ret = cstring_elide (exprNode_unparse (e), 20);
8997 cstring_markOwned (ret);
9003 return cstring_makeLiteralTemp ("<error>");
9007 /*@observer@*/ cstring
9008 exprNode_unparse (/*@temp@*/ exprNode e)
9010 if (exprNode_isError (e))
9012 return cstring_makeLiteralTemp ("<error>");
9015 if (cstring_isDefined (e->etext))
9021 cstring ret = exprNode_doUnparse (e);
9023 /*@-modifies@*/ /* benevolent */
9030 /*@observer@*/ fileloc
9031 exprNode_loc (exprNode e)
9033 if (exprNode_isError (e))
9035 return (g_currentloc);
9044 ** executes exprNode e
9045 ** recursively rexecutes as though in original parse using
9046 ** information in e->edata
9049 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
9051 exprNodeList ret = exprNodeList_new ();
9053 exprNodeList_elements (e, current)
9055 exprNodeList_addh (ret, exprNode_effect (current));
9056 } end_exprNodeList_elements;
9061 static /*@only@*/ exprNode exprNode_effect (exprNode e)
9062 /*@globals internalState@*/
9064 bool innerEffect = inEffect;
9070 context_clearJustPopped ();
9072 if (exprNode_isError (e))
9074 ret = exprNode_undefined;
9079 ** Turn off expose and dependent transfer checking.
9080 ** Need to pass exposed internal nodes,
9081 ** [ copying would be a waste! ]
9082 ** [ Actually, I think I wasted a lot more time than its worth ]
9083 ** [ trying to do this. ]
9087 /*@-observertrans@*/
9088 /*@-dependenttrans@*/
9095 ret = exprNode_addParens (exprData_getUopTok (data),
9096 exprNode_effect (exprData_getUopNode (data)));
9099 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
9100 exprNode_effect (exprData_getOpB (data)),
9101 exprData_getOpTok (data));
9104 ret = exprNode_undefined;
9107 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
9108 exprNodeList_effect (exprData_getArgs (data)));
9121 cstring id = exprData_getId (data);
9122 uentry ue = usymtab_lookupSafe (id);
9124 ret = exprNode_fromIdentifierAux (ue);
9125 ret->loc = fileloc_update (ret->loc, e->loc);
9132 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
9133 exprNode_effect (exprData_getPairB (data)));
9137 ** evans 2002-03-15: for && and ||, need to do the guards also
9138 ** this is what cgrammar.y does - should be
9139 ** able to avoid duplication, but need to
9140 ** time with grammar productions.
9143 DPRINTF (("Effect: %s", exprNode_unparse (e)));
9145 if (lltok_getTok (exprData_getOpTok (data)) == AND_OP)
9147 exprNode e1 = exprNode_effect (exprData_getOpA (data));
9149 exprNode_produceGuards (e1);
9150 context_enterAndClause (e1);
9151 e2 = exprNode_effect (exprData_getOpB (data));
9153 ret = exprNode_op (e1, e2,
9154 exprData_getOpTok (data));
9156 context_exitAndClause (ret, e2);
9158 else if (lltok_getTok (exprData_getOpTok (data)) == OR_OP)
9160 exprNode e1 = exprNode_effect (exprData_getOpA (data));
9162 exprNode_produceGuards (e1);
9163 context_enterOrClause (e1);
9164 e2 = exprNode_effect (exprData_getOpB (data));
9166 ret = exprNode_op (e1, e2,
9167 exprData_getOpTok (data));
9169 context_exitOrClause (ret, e2);
9173 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
9174 exprNode_effect (exprData_getOpB (data)),
9175 exprData_getOpTok (data));
9180 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
9181 exprData_getUopTok (data));
9184 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
9185 exprData_getUopTok (data));
9197 ret = exprNode_vaArg (exprData_getCastTok (data),
9198 exprNode_effect (exprData_getCastNode (data)),
9199 exprData_getCastType (data));
9203 ret = exprNode_cast (exprData_getCastTok (data),
9204 exprNode_effect (exprData_getCastNode (data)),
9205 exprData_getCastType (data));
9208 ret = exprNode_iterStart (exprData_getIterCallIter (data),
9210 (exprData_getIterCallArgs (data)));
9214 ret = exprNode_iter (exprData_getIterSname (data),
9215 exprNodeList_effect (exprData_getIterAlist (data)),
9216 exprNode_effect (exprData_getIterBody (data)),
9217 exprData_getIterEname (data));
9221 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
9222 exprNode_effect (exprData_getPairB (data)));
9226 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
9227 exprNode_effect (exprData_getTripleTest (data)),
9228 exprNode_effect (exprData_getTripleInc (data)));
9232 ret = exprNode_createTok (exprData_getTok (data));
9236 ret = exprNode_goto (exprData_getLiteral (data));
9237 ret->loc = fileloc_update (ret->loc, e->loc);
9241 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
9245 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
9249 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
9252 case XPR_NULLRETURN:
9253 ret = exprNode_nullReturn (exprData_getTok (data));
9257 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
9258 exprNode_effect (exprData_getPairB (data)));
9262 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
9263 exprNode_effect (exprData_getTripleTrue (data)),
9264 exprNode_effect (exprData_getTripleFalse (data)));
9267 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
9268 exprNode_effect (exprData_getPairB (data)));
9272 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
9273 exprNode_effect (exprData_getTripleTrue (data)),
9274 exprNode_effect (exprData_getTripleFalse (data)));
9277 ret = exprNode_whilePred (exprData_getSingle (data));
9281 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
9282 exprNode_effect (exprData_getPairB (data)));
9286 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
9287 exprNode_effect (exprData_getPairB (data)));
9291 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
9295 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
9296 exprData_getUopTok (data));
9300 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
9301 exprNode_effect (exprData_getPairB (data)));
9306 ret = exprNode_caseMarker
9307 (exprNode_effect (exprData_getSingle (data)),
9313 ret = exprNode_createTok (exprData_getTok (data));
9317 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
9318 exprNode_effect (exprData_getPairB (data)));
9322 ret = exprNode_makeInitialization
9323 (exprData_getInitId (data),
9324 exprNode_effect (exprData_getInitNode (data)));
9328 ret = exprNode_fieldAccessAux
9329 (exprNode_effect (exprData_getFieldNode (data)),
9330 exprNode_loc (exprData_getFieldNode (data)),
9331 cstring_copy (exprData_getFieldName (data)));
9335 ret = exprNode_arrowAccessAux
9336 (exprNode_effect (exprData_getFieldNode (data)),
9337 exprNode_loc (exprData_getFieldNode (data)),
9338 cstring_copy (exprData_getFieldName (data)));
9341 case XPR_STRINGLITERAL:
9355 /*@=observertrans@*/
9357 /*@=dependenttrans@*/
9368 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
9373 if (exprNode_isError (e))
9375 return cstring_undefined;
9383 ret = exprNode_rootVarName (exprData_getUopNode (data));
9386 ret = exprNode_rootVarName (exprData_getOpA (data));
9390 ret = exprData_getId (data);
9393 ret = idDecl_getName (exprData_getInitId (data));
9418 case XPR_NULLRETURN:
9440 case XPR_STRINGLITERAL:
9441 ret = cstring_undefined;
9448 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
9453 if (exprNode_isError (e))
9455 static /*@only@*/ cstring error = cstring_undefined;
9457 if (!cstring_isDefined (error))
9459 error = cstring_makeLiteral ("<error>");
9470 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
9473 ret = message ("%s %s %s",
9474 exprNode_unparse (exprData_getOpA (data)),
9475 lltok_unparse (exprData_getOpTok (data)),
9476 exprNode_unparse (exprData_getOpB (data)));
9479 ret = message ("%s(%q)",
9480 exprNode_unparse (exprData_getFcn (data)),
9481 exprNodeList_unparse (exprData_getArgs (data)));
9484 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
9487 ret = cstring_undefined;
9490 ret = message ("%s:", exprData_getId (data));
9494 ret = cstring_copy (exprData_getId (data));
9497 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
9498 exprNode_unparse (exprData_getPairB (data)));
9501 ret = message ("<body>");
9504 ret = message ("%s %s %s",
9505 exprNode_unparse (exprData_getOpA (data)),
9506 lltok_unparse (exprData_getOpTok (data)),
9507 exprNode_unparse (exprData_getOpB (data)));
9511 ret = message ("%s%s",
9512 lltok_unparse (exprData_getUopTok (data)),
9513 exprNode_unparse (exprData_getUopNode (data)));
9517 ret = message ("%s%s",
9518 exprNode_unparse (exprData_getUopNode (data)),
9519 lltok_unparse (exprData_getUopTok (data)));
9523 ret = message ("offsetof(%s,%q)",
9524 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
9525 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
9529 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9533 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
9537 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9541 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
9545 ret = message ("va_arg(%s, %q)",
9546 exprNode_unparse (exprData_getCastNode (data)),
9547 qtype_unparse (exprData_getCastType (data)));
9551 ret = message ("%q(%q)",
9552 uentry_getName (exprData_getIterCallIter (data)),
9553 exprNodeList_unparse (exprData_getIterCallArgs (data)));
9556 ret = message ("%q(%q) %s %q",
9557 uentry_getName (exprData_getIterSname (data)),
9558 exprNodeList_unparse (exprData_getIterAlist (data)),
9559 exprNode_unparse (exprData_getIterBody (data)),
9560 uentry_getName (exprData_getIterEname (data)));
9563 ret = message ("(%q)%s",
9564 qtype_unparse (exprData_getCastType (data)),
9565 exprNode_unparse (exprData_getCastNode (data)));
9569 ret = message ("%s %s",
9570 exprNode_unparse (exprData_getPairA (data)),
9571 exprNode_unparse (exprData_getPairB (data)));
9575 ret = message ("for (%s; %s; %s)",
9576 exprNode_unparse (exprData_getTripleInit (data)),
9577 exprNode_unparse (exprData_getTripleTest (data)),
9578 exprNode_unparse (exprData_getTripleInc (data)));
9582 ret = message ("goto %s", exprData_getLiteral (data));
9586 ret = cstring_makeLiteral ("continue");
9590 ret = cstring_makeLiteral ("break");
9594 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
9597 case XPR_NULLRETURN:
9598 ret = cstring_makeLiteral ("return");
9602 ret = message ("%s, %s",
9603 exprNode_unparse (exprData_getPairA (data)),
9604 exprNode_unparse (exprData_getPairB (data)));
9608 ret = message ("%s ? %s : %s",
9609 exprNode_unparse (exprData_getTriplePred (data)),
9610 exprNode_unparse (exprData_getTripleTrue (data)),
9611 exprNode_unparse (exprData_getTripleFalse (data)));
9614 ret = message ("if (%s) %s",
9615 exprNode_unparse (exprData_getPairA (data)),
9616 exprNode_unparse (exprData_getPairB (data)));
9620 ret = message ("if (%s) %s else %s",
9621 exprNode_unparse (exprData_getTriplePred (data)),
9622 exprNode_unparse (exprData_getTripleTrue (data)),
9623 exprNode_unparse (exprData_getTripleFalse (data)));
9626 ret = message ("while (%s) %s",
9627 exprNode_unparse (exprData_getPairA (data)),
9628 exprNode_unparse (exprData_getPairB (data)));
9632 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9636 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9640 ret = message ("do { %s } while (%s)",
9641 exprNode_unparse (exprData_getPairB (data)),
9642 exprNode_unparse (exprData_getPairA (data)));
9646 ret = message ("{ %s }", exprNode_unparse (exprData_getSingle (data)));
9647 /* evans 2002-02-20 was unparseFirst! */
9651 ret = message ("%s;", exprNode_unparse (exprData_getUopNode (data)));
9655 if (exprNode_isStatement (exprData_getPairA (data)))
9658 ** statement expressions already print the ;
9661 ret = message ("%s %s",
9662 exprNode_unparse (exprData_getPairA (data)),
9663 exprNode_unparse (exprData_getPairB (data)));
9667 ret = message ("%s; %s",
9668 exprNode_unparse (exprData_getPairA (data)),
9669 exprNode_unparse (exprData_getPairB (data)));
9675 ret = cstring_makeLiteral ("default:");
9679 ret = message ("switch (%s) %s",
9680 exprNode_unparse (exprData_getPairA (data)),
9681 exprNode_unparse (exprData_getPairB (data)));
9686 ret = message ("case %s:",
9687 exprNode_unparse (exprData_getSingle (data)));
9691 if (exprNode_isError (exprData_getInitNode (data)))
9693 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9697 ret = message ("%q = %s",
9698 idDecl_unparseC (exprData_getInitId (data)),
9699 exprNode_unparse (exprData_getInitNode (data)));
9704 ret = message ("%s.%s",
9705 exprNode_unparse (exprData_getFieldNode (data)),
9706 exprData_getFieldName (data));
9710 ret = message ("%s->%s",
9711 exprNode_unparse (exprData_getFieldNode (data)),
9712 exprData_getFieldName (data));
9715 case XPR_STRINGLITERAL:
9716 if (ctype_isWideString (e->typ))
9718 ret = message ("L\"%s\"", exprData_getLiteral (data));
9722 ret = message ("\"%s\"", exprData_getLiteral (data));
9727 ret = cstring_copy (exprData_getLiteral (data));
9731 ret = cstring_makeLiteral ("<node>");
9739 exprNode_isInitializer (exprNode e)
9741 return (exprNode_isDefined (e)
9742 && e->kind == XPR_INIT);
9746 exprNode_isCharLit (exprNode e)
9748 if (exprNode_isDefined (e))
9750 return (multiVal_isChar (exprNode_getValue (e)));
9759 exprNode_isNumLit (exprNode e)
9761 if (exprNode_isDefined (e))
9763 return (multiVal_isInt (exprNode_getValue (e)));
9772 exprNode_isFalseConstant (exprNode e)
9774 if (exprNode_isDefined (e))
9776 cstring s = exprNode_rootVarName (e);
9778 if (cstring_equal (s, context_getFalseName ()))
9788 exprNode_matchLiteral (ctype expected, exprNode e)
9790 if (exprNode_isDefined (e))
9792 multiVal m = exprNode_getValue (e);
9794 if (multiVal_isDefined (m))
9796 if (multiVal_isInt (m))
9798 long int val = multiVal_forceInt (m);
9800 if (ctype_isDirectBool (ctype_realishType (expected)))
9804 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9812 if (ctype_isRealInt (expected))
9815 ** unsigned <- [ constant >= 0 is okay ]
9818 if (ctype_isUnsigned (expected))
9827 ** No checks on sizes of integers...maybe add
9831 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9832 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9833 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9835 if (context_getFlag (FLG_NUMLITERAL)
9836 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9842 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9846 else if (ctype_isChar (expected))
9850 else if (ctype_isArrayPtr (expected))
9853 ** evans 2001-10-14: We allow 0 to match any pointer, but only if the type matches or is void *.
9858 if (ctype_match (exprNode_getType (e), expected)
9859 || ctype_isVoidPointer (exprNode_getType (e)))
9869 else if (ctype_isAnyFloat (expected))
9871 return (context_getFlag (FLG_NUMLITERAL));
9878 else if (multiVal_isDouble (m))
9880 if (ctype_isAnyFloat (expected))
9885 else if (multiVal_isChar (m))
9887 char val = multiVal_forceChar (m);
9889 if (ctype_isChar (expected))
9891 if (ctype_isUnsigned (expected) && ((int)val) < 0)
9912 exprNode_matchType (ctype expected, exprNode e)
9916 if (!exprNode_isDefined (e)) return TRUE;
9918 actual = ctype_realishType (exprNode_getType (e));
9920 if (ctype_match (ctype_realishType (expected), actual))
9925 llassert (!exprNode_isError (e));
9926 return (exprNode_matchLiteral (expected, e));
9930 exprNode_matchTypes (exprNode e1, exprNode e2)
9935 if (!exprNode_isDefined (e1)) return TRUE;
9936 if (!exprNode_isDefined (e2)) return TRUE;
9939 ** realish type --- keep bools, bools
9942 t1 = ctype_realishType (exprNode_getType (e1));
9943 t2 = ctype_realishType (exprNode_getType (e2));
9945 if (ctype_match (t1, t2))
9950 DPRINTF (("Matching literal! %s %s %s %s",
9951 ctype_unparse (t1), exprNode_unparse (e2),
9952 ctype_unparse (t2), exprNode_unparse (e1)));
9954 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9962 exprNode_matchArgType (ctype ct, exprNode e)
9966 if (!exprNode_isDefined (e))
9971 et = ctype_realType (exprNode_getType (e));
9973 if (ctype_matchArg (ct, et)) return TRUE;
9975 llassert (!exprNode_isError (e));
9976 return (exprNode_matchLiteral (ct, e));
9979 static /*@only@*/ exprNodeSList
9980 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9982 if (exprNode_isDefined (e))
9984 if (e->kind == XPR_STMTLIST)
9986 return (exprNodeSList_append
9987 (exprNode_flatten (exprData_getPairA (e->edata)),
9988 exprNode_flatten (exprData_getPairB (e->edata))));
9990 else if (e->kind == XPR_BLOCK)
9992 return (exprNode_flatten (exprData_getSingle (e->edata)));
9996 return (exprNodeSList_singleton (e));
10000 return exprNodeSList_new ();
10003 static /*@exposed@*/ exprNode
10004 exprNode_lastStatement (/*@returned@*/ exprNode e)
10006 if (exprNode_isDefined (e))
10008 if (e->kind == XPR_STMTLIST)
10010 exprNode b = exprData_getPairB (e->edata);
10012 if (exprNode_isDefined (b))
10014 return exprNode_lastStatement (b);
10018 return exprNode_lastStatement (exprData_getPairA (e->edata));
10021 else if (e->kind == XPR_BLOCK)
10023 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
10031 return exprNode_undefined;
10034 static /*@exposed@*/ exprNode
10035 exprNode_firstStatement (/*@returned@*/ exprNode e)
10037 if (exprNode_isDefined (e))
10039 if (e->kind == XPR_STMTLIST)
10041 exprNode b = exprData_getPairA (e->edata);
10043 if (exprNode_isDefined (b))
10045 return exprNode_firstStatement (b);
10049 return exprNode_firstStatement (exprData_getPairB (e->edata));
10052 else if (e->kind == XPR_BLOCK)
10054 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
10062 return exprNode_undefined;
10066 exprNode_mergeUSs (exprNode res, exprNode other)
10068 if (exprNode_isDefined (res) && exprNode_isDefined (other))
10070 res->msets = sRefSet_union (res->msets, other->msets);
10071 res->sets = sRefSet_union (res->sets, other->sets);
10072 res->uses = sRefSet_union (res->uses, other->uses);
10077 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
10079 if (exprNode_isDefined (res))
10081 if (exprNode_isDefined (other1))
10083 res->sets = sRefSet_union (res->sets, other1->sets);
10084 res->msets = sRefSet_union (res->msets, other1->msets);
10085 res->uses = sRefSet_union (res->uses, other1->uses);
10087 if (exprNode_isDefined (other2))
10089 res->sets = sRefSet_union (res->sets, other2->sets);
10090 res->msets = sRefSet_union (res->msets, other2->msets);
10091 res->uses = sRefSet_union (res->uses, other2->uses);
10097 ** modifies e->uses
10099 ** Reports errors is s is not defined.
10103 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
10105 if (exprNode_isDefined (e))
10107 e->uses = sRefSet_insert (e->uses, s);
10112 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
10114 if (sRef_isKnown (s) && !sRef_isConst (s))
10117 ** need to check all outer types are useable
10120 DPRINTF (("Check use: %s / %s",
10121 exprNode_unparse (e), sRef_unparse (s)));
10123 exprNode_addUse (e, s);
10125 if (!context_inProtectVars ())
10128 ** only report the deepest error
10131 sRef errorRef = sRef_undefined;
10132 sRef lastRef = sRef_undefined;
10133 bool deadRef = FALSE;
10134 bool unuseable = FALSE;
10135 bool errorMaybe = FALSE;
10137 while (sRef_isValid (s) && sRef_isKnown (s))
10139 ynm readable = sRef_isValidLvalue (s);
10141 DPRINTF (("Readable: %s / %s",
10142 sRef_unparseFull (s), ynm_unparse (readable)));
10144 if (!(ynm_toBoolStrict (readable)))
10146 if (ynm_isMaybe (readable))
10148 lastRef = errorRef;
10150 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
10151 deadRef = sRef_isPossiblyDead (errorRef);
10152 unuseable = sRef_isUnuseable (errorRef);
10157 lastRef = errorRef;
10159 deadRef = sRef_isDead (errorRef);
10160 unuseable = sRef_isUnuseable (errorRef);
10161 errorMaybe = FALSE;
10164 if (!sRef_isPartial (s))
10166 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
10167 sRef_setDefined (s, fileloc_undefined);
10171 s = sRef_getBaseSafe (s);
10174 if (sRef_isValid (errorRef))
10176 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
10177 && sRef_isPointer (errorRef))
10179 errorRef = lastRef;
10184 if (sRef_isThroughArrayFetch (errorRef))
10187 (FLG_STRICTUSERELEASED,
10188 message ("%q %q may be used after being released",
10189 sRef_unparseKindNamePlain (errorRef),
10190 sRef_unparse (errorRef)),
10193 sRef_showRefKilled (errorRef);
10195 if (sRef_isKept (errorRef))
10197 sRef_clearAliasState (errorRef, loc);
10203 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
10207 message ("%q %q %qused after being released",
10208 sRef_unparseKindNamePlain (errorRef),
10209 sRef_unparse (errorRef),
10210 cstring_makeLiteral (errorMaybe
10211 ? "may be " : "")),
10214 sRef_showRefKilled (errorRef);
10216 if (sRef_isKept (errorRef))
10218 sRef_clearAliasState (errorRef, loc);
10223 else if (unuseable)
10227 message ("%q %q%qused in inconsistent state",
10228 sRef_unparseKindName (errorRef),
10229 sRef_unparseOpt (errorRef),
10230 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10233 sRef_showStateInconsistent (errorRef);
10238 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
10242 message ("%q %q%qused before definition",
10243 sRef_unparseKindName (errorRef),
10244 sRef_unparseOpt (errorRef),
10245 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10248 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
10251 sRef_setDefined (errorRef, loc);
10253 if (sRef_isAddress (errorRef))
10255 sRef_setDefined (sRef_getRootBase (errorRef), loc);
10257 } /* end is error */
10265 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
10267 if (exprNode_isDefined (e) && sRef_isKnown (s))
10269 e->uses = sRefSet_insert (e->uses, s);
10274 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
10276 if (exprNode_isDefined (e))
10278 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
10283 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
10285 sRef defines = sRef_undefined;
10287 if (sRef_isValid (s) && !sRef_isNothing (s))
10289 uentry ue = sRef_getBaseUentry (s);
10291 if (uentry_isValid (ue))
10293 uentry_setLset (ue);
10296 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10298 voptgenerror (FLG_USEDEF,
10299 message ("Attempt to set unuseable storage: %q",
10304 if (sRef_isMeaningful (s))
10306 if (sRef_isDead (s))
10308 sRef base = sRef_getBaseSafe (s);
10310 if (sRef_isValid (base)
10311 && sRef_isDead (base))
10313 sRef_setPartial (s, exprNode_loc (e));
10316 defines = s; /* okay - modifies for only param */
10318 else if (sRef_isPartial (s))
10320 sRef eref = exprNode_getSref (e);
10322 if (!sRef_isPartial (eref))
10325 ** should do something different here???
10328 sRef_setDefinedComplete (eref, exprNode_loc (e));
10332 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
10335 if (sRef_isMeaningful (eref))
10344 else if (sRef_isAllocated (s))
10346 sRef eref = exprNode_getSref (e);
10349 if (!sRef_isAllocated (eref))
10351 sRef_setDefinedComplete (eref, exprNode_loc (e));
10355 sRef base = sRef_getBaseSafe (eref);
10357 if (sRef_isValid (base))
10359 sRef_setPdefined (base, exprNode_loc (e));
10367 sRef_setDefinedNCComplete (s, exprNode_loc (e));
10372 else /* not meaningful...but still need to insert it */
10378 if (exprNode_isDefined (e) && sRef_isValid (defines))
10380 e->sets = sRefSet_insert (e->sets, defines);
10385 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
10387 if (sRef_isValid (s) && !sRef_isNothing (s))
10389 uentry ue = sRef_getBaseUentry (s);
10391 if (uentry_isValid (ue))
10393 uentry_setLset (ue);
10396 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10398 voptgenerror (FLG_USEDEF,
10399 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
10403 if (sRef_isMeaningful (s))
10405 sRef_setDefinedComplete (s, exprNode_loc (e));
10408 if (exprNode_isDefined (e))
10410 e->msets = sRefSet_insert (e->msets, s);
10416 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
10418 checkAnyCall (fcn, cstring_undefined, params, args,
10419 FALSE, sRefSet_undefined, FALSE, 0);
10423 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
10424 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
10428 if (uentry_isYield (ucurrent))
10430 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
10431 exprNode_checkSet (current, current->sref);
10435 if (uentry_isSefParam (ucurrent))
10437 sRefSet sets = current->sets;
10438 sRef ref = exprNode_getSref (current);
10440 if (sRef_isMacroParamRef (ref))
10442 uentry ue = sRef_getUentry (ref);
10444 if (!uentry_isSefParam (ue))
10449 ("Parameter %d to %s is declared sef, but "
10450 "the argument is a macro parameter declared "
10452 argno, exprNode_unparse (fcn),
10453 exprNode_unparse (current)),
10454 exprNode_loc (current));
10458 if (!sRefSet_isEmpty (sets))
10460 sRefSet reported = sRefSet_undefined;
10462 sRefSet_realElements (current->sets, el)
10464 if (sRefSet_isSameNameMember (reported, el))
10466 ; /* don't report again */
10470 if (sRef_isUnconstrained (el))
10475 ("Parameter %d to %s is declared sef, but "
10476 "the argument calls unconstrained function %s "
10477 "(no guarantee it will not modify something): %s",
10478 argno, exprNode_unparse (fcn),
10479 sRef_unconstrainedName (el),
10480 exprNode_unparse (current)),
10481 exprNode_loc (current));
10488 ("Parameter %d to %s is declared sef, but "
10489 "the argument may modify %q: %s",
10490 argno, exprNode_unparse (fcn),
10492 exprNode_unparse (current)),
10493 exprNode_loc (current));
10496 } end_sRefSet_realElements;
10500 transferChecks_passParam (current, ucurrent, isSpec, fcn, argno, totargs);
10501 exprNode_mergeUSs (fcn, current);
10506 checkAnyCall (/*@dependent@*/ exprNode fcn,
10507 /*@dependent@*/ cstring fname,
10510 bool hasMods, sRefSet mods,
10515 int nargs = exprNodeList_size (args);
10520 ** concat all args ud's to f, add each arg sref as a use unless
10521 ** it was specified as "out", in which case it is a def.
10524 uentryList_reset (pn);
10527 ** aliasing checks:
10529 ** if paramn is only or unique, no other arg may alias argn
10532 exprNodeList_elements (args, current)
10536 if (exprNode_isDefined (current))
10538 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
10540 uentry ucurrent = uentryList_current (pn);
10542 if (specialArgs == 0
10543 || (paramno < specialArgs))
10545 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
10547 if (context_maybeSet (FLG_ALIASUNIQUE))
10549 if (uentry_isOnly (ucurrent)
10550 || uentry_isUnique (ucurrent))
10552 checkUniqueParams (fcn, current, args,
10553 paramno, ucurrent);
10558 else /* uentry is undefined */
10560 if (specialArgs == 0)
10562 exprNode_checkUseParam (current);
10565 exprNode_mergeUSs (fcn, current);
10568 uentryList_advanceSafe (pn);
10569 } end_exprNodeList_elements;
10575 sRefSet_allElements (mods, s)
10578 sRef rb = sRef_getRootBase (s);
10580 if (sRef_isFileOrGlobalScope (rb))
10582 context_usedGlobal (rb);
10585 fb = sRef_fixBaseParam (s, args);
10587 if (!sRef_isMacroParamRef (fb))
10589 if (sRef_isNothing (fb))
10595 if (sRef_isValid (fb))
10597 uentry ue = sRef_getBaseUentry (s);
10599 if (uentry_isValid (ue))
10601 uentry_setLset (ue);
10605 fcn->sets = sRefSet_insert (fcn->sets, fb);
10608 sRef_clearDerivedComplete (s);
10609 } end_sRefSet_allElements;
10615 if (context_hasMods ())
10617 if (context_maybeSet (FLG_MODUNCON))
10621 message ("Undetected modification possible "
10622 "from call to unconstrained function %s: %s",
10624 exprNode_unparse (fcn)),
10625 exprNode_loc (fcn));
10630 if (context_maybeSet (FLG_MODUNCONNOMODS)
10631 && !(context_inIterDef () || context_inIterEnd ()))
10634 (FLG_MODUNCONNOMODS,
10635 message ("Undetected modification possible "
10636 "from call to unconstrained function %s: %s",
10638 exprNode_unparse (fcn)),
10639 exprNode_loc (fcn));
10643 exprNode_checkSetAny (fcn, fname);
10647 void exprNode_checkUseParam (exprNode current)
10649 if (exprNode_isDefined (current))
10651 exprNode_checkUse (current, current->sref, current->loc);
10656 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10657 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10662 if (!ctype_match (tr1, tr2))
10664 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10665 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10667 DPRINTF (("No error: [%s] %s / [%s] %s",
10668 exprNode_unparse (e1), ctype_unparse (tr1),
10669 exprNode_unparse (e2), ctype_unparse (tr2)));
10673 (void) gentypeerror
10675 message ("Incompatible types for %s (%s, %s): %s %s %s",
10676 lltok_unparse (op),
10677 ctype_unparse (te1),
10678 ctype_unparse (te2),
10679 exprNode_unparse (e1), lltok_unparse (op),
10680 exprNode_unparse (e2)),
10683 ret = ctype_unknown;
10687 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
10689 ret = ctype_resolveNumerics (tr1, tr2);
10691 else if (!context_msgStrictOps ())
10693 if (ctype_isPointer (tr1))
10695 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10699 else if (ctype_isInt (tr2))
10705 ret = ctype_unknown;
10708 else if (ctype_isPointer (tr2))
10710 if (ctype_isPointer (tr1))
10714 else if (ctype_isInt (tr1))
10720 ret = ctype_unknown;
10725 ret = ctype_resolveNumerics (tr1, tr2);
10730 int opid = lltok_getTok (op);
10731 bool comparop = (opid == EQ_OP || opid == NE_OP
10732 || opid == TLT || opid == TGT
10733 || opid == LE_OP || opid == GE_OP);
10735 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10738 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10739 || (ctype_isBool (tr1) && ctype_isBool (tr2))
10740 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10746 if (ctype_sameName (te1, te2))
10750 message ("Operands of %s are non-numeric (%t): %s %s %s",
10751 lltok_unparse (op), te1,
10752 exprNode_unparse (e1), lltok_unparse (op),
10753 exprNode_unparse (e2)),
10760 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10761 lltok_unparse (op), te1, te2,
10762 exprNode_unparse (e1), lltok_unparse (op),
10763 exprNode_unparse (e2)),
10768 else if (!ctype_isNumeric (tr1))
10772 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10773 lltok_unparse (op), te1,
10774 exprNode_unparse (e1), lltok_unparse (op),
10775 exprNode_unparse (e2)),
10780 if (!ctype_isNumeric (tr2))
10784 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10785 lltok_unparse (op), te2,
10786 exprNode_unparse (e1), lltok_unparse (op),
10787 exprNode_unparse (e2)),
10792 ret = ctype_unknown;
10800 abstractOpError (ctype tr1, ctype tr2, lltok op,
10801 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10802 fileloc loc1, fileloc loc2)
10804 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10806 if (ctype_match (tr1, tr2))
10810 message ("Operands of %s are abstract type (%t): %s %s %s",
10811 lltok_unparse (op), tr1,
10812 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10819 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10820 lltok_unparse (op), tr1, tr2,
10821 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10825 else if (ctype_isRealAbstract (tr1))
10829 message ("Left operand of %s is abstract type (%t): %s %s %s",
10830 lltok_unparse (op), tr1,
10831 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10836 if (ctype_isRealAbstract (tr2))
10840 message ("Right operand of %s is abstract type (%t): %s %s %s",
10841 lltok_unparse (op), tr2,
10842 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10851 ** requies e1 and e2 and not error exprNode's.
10855 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10856 ** the rep of the abstract type is exposed.
10858 ** The order is very important:
10860 ** check rep expose (move into check transfer)
10866 ** This isn't really a sensible procedure, but the indententation
10867 ** was getting too deep.
10871 checkOneRepExpose (sRef ysr, sRef base,
10872 /*@notnull@*/ exprNode e1,
10873 /*@notnull@*/ exprNode e2, ctype ct,
10876 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
10877 || sRef_isOwned (ysr)
10878 || sRef_isExposed (ysr)))
10880 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10881 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10884 if (sRef_isIReference (ysr))
10886 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10891 ("Assignment of mutable component of parameter %q "
10892 "to component of abstract "
10893 "type %s exposes rep: %s = %s",
10894 sRef_unparse (base),
10895 ctype_unparse (ct),
10896 exprNode_unparse (e1), exprNode_unparse (e2)),
10904 ("Assignment of mutable component of parameter %q "
10905 "(through alias %q) to component of abstract "
10906 "type %s exposes rep: %s = %s",
10907 sRef_unparse (base),
10908 sRef_unparse (e2->sref),
10909 ctype_unparse (ct),
10910 exprNode_unparse (e1), exprNode_unparse (e2)),
10916 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10920 message ("Assignment of mutable parameter %q "
10921 "to component of abstract type %s "
10922 "exposes rep: %s = %s",
10923 sRef_unparse (base),
10924 ctype_unparse (ct),
10925 exprNode_unparse (e1),
10926 exprNode_unparse (e2)),
10933 message ("Assignment of mutable parameter %q "
10934 "(through alias %q) to "
10935 "component of abstract type %s exposes "
10937 sRef_unparse (base),
10938 sRef_unparse (e2->sref),
10939 ctype_unparse (ct),
10940 exprNode_unparse (e1),
10941 exprNode_unparse (e2)),
10947 if (sRef_isFileOrGlobalScope (s2b))
10949 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10953 message ("Assignment of global %q "
10955 "abstract type %s exposes rep: %s = %s",
10956 sRef_unparse (base),
10957 ctype_unparse (ct),
10958 exprNode_unparse (e1), exprNode_unparse (e2)),
10965 message ("Assignment of global %q (through alias %q) "
10967 "abstract type %s exposes rep: %s = %s",
10968 sRef_unparse (base),
10969 sRef_unparse (e2->sref),
10970 ctype_unparse (ct),
10971 exprNode_unparse (e1), exprNode_unparse (e2)),
10979 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
10981 DPRINTF (("Do assign: %s <- %s",
10982 exprNode_unparse (e1), exprNode_unparse (e2)));
10983 DPRINTF (("Ctype: %s", ctype_unparse (exprNode_getType (e1))));
10985 if (ctype_isRealFunction (exprNode_getType (e1))
10986 && !ctype_isRealPointer (exprNode_getType (e1)))
10990 message ("Invalid left-hand side of assignment (function type %s): %s",
10991 ctype_unparse (exprNode_getType (e1)),
10992 exprNode_unparse (e1)),
10996 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
10998 ctype t2 = exprNode_getType (e2);
10999 sRef sr = sRef_getRootBase (e1->sref);
11000 ctype ct = sRef_getType (sr);
11002 if (ctype_isAbstract (t2)
11003 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
11005 /* it is immutable, okay to reference */
11006 goto donerepexpose;
11009 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
11011 sRef s2b = sRef_getRootBase (e2->sref);
11012 sRef s1 = e1->sref;
11013 sRef s1b = sRef_getRootBase (s1);
11016 aliases = usymtab_canAlias (e2->sref);
11018 if (!sRef_similar (s2b, s1b)
11019 && !sRef_isExposed (s1)
11020 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
11022 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
11023 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
11024 && !sRef_isExposed (s2b))
11026 if (sRef_isIReference (e2->sref))
11031 ("Assignment of mutable component of parameter %q "
11032 "to component of abstract type %s exposes rep: %s = %s",
11033 sRef_unparse (s2b),
11034 ctype_unparse (ct),
11035 exprNode_unparse (e1), exprNode_unparse (e2)),
11042 message ("Assignment of mutable parameter %q to "
11043 "component of abstract type %s exposes rep: %s = %s",
11044 sRef_unparse (s2b),
11045 ctype_unparse (ct),
11046 exprNode_unparse (e1), exprNode_unparse (e2)),
11051 if (sRef_isFileOrGlobalScope (s2b))
11055 message ("Assignment of global %q to component of "
11056 "abstract type %s exposes rep: %s = %s",
11057 sRef_unparse (s2b),
11058 ctype_unparse (ct),
11059 exprNode_unparse (e1), exprNode_unparse (e2)),
11063 sRefSet_realElements (aliases, ysr)
11065 sRef base = sRef_getRootBase (ysr);
11067 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
11068 || sRef_sameName (base, s1b))
11070 ; /* error already reported or same sref */
11074 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
11076 } end_sRefSet_realElements;
11078 sRefSet_free (aliases);
11085 ** function variables don't really work...
11088 if (!ctype_isFunction (ctype_realType (e2->typ)))
11092 DPRINTF (("Check init: %s / %s",
11093 exprNode_unparse (e1), exprNode_unparse (e2)));
11094 transferChecks_initialization (e1, e2);
11098 transferChecks_assign (e1, e2);
11103 sRef fref = e2->sref;
11105 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
11106 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
11108 /* Need to typecheck the annotation on the parameters */
11110 if (ctype_isRealFunction (e1->typ)) {
11111 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
11112 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
11114 if (!uentryList_isMissingParams (e1p)
11115 && !uentryList_isMissingParams (e2p)
11116 && uentryList_size (e1p) > 0) {
11117 if (uentryList_size (e1p) == uentryList_size (e2p)) {
11120 uentryList_elements (e1p, el1) {
11123 el2 = uentryList_getN (e2p, n);
11125 uentry_checkMatchParam (el1, el2, n, e2);
11126 } end_uentryList_elements;
11132 if (exprNode_isStringLiteral (e2))
11134 exprNode_checkStringLiteralLength (exprNode_getType (e1), e2);
11137 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
11143 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
11144 updateAliases (e1, e2);
11149 checkMacroParen (exprNode e)
11151 if (exprNode_isError (e) || e->kind == XPR_CAST)
11157 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
11161 message ("Macro parameter used without parentheses: %s",
11162 exprNode_unparse (e)),
11169 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
11173 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
11177 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
11184 ** if e2 is a parameter or global derived location which
11185 ** can be modified (that is, e2 is a mutable abstract type,
11186 ** or a derived pointer), then e1 can alias e2.
11188 ** e1 can alias everything which e2 can alias.
11190 ** Also, if e1 is guarded, remove from guard sets!
11193 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
11195 if (!context_inProtectVars ())
11198 ** depends on types of e1 and e2
11201 sRef s1 = e1->sref;
11202 sRef s2 = e2->sref;
11203 ctype t1 = exprNode_getType (e1);
11205 /* handle pointer sRefs, record fields, arrays, etc... */
11207 if (!ctype_isRealSU (t1))
11209 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
11210 sRef_copyRealDerivedComplete (s1, s2);
11215 ** Fields should alias
11218 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
11221 if (ctype_isMutable (t1) && sRef_isKnown (s1))
11223 usymtab_clearAlias (s1);
11224 usymtab_addMustAlias (s1, s2);
11225 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
11229 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
11232 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
11234 usymtab_unguard (s1);
11239 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
11241 if (exprNode_isDefined (e))
11243 e->loc = fileloc_update (e->loc, loc);
11247 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
11253 static void checkUniqueParams (exprNode fcn,
11254 /*@notnull@*/ exprNode current,
11256 int paramno, uentry ucurrent)
11259 sRef thisref = exprNode_getSref (current);
11262 ** Check if any argument could match this argument.
11265 exprNodeList_elements (args, icurrent)
11269 if (iparamno != paramno)
11271 sRef sr = exprNode_getSref (icurrent);
11273 if (sRef_similarRelaxed (thisref, sr))
11275 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
11280 ("Parameter %d (%s) to function %s is declared %s but "
11281 "is aliased by parameter %d (%s)",
11283 exprNode_unparse (current),
11284 exprNode_unparse (fcn),
11285 alkind_unparse (uentry_getAliasKind (ucurrent)),
11286 iparamno, exprNode_unparse (icurrent)),
11292 sRefSet aliases = usymtab_canAlias (sr);
11294 sRefSet_allElements (aliases, asr)
11296 if (ctype_isUnknown (sRef_getType (thisref)))
11298 sRef_setType (thisref, uentry_getType (ucurrent));
11301 if (sRef_similarRelaxed (thisref, asr))
11303 if (sRef_isExternal (asr))
11305 if (sRef_isLocalState (thisref))
11311 sRef base = sRef_getRootBase (asr);
11313 if (!sRef_similar (sRef_getBase (asr), thisref))
11315 if (sRef_isUnique (base) || sRef_isOnly (base)
11316 || sRef_isKept (base)
11317 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
11318 || (sRef_isAddress (thisref)
11319 && sRef_isLocalVar (sRef_getRootBase (thisref))))
11321 ; /* okay, no error */
11326 (FLG_MAYALIASUNIQUE,
11328 ("Parameter %d (%s) to function %s is declared %s but "
11329 "may be aliased externally by parameter %d (%s)",
11331 exprNode_unparse (current),
11332 exprNode_unparse (fcn),
11333 alkind_unparse (uentry_getAliasKind (ucurrent)),
11334 iparamno, exprNode_unparse (icurrent)),
11345 ("Parameter %d (%s) to function %s is declared %s but "
11346 "is aliased externally by parameter %d (%s) through "
11349 exprNode_unparse (current),
11350 exprNode_unparse (fcn),
11351 alkind_unparse (uentry_getAliasKind (ucurrent)),
11352 iparamno, exprNode_unparse (icurrent),
11353 sRef_unparse (asr)),
11357 } end_sRefSet_allElements;
11358 sRefSet_free (aliases);
11361 } end_exprNodeList_elements;
11364 long exprNode_getLongValue (exprNode e) {
11367 if (exprNode_hasValue (e)
11368 && multiVal_isInt (exprNode_getValue (e)))
11370 value = multiVal_forceInt (exprNode_getValue (e));
11381 /*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
11383 if (exprNode_isDefined (p_e) )
11384 return ( p_e->loc );
11386 return fileloc_undefined;
11389 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
11392 ** Returns the location of the sequence point following e.
11394 ** Only works for statements (for now).
11397 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
11398 lltok t = exprData_getUopTok (e->edata);
11399 return fileloc_copy(lltok_getLoc (t));
11401 /* drl possible problem : warning fix
11402 llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
11404 return fileloc_undefined;
11408 exprNode exprNode_createNew(ctype c)
11412 ret = exprNode_createPlain (c);
11417 bool exprNode_isInitBlock (exprNode e)
11419 return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);