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);
1052 static void exprNode_checkStringLiteralLength (ctype t1, exprNode e2)
1054 multiVal mval = exprNode_getValue (e2);
1058 if (ctype_isFixedArray (t1))
1060 size_t nelements = ctype_getArraySize (t1);
1062 llassert (multiVal_isString (mval));
1063 slit = multiVal_forceString (mval);
1065 len = cstring_lengthExpandEscapes (slit);
1067 llassert (exprNode_isDefined (e2));
1069 if (len == nelements)
1073 temp = cstring_expandEscapes (slit);
1075 if (temp[len-1] == '\0')
1078 (FLG_STRINGLITNOROOMFINALNULL,
1079 message ("String literal with %d character%& "
1080 "is assigned to %s (no room for final null terminator): %s",
1083 exprNode_unparse (e2)),
1089 (FLG_STRINGLITNOROOM,
1090 message ("String literal with %d character%& "
1091 "is assigned to %s (no room for null terminator): %s",
1094 exprNode_unparse (e2)),
1098 else if (len > nelements)
1101 (FLG_STRINGLITTOOLONG,
1102 message ("String literal with %d character%& (counting null terminator) "
1103 "is assigned to %s (insufficient storage available): %s",
1106 exprNode_unparse (e2)),
1109 else if (len < nelements - 1)
1112 (FLG_STRINGLITSMALLER,
1113 message ("String literal with %d character%& is assigned to %s (possible waste of storage): %s",
1116 exprNode_unparse (e2)),
1126 static /*@only@*/ /*@notnull@*/ exprNode
1127 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
1129 exprNode e = exprNode_createId (c);
1132 uentry_setUsed (c, e->loc);
1134 if (uentry_isVar (c) && sRef_isFileOrGlobalScope (sr))
1136 checkGlobUse (c, FALSE, e);
1143 exprNode_isZero (exprNode e)
1145 if (exprNode_isDefined (e))
1147 multiVal m = exprNode_getValue (e);
1149 if (multiVal_isInt (m))
1151 return (multiVal_forceInt (m) == 0);
1159 exprNode_isNonNegative (exprNode e)
1161 if (exprNode_isDefined (e))
1163 multiVal m = exprNode_getValue (e);
1165 if (multiVal_isInt (m))
1167 return (multiVal_forceInt (m) >= 0);
1171 ** This is not always true if programmer defines enum
1172 ** values, but then the constant should be known.
1175 if (ctype_isEnum (ctype_realType (e->typ)))
1185 ** a[x] - uses a but NOT a[]
1186 ** result sref = a[] (set/use in assignment)
1188 ** The syntax x[a] is also legal in C, and has the same
1189 ** semantics. If ind is an array, and arr is an int, flip
1194 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
1197 ** error in arr, error propagates (no new messages)
1198 ** error in ind, assume valid and continue
1201 DPRINTF (("Array fetch: %s / %s",
1202 exprNode_unparse (e1), exprNode_unparse (e2)));
1204 if (exprNode_isError (e1))
1207 return (exprNode_makeError ());
1213 ctype carr = exprNode_getType (e1);
1214 ctype crarr = ctype_realType (carr);
1217 ** this sets up funny aliasing, that leads to spurious
1218 ** splint errors. Hence, the i2 comments.
1221 /* evans 2001-09-09 added ctype_isKnown so there is no swap when e1 type is unknown */
1222 if (ctype_isKnown (crarr)
1223 && !ctype_isRealArray (crarr)
1224 && ctype_isRealNumeric (crarr)
1225 && !exprNode_isError (e2)
1226 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1231 carr = exprNode_getType (arr);
1232 crarr = ctype_realType (carr);
1240 DPRINTF (("arr: %s", exprNode_unparse (arr)));
1242 if (sRef_possiblyNull (arr->sref))
1244 if (!usymtab_isGuarded (arr->sref))
1246 if (optgenerror (FLG_NULLDEREF,
1247 message ("Index of %s pointer %q: %s",
1248 sRef_nullMessage (arr->sref),
1249 sRef_unparse (arr->sref),
1250 exprNode_unparse (arr)),
1253 DPRINTF (("ref: %s", sRef_unparseFull (arr->sref)));
1254 sRef_showNullInfo (arr->sref);
1256 /* suppress future messages */
1257 sRef_setNullError (arr->sref);
1262 if (exprNode_isError (ind))
1264 if ((ctype_isArrayPtr (crarr)
1265 && !ctype_isFunction (crarr))
1266 || ctype_isUnknown (carr))
1268 exprNode ret = exprNode_createPartialCopy (arr);
1270 if (ctype_isKnown (carr))
1272 ret->typ = ctype_baseArrayPtr (crarr);
1276 ret->typ = ctype_unknown;
1279 ret->sref = sRef_makeArrayFetch (arr->sref);
1281 ret->kind = XPR_FETCH;
1284 ** Because of funny aliasing (when arr and ind are
1285 ** flipped) spurious errors would be reported here.
1288 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1289 checkSafeUse (ret, arr->sref);
1294 voptgenerror (FLG_TYPE,
1295 message ("Array fetch from non-array (%t): %s[%s]", carr,
1296 exprNode_unparse (e1), exprNode_unparse (e2)),
1298 exprNode_free (arr);
1299 return (exprNode_makeError ());
1304 if (!ctype_isForceRealInt (&(ind->typ)))
1306 ctype rt = ctype_realType (ind->typ);
1308 if (ctype_isChar (rt))
1312 message ("Array fetch using non-integer, %t: %s[%s]",
1314 exprNode_unparse (e1), exprNode_unparse (e2)),
1317 else if (ctype_isEnum (rt))
1321 message ("Array fetch using non-integer, %t: %s[%s]",
1323 exprNode_unparse (e1), exprNode_unparse (e2)),
1330 message ("Array fetch using non-integer, %t: %s[%s]",
1332 exprNode_unparse (e1), exprNode_unparse (e2)),
1336 multiVal_free (ind->val);
1337 ind->val = multiVal_unknown ();
1340 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1342 exprNode ret = exprNode_createSemiCopy (arr);
1343 multiVal m = exprNode_getValue (ind);
1345 ret->typ = ctype_baseArrayPtr (crarr);
1346 ret->kind = XPR_FETCH;
1348 if (multiVal_isInt (m))
1350 int i = (int) multiVal_forceInt (m);
1352 if (sRef_isValid (arr->sref)) {
1353 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1355 ret->sref = sRef_undefined;
1360 ret->sref = sRef_makeArrayFetch (arr->sref);
1363 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1364 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1365 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1367 /* (see comment on spurious errors above) */
1368 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1370 exprNode_checkUse (ret, ind->sref, ind->loc);
1371 exprNode_checkUse (ret, arr->sref, arr->loc);
1377 if (ctype_isUnknown (carr))
1379 exprNode ret = exprNode_createPartialCopy (arr);
1381 ret->kind = XPR_FETCH;
1382 ret->typ = ctype_unknown;
1383 ret->sets = sRefSet_union (ret->sets, ind->sets);
1384 ret->msets = sRefSet_union (ret->msets, ind->msets);
1385 ret->uses = sRefSet_union (ret->uses, ind->uses);
1387 /* (see comment on spurious errors above) */
1388 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1390 exprNode_checkUse (ret, ind->sref, ind->loc);
1391 exprNode_checkUse (ret, arr->sref, arr->loc);
1398 message ("Array fetch from non-array (%t): %s[%s]", carr,
1399 exprNode_unparse (e1), exprNode_unparse (e2)),
1402 exprNode_free (arr);
1403 exprNode_free (ind);
1405 return (exprNode_makeError ());
1415 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1416 exprNodeList args, exprNode ret)
1418 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1422 ** checkPrintfArgs --- checks arguments for printf-like functions
1423 ** Arguments before ... have already been checked.
1424 ** The argument before the ... is a char *.
1425 ** argno is the format string argument.
1429 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1430 exprNodeList args, exprNode ret, int argno)
1433 ** the last argument before the elips is the format string
1438 int nargs = exprNodeList_size (args);
1439 uentryList params = uentry_getParams (fcn);
1443 ** These should be ensured by checkSpecialFunction
1446 llassert (uentryList_size (params) == argno + 1);
1447 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1449 a = exprNodeList_getN (args, argno - 1);
1450 formatloc = fileloc_copy (exprNode_loc (a));
1452 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1453 && exprNode_knownStringValue (a))
1455 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1456 char *code = format;
1459 nargs = exprNodeList_size (args);
1461 while ((code = strchr (code, '%')) != NULL)
1463 char *origcode = code;
1464 cstring codetext = cstring_newEmpty ();
1465 char key = *(++code);
1466 ctype modtype = ctype_int;
1467 bool modified = FALSE;
1469 fileloc_addColumn (formatloc, code - ocode);
1471 codetext = cstring_appendChar (codetext, key);
1474 while (isFlagKey (key))
1477 codetext = cstring_appendChar (codetext, key);
1478 fileloc_incColumn (formatloc);
1481 if (key == 'm') /* skipped in syslog */
1486 /* ignore field width */
1487 while (isdigit ((int) key) != 0)
1490 codetext = cstring_appendChar (codetext, key);
1491 fileloc_incColumn (formatloc);
1494 /* ignore precision */
1498 codetext = cstring_appendChar (codetext, key);
1499 fileloc_incColumn (formatloc);
1502 ** In printf, '*' means: read the next arg as an int for the
1503 ** field width. This seems to be missing from my copy of the
1504 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1505 ** later) but never does.
1510 ; /* don't do anything --- handle later */
1514 while (isdigit ((int) key) != 0)
1517 codetext = cstring_appendChar (codetext, key);
1518 fileloc_incColumn (formatloc);
1525 modtype = ctype_sint; /* short */
1527 codetext = cstring_appendChar (codetext, key);
1528 fileloc_incColumn (formatloc);
1530 else if (key == 'l' || key == 'L')
1532 modtype = ctype_lint; /* long */
1534 codetext = cstring_appendChar (codetext, key);
1535 fileloc_incColumn (formatloc);
1537 if (key == 'l' || key == 'L') {
1538 modtype = ctype_llint; /* long long */
1540 codetext = cstring_appendChar (codetext, key);
1541 fileloc_incColumn (formatloc);
1549 /* now, key = type of conversion to apply */
1551 fileloc_incColumn (formatloc);
1559 message ("No argument corresponding to %q format "
1560 "code %d (%%%s): \"%s\"",
1561 uentry_getName (fcn),
1563 cstring_fromChars (format)),
1566 if (fileloc_isDefined (formatloc)
1567 && context_getFlag (FLG_SHOWCOL))
1569 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1577 a = exprNodeList_getN (args, i);
1580 if (!exprNode_isError (a))
1586 case '*': /* int argument for fieldwidth */
1587 expecttype = ctype_int;
1588 *(--code) = '%'; /* convert it for next code */
1589 fileloc_subColumn (formatloc, 1);
1590 /*@switchbreak@*/ break;
1593 expecttype = ctype_combine (ctype_uint, modtype);
1594 /*@switchbreak@*/ break;
1596 case 'i': /* int argument */
1598 expecttype = ctype_combine (ctype_int, modtype);
1599 /*@switchbreak@*/ break;
1601 case 'x': /* unsigned int */
1603 expecttype = ctype_combine (ctype_uint, modtype);
1605 /*@switchbreak@*/ break;
1611 case 'f': /* double */
1612 expecttype = ctype_combine (ctype_double, modtype);
1613 /*@switchbreak@*/ break;
1615 case 'c': /* int converted to char (check its a char?) */
1616 expecttype = ctype_makeConj (ctype_int,
1617 ctype_makeConj (ctype_char,
1620 /* evans 2001-10-05 - changed to reflect correct ISO spec:
1621 int converted to char */
1623 /* expecttype = ctype_makeConj (ctype_char, ctype_uchar); */
1624 /*@switchbreak@*/ break;
1626 case 's': /* string */
1627 expecttype = ctype_string;
1628 /*@switchbreak@*/ break;
1631 while (((key = *(++code)) != ']')
1634 codetext = cstring_appendChar (codetext, key);
1635 fileloc_incColumn (formatloc);
1641 (message ("Bad character set format: %s",
1642 cstring_fromChars (origcode)));
1645 expecttype = ctype_string;
1646 /*@switchbreak@*/ break;
1648 case 'p': /* pointer */
1649 expecttype = ctype_makePointer (ctype_void);
1650 /* need not be defined */
1651 uentry_setDefState (regArg, SS_RELDEF);
1652 sRef_setPosNull (uentry_getSref (regArg),
1655 /*@switchbreak@*/ break;
1657 case 'n': /* pointer to int, modified by call! */
1658 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1660 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1661 /*@switchbreak@*/ break;
1663 case 'm': /* in a syslog, it doesn't consume an argument */
1664 /* should check we're really doing syslog */
1666 /*@switchbreak@*/ break;
1670 expecttype = ctype_unknown;
1674 message ("Unrecognized format code: %s",
1675 cstring_fromChars (origcode)),
1676 fileloc_isDefined (formatloc)
1677 ? formatloc : g_currentloc);
1679 /*@switchbreak@*/ break;
1682 if (!(exprNode_matchArgType (expecttype, a)))
1684 if (ctype_isVoidPointer (expecttype)
1685 && ctype_isRealAbstract (a->typ)
1686 && (context_getFlag (FLG_ABSTVOIDP)))
1692 if (llgenformattypeerror
1693 (expecttype, exprNode_undefined,
1695 message ("Format argument %d to %q (%%%s) expects "
1698 uentry_getName (fcn),
1701 a->typ, exprNode_unparse (a)),
1704 if (fileloc_isDefined (formatloc)
1705 && context_getFlag (FLG_SHOWCOL))
1708 (cstring_makeLiteral
1709 ("Corresponding format code"),
1716 uentry_setType (regArg, expecttype);
1717 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1719 if (ctype_equal (expecttype, ctype_string))
1721 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1724 uentry_setType (regArg, ctype_unknown);
1725 uentry_fixupSref (regArg);
1729 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1740 cstring_free (codetext);
1745 voptgenerror (FLG_TYPE,
1746 message ("Format string for %q has %d arg%&, given %d",
1747 uentry_getName (fcn), i - argno, nargs - argno),
1753 /* no checking possible for compile-time unknown format strings */
1754 if (exprNode_isDefined (a))
1758 message ("Format string parameter to %s is not a compile-time constant: %s",
1759 exprNode_unparse (f),
1760 exprNode_unparse (a)),
1765 fileloc_free (formatloc);
1769 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1770 exprNodeList args, exprNode ret, int argno)
1774 int nargs = exprNodeList_size (args);
1775 uentryList params = uentry_getParams (fcn);
1779 ** These should be ensured by checkSpecialFunction
1782 llassert (uentryList_size (params) == argno + 1);
1783 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1785 a = exprNodeList_getN (args, argno - 1);
1786 formatloc = fileloc_copy (exprNode_loc (a));
1788 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1789 && exprNode_knownStringValue (a))
1791 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1792 char *code = format;
1795 nargs = exprNodeList_size (args);
1797 while ((code = strchr (code, '%')) != NULL)
1799 char *origcode = code;
1800 char key = *(++code);
1801 cstring codetext = cstring_newEmpty ();
1802 ctype modtype = ctype_int;
1803 char modifier = '\0';
1804 bool modified = TRUE;
1805 bool ignore = FALSE;
1807 codetext = cstring_appendChar (codetext, key);
1808 fileloc_addColumn (formatloc, code - ocode);
1811 ** this is based on ANSI standard library description of fscanf
1812 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1815 /* '*' suppresses assignment (does not need match argument) */
1820 codetext = cstring_appendChar (codetext, key);
1823 fileloc_incColumn (formatloc);
1826 /* ignore field width */
1827 while (isdigit ((int) key) != 0)
1830 codetext = cstring_appendChar (codetext, key);
1831 fileloc_incColumn (formatloc);
1836 modtype = ctype_sint; /* short */
1838 codetext = cstring_appendChar (codetext, key);
1839 fileloc_incColumn (formatloc);
1841 else if (key == 'l' || key == 'L')
1843 modtype = ctype_lint; /* long */
1847 codetext = cstring_appendChar (codetext, key);
1849 fileloc_incColumn (formatloc);
1851 if (key == 'l' || key == 'L') {
1852 modtype = ctype_llint; /* long long */
1854 codetext = cstring_appendChar (codetext, key);
1855 fileloc_incColumn (formatloc);
1863 /* now, key = type of conversion to apply */
1865 fileloc_incColumn (formatloc);
1879 message ("No argument corresponding to %q format "
1880 "code %d (%%%s): \"%s\"",
1881 uentry_getName (fcn),
1883 cstring_fromChars (format)),
1886 if (fileloc_isDefined (formatloc)
1887 && context_getFlag (FLG_SHOWCOL))
1890 (cstring_makeLiteral ("Corresponding format code"),
1898 a = exprNodeList_getN (args, i);
1901 if (!exprNode_isError (a))
1907 case '*': /* int argument for fieldwidth */
1908 expecttype = ctype_makePointer (ctype_int);
1909 *(--code) = '%'; /* convert it for next code */
1910 fileloc_subColumn (formatloc, 1);
1911 /*@switchbreak@*/ break;
1914 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1915 /*@switchbreak@*/ break;
1920 case 'X': /* unsigned int */
1921 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1922 /*@switchbreak@*/ break;
1929 /* printf is double, scanf is float! */
1931 if (modifier == 'l')
1933 expecttype = ctype_makePointer (ctype_double);
1935 else if (modifier == 'L')
1937 expecttype = ctype_makePointer (ctype_ldouble);
1941 llassert (modifier == '\0');
1942 expecttype = ctype_makePointer (ctype_float);
1944 /*@switchbreak@*/ break;
1946 case 'c': /* int converted to char (check its a char?) */
1947 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1948 /*@switchbreak@*/ break;
1950 case 's': /* string */
1951 expecttype = ctype_string;
1952 /*@switchbreak@*/ break;
1956 while (((key = *(++code)) != ']')
1959 codetext = cstring_appendChar (codetext, key);
1960 fileloc_incColumn (formatloc);
1966 (message ("Bad character set format: %s",
1967 cstring_fromChars (origcode)));
1970 expecttype = ctype_string;
1971 /*@switchbreak@*/ break;
1974 case 'p': /* pointer */
1977 message ("Format code should not be used in scanf: %s",
1978 cstring_fromChars (origcode)),
1979 fileloc_isDefined (formatloc)
1980 ? formatloc : g_currentloc);
1982 expecttype = ctype_unknown;
1983 /*@switchbreak@*/ break;
1985 case 'n': /* pointer to int, modified by call! */
1986 expecttype = ctype_makePointer (ctype_int);
1987 /*@switchbreak@*/ break;
1990 expecttype = ctype_unknown;
1994 message ("Unrecognized format code: %s",
1995 cstring_fromChars (origcode)),
1996 fileloc_isDefined (formatloc)
1997 ? formatloc : g_currentloc);
1999 /*@switchbreak@*/ break;
2002 if (!(exprNode_matchArgType (expecttype, a)))
2004 if (ctype_isVoidPointer (expecttype)
2005 && ctype_isRealAbstract (a->typ)
2006 && (context_getFlag (FLG_ABSTVOIDP)))
2012 if (llgenformattypeerror
2013 (expecttype, exprNode_undefined,
2015 message ("Format argument %d to %q (%%%s) expects "
2018 uentry_getName (fcn),
2019 codetext, expecttype,
2020 a->typ, exprNode_unparse (a)),
2023 if (fileloc_isDefined (formatloc)
2024 && context_getFlag (FLG_SHOWCOL))
2027 (cstring_makeLiteral
2028 ("Corresponding format code"),
2035 uentry_setType (outArg, expecttype);
2036 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
2037 uentry_setType (outArg, ctype_unknown);
2038 uentry_fixupSref (outArg);
2042 exprNode_checkCallModifyVal (a->sref, args, f, ret);
2047 /* a->sref = sRef_undefined; */
2054 cstring_free (codetext);
2059 voptgenerror (FLG_TYPE,
2060 message ("Format string for %q has %d arg%&, given %d",
2061 uentry_getName (fcn), i - argno, nargs - argno),
2067 /* no checking possible for compile-time unknown format strings */
2070 fileloc_free (formatloc);
2074 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
2077 /*@unused@*/ int argno)
2080 ** the last argument before the elips is the format string
2083 int nargs = exprNodeList_size (args);
2088 a = exprNodeList_getN (args, argno - 1);
2089 formatloc = fileloc_copy (exprNode_loc (a));
2091 if (ctype_isUnknown (cstringType)) {
2092 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
2094 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
2098 if (ctype_isUnknown (ctypeType)) {
2099 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
2101 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
2105 if (ctype_isUnknown (filelocType)) {
2106 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
2108 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
2112 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
2113 && exprNode_knownStringValue (a))
2115 cstring format = multiVal_forceString (exprNode_getValue (a));
2116 char *code = cstring_toCharsSafe (format);
2119 nargs = exprNodeList_size (args);
2121 while ((code = strchr (code, '%')) != NULL)
2123 char *origcode = code;
2124 char key = *(++code);
2125 cstring codetext = cstring_newEmpty ();
2126 bool isOnly = FALSE;
2128 codetext = cstring_appendChar (codetext, key);
2130 fileloc_addColumn (formatloc, code - ocode);
2132 while (key >= '0' && key <= '9')
2135 codetext = cstring_appendChar (codetext, key);
2136 fileloc_incColumn (formatloc);
2140 fileloc_incColumn (formatloc);
2144 if (key == '&') /* plural marker */
2153 message ("Message missing format arg %d (%%%s): \"%s\"",
2154 i + 1, codetext, format),
2160 a = exprNodeList_getN (args, i);
2164 if (!exprNode_isError (a))
2168 /*@-loopswitchbreak@*/
2174 expecttype = ctype_char; break;
2176 expecttype = cstringType; break;
2178 expecttype = cstringType; isOnly = TRUE; break;
2180 expecttype = cstringType; isOnly = TRUE; break;
2181 case 'd': expecttype = ctype_int; break;
2182 case 'u': expecttype = ctype_uint; break;
2183 case 'w': expecttype = ctype_ulint; break;
2184 case 'f': expecttype = ctype_float; break;
2185 case 'b': expecttype = ctype_bool; break;
2186 case 't': expecttype = ctypeType; break;
2188 expecttype = ctype_makePointer (ctype_void);
2189 /* need not be defined */
2190 uentry_setDefState (regArg, SS_RELDEF);
2191 sRef_setPosNull (uentry_getSref (regArg),
2194 /*@switchbreak@*/ break;
2195 case 'l': expecttype = filelocType; break;
2196 case '&': /* a wee bit of a hack methinks */
2197 expecttype = ctype_int;
2199 case 'r': expecttype = ctype_bool; break;
2201 expecttype = ctype_unknown;
2204 message ("Unrecognized format code: %s",
2205 cstring_fromChars (origcode)),
2206 fileloc_isDefined (formatloc)
2207 ? formatloc : g_currentloc);
2210 /*@=loopswitchbreak@*/
2212 if (!(exprNode_matchArgType (expecttype, a)))
2214 if (ctype_isVoidPointer (expecttype)
2215 && ctype_isRealAbstract (a->typ)
2216 && (context_getFlag (FLG_ABSTVOIDP)))
2222 if (llgenformattypeerror
2223 (expecttype, exprNode_undefined,
2225 message ("Format argument %d to %q (%%%s) expects "
2228 uentry_getName (fcn),
2229 codetext, expecttype,
2230 a->typ, exprNode_unparse (a)),
2233 if (fileloc_isDefined (formatloc)
2234 && context_getFlag (FLG_SHOWCOL))
2237 (cstring_makeLiteral
2238 ("Corresponding format code"),
2245 if (ctype_equal (expecttype, cstringType))
2249 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2250 uentry_fixupSref (csOnlyArg);
2254 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2255 uentry_fixupSref (csArg);
2260 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2261 uentry_fixupSref (regArg);
2267 cstring_free (codetext);
2272 voptgenerror (FLG_TYPE,
2273 message ("Format string for %q has %d arg%&, given %d",
2274 uentry_getName (fcn), i - argno, nargs -argno),
2280 /* no checking possible for compile-time unknown format strings */
2283 fileloc_free (formatloc);
2287 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2288 /*@notnull@*/ exprNode e2,
2294 bool hadUncon = FALSE;
2296 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
2297 sRefSet_hasUnconstrained (sets2))
2300 (FLG_EVALORDERUNCON,
2302 ("Expression may have undefined behavior (%q used in right operand "
2303 "may set global variable %q used in left operand): %s %s %s",
2304 sRefSet_unparseUnconstrained (sets2),
2305 sRef_unparse (sRef_getRootBase (e1->sref)),
2306 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2310 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
2311 sRefSet_hasUnconstrained (sets1))
2314 (FLG_EVALORDERUNCON,
2316 ("Expression has undefined behavior (%q used in left operand "
2317 "may set global variable %q used in right operand): %s %s %s",
2318 sRefSet_unparseUnconstrained (sets1),
2319 sRef_unparse (e2->sref),
2320 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2324 sRefSet_realElements (e1->uses, sr)
2326 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2331 ("Expression has undefined behavior (left operand uses %q, "
2332 "modified by right operand): %s %s %s",
2334 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2337 } end_sRefSet_realElements;
2339 sRefSet_realElements (sets1, sr)
2341 if (sRef_isMeaningful (sr))
2343 if (sRef_same (sr, e2->sref))
2348 ("Expression has undefined behavior (value of right operand "
2349 "modified by left operand): %s %s %s",
2350 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2353 else if (sRefSet_member (e2->uses, sr))
2358 ("Expression has undefined behavior (left operand modifies %q, "
2359 "used by right operand): %s %s %s",
2361 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2366 if (sRefSet_member (sets2, sr))
2368 if (sRef_isUnconstrained (sr))
2376 hadUncon = optgenerror
2377 (FLG_EVALORDERUNCON,
2379 ("Expression may have undefined behavior. Left operand "
2380 "calls %q; right operand calls %q. The unconstrained "
2381 "functions may modify global state used by "
2382 "the other operand): %s %s %s",
2383 sRefSet_unparseUnconstrained (sets1),
2384 sRefSet_unparseUnconstrained (sets2),
2385 exprNode_unparse (e1), lltok_unparse (op),
2386 exprNode_unparse (e2)),
2395 ("Expression has undefined behavior (both "
2396 "operands modify %q): %s %s %s",
2398 exprNode_unparse (e1),
2399 lltok_unparse (op), exprNode_unparse (e2)),
2405 } end_sRefSet_realElements;
2408 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2410 bool hasError = FALSE;
2412 if (exprNode_isError (e1) || exprNode_isError (e2))
2417 if (sRefSet_member (e2->sets, e1->sref))
2419 if (e2->kind == XPR_CALL)
2425 hasError = optgenerror
2427 message ("Expression has undefined behavior "
2428 "(value of left operand %s is modified "
2429 "by right operand %s): %s %s %s",
2430 exprNode_unparse (e1),
2431 exprNode_unparse (e2),
2432 exprNode_unparse (e1), lltok_unparse (op),
2433 exprNode_unparse (e2)),
2438 if (context_getFlag (FLG_EVALORDERUNCON))
2440 if (sRefSet_member (e2->msets, e1->sref))
2442 if (e2->kind == XPR_CALL)
2448 hasError = optgenerror
2451 ("Expression has undefined behavior (value of left "
2452 "operand may be modified by right operand): %s %s %s",
2453 exprNode_unparse (e1), lltok_unparse (op),
2454 exprNode_unparse (e2)),
2462 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2464 if (context_maybeSet (FLG_EVALORDERUNCON))
2466 checkExpressionDefinedAux (e1, e2, e1->msets,
2467 e2->msets, op, FLG_EVALORDERUNCON);
2472 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2475 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2476 exprNodeList args, bool isIter, exprNode ret)
2480 if (!exprNode_isError (f))
2482 if (!uentryList_isMissingParams (cl))
2484 int nargs = exprNodeList_size (args);
2485 int expectargs = uentryList_size (cl);
2489 if (expectargs == 0)
2497 message ("Iter %q invoked with %d args, "
2499 uentry_getName (fcn),
2507 message ("Function %s called with %d args, "
2509 exprNode_unparse (f), nargs),
2516 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2518 exprNodeList_reset (args);
2520 uentryList_elements (cl, current)
2522 ctype ct = uentry_getType (current);
2525 if (ctype_isElips (ct))
2528 ** do special checking for printf/scanf library functions
2530 ** this is kludgey code, just for handling the special case
2534 if (uentry_isPrintfLike (fcn))
2536 checkPrintfArgs (f, fcn, args, ret, i);
2539 else if (uentry_isScanfLike (fcn))
2541 checkScanfArgs (f, fcn, args, ret, i);
2544 else if (uentry_isMessageLike (fcn))
2546 checkMessageArgs (f, fcn, args, i);
2551 llassert (!uentry_isSpecialFunction (fcn));
2554 nargs = expectargs; /* avoid errors */
2559 if (i >= nargs) break;
2561 a = exprNodeList_current (args);
2562 exprNodeList_advance (args);
2566 if (exprNode_isError (a))
2573 probably necessary? I'm not sure about this one
2574 checkMacroParen (a);
2577 f->guards = guardSet_union (f->guards, a->guards);
2579 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2581 if (!(exprNode_matchArgType (ct, a)))
2583 DPRINTF (("Args mismatch!"));
2585 if (ctype_isVoidPointer (ct)
2586 && (ctype_isPointer (a->typ)
2587 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2592 ("Pointer to abstract type (%t) used "
2594 "(arg %d to %q): %s",
2596 uentry_getName (fcn),
2597 exprNode_unparse (a)),
2605 (ct, exprNode_undefined,
2608 ("Iter %q expects arg %d to "
2609 "be %t gets %t: %s",
2610 uentry_getName (fcn),
2611 i, ct, a->typ, exprNode_unparse (a)),
2622 ("Function %q expects arg %d to be %t gets %t: %s",
2623 uentry_getName (fcn),
2624 i, ct, a->typ, exprNode_unparse (a)),
2627 DPRINTF (("Types: %s / %s",
2629 ctype_unparse (a->typ)));
2633 ** Clear null marker for abstract types.
2634 ** (It is not revealed, so suppress future messages.)
2637 if (ctype_isAbstract (a->typ))
2639 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2646 } end_uentryList_elements ;
2649 if (expectargs != nargs) /* note: not != since we may have ... */
2651 if (ctype_isElips (last))
2655 message ("Function %s called with %d args, expects at least %d",
2656 exprNode_unparse (f),
2657 nargs, expectargs - 1),
2666 message ("Iter %q invoked with %d args, expects %d",
2667 uentry_getName (fcn), nargs, expectargs),
2674 message ("Function %s called with %d args, expects %d",
2675 exprNode_unparse (f),
2688 ** Check for undefined code sequences in function arguments:
2690 ** one parameter sets something used by another parameter
2691 ** one parameter sets something set by another parameter
2695 checkSequencingOne (exprNode f, exprNodeList args,
2696 /*@notnull@*/ exprNode el, int argno)
2699 ** Do second loop, iff +undefunspec
2703 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2705 for (checkloop = 0; checkloop < numloops; checkloop++)
2711 thissets = el->sets;
2715 llassert (checkloop == 1);
2716 thissets = el->msets;
2719 sRefSet_realElements (thissets, thisset)
2723 /*@access exprNodeList@*/
2724 for (j = 0; j < args->nelements; j++)
2726 exprNode jl = args->elements[j];
2727 int thisargno = j + 1;
2729 if (thisargno != argno && exprNode_isDefined (jl))
2731 sRefSet otheruses = jl->uses;
2733 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
2734 sRefSet_hasUnconstrained (thissets))
2737 (FLG_EVALORDERUNCON,
2740 ("%q used in argument %d may set "
2741 "global variable %q used by argument %d: %s(%q)",
2742 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2745 sRef_unparse (sRef_getRootBase (jl->sref)),
2747 exprNode_unparse (f), exprNodeList_unparse (args)),
2751 if (sRefSet_member (otheruses, thisset))
2753 if (sRef_isUnconstrained (thisset))
2756 (FLG_EVALORDERUNCON,
2758 ("Unconstrained functions used in arguments %d (%q) "
2759 "and %d (%s) may modify "
2760 "or use global state in undefined way: %s(%q)",
2762 sRefSet_unparseUnconstrainedPlain (otheruses),
2764 sRef_unconstrainedName (thisset),
2765 exprNode_unparse (f),
2766 exprNodeList_unparse (args)),
2774 ("Argument %d modifies %q, used by argument %d "
2775 "(order of evaluation of actual parameters is "
2776 "undefined): %s(%q)",
2777 argno, sRef_unparse (thisset), thisargno,
2778 exprNode_unparse (f), exprNodeList_unparse (args)),
2784 sRefSet othersets = jl->sets;
2786 if (sRefSet_member (othersets, thisset))
2788 if (sRef_isUnconstrained (thisset))
2791 (FLG_EVALORDERUNCON,
2793 ("Unconstrained functions used in "
2794 "arguments %d (%q) and %d (%s) may modify "
2795 "or use global state in undefined way: %s(%q)",
2797 sRefSet_unparseUnconstrainedPlain (othersets),
2799 sRef_unconstrainedName (thisset),
2800 exprNode_unparse (f), exprNodeList_unparse (args)),
2808 ("Argument %d modifies %q, set by argument %d (order of"
2809 " evaluation of actual parameters is undefined): %s(%q)",
2810 argno, sRef_unparse (thisset), thisargno,
2811 exprNode_unparse (f), exprNodeList_unparse (args)),
2818 /*@noaccess exprNodeList@*/
2819 } end_sRefSet_realElements;
2824 checkSequencing (exprNode f, exprNodeList args)
2826 if (exprNodeList_size (args) > 1)
2831 /*@access exprNodeList*/
2833 for (i = 0; i < args->nelements; i++)
2835 el = args->elements[i];
2837 if (!exprNode_isError (el))
2839 checkSequencingOne (f, args, el, i + 1);
2842 /*@noaccess exprNodeList*/
2847 ** requires le = exprNode_getUentry (f)
2851 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2852 uentry le, exprNodeList args,
2853 /*@notnull@*/ exprNode ret, int specialArgs)
2855 bool isSpec = FALSE;
2856 bool hasMods = FALSE;
2858 globSet usesGlobs = globSet_undefined;
2859 sRefSet mods = sRefSet_undefined;
2860 bool freshMods = FALSE;
2861 uentryList params = uentryList_undefined;
2863 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2866 ** check globals and modifies
2871 if (!uentry_isValid (le))
2873 ctype fr = ctype_realType (f->typ);
2875 if (ctype_isFunction (fr))
2877 params = ctype_argsFunction (fr);
2881 params = uentryList_missingParams;
2884 if (!context_getFlag (FLG_MODNOMODS)
2885 && !context_getFlag (FLG_GLOBUNSPEC))
2887 checkUnspecCall (f, params, args);
2893 fname = uentry_rawName (le);
2897 if (uentry_isFunction (le))
2899 params = uentry_getParams (le);
2900 mods = uentry_getMods (le);
2901 hasMods = uentry_hasMods (le);
2902 usesGlobs = uentry_getGlobs (le);
2903 isSpec = uentry_isSpecified (le);
2905 else /* not a function */
2907 ctype ct = ctype_realType (uentry_getType (le));
2909 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2910 ("checkModGlobs: uentry not a function: %s",
2911 uentry_unparse (le)));
2913 params = ctype_argsFunction (ct);
2914 return; /*@32 ! remove this? */
2923 globSet_allElements (usesGlobs, el)
2925 if (sRef_isValid (el))
2927 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2929 context_usedGlobal (el);
2930 exprNode_checkUse (f, el, f->loc);
2932 if (context_checkInternalUse ())
2934 if (!context_globAccess (el))
2936 if (sRef_isSystemState (el)
2937 && !context_getFlag (FLG_MODFILESYSTEM))
2946 ("Called procedure %s may access %q, but "
2947 "globals list does not include globals %s",
2948 exprNode_unparse (f),
2950 cstring_makeLiteralTemp (sRef_isInternalState (el)
2958 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2964 uentry gle = sRef_getUentry (el);
2965 sRef sr = sRef_updateSref (el);
2967 if (sRef_isUndefGlob (el))
2969 sRef_setDefined (sr, f->loc);
2970 exprNode_checkSet (f, sr);
2978 if (sRef_isAllocated (el))
2980 exprNode_checkSet (f, sr);
2984 if (sRef_isStateUndefined (sr))
2989 ("%s %q used by function undefined before call: %s",
2990 sRef_getScopeName (sr),
2992 exprNode_unparse (f)),
2994 sRef_setDefined (sr, f->loc);
2996 exprNode_checkUse (f, sr, f->loc);
2999 checkGlobUse (gle, TRUE, f);
3002 if (sRef_isKilledGlob (el))
3004 sRef_kill (sr, f->loc);
3005 context_usedGlobal (sr);
3009 } end_globSet_allElements;
3015 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
3017 sRefSet smods = sRefSet_undefined;
3020 ** NEED to check for modifies anything
3024 ** check each sRef that called function modifies (ml), is
3030 sRefSet_allElements (mods, s) /* s is something which may be modified */
3032 DPRINTF (("Check modify: %s", sRef_unparse (s)));
3034 if (sRef_isKindSpecial (s))
3036 if (sRef_isSpecInternalState (s))
3038 if (context_getFlag (FLG_MODINTERNALSTRICT))
3040 exprNode_checkCallModifyVal (s, args, f, ret);
3044 sRefSet mmods = context_modList ();
3046 sRefSet_allElements (mmods, el)
3048 if (sRef_isInternalState (el))
3050 sRef_setModified (el);
3052 } end_sRefSet_allElements ;
3057 exprNode_checkCallModifyVal (s, args, f, ret);
3062 sRef rb = sRef_getRootBase (s);
3064 if (sRef_isFileOrGlobalScope (rb))
3066 context_usedGlobal (rb);
3069 if (sRef_isFileStatic (s)
3070 && !fileId_equal (fileloc_fileId (f->loc),
3071 fileloc_fileId (uentry_whereDefined (le))))
3073 smods = sRefSet_insert (smods, s);
3077 exprNode_checkCallModifyVal (s, args, f, ret);
3080 } end_sRefSet_allElements;
3085 ** Static elements in modifies set can have nasty consequences.
3086 ** (I think...have not been able to reproduce a possible bug.)
3089 if (!sRefSet_isDefined (smods))
3091 mods = sRefSet_newCopy (mods);
3094 sRefSet_allElements (smods, el)
3096 bool res = sRefSet_delete (mods, el);
3099 } end_sRefSet_allElements;
3101 sRefSet_free (smods);
3106 else if (sRefSet_isDefined (mods))
3107 { /* just check observers */
3110 sRefSet_allElements (mods, s) /* s is something which may be modified */
3112 sRef rb = sRef_getRootBase (s);
3116 if (sRef_isParam (rb))
3118 sRef b = sRef_fixBaseParam (s, args);
3120 if (sRef_isObserver (b))
3122 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
3126 message ("Function call may modify observer%q: %s",
3127 sRef_unparsePreOpt (b), exprNode_unparse (e)),
3130 sRef_showExpInfo (b);
3134 } end_sRefSet_allElements;
3138 if (!hasMods) /* no specified modifications */
3140 if (context_getFlag (FLG_MODOBSERVERUNCON))
3142 exprNodeList_elements (args, e)
3144 if (exprNode_isDefined (e))
3146 sRef s = exprNode_getSref (e);
3148 if (sRef_isObserver (s)
3149 && ctype_isMutable (sRef_getType (s)))
3152 (FLG_MODOBSERVERUNCON,
3154 ("Call to unconstrained function %s may modify observer%q: %s",
3155 exprNode_unparse (f),
3156 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3159 sRef_showExpInfo (s);
3163 } end_exprNodeList_elements;
3168 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3170 ret->uses = sRefSet_union (ret->uses, f->uses);
3171 ret->sets = sRefSet_union (ret->sets, f->sets);
3172 ret->msets = sRefSet_union (ret->msets, f->msets);
3177 ** Spurious errors reported, because splint can't tell
3178 ** mods must be fresh if freshMods is true.
3181 /*@i@*/ sRefSet_free (mods);
3187 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3189 if (uentry_isVar (glob))
3191 if (context_inFunctionLike ())
3193 sRef sr = uentry_getSref (glob);
3195 context_usedGlobal (sr);
3197 if (context_checkGlobUse (glob))
3199 if (!context_globAccess (sr))
3205 message ("Called procedure %s may access %s %q",
3206 exprNode_unparse (e),
3207 sRef_unparseScope (sr),
3208 uentry_getName (glob)),
3215 message ("Undocumented use of %s %s",
3216 sRef_unparseScope (sr),
3217 exprNode_unparse (e)),
3226 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3231 reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
3233 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3234 exprNode_unparse (f), exprNodeList_unparse (args),
3235 uentry_unparseFull (le),
3236 stateClauseList_unparse (uentry_getStateClauseList (le))));
3238 if (uentry_isValid (le) && uentry_isFunction (le))
3240 stateClauseList sclauses = uentry_getStateClauseList (le);
3242 if (stateClauseList_isDefined (sclauses))
3244 DPRINTF (("Reflect ensures: %s / %s / %s",
3245 uentry_unparse (le),
3246 exprNode_unparse (f), exprNodeList_unparse (args)));
3248 stateClauseList_elements (sclauses, cl)
3250 if (stateClause_hasEnsures (cl))
3252 /* Same in usymtab.c:1904 */
3253 if (stateClause_setsMetaState (cl))
3255 qual q = stateClause_getMetaQual (cl);
3256 annotationInfo ainfo = qual_getAnnotationInfo (q);
3257 metaStateInfo minfo = annotationInfo_getState (ainfo);
3258 cstring key = metaStateInfo_getName (minfo);
3259 int mvalue = annotationInfo_getValue (ainfo);
3261 sRefSet osrs = sRefSet_undefined;
3264 if (stateClause_isGlobal (cl))
3266 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3271 srs = stateClause_getRefs (cl);
3274 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3277 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3279 sRefSet_elements (srs, sel)
3283 if (sRef_isResult (sRef_getRootBase (sel)))
3285 s = exprNode_getSref (ret);
3289 s = sRef_fixBaseParam (sel, args);
3292 DPRINTF (("Reflecting state clause on: %s / %s",
3293 sRef_unparse (sel), sRef_unparse (s)));
3295 sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3296 } end_sRefSet_elements;
3298 sRefSet_free (osrs);
3302 sRefSet srs = stateClause_getRefs (cl);
3303 sRefModVal modf = stateClause_getEnsuresFunction (cl);
3304 int eparam = stateClause_getStateParameter (cl);
3306 llassert (modf != NULL);
3308 DPRINTF (("Reflect after clause: %s / %s",
3309 stateClause_unparse (cl),
3310 sRefSet_unparse (srs)));
3312 sRefSet_elements (srs, sel)
3316 DPRINTF (("elements: %s", sRef_unparse (sel)));
3317 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3319 if (sRef_isResult (sRef_getRootBase (sel)))
3321 DPRINTF (("Fix base: %s / %s",
3322 sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
3323 s = sRef_fixBase (sel, exprNode_getSref (ret));
3324 DPRINTF (("==> %s", sRef_unparseFull (s)));
3328 s = sRef_fixBaseParam (sel, args);
3331 DPRINTF (("elements: %s", sRef_unparse (s)));
3332 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3334 DPRINTF (("Reflecting state clause on: %s / %s",
3335 sRef_unparseFull (sel), sRef_unparseFull (s)));
3337 /* evans 2001-08-24 - added aliasSetCompleteParam */
3338 sRef_aliasSetCompleteParam (modf, s, eparam, exprNode_loc (f));
3340 DPRINTF (("After reflecting state clause on: %s / %s",
3341 sRef_unparseFull (sel), sRef_unparseFull (s)));
3342 } end_sRefSet_elements;
3345 } end_stateClauseList_elements ;
3348 DPRINTF (("Here: %s / %s",
3349 uentry_unparseFull (le),
3350 bool_unparse (uentry_hasMetaStateEnsures (le))));
3352 if (uentry_hasMetaStateEnsures (le))
3354 fileloc loc = exprNode_loc (f);
3356 metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3358 metaStateConstraintList_elements (mscl, msc)
3360 metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3361 metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3362 metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
3363 cstring key = metaStateInfo_getName (msinfo);
3364 sRef mlsr = metaStateSpecifier_getSref (msspec);
3366 sRef lastref = sRef_undefined;
3367 stateValue sval = stateValue_undefined;
3369 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3370 metaStateConstraint_unparse (msc)));
3371 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3373 if (sRef_isResult (sRef_getRootBase (mlsr)))
3375 s = exprNode_getSref (ret);
3379 s = sRef_fixBaseParam (mlsr, args);
3382 DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3384 while (metaStateExpression_isDefined (msexpr))
3386 metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
3387 metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
3390 DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3392 if (metaStateExpression_isMerge (msexpr))
3394 msexpr = metaStateExpression_getRest (msexpr);
3398 msexpr = metaStateExpression_undefined;
3401 if (metaStateInfo_isDefined (msi))
3403 /* Must match lhs state */
3404 llassert (metaStateInfo_equal (msinfo, msi));
3407 if (metaStateSpecifier_isElipsis (ms))
3410 ** For elipsis, we need to merge all the relevant elipsis parameters
3414 uentryList params = uentry_getParams (le);
3415 int paramno = uentryList_size (params) - 1;
3417 if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
3421 message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3422 uentry_getName (le)),
3423 uentry_whereLast (le));
3424 /*@innerbreak@*/ break;
3427 while (paramno < exprNodeList_size (args))
3429 exprNode arg = exprNodeList_getN (args, paramno);
3430 fs = exprNode_getSref (arg);
3431 DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3433 /* cut and pasted... gack*/
3434 if (stateValue_isDefined (sval))
3436 /* Use combination table to merge old state value with new one: */
3437 stateValue tval = sRef_getMetaStateValue (fs, key);
3439 if (stateValue_isDefined (tval))
3441 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3442 cstring msg = cstring_undefined;
3443 int nval = stateCombinationTable_lookup (sctable,
3444 stateValue_getValue (sval),
3445 stateValue_getValue (tval),
3447 DPRINTF (("Combining: %s + %s -> %d",
3448 stateValue_unparseValue (sval, msinfo),
3449 stateValue_unparseValue (tval, msinfo),
3452 if (nval == stateValue_error)
3457 ("Attributes merged in ensures clause in states that "
3458 "cannot be combined (%q is %q, %q is %q)%q",
3459 sRef_unparse (lastref),
3460 stateValue_unparseValue (sval, msinfo),
3462 stateValue_unparseValue (tval, msinfo),
3463 cstring_isDefined (msg) ?
3464 message (": %s", msg) : cstring_undefined),
3467 sRef_showMetaStateInfo (fs, key);
3471 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3472 loc = exprNode_loc (arg);
3476 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3481 sval = sRef_getMetaStateValue (fs, key);
3486 if (stateValue_isError (sval))
3488 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3497 msr = metaStateSpecifier_getSref (ms);
3500 llassert (sRef_isParam (sRef_getRootBase (msr)));
3501 fs = sRef_fixBaseParam (msr, args);
3503 if (stateValue_isDefined (sval))
3505 /* Use combination table to merge old state value with new one: */
3506 stateValue tval = sRef_getMetaStateValue (fs, key);
3508 if (stateValue_isDefined (tval))
3510 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3511 cstring msg = cstring_undefined;
3512 int nval = stateCombinationTable_lookup (sctable,
3513 stateValue_getValue (sval),
3514 stateValue_getValue (tval),
3516 DPRINTF (("Combining: %s + %s -> %d",
3517 stateValue_unparseValue (sval, msinfo),
3518 stateValue_unparseValue (tval, msinfo),
3521 if (nval == stateValue_error)
3526 ("Attributes merged in ensures clause in states that "
3527 "cannot be combined (%q is %q, %q is %q)%q",
3528 sRef_unparse (lastref),
3529 stateValue_unparseValue (sval, msinfo),
3531 stateValue_unparseValue (tval, msinfo),
3532 cstring_isDefined (msg)
3533 ? message (": %s", msg) : cstring_undefined),
3536 sRef_showMetaStateInfo (fs, key);
3540 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3544 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3549 sval = sRef_getMetaStateValue (fs, key);
3554 if (stateValue_isError (sval))
3556 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3561 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3563 if (stateValue_isDefined (sval))
3565 sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
3569 DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
3571 } end_metaStateConstraintList_elements ;
3573 metaStateConstraintList_free (mscl);
3579 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3581 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3582 exprNode_unparse (f), exprNodeList_unparse (args),
3583 uentry_unparseFull (le),
3584 stateClauseList_unparse (uentry_getStateClauseList (le))));
3586 if (uentry_isValid (le) && uentry_isFunction (le))
3588 stateClauseList sclauses = uentry_getStateClauseList (le);
3590 if (stateClauseList_isDefined (sclauses))
3592 DPRINTF (("Check requires: %s / %s / %s",
3593 uentry_unparse (le),
3594 exprNode_unparse (f), exprNodeList_unparse (args)));
3596 stateClauseList_elements (sclauses, cl)
3598 DPRINTF (("Check clause: %s / %s",
3599 stateClause_unparse (cl),
3600 bool_unparse (stateClause_hasRequires (cl))));
3602 if (stateClause_hasRequires (cl))
3604 sRefSet osrs = sRefSet_undefined;
3607 if (stateClause_isGlobal (cl))
3609 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3614 srs = stateClause_getRefs (cl);
3617 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3619 if (stateClause_setsMetaState (cl))
3621 qual q = stateClause_getMetaQual (cl);
3622 annotationInfo ainfo = qual_getAnnotationInfo (q);
3623 metaStateInfo minfo = annotationInfo_getState (ainfo);
3624 cstring key = metaStateInfo_getName (minfo);
3625 int mvalue = annotationInfo_getValue (ainfo);
3627 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3629 sRefSet_elements (srs, sel)
3631 sRef s = sRef_fixBaseParam (sel, args);
3633 if (sRef_isResult (sRef_getRootBase (sel)))
3639 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3640 sRef_unparseFull (sel), sRef_unparseFull (s),
3643 if (!sRef_checkMetaStateValue (s, key, mvalue))
3645 DPRINTF (("HERE: %s", sRef_unparse (s)));
3649 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3650 uentry_getName (le),
3651 sRef_isGlobalMarker (s)
3653 : message (" by %q", sRef_unparse (s)),
3654 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3656 stateClause_unparse (cl)),
3659 sRef_showAliasInfo (s);
3663 DPRINTF (("Error supressed!"));
3664 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3665 DPRINTF (("Context supress: %s",
3666 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3670 } end_sRefSet_elements;
3674 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3675 int eparam = stateClause_getStateParameter (cl);
3677 DPRINTF (("Reflect after clause: %s / %s",
3678 stateClause_unparse (cl),
3679 sRefSet_unparse (srs)));
3681 llassert (modf != NULL);
3683 sRefSet_elements (srs, sel)
3687 DPRINTF (("elements: %s", sRef_unparse (sel)));
3688 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3690 s = sRef_fixBaseParam (sel, args);
3692 DPRINTF (("elements: %s", sRef_unparse (s)));
3693 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3695 if (sRef_isResult (sRef_getRootBase (sel)))
3697 ; /*@i423 what do we do about results */
3701 DPRINTF (("Reflecting state clause on: %s / %s",
3702 sRef_unparse (sel), sRef_unparse (s)));
3704 modf (s, eparam, exprNode_loc (f));
3706 } end_sRefSet_elements;
3709 sRefSet_free (osrs);
3711 } end_stateClauseList_elements ;
3716 static /*@only@*/ exprNode
3717 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3718 ctype t, /*@keep@*/ exprNodeList args)
3720 /* requires f is a non-error exprNode, with type function */
3721 cstring fname = exprNode_unparse (f);
3722 uentry le = exprNode_getUentry (f);
3723 exprNode ret = exprNode_createPartialCopy (f);
3728 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3730 ret->typ = ctype_getReturnType (t);
3731 ret->kind = XPR_CALL;
3733 ret->edata = exprData_makeCall (f, args);
3736 ** Order of these steps is very important!
3738 ** Must check for argument dependencies before messing up uses and sets.
3741 if (context_getFlag (FLG_EVALORDER))
3743 exprNodeList_elements (args, current)
3745 if (exprNode_isDefined (current))
3747 exprNode_addUse (current, current->sref);
3749 } end_exprNodeList_elements;
3751 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3753 checkSequencing (f, args);
3756 exprNodeList_elements (args, current)
3758 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3760 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3762 } end_exprNodeList_elements ;
3765 special = checkArgs (le, f, t, args, ret);
3766 checkGlobMods (f, le, args, ret, special);
3767 checkRequiresClause (le, f, args);
3770 if (uentry_isValid (le)
3771 && (uentry_isFunction (le)
3772 || (uentry_isVariable (le)
3773 && ctype_isFunction (uentry_getType (le)))))
3775 exitkind exk = uentry_getExitCode (le);
3777 /* f->typ is already set to the return type */
3779 DPRINTF (("Function: %s", uentry_unparseFull (le)));
3780 ret->sref = uentry_returnedRef (le, args);
3781 DPRINTF (("Returned: %s / %s",
3782 uentry_unparseFull (le),
3783 sRef_unparseFull (ret->sref)));
3785 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3787 qual nullPred = uentry_nullPred (le);
3789 if (qual_isTrueNull (nullPred))
3791 exprNode arg = exprNodeList_head (args);
3793 if (exprNode_isDefined (arg))
3795 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3798 else if (qual_isFalseNull (nullPred))
3800 exprNode arg = exprNodeList_head (args);
3802 if (exprNode_isDefined (arg))
3804 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3809 llassert (qual_isUnknown (nullPred));
3813 if (exitkind_isConditionalExit (exk))
3817 ** if (arg0) then { exit! } else { ; }
3819 ** if (arg0) then { ; } else { exit! }
3824 llassert (!exprNodeList_isEmpty (args));
3825 firstArg = exprNodeList_head (args);
3827 if (exprNode_isDefined (firstArg)
3828 && !guardSet_isEmpty (firstArg->guards))
3830 usymtab_trueBranch (guardSet_undefined);
3831 usymtab_altBranch (guardSet_undefined);
3833 if (exitkind_isTrueExit (exk))
3835 usymtab_popBranches (firstArg,
3836 exprNode_makeMustExit (),
3838 TRUE, TRUEEXITCLAUSE);
3842 usymtab_popBranches (firstArg,
3844 exprNode_makeMustExit (),
3845 TRUE, FALSEEXITCLAUSE);
3849 ret->exitCode = XK_MAYEXIT;
3851 else if (exitkind_mustExit (exk))
3853 ret->exitCode = XK_MUSTEXIT;
3855 else if (exitkind_couldExit (exk))
3857 ret->exitCode = XK_MAYEXIT;
3864 if (cstring_equalLit (fname, "exit"))
3866 if (exprNodeList_size (args) == 1)
3868 exprNode arg = exprNodeList_head (args);
3870 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3872 long int val = multiVal_forceInt (exprNode_getValue (arg));
3879 ("Argument to exit has implementation defined behavior: %s",
3880 exprNode_unparse (arg)),
3881 exprNode_loc (arg));
3889 ret->sref = sRef_undefined;
3890 exprNode_checkSetAny (ret, uentry_rawName (le));
3893 DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3894 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3895 reflectEnsuresClause (ret, le, f, args);
3902 ** this is yucky! should keep the uentry as part of exprNode!
3905 uentry exprNode_getUentry (exprNode e)
3907 if (exprNode_isError (e))
3909 return uentry_undefined;
3913 cstring s = exprNode_rootVarName (e);
3914 uentry ue = usymtab_lookupSafe (s);
3921 ** Returns true iff e1 and e2 are both exactly the same storage
3925 static bool exprNode_sameStorage (exprNode e1, exprNode e2)
3927 sRef s1 = exprNode_getSref (e1);
3928 sRef s2 = exprNode_getSref (e2);
3930 return (sRef_realSame (s1, s2));
3934 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3936 exprNode ret = exprNode_createPlain (ctype_unknown);
3938 ret->kind = XPR_INITBLOCK;
3939 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3940 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3946 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3951 usymtab_checkAllValid ();
3954 if (exprNode_isUndefined (f))
3957 exprNodeList_free (args);
3958 return exprNode_undefined;
3961 t = exprNode_getType (f);
3963 if (sRef_isLocalVar (f->sref))
3965 exprNode_checkUse (f, f->sref, f->loc);
3967 if (sRef_possiblyNull (f->sref))
3969 if (!usymtab_isGuarded (f->sref))
3971 if (optgenerror (FLG_NULLDEREF,
3972 message ("Function call using %s pointer %q",
3973 sRef_nullMessage (f->sref),
3974 sRef_unparse (f->sref)),
3977 sRef_showNullInfo (f->sref);
3978 sRef_setNullError (f->sref);
3986 if (ctype_isRealFunction (t))
3988 exprNode ret = functionCallSafe (f, t, args);
3992 else if (ctype_isUnknown (t))
3994 exprNode ret = exprNode_createPartialCopy (f);
4000 exprNodeList_elements (args, current)
4002 if (exprNode_isDefined (current))
4004 exprNode_checkUse (ret, current->sref, ret->loc);
4007 ** also, anything derivable from current->sref may be used
4010 exprNode_addUse (ret, sRef_makeDerived (current->sref));
4011 exprNode_mergeUSs (ret, current);
4013 } end_exprNodeList_elements;
4015 ret->edata = exprData_makeCall (f, args);
4016 ret->kind = XPR_CALL;
4018 tstring = cstring_copy (exprNode_unparse (f));
4020 cstring_markOwned (tstring);
4021 exprNode_checkSetAny (ret, tstring);
4027 voptgenerror (FLG_TYPE,
4028 message ("Call to non-function (type %t): %s", t,
4029 exprNode_unparse (f)),
4032 exprNodeList_free (args);
4034 return (exprNode_makeError ());
4039 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4040 /*@only@*/ cstring f)
4042 exprNode ret = exprNode_createPartialCopy (s);
4044 ret->kind = XPR_FACCESS;
4046 if (exprNode_isError (s))
4048 ret->edata = exprData_makeField (s, f);
4053 ctype t = exprNode_getType (s);
4054 ctype tr = ctype_realType (t);
4056 checkMacroParen (s);
4058 ret->edata = exprData_makeField (s, f);
4060 if (ctype_isStructorUnion (tr))
4062 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
4064 if (uentry_isUndefined (tf))
4066 voptgenerror (FLG_TYPE,
4067 message ("Access non-existent field %s of %t: %s", f, t,
4068 exprNode_unparse (ret)),
4070 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
4075 uentry_setUsed (tf, exprNode_loc (ret));
4077 ret->typ = uentry_getType (tf);
4078 checkSafeUse (ret, s->sref);
4080 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
4081 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
4085 else /* isStructorUnion */
4087 if (ctype_isRealAbstract (tr))
4091 message ("Access field of abstract type (%t): %s.%s",
4092 t, exprNode_unparse (s), f),
4094 ret->typ = ctype_unknown;
4098 if (ctype_isKnown (tr))
4103 ("Access field of non-struct or union (%t): %s.%s",
4104 t, exprNode_unparse (s), f),
4107 ret->typ = ctype_unknown;
4111 cstring sn = cstring_copy (f);
4113 checkSafeUse (ret, s->sref);
4114 cstring_markOwned (sn);
4115 ret->sref = sRef_makeField (s->sref, sn);
4127 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
4128 /*@only@*/ cstring f)
4130 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
4136 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
4138 exprNode ret = exprNode_createPartialCopy (e);
4140 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
4141 ret->kind = XPR_PARENS;
4142 ret->edata = exprData_makeUop (e, lpar);
4144 if (!exprNode_isError (e))
4146 ret->exitCode = e->exitCode;
4147 ret->canBreak = e->canBreak;
4148 ret->mustBreak = e->mustBreak;
4149 ret->isJumpPoint = e->isJumpPoint;
4150 ret->sref = e->sref;
4157 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4158 /*@only@*/ cstring f)
4160 exprNode ret = exprNode_createPartialCopy (s);
4162 ret->edata = exprData_makeField (s, f);
4163 ret->kind = XPR_ARROW;
4165 if (exprNode_isError (s))
4171 ctype t = exprNode_getType (s);
4172 ctype tr = ctype_realType (t);
4174 checkMacroParen (s);
4176 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4178 if (ctype_isRealPointer (tr))
4180 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4182 if (ctype_isStructorUnion (b))
4184 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4186 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4188 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4192 message ("Arrow access from %s pointer%q: %s",
4193 sRef_nullMessage (s->sref),
4194 sRef_unparsePreOpt (s->sref),
4195 exprNode_unparse (ret)),
4198 sRef_showNullInfo (s->sref);
4199 sRef_setNullError (s->sref);
4204 if (uentry_isUndefined (fentry))
4208 message ("Access non-existent field %s of %t: %s",
4209 f, t, exprNode_unparse (ret)),
4211 ret->typ = ctype_unknown;
4217 ** was safeUse: shouldn't be safe!
4220 ** rec must be defined,
4221 ** *rec must be allocated
4222 ** rec->field need only be defined it if is an rvalue
4225 uentry_setUsed (fentry, exprNode_loc (ret));
4226 ret->typ = uentry_getType (fentry);
4228 exprNode_checkUse (ret, s->sref, s->loc);
4230 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4231 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4235 else /* Pointer to something that is not a struct or union*/
4237 if (ctype_isRealAbstract (tr))
4239 ctype xrt = ctype_forceRealType (tr);
4243 message ("Arrow access field of abstract type (%t): %s->%s",
4244 t, exprNode_unparse (s), f),
4248 ** Set the state correctly, as if the abstraction is broken.
4251 if (ctype_isRealPointer (xrt) &&
4252 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4253 ctype_isStructorUnion (b)))
4255 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4256 ret->typ = uentry_getType (fentry);
4257 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4261 ret->typ = ctype_unknown;
4262 ret->sref = sRef_undefined;
4265 else /* not a struct, union or abstract */
4267 if (ctype_isUnknown (tr)) {
4268 cstring sn = cstring_copy (f);
4270 DPRINTF (("Here: %s", exprNode_unparse (s)));
4272 exprNode_checkUse (ret, s->sref, s->loc);
4273 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4275 cstring_markOwned (sn);
4276 ret->sref = sRef_makeArrow (s->sref, sn);
4278 ret->kind = XPR_ARROW;
4283 message ("Arrow access field of non-struct or union "
4284 "pointer (%t): %s->%s",
4285 t, exprNode_unparse (s), f),
4288 ret->typ = ctype_unknown;
4289 ret->sref = sRef_undefined;
4294 else /* its not a pointer */
4296 if (!ctype_isUnknown (tr))
4300 message ("Arrow access of non-pointer (%t): %s->%s",
4301 t, exprNode_unparse (s), f),
4304 ret->typ = ctype_unknown;
4305 ret->sref = sRef_undefined;
4309 cstring sn = cstring_copy (f);
4311 DPRINTF (("Here: %s", exprNode_unparse (s)));
4313 exprNode_checkUse (ret, s->sref, s->loc);
4314 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4316 cstring_markOwned (sn);
4317 ret->sref = sRef_makeArrow (s->sref, sn);
4319 ret->kind = XPR_ARROW;
4330 exprNode_arrowAccess (/*@only@*/ exprNode s,
4331 /*@only@*/ lltok arrow,
4332 /*@only@*/ cstring f)
4334 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4340 ** only postOp's in C: i++ and i--
4344 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4346 /* check modification also */
4347 /* cstring opname = lltok_unparse (op);*/
4349 exprNode ret = exprNode_createPartialCopy (e);
4351 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4352 ret->kind = XPR_POSTOP;
4353 ret->edata = exprData_makeUop (e, op);
4355 if (!exprNode_isDefined (e))
4360 checkMacroParen (e);
4362 exprNode_checkUse (ret, e->sref, e->loc);
4363 exprNode_checkSet (ret, e->sref);
4365 t = exprNode_getType (e);
4367 if (sRef_isUnsafe (e->sref))
4369 voptgenerror (FLG_MACROPARAMS,
4370 message ("Operand of %s is macro parameter (non-functional): %s%s",
4371 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4373 sRef_makeSafe (e->sref);
4374 sRef_makeSafe (ret->sref);
4377 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4383 if (ctype_isRealAbstract (t))
4387 message ("Operand of %s is abstract type (%t): %s",
4388 lltok_unparse (op), t, exprNode_unparse (e)),
4395 message ("Operand of %s is non-numeric (%t): %s",
4396 lltok_unparse (op), t, exprNode_unparse (e)),
4399 ret->typ = ctype_unknown;
4402 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4404 exprNode_checkModify (e, ret);
4406 /* added 7/11/2000 D.L */
4408 /*DRL 6/8/01 I decided to disable all Splint warnings here since the code
4409 probably needs a rewrite any way */
4414 /* updateEnvironmentForPostOp (e); */
4416 /* start modifications */
4417 /* added by Seejo on 4/16/2000 */
4419 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4421 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4423 ret->sref = sRef_copy (e->sref);
4426 if (lltok_getTok (op) == INC_OP) {
4427 if (sRef_getSize(e->sref) > 0) {
4429 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4431 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4432 /* Assumption: there is only 1 \0 in the buffer */
4433 /* This will not be correct if there are 2 \0's in the buffer */
4434 sRef_setNotNullTerminatedState(ret->sref);
4435 sRef_resetLen(ret->sref);
4437 sRef_setNullTerminatedState(ret->sref);
4438 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4440 if (sRef_isNullTerminated (ret->sref))
4441 printf ("ret->sref is Null Terminated\n");
4442 else if (sRef_isPossiblyNullTerminated (ret->sref))
4443 printf ("ret->sref is Possibly Null Terminated\n");
4444 else if (sRef_isNotNullTerminated (ret->sref))
4445 printf ("ret->sref is Not Null Terminated\n");
4450 if (lltok_getTok (op) == DEC_OP) {
4451 if (sRef_getSize(e->sref) >= 0) {
4452 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4453 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4458 /* end modifications */
4464 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4466 bool checkMod = FALSE;
4468 int opid = lltok_getTok (op);
4469 exprNode ret = exprNode_createSemiCopy (e);
4471 exprNode_copySets (ret, e);
4473 multiVal_free (ret->val);
4474 ret->val = multiVal_undefined;
4475 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4476 ret->kind = XPR_PREOP;
4477 ret->edata = exprData_makeUop (e, op);
4479 if (exprNode_isError (e))
4484 checkMacroParen (e);
4486 te = exprNode_getType (e);
4487 tr = ctype_realType (te);
4489 if (opid != TAMPERSAND)
4491 exprNode_checkUse (ret, e->sref, e->loc);
4493 if (ctype_isRealAbstract (tr)
4494 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4496 if (optgenerror (FLG_ABSTRACT,
4497 message ("Operand of %s is abstract type (%t): %s",
4498 lltok_unparse (op), tr,
4499 exprNode_unparse (ret)),
4502 tr = te = ctype_unknown;
4503 ret->typ = ctype_unknown;
4504 sRef_setNullError (e->sref);
4512 case DEC_OP: /* should also check modification! */
4513 if (sRef_isMacroParamRef (e->sref))
4517 message ("Operand of %s is macro parameter (non-functional): %s",
4518 lltok_unparse (op), exprNode_unparse (ret)),
4523 exprNode_checkSet (ret, e->sref);
4526 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4531 if (context_msgStrictOps ())
4535 message ("Operand of %s is non-numeric (%t): %s",
4536 lltok_unparse (op), te, exprNode_unparse (ret)),
4539 ret->typ = ctype_int;
4542 /* start modifications */
4543 /* added by Seejo on 4/16/2000 */
4545 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4547 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4549 ret->sref = sRef_copy (e->sref);
4552 if (lltok_getTok (op) == INC_OP) {
4553 if (sRef_getSize(e->sref) > 0) {
4555 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4557 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4558 /* Assumption: there is only 1 \0 in the buffer */
4559 /* This will not be correct if there are 2 \0's in the buffer */
4560 sRef_setNotNullTerminatedState(ret->sref);
4561 sRef_resetLen (ret->sref);
4563 sRef_setNullTerminatedState(ret->sref);
4564 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4570 if (lltok_getTok (op) == DEC_OP) {
4571 if (sRef_getSize(e->sref) >= 0) {
4572 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4573 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4578 /* end modifications */
4585 if (ctype_isForceRealNumeric (&tr))
4589 ret->val = multiVal_invert (exprNode_getValue (e));
4593 ret->val = multiVal_copy (exprNode_getValue (e));
4598 if (context_msgStrictOps ())
4602 message ("Operand of %s is non-numeric (%t): %s",
4603 lltok_unparse (op), te, exprNode_unparse (ret)),
4607 ret->typ = ctype_int;
4611 case TEXCL: /* maybe this should be restricted */
4612 guardSet_flip (ret->guards);
4614 if (ctype_isRealBool (te) || ctype_isUnknown (te))
4620 if (ctype_isRealPointer (tr))
4622 if (sRef_isKnown (e->sref))
4624 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4628 (FLG_BOOLOPS, FLG_PTRNEGATE,
4629 message ("Operand of %s is non-boolean (%t): %s",
4630 lltok_unparse (op), te, exprNode_unparse (ret)),
4637 message ("Operand of %s is non-boolean (%t): %s",
4638 lltok_unparse (op), te, exprNode_unparse (ret)),
4642 ret->typ = ctype_bool;
4647 if (ctype_isForceRealInt (&tr))
4652 if (context_msgStrictOps ())
4656 message ("Operand of %s is non-integer (%t): %s",
4657 lltok_unparse (op), te, exprNode_unparse (ret)),
4661 if (ctype_isInt (e->typ))
4667 ret->typ = ctype_int;
4673 ret->typ = ctype_makePointer (e->typ);
4675 if (sRef_isKnown (e->sref))
4677 ret->sref = sRef_makeAddress (e->sref);
4684 if (ctype_isAP (tr))
4686 ret->typ = ctype_baseArrayPtr (e->typ);
4690 if (ctype_isKnown (te))
4692 if (ctype_isFunction (te))
4698 message ("Dereference of function type (%t): %s",
4699 te, exprNode_unparse (ret)),
4704 voptgenerror (FLG_TYPE,
4705 message ("Dereference of non-pointer (%t): %s",
4706 te, exprNode_unparse (ret)),
4708 ret->typ = ctype_unknown;
4713 ret->typ = ctype_unknown;
4718 if (sRef_isKnown (e->sref))
4720 DPRINTF (("Checking possibly null: %s", sRef_unparseFull (e->sref)));
4722 if (sRef_possiblyNull (e->sref))
4724 DPRINTF (("Checking possibly null: %s", sRef_unparse (e->sref)));
4725 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4729 message ("Dereference of %s pointer %q: %s",
4730 sRef_nullMessage (e->sref),
4731 sRef_unparse (e->sref),
4732 exprNode_unparse (ret)),
4735 sRef_showNullInfo (e->sref);
4736 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4741 ret->sref = sRef_makePointer (e->sref);
4746 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4751 exprNode_checkModify (e, ret);
4758 ** any reason to disallow sizeof (abstract type) ?
4762 ** used by both sizeof
4766 ctype sizeof_resultType (void)
4768 static ctype sizet = ctype_unknown;
4770 if (ctype_isUnknown (sizet))
4772 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4774 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4778 sizet = ctype_ulint;
4785 exprNode_sizeofType (/*@only@*/ qtype qt)
4787 exprNode ret = exprNode_create (sizeof_resultType ());
4788 ctype ct = qtype_getType (qt);
4790 ret->kind = XPR_SIZEOFT;
4791 ret->edata = exprData_makeSizeofType (qt);
4793 voptgenerror (FLG_SIZEOFTYPE,
4794 message ("Parameter to sizeof is type %s: %s",
4796 exprNode_unparse (ret)),
4803 exprNode_alignofType (/*@only@*/ qtype qt)
4805 exprNode ret = exprNode_create (sizeof_resultType ());
4806 ctype ct = qtype_getType (qt);
4808 ret->kind = XPR_ALIGNOFT;
4809 ret->edata = exprData_makeSizeofType (qt);
4811 voptgenerror (FLG_SIZEOFTYPE,
4812 message ("Parameter to alignof is type %s: %s",
4814 exprNode_unparse (ret)),
4820 exprNode exprNode_offsetof (qtype qt, cstringList s)
4822 exprNode ret = exprNode_create (sizeof_resultType ());
4823 ctype ct = qtype_getType (qt);
4825 ret->kind = XPR_OFFSETOF;
4826 ret->edata = exprData_makeOffsetof (qt, s);
4828 if (!ctype_isRealSU (ct))
4830 voptgenerror (FLG_TYPE,
4831 message ("First parameter to offsetof is not a "
4832 "struct or union type (type %s): %s",
4834 exprNode_unparse (ret)),
4841 cstringList_elements (s, el) {
4845 if (ctype_isUndefined (lt))
4849 else if (!ctype_isRealSU (lt))
4851 voptgenerror (FLG_TYPE,
4852 message ("Inner offsetof type is not a "
4853 "struct or union type (type %s before field %s): %s",
4854 ctype_unparse (lt), el,
4855 exprNode_unparse (ret)),
4861 fields = ctype_getFields (ctype_realType (lt));
4862 fld = uentryList_lookupField (fields, el);
4863 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4865 if (uentry_isUndefined (fld))
4867 if (ctype_equal (lt, ct)) {
4868 voptgenerror (FLG_TYPE,
4869 message ("Field %s in offsetof is not the "
4870 "name of a field of %s: %s",
4873 exprNode_unparse (ret)),
4876 voptgenerror (FLG_TYPE,
4877 message ("Deep field %s in offsetof is not the "
4878 "name of a field of %s: %s",
4881 exprNode_unparse (ret)),
4887 lt = uentry_getType (fld);
4890 } end_cstringList_elements;
4892 /* Should report error if its a bit field - behavior is undefined! */
4899 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4903 if (exprNode_isUndefined (e))
4905 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4906 ret->edata = exprData_makeSingle (e);
4907 ret->typ = sizeof_resultType ();
4908 ret->kind = XPR_SIZEOF;
4912 uentry u = exprNode_getUentry (e);
4914 ret = exprNode_createPartialCopy (e);
4915 ret->edata = exprData_makeSingle (e);
4917 ret->typ = sizeof_resultType ();
4918 ret->kind = XPR_SIZEOF;
4920 if (uentry_isValid (u)
4921 && uentry_isRefParam (u)
4922 && ctype_isRealArray (uentry_getType (u)))
4925 (FLG_SIZEOFFORMALARRAY,
4926 message ("Parameter to sizeof is an array-type function parameter: %s",
4927 exprNode_unparse (ret)),
4933 ** sizeof (x) doesn't "really" use x
4940 exprNode_alignofExpr (/*@only@*/ exprNode e)
4944 if (exprNode_isUndefined (e))
4946 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4950 ret = exprNode_createPartialCopy (e);
4953 ret->edata = exprData_makeSingle (e);
4954 ret->typ = sizeof_resultType ();
4955 ret->kind = XPR_ALIGNOF;
4958 ** sizeof (x) doesn't "really" use x
4965 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4971 if (exprNode_isError (e))
4975 return exprNode_undefined;
4978 checkMacroParen (e);
4980 c = qtype_getType (q);
4981 t = exprNode_getType (e);
4983 ret = exprNode_createPartialCopy (e);
4985 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4987 ret->kind = XPR_CAST;
4988 ret->edata = exprData_makeCast (tok, e, q);
4990 ret->sref = sRef_copy (e->sref);
4992 if (!sRef_isConst (e->sref))
4994 usymtab_addForceMustAlias (ret->sref, e->sref);
4997 sRef_setTypeFull (ret->sref, c);
4998 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
5004 ** void * <-> abstract * (if FLG_ABSTVOIDP)
5005 ** abstract * <-> void * (if FLG_ABSTVOIDP)
5008 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
5012 else if (ctype_isRealAP (c)) /* casting to array or pointer */
5014 ctype bc = ctype_getBaseType (c);
5015 ctype bt = ctype_getBaseType (t);
5016 ctype rt = ctype_realType (t);
5018 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
5019 && (ctype_isArrayPtr (rt)
5020 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5024 message ("Cast from function pointer type (%t) to "
5025 "non-function pointer (%t): %s",
5026 c, t, exprNode_unparse (ret)),
5030 if (!ctype_isFunction (ctype_baseArrayPtr (c))
5031 && (ctype_isArrayPtr (rt)
5032 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
5036 message ("Cast from non-function pointer type (%t) to "
5037 "function pointer (%t): %s",
5038 c, t, exprNode_unparse (ret)),
5042 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
5043 !(ctype_isRealAbstract (bc)
5044 && context_hasAccess (ctype_typeId (bc))))
5046 ; /* okay to cast zero */
5050 if (ctype_isRealAbstract (bc)
5051 && !context_hasAccess (ctype_typeId (bc)))
5053 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
5057 message ("Cast to underlying abstract type %t: %s",
5058 c, exprNode_unparse (ret)),
5065 message ("Cast to underlying abstract type %t: %s",
5066 c, exprNode_unparse (ret)),
5071 if (ctype_isRealAbstract (bt)
5072 && !context_hasAccess (ctype_typeId (bt)))
5074 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
5078 message ("Cast from underlying abstract type %t: %s",
5079 t, exprNode_unparse (ret)),
5086 message ("Cast from underlying abstract type %t: %s",
5087 t, exprNode_unparse (ret)),
5095 ctype bt = ctype_realType (ctype_getBaseType (t));
5096 ctype bc = ctype_realType (ctype_getBaseType (c));
5098 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
5100 if (ctype_match (c, t))
5102 if (ctype_equal (c, t))
5106 message ("Redundant cast involving abstract type %t: %s",
5107 bt, exprNode_unparse (ret)),
5115 message ("Cast from abstract type %t: %s",
5116 bt, exprNode_unparse (ret)),
5121 if (ctype_isAbstract (bc)
5122 && !context_hasAccess (ctype_typeId (bc)))
5124 if (ctype_match (c, t))
5130 DPRINTF (("No access to: %s / %d",
5131 ctype_unparse (bc), ctype_typeId (bc)));
5132 DPRINTF (("Context %s %s",
5133 bool_unparse (context_inFunctionLike ()),
5134 context_unparse ()));
5137 message ("Cast to abstract type %t: %s", bc,
5138 exprNode_unparse (ret)),
5144 if (ctype_isAbstract (c))
5146 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
5148 /* okay, cast exposed to abstract */
5149 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
5153 if (ctype_isVisiblySharable (t)
5154 && sRef_isExternallyVisible (e->sref)
5155 && !(ctype_isAbstract (t)
5156 && context_hasAccess (ctype_typeId (t))))
5160 message ("Cast to abstract type from externally visible "
5161 "mutable storage exposes rep of %s: %s",
5163 exprNode_unparse (e)),
5173 evaluationOrderUndefined (lltok op)
5175 int opid = lltok_getTok (op);
5177 return (opid != AND_OP && opid != OR_OP);
5180 static bool checkIntegral (/*@notnull@*/ exprNode e1,
5181 /*@notnull@*/ exprNode e2,
5182 /*@notnull@*/ exprNode ret,
5187 ctype te1 = exprNode_getType (e1);
5188 ctype te2 = exprNode_getType (e2);
5190 ctype tr1 = ctype_realishType (te1);
5191 ctype tr2 = ctype_realishType (te2);
5193 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5199 if (context_msgStrictOps ())
5201 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5203 if (ctype_sameName (te1, te2))
5207 message ("Operands of %s are non-integer (%t): %s",
5208 lltok_unparse (op), te1,
5209 exprNode_unparse (ret)),
5216 message ("Operands of %s are non-integers (%t, %t): %s",
5217 lltok_unparse (op), te1, te2,
5218 exprNode_unparse (ret)),
5222 else if (!ctype_isInt (tr1))
5226 message ("Left operand of %s is non-integer (%t): %s",
5227 lltok_unparse (op), te1, exprNode_unparse (ret)),
5231 /* !ctype_isInt (te2) */
5235 message ("Right operand of %s is non-integer (%t): %s",
5236 lltok_unparse (op), te2, exprNode_unparse (ret)),
5246 ** returns exprNode representing e1 op e2
5248 ** uses msg if there are errors
5249 ** can be used for both assignment ops and regular ops
5254 static /*@only@*/ /*@notnull@*/ exprNode
5255 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
5256 /*@keep@*/ lltok op)
5258 ctype te1, te2, tr1, tr2, tret;
5259 int opid = lltok_getTok (op);
5260 bool hasError = FALSE;
5263 if (exprNode_isError (e1))
5265 ret = exprNode_createPartialNVCopy (e2);
5269 ret = exprNode_createPartialNVCopy (e1);
5272 ret->val = multiVal_undefined;
5275 ret->edata = exprData_makeOp (e1, e2, op);
5277 if (exprNode_isError (e1) || exprNode_isError (e2))
5279 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5280 || opid == EQ_OP || opid == NE_OP
5281 || opid == AND_OP || opid == OR_OP)
5283 ret->typ = ctype_bool;
5286 if (exprNode_isDefined (e1))
5288 exprNode_checkUse (ret, e1->sref, e1->loc);
5291 if (exprNode_isDefined (e2))
5293 exprNode_mergeUSs (ret, e2);
5294 exprNode_checkUse (ret, e2->sref, e2->loc);
5300 tret = ctype_unknown;
5301 te1 = exprNode_getType (e1);
5303 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5305 te2 = exprNode_getType (e2);
5307 tr1 = ctype_realishType (te1);
5308 tr2 = ctype_realishType (te2);
5312 ret->guards = guardSet_or (ret->guards, e2->guards);
5314 else if (opid == AND_OP)
5316 ret->guards = guardSet_and (ret->guards, e2->guards);
5323 if (opid == EQ_OP || opid == NE_OP)
5325 exprNode temp1 = e1, temp2 = e2;
5327 /* could do NULL == x */
5329 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5331 temp1 = e2; temp2 = e1;
5334 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5336 reflectNullTest (temp1, (opid == NE_OP));
5337 guardSet_free (ret->guards);
5338 ret->guards = guardSet_copy (temp1->guards);
5342 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5343 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5348 if (anyAbstract (tr1, tr2) &&
5349 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
5350 (opid == AND_OP || opid == OR_OP
5351 || opid == EQ_OP || opid == NE_OP))))
5353 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
5355 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5357 /* unknown types, no comparisons possible */
5363 case TMULT: /* multiplication and division: */
5365 case MUL_ASSIGN: /* numeric, numeric -> numeric */
5366 case DIV_ASSIGN: /* */
5368 if (opid == TMULT || opid == MUL_ASSIGN)
5370 ret->val = multiVal_multiply (exprNode_getValue (e1),
5371 exprNode_getValue (e2));
5375 ret->val = multiVal_divide (exprNode_getValue (e1),
5376 exprNode_getValue (e2));
5379 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5382 case TPLUS: /* addition and subtraction: */
5383 case TMINUS: /* pointer, int -> pointer */
5384 case SUB_ASSIGN: /* int, pointer -> pointer */
5385 case ADD_ASSIGN: /* numeric, numeric -> numeric */
5387 if (opid == TPLUS || opid == ADD_ASSIGN)
5389 ret->val = multiVal_add (exprNode_getValue (e1),
5390 exprNode_getValue (e2));
5394 ret->val = multiVal_subtract (exprNode_getValue (e1),
5395 exprNode_getValue (e2));
5398 tr1 = ctype_fixArrayPtr (tr1);
5400 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5401 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5405 if (context_msgPointerArith ())
5409 message ("Pointer arithmetic (%t, %t): %s",
5410 te1, te2, exprNode_unparse (ret)),
5415 ** Swap terms so e1 is always the pointer
5418 if (ctype_isRealPointer (tr1))
5424 exprNode_swap (e1, e2);
5428 if (sRef_possiblyNull (e1->sref)
5429 && !usymtab_isGuarded (e1->sref))
5432 (FLG_NULLPOINTERARITH,
5433 message ("Pointer arithmetic involving possibly "
5434 "null pointer %s: %s",
5435 exprNode_unparse (e1),
5436 exprNode_unparse (ret)),
5440 ret->sref = sRef_copy (e1->sref);
5442 /* start modifications */
5443 /* added by Seejo on 4/16/2000 */
5445 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5447 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5450 added ugly fixed to stop
5451 program from crashing on point + int +int
5452 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5454 if (!multiVal_isInt (e2->val) )
5458 val = (int) multiVal_forceInt (e2->val);
5460 /* Operator : + or += */
5461 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5462 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5463 val should not result in a
5464 size < 0 (size = 0 is ok !) */
5466 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5468 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5469 sRef_setNotNullTerminatedState(ret->sref);
5470 sRef_resetLen (ret->sref);
5472 sRef_setNullTerminatedState(ret->sref);
5473 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5478 /* Operator : - or -= */
5479 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5480 if (sRef_getSize(e1->sref) >= 0) {
5481 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5482 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5487 /* end modifications */
5489 sRef_setNullError (ret->sref);
5492 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5493 ** since is points to storage that should not be deallocated
5494 ** through this pointer.
5497 if (sRef_isOnly (ret->sref)
5498 || sRef_isFresh (ret->sref))
5500 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5505 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5506 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5508 if (context_msgPointerArith ())
5512 message ("Pointer arithmetic (%t, %t): %s",
5513 te1, te2, exprNode_unparse (ret)),
5517 if (sRef_possiblyNull (e1->sref)
5518 && !usymtab_isGuarded (e1->sref))
5521 (FLG_NULLPOINTERARITH,
5522 message ("Pointer arithmetic involving possibly "
5523 "null pointer %s: %s",
5524 exprNode_unparse (e2),
5525 exprNode_unparse (ret)),
5529 ret->sref = sRef_copy (e2->sref);
5531 /* start modifications */
5532 /* added by Seejo on 4/16/2000 */
5534 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5537 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5538 int val = (int) multiVal_forceInt (e1->val);
5540 /* Operator : + or += */
5541 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5542 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5543 val should not result in a
5544 size < 0 (size = 0 is ok !) */
5546 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5548 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5549 sRef_setNotNullTerminatedState(ret->sref);
5550 sRef_resetLen (ret->sref);
5552 sRef_setNullTerminatedState(ret->sref);
5553 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5558 /* Operator : - or -= */
5559 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5560 if (sRef_getSize(e2->sref) >= 0) {
5561 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5562 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5566 /* end modifications */
5568 sRef_setNullError (ret->sref);
5571 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5572 ** since is points to storage that should not be deallocated
5573 ** through this pointer.
5576 if (sRef_isOnly (ret->sref)
5577 || sRef_isFresh (ret->sref)) {
5578 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5582 ret->sref = e2->sref;
5586 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5595 case TAMPERSAND: /* bitwise & */
5597 case TCIRC: /* ^ (XOR) */
5602 bool reported = FALSE;
5608 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5609 || opid == RIGHT_OP || opid == RIGHT_ASSIGN)
5612 ** evans 2002-01-01: fixed this to follow ISO 6.5.7.
5615 if (!ctype_isUnsigned (tr2)
5616 && !exprNode_isNonNegative (e2))
5618 reported = optgenerror
5620 message ("Right operand of %s may be negative (%t): %s",
5621 lltok_unparse (op), te2,
5622 exprNode_unparse (ret)),
5626 if (!ctype_isUnsigned (tr1)
5627 && !exprNode_isNonNegative (e1))
5629 reported = optgenerror
5630 (FLG_SHIFTIMPLEMENTATION,
5631 message ("Left operand of %s may be negative (%t): %s",
5632 lltok_unparse (op), te1,
5633 exprNode_unparse (ret)),
5638 ** Should check size of right operand also...
5644 if (!ctype_isUnsigned (tr1))
5646 if (exprNode_isNonNegative (e1)) {
5649 reported = optgenerror
5651 message ("Left operand of %s is not unsigned value (%t): %s",
5652 lltok_unparse (op), te1,
5653 exprNode_unparse (ret)),
5663 if (!ctype_isUnsigned (tr2))
5665 if (!exprNode_isNonNegative (e2)) {
5666 reported = optgenerror
5668 message ("Right operand of %s is not unsigned value (%t): %s",
5669 lltok_unparse (op), te2,
5670 exprNode_unparse (ret)),
5679 if (!checkIntegral (e1, e2, ret, op)) {
5680 te1 = ctype_unknown;
5684 DPRINTF (("Set: %s", ctype_unparse (te1)));
5687 ** tret is the widest type of te1 and te2
5690 tret = ctype_widest (te1, te2);
5695 if (checkIntegral (e1, e2, ret, op)) {
5698 tret = ctype_unknown;
5703 case TLT: /* comparisons */
5704 case TGT: /* numeric, numeric -> bool */
5706 DPRINTF (("Here we go: %s / %s",
5707 ctype_unparse (tr1), ctype_unparse (tr2)));
5709 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5710 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5713 bool fepsilon = FALSE;
5715 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5720 if (opid == TLT || opid == TGT)
5722 uentry ue1 = exprNode_getUentry (e1);
5723 uentry ue2 = exprNode_getUentry (e2);
5726 ** FLT_EPSILON, etc. really is a variable, not
5730 if (uentry_isVariable (ue1))
5732 cstring uname = uentry_rawName (ue1);
5734 if (cstring_equalLit (uname, "FLT_EPSILON")
5735 || cstring_equalLit (uname, "DBL_EPSILON")
5736 || cstring_equalLit (uname, "LDBL_EPSILON"))
5742 if (uentry_isVariable (ue2))
5744 cstring uname = uentry_rawName (ue2);
5746 if (cstring_equalLit (uname, "FLT_EPSILON")
5747 || cstring_equalLit (uname, "DBL_EPSILON")
5748 || cstring_equalLit (uname, "LDBL_EPSILON"))
5757 ; /* Don't complain. */
5763 message ("Dangerous comparison involving %s types: %s",
5764 ctype_unparse (rtype),
5765 exprNode_unparse (ret)),
5774 ** Types should match.
5777 DPRINTF (("Match types: %s / %s", exprNode_unparse (e1),
5778 exprNode_unparse (e2)));
5780 if (!exprNode_matchTypes (e1, e2))
5782 hasError = gentypeerror
5784 message ("Operands of %s have incompatible types (%t, %t): %s",
5785 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5791 || (ctype_isForceRealNumeric (&tr1)
5792 && ctype_isForceRealNumeric (&tr2)) ||
5793 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5799 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5800 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5804 message ("Comparison of pointer and numeric (%t, %t): %s",
5805 te1, te2, exprNode_unparse (ret)),
5810 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5815 /* certain comparisons on unsigned's and zero look suspicious */
5817 if (opid == TLT || opid == LE_OP || opid == GE_OP)
5819 if ((ctype_isUnsigned (tr1) && exprNode_isZero (e2))
5820 || (ctype_isUnsigned (tr2) && exprNode_isZero (e1)))
5823 (FLG_UNSIGNEDCOMPARE,
5824 message ("Comparison of unsigned value involving zero: %s",
5825 exprNode_unparse (ret)),
5830 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5832 if ((opid == EQ_OP || opid == NE_OP) &&
5833 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5836 ** is one a variable?
5839 if (uentry_isVariable (exprNode_getUentry (e1))
5840 || uentry_isVariable (exprNode_getUentry (e2)))
5843 ** comparisons with FALSE are okay
5846 if (exprNode_isFalseConstant (e1)
5847 || exprNode_isFalseConstant (e2))
5856 ("Use of %q with %s variables (risks inconsistency because "
5857 "of multiple true values): %s",
5858 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5859 context_printBoolName (), exprNode_unparse (ret)),
5866 case AND_OP: /* bool, bool -> bool */
5869 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5875 if (context_maybeSet (FLG_BOOLOPS))
5877 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5879 if (ctype_sameName (te1, te2))
5883 message ("Operands of %s are non-boolean (%t): %s",
5884 lltok_unparse (op), te1,
5885 exprNode_unparse (ret)),
5893 ("Operands of %s are non-booleans (%t, %t): %s",
5894 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5898 else if (!ctype_isRealBool (te1))
5902 message ("Left operand of %s is non-boolean (%t): %s",
5903 lltok_unparse (op), te1, exprNode_unparse (ret)),
5906 else if (!ctype_isRealBool (te2))
5910 message ("Right operand of %s is non-boolean (%t): %s",
5911 lltok_unparse (op), te2, exprNode_unparse (ret)),
5924 (cstring_makeLiteral
5925 ("There has been a problem in the parser. This is believed to result "
5926 "from a problem with bison v. 1.25. Please try rebuidling Splint "
5927 "using the pre-compiled grammar files by commenting out the "
5928 "BISON= line in the top-level Makefile."));
5933 DPRINTF (("Return type: %s", ctype_unparse (tret)));
5936 exprNode_checkUse (ret, e1->sref, e1->loc);
5937 exprNode_mergeUSs (ret, e2);
5938 exprNode_checkUse (ret, e2->sref, e2->loc);
5944 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5945 /*@only@*/ lltok op)
5949 checkMacroParen (e1);
5950 checkMacroParen (e2);
5952 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5954 checkExpressionDefined (e1, e2, op);
5957 ret = exprNode_makeOp (e1, e2, op);
5962 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5965 ** This is somewhat bogus!
5967 ** Assigning to a nested observer in a non-observer datatype
5968 ** should not produce an error.
5971 sRef ref = exprNode_getSref (e1);
5973 DPRINTF (("Check assign mod: %s",
5974 sRef_unparseFull (ref)));
5976 if (sRef_isObserver (ref)
5977 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
5978 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5980 sRef base = sRef_getBase (ref);
5982 if (sRef_isValid (base) && sRef_isObserver (base))
5984 exprNode_checkModify (e1, ret);
5988 exprNode_checkModifyVal (e1, ret);
5993 exprNode_checkModify (e1, ret);
5998 exprNode_assign (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2, /*@only@*/ lltok op)
6000 bool isalloc = FALSE;
6001 bool isjustalloc = FALSE;
6002 bool noalias = FALSE;
6005 DPRINTF (("%s [%s] <- %s [%s]",
6006 exprNode_unparse (e1),
6007 ctype_unparse (e1->typ),
6008 exprNode_unparse (e2),
6009 ctype_unparse (e2->typ)));
6011 if (lltok_getTok (op) != TASSIGN)
6013 ret = exprNode_makeOp (e1, e2, op);
6015 DPRINTF (("Here goes: %s %s",
6016 ctype_unparse (e1->typ),
6017 ctype_unparse (e2->typ)));
6019 if (exprNode_isDefined (e1)
6020 && exprNode_isDefined (e2))
6022 if (ctype_isNumeric (e2->typ)
6023 || ctype_isNumeric (e1->typ))
6025 /* Its a pointer arithmetic expression like ptr += i */
6032 ret = exprNode_createPartialCopy (e1);
6033 ret->kind = XPR_ASSIGN;
6034 ret->edata = exprData_makeOp (e1, e2, op);
6036 if (!exprNode_isError (e2))
6038 ret->sets = sRefSet_union (ret->sets, e2->sets);
6039 ret->msets = sRefSet_union (ret->msets, e2->msets);
6040 ret->uses = sRefSet_union (ret->uses, e2->uses);
6044 checkExpressionDefined (e1, e2, op);
6046 if (exprNode_isError (e1))
6048 if (!exprNode_isError (e2))
6050 ret->loc = fileloc_update (ret->loc, e2->loc);
6054 ret->loc = fileloc_update (ret->loc, g_currentloc);
6058 if (!exprNode_isError (e2))
6060 checkMacroParen (e2);
6063 if (exprNode_isDefined (e1))
6065 if (sRef_isMacroParamRef (e1->sref))
6067 if (context_inIterDef ())
6069 uentry ue = sRef_getUentry (e1->sref);
6071 if (uentry_isYield (ue))
6077 if (fileloc_isDefined (e1->loc))
6081 message ("Assignment to non-yield iter parameter: %q",
6082 sRef_unparse (e1->sref)),
6089 message ("Assignment to non-yield iter parameter: %q",
6090 sRef_unparse (e1->sref)),
6097 if (fileloc_isDefined (e1->loc))
6101 message ("Assignment to macro parameter: %q",
6102 sRef_unparse (e1->sref)),
6109 message ("Assignment to macro parameter: %q",
6110 sRef_unparse (e1->sref)),
6114 exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
6119 exprNode_checkAssignMod (e1, ret);
6122 if (exprNode_isDefined (e2))
6124 if (lltok_getTok (op) == TASSIGN)
6126 ctype te1 = exprNode_getType (e1);
6127 ctype te2 = exprNode_getType (e2);
6129 if (ctype_isVoid (te2))
6133 message ("Assignment of void value to %t: %s %s %s",
6134 te1, exprNode_unparse (e1),
6136 exprNode_unparse (e2)),
6139 else if (!ctype_forceMatch (te1, te2))
6141 if (exprNode_matchLiteral (te1, e2))
6149 message ("Assignment of %t to %t: %s %s %s",
6150 te2, te1, exprNode_unparse (e1),
6152 exprNode_unparse (e2)),
6158 /* Type checks okay */
6162 exprNode_mergeUSs (ret, e2);
6163 exprNode_checkUse (ret, e2->sref, e2->loc);
6165 DPRINTF (("Do assign! %s %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6172 doAssign (e1, e2, FALSE);
6175 ret->sref = e1->sref;
6179 if (exprNode_isDefined (e2))
6181 exprNode_mergeUSs (ret, e2);
6182 exprNode_checkUse (ret, e2->sref, e2->loc);
6186 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
6188 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
6191 isjustalloc = sRef_isJustAllocated (e1->sref);
6192 isalloc = sRef_isAllocated (e1->sref);
6194 if (sRef_isField (e1->sref))
6196 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
6198 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
6200 exprNode_checkUse (ret, root, e1->loc);
6206 ** be careful! this defines e1->sref.
6209 /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
6211 DPRINTF (("Setting: %s -> %s", exprNode_unparse (ret), sRef_unparse (e1->sref)));
6212 exprNode_checkSet (ret, e1->sref);
6216 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
6217 ? e2->loc : e1->loc);
6223 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
6232 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
6233 /*@keep@*/ exprNode elseclause)
6237 if (!exprNode_isError (pred))
6239 ret = exprNode_createPartialCopy (pred);
6240 checkMacroParen (pred);
6241 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
6243 if (!exprNode_isError (ifclause))
6245 checkMacroParen (ifclause); /* update macro counts! */
6247 if (!exprNode_isError (elseclause))
6249 checkMacroParen (elseclause);
6251 if (!exprNode_matchTypes (ifclause, elseclause))
6254 (exprNode_getType (ifclause),
6256 exprNode_getType (elseclause),
6258 message ("Conditional clauses are not of same type: "
6260 exprNode_unparse (ifclause),
6261 exprNode_getType (ifclause),
6262 exprNode_unparse (elseclause),
6263 exprNode_getType (elseclause)),
6266 ret->sref = sRef_undefined;
6267 ret->typ = ctype_unknown;
6272 /* for now...should merge the states */
6273 ret->sref = ifclause->sref;
6274 ret->typ = ifclause->typ;
6276 if (exprNode_isNullValue (ifclause))
6278 ret->typ = elseclause->typ;
6282 exprNode_checkUse (ret, pred->sref, pred->loc);
6283 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6284 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6286 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6291 ret->typ = ifclause->typ;
6293 exprNode_checkUse (pred, pred->sref, pred->loc);
6294 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6296 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6301 if (!exprNode_isError (elseclause))
6303 ret->typ = elseclause->typ;
6305 exprNode_checkUse (pred, pred->sref, pred->loc);
6306 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6308 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6312 else /* pred is error */
6314 if (!exprNode_isError (ifclause))
6316 ret = exprNode_createSemiCopy (ifclause);
6318 checkMacroParen (ifclause); /* update macro counts! */
6320 if (!exprNode_isError (elseclause))
6322 checkMacroParen (elseclause);
6324 ret->typ = ifclause->typ;
6326 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6329 (exprNode_getType (ifclause),
6331 exprNode_getType (elseclause),
6333 message ("Conditional clauses are not of same type: "
6335 exprNode_unparse (ifclause),
6336 exprNode_getType (ifclause),
6337 exprNode_unparse (elseclause),
6338 exprNode_getType (elseclause)),
6341 ret->typ = ctype_unknown;
6345 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6346 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6348 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6351 else if (!exprNode_isError (elseclause)) /* pred, if errors */
6353 ret = exprNode_createSemiCopy (ifclause);
6355 ret->typ = elseclause->typ;
6356 checkMacroParen (elseclause);
6358 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6359 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6361 else /* all errors! */
6363 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6367 ret->kind = XPR_COND;
6368 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
6370 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6372 exprNode_combineControl (ret, ifclause, elseclause);
6379 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6381 ctype totype = qtype_getType (qt);
6383 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6387 ** check use of va_arg : <valist>, type -> type
6390 if (exprNode_isError (arg))
6395 targ = exprNode_getType (arg);
6398 ** arg should have be a pointer
6401 if (!ctype_isUA (targ) ||
6402 (!usymId_equal (ctype_typeId (targ),
6403 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6407 message ("First argument to va_arg is not a va_list (type %t): %s",
6408 targ, exprNode_unparse (arg)),
6412 exprNode_checkSet (ret, arg->sref);
6416 ** return type is totype
6420 ret->kind = XPR_VAARG;
6421 ret->edata = exprData_makeCast (tok, arg, qt);
6426 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6428 exprNode ret = exprNode_createPlain (ctype_undefined);
6429 ret->kind = XPR_LABEL;
6430 ret->edata = exprData_makeLiteral (label);
6431 ret->isJumpPoint = TRUE;
6433 return (ret); /* for now, ignore label */
6436 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6438 if (exprNode_isDefined (stmt))
6440 stmt->isJumpPoint = TRUE;
6442 /* This prevent stray no return path errors, etc. */
6443 stmt->exitCode = XK_MUSTEXIT;
6449 bool exprNode_isDefaultMarker (exprNode e)
6451 if (exprNode_isDefined (e))
6453 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6459 bool exprNode_isCaseMarker (exprNode e)
6461 if (exprNode_isDefined (e))
6463 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6469 bool exprNode_isLabelMarker (exprNode e)
6471 if (exprNode_isDefined (e))
6473 return (e->kind == XPR_LABEL);
6479 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6481 exprNode ret = exprNode_createPartialCopy (test);
6483 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6485 if (exprNode_isError (test)) {
6489 exprNode_checkUse (ret, test->sref, test->loc);
6491 usymtab_setExitCode (ret->exitCode);
6495 usymtab_setMustBreak ();
6498 ret->edata = exprData_makeSingle (test);
6499 ret->isJumpPoint = TRUE;
6505 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6507 exprNode ret = exprNode_createPartialCopy (test);
6509 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6510 ret->edata = exprData_makePair (test, stmt);
6511 ret->isJumpPoint = TRUE;
6513 if (exprNode_isError (test))
6518 exprNode_checkUse (ret, test->sref, test->loc);
6520 if (exprNode_isError (stmt))
6525 exprNode_mergeUSs (ret, stmt);
6527 ret->exitCode = stmt->exitCode;
6528 ret->mustBreak = stmt->mustBreak;
6529 ret->canBreak = stmt->canBreak;
6531 usymtab_setExitCode (ret->exitCode);
6535 usymtab_setMustBreak ();
6542 /*@notnull@*/ /*@only@*/ exprNode
6543 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6545 exprNode ret = exprNode_createTok (def);
6547 ret->isJumpPoint = TRUE;
6548 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6553 exprNode_mayEscape (exprNode e)
6555 if (exprNode_isDefined (e))
6557 return exitkind_couldEscape (e->exitCode);
6563 exprNode_mustBreak (exprNode e)
6565 if (exprNode_isDefined (e))
6567 return e->mustBreak;
6574 exprNode_mustEscape (exprNode e)
6576 if (exprNode_isDefined (e))
6578 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6585 exprNode_errorEscape (exprNode e)
6587 if (exprNode_isDefined (e))
6589 return exitkind_isError (e->exitCode);
6595 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6597 exprNode ret = exprNode_createPartialCopy (e1);
6599 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6601 ret->edata = exprData_makePair (e1, e2);
6602 ret->kind = XPR_STMTLIST;
6604 if (exprNode_isDefined (e1))
6606 ret->isJumpPoint = e1->isJumpPoint;
6607 ret->canBreak = e1->canBreak;
6611 if (exprNode_isDefined (e2))
6613 ret->loc = fileloc_update (ret->loc, e2->loc);
6617 if (exprNode_isDefined (e2))
6619 ret->exitCode = e2->exitCode;
6620 ret->mustBreak = e2->mustBreak;
6621 if (e2->canBreak) ret->canBreak = TRUE;
6625 ** if e1 must return, then e2 is unreachable!
6628 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6630 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6631 && !(e2->isJumpPoint))
6633 if (context_getFlag (FLG_UNREACHABLE))
6637 if (e2->kind == XPR_STMT)
6639 nr = exprData_getUopNode (e2->edata);
6642 if ((nr->kind == XPR_TOK
6643 && lltok_isSemi (exprData_getTok (nr->edata))))
6645 /* okay to have unreachable ";" */
6646 ret->exitCode = XK_MUSTEXIT;
6647 ret->canBreak = TRUE;
6651 if (optgenerror (FLG_UNREACHABLE,
6652 message ("Unreachable code: %s",
6653 exprNode_unparseFirst (nr)),
6656 ret->isJumpPoint = TRUE;
6657 ret->mustBreak = FALSE;
6658 ret->exitCode = XK_ERROR;
6659 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6663 ret->exitCode = XK_MUSTEXIT;
6664 ret->canBreak = TRUE;
6672 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6675 ** We want a warning anytime we have:
6677 ** yyy; <<<- no break or return
6681 exprNode lastStmt = exprNode_lastStatement (e1);
6683 if (exprNode_isDefined (lastStmt)
6684 && !exprNode_mustEscape (lastStmt)
6685 && !exprNode_mustBreak (lastStmt)
6686 && !exprNode_isCaseMarker (lastStmt)
6687 && !exprNode_isDefaultMarker (lastStmt)
6688 && !exprNode_isLabelMarker (lastStmt))
6690 voptgenerror (FLG_CASEBREAK,
6692 ("Fall through case (no preceding break)"),
6699 exprNode_mergeUSs (ret, e2);
6701 usymtab_setExitCode (ret->exitCode);
6705 usymtab_setMustBreak ();
6708 DPRINTF (("==> %s", exprNode_unparse (ret)));
6712 exprNode exprNode_createTok (/*@only@*/ lltok t)
6714 exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6715 ret = exprNode_create (ctype_unknown);
6716 ret->kind = XPR_TOK;
6717 ret->edata = exprData_makeTok (t);
6721 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6723 if (!exprNode_isError (e))
6725 exprChecks_checkStatementEffect(e);
6728 return (exprNode_statementError (e, t));
6731 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6733 exprNode ret = exprNode_createPartialCopy (e);
6735 if (!exprNode_isError (e))
6737 if (e->kind != XPR_ASSIGN)
6739 exprNode_checkUse (ret, e->sref, e->loc);
6742 ret->exitCode = e->exitCode;
6743 ret->canBreak = e->canBreak;
6744 ret->mustBreak = e->mustBreak;
6747 ret->edata = exprData_makeUop (e, t);
6748 ret->kind = XPR_STMT;
6753 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6755 if (!exprNode_isError (e))
6757 if (e->kind != XPR_ASSIGN)
6759 exprNode_checkUse (e, e->sref, e->loc);
6766 void exprNode_produceGuards (exprNode pred)
6768 if (!exprNode_isError (pred))
6770 if (ctype_isRealPointer (pred->typ))
6772 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6775 exprNode_checkUse (pred, pred->sref, pred->loc);
6776 exprNode_resetSref (pred);
6780 exprNode exprNode_compoundStatementExpression (/*@only@*/ lltok tlparen, /*@only@*/ exprNode e)
6784 DPRINTF (("Compound: %s", exprNode_unparse (e)));
6786 if (!context_flagOn (FLG_GNUEXTENSIONS, exprNode_loc (e)))
6788 (void) llgenhinterror
6790 message ("Compound statement expressions is not supported by ISO C99"),
6791 message ("Use +gnuextensions to allow compound statement expressions (and other GNU language extensions) "
6792 "without this warning"),
6797 ** The type of a compoundStatementExpression is the type of the last statement
6800 llassert (exprNode_isBlock (e));
6801 laststmt = exprNode_lastStatement (e);
6803 DPRINTF (("Last statement: %s / %s", exprNode_unparse (laststmt), ctype_unparse (exprNode_getType (laststmt))));
6804 DPRINTF (("e: %s", exprNode_unparse (e)));
6805 e->typ = exprNode_getType (laststmt);
6806 return exprNode_addParens (tlparen, e);
6810 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6812 exprNode ret = exprNode_createPartialCopy (e);
6814 if (!exprNode_isError (e))
6816 ret->exitCode = e->exitCode;
6817 ret->canBreak = e->canBreak;
6818 ret->mustBreak = e->mustBreak;
6821 DPRINTF (("Block e: %s", exprNode_unparse (e)));
6822 ret->edata = exprData_makeSingle (e);
6823 ret->kind = XPR_BLOCK;
6824 DPRINTF (("Block: %s", exprNode_unparse (ret)));
6828 bool exprNode_isBlock (exprNode e)
6830 return (exprNode_isDefined (e)
6831 && ((e)->kind == XPR_BLOCK));
6834 bool exprNode_isStatement (exprNode e)
6836 return (exprNode_isDefined (e)
6837 && ((e)->kind == XPR_STMT));
6840 bool exprNode_isAssign (exprNode e)
6842 if (exprNode_isDefined (e))
6844 return (e->kind == XPR_ASSIGN);
6850 bool exprNode_isEmptyStatement (exprNode e)
6852 return (exprNode_isDefined (e)
6853 && (e->kind == XPR_TOK)
6854 && (lltok_isSemi (exprData_getTok (e->edata))));
6857 bool exprNode_isMultiStatement (exprNode e)
6859 return (exprNode_isDefined (e)
6860 && ((e->kind == XPR_FOR)
6861 || (e->kind == XPR_FORPRED)
6862 || (e->kind == XPR_IF)
6863 || (e->kind == XPR_IFELSE)
6864 || (e->kind == XPR_WHILE)
6865 || (e->kind == XPR_WHILEPRED)
6866 || (e->kind == XPR_DOWHILE)
6867 || (e->kind == XPR_BLOCK)
6868 || (e->kind == XPR_STMT)
6869 || (e->kind == XPR_STMTLIST)
6870 || (e->kind == XPR_SWITCH)));
6873 void exprNode_checkIfPred (exprNode pred)
6875 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6878 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6881 bool emptyErr = FALSE;
6883 if (context_maybeSet (FLG_IFEMPTY))
6885 if (exprNode_isEmptyStatement (tclause))
6887 emptyErr = optgenerror (FLG_IFEMPTY,
6889 ("Body of if statement is empty"),
6890 exprNode_loc (tclause));
6894 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6896 if (exprNode_isDefined (tclause)
6897 && !exprNode_isBlock (tclause))
6899 voptgenerror (FLG_IFBLOCK,
6901 ("Body of if statement is not a block: %s",
6902 exprNode_unparse (tclause)),
6903 exprNode_loc (tclause));
6907 if (exprNode_isError (pred))
6909 if (exprNode_isError (tclause))
6911 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6915 ret = exprNode_createPartialCopy (tclause);
6920 if (exprNode_mustEscape (pred))
6924 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6925 exprNode_loc (pred));
6928 /*! exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred); */ /*@i523@*/
6929 exprNode_checkUse (pred, pred->sref, pred->loc);
6931 if (!exprNode_isError (tclause))
6933 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
6936 ret = exprNode_createPartialCopy (pred);
6940 ret->edata = exprData_makePair (pred, tclause);
6942 ret->exitCode = XK_UNKNOWN;
6944 if (exprNode_isDefined (tclause))
6946 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
6947 ret->canBreak = tclause->canBreak;
6948 ret->sets = sRefSet_union (ret->sets, tclause->sets);
6949 ret->msets = sRefSet_union (ret->msets, tclause->msets);
6950 ret->uses = sRefSet_union (ret->uses, tclause->uses);
6953 ret->mustBreak = FALSE;
6958 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
6959 /*@only@*/ exprNode tclause,
6960 /*@only@*/ exprNode eclause)
6963 bool tEmptyErr = FALSE;
6964 bool eEmptyErr = FALSE;
6966 if (context_maybeSet (FLG_IFEMPTY))
6968 if (exprNode_isEmptyStatement (tclause))
6970 tEmptyErr = optgenerror
6973 ("Body of if clause of if statement is empty"),
6974 exprNode_loc (tclause));
6977 if (exprNode_isEmptyStatement (eclause))
6979 eEmptyErr = optgenerror
6982 ("Body of else clause of if statement is empty"),
6983 exprNode_loc (eclause));
6987 if (context_maybeSet (FLG_IFBLOCK))
6990 && exprNode_isDefined (tclause)
6991 && !exprNode_isBlock (tclause))
6993 voptgenerror (FLG_IFBLOCK,
6995 ("Body of if clause of if statement is not a block: %s",
6996 exprNode_unparse (tclause)),
6997 exprNode_loc (tclause));
7001 && exprNode_isDefined (eclause)
7002 && !exprNode_isBlock (eclause)
7003 && !(eclause->kind == XPR_IF)
7004 && !(eclause->kind == XPR_IFELSE))
7009 ("Body of else clause of if statement is not a block: %s",
7010 exprNode_unparse (eclause)),
7011 exprNode_loc (eclause));
7015 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
7017 if (exprNode_isDefined (eclause)
7018 && (eclause->kind == XPR_IF))
7020 voptgenerror (FLG_ELSEIFCOMPLETE,
7021 message ("Incomplete else if logic (no final else): %s",
7022 exprNode_unparse (eclause)),
7023 exprNode_loc (eclause));
7027 if (exprNode_isError (pred))
7029 if (exprNode_isError (tclause))
7031 if (exprNode_isError (eclause))
7033 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7037 ret = exprNode_createPartialCopy (eclause);
7042 ret = exprNode_createPartialCopy (tclause);
7045 else /* pred is okay */
7047 ret = exprNode_createPartialCopy (pred);
7049 if (exprNode_mustEscape (pred))
7053 message ("Predicate always exits: %s", exprNode_unparse (pred)),
7054 exprNode_loc (pred));
7057 /*@i3423 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);*/
7058 exprNode_checkUse (ret, pred->sref, pred->loc);
7060 exprNode_mergeCondUSs (ret, tclause, eclause);
7063 ret->kind = XPR_IFELSE;
7064 ret->edata = exprData_makeCond (pred, tclause, eclause);
7066 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
7068 exprNode_combineControl (ret, tclause, eclause);
7069 ret->loc = fileloc_update (ret->loc, eclause->loc);
7076 ** *allpaths <- TRUE iff all executions paths must go through the switch
7080 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
7082 exprNodeSList el = exprNode_flatten (e);
7083 bool mustReturn = TRUE; /* find a branch that doesn't */
7084 bool thisReturn = FALSE;
7085 bool hasDefault = FALSE;
7086 bool hasAllMembers = FALSE;
7087 bool inSwitch = FALSE;
7088 bool isEnumSwitch = FALSE;
7089 bool canBreak = FALSE;
7090 bool fallThrough = FALSE;
7091 ctype ct = ctype_unknown;
7092 enumNameSList usedEnums;
7095 if (exprNode_isDefined (test))
7100 ttype = ctype_realType (ct);
7102 if (ctype_isEnum (ttype))
7104 isEnumSwitch = TRUE;
7105 enums = ctype_elist (ttype);
7106 usedEnums = enumNameSList_new ();
7110 exprNodeSList_elements (el, current)
7113 DPRINTF ((message("checkSwitchExpr current = %s ", exprNode_unparse(current) ) ));
7115 if (exprNode_isDefined (current))
7117 switch (current->kind)
7124 (FLG_DUPLICATECASES,
7125 message ("Duplicate default cases in switch"),
7126 exprNode_loc (current));
7131 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
7139 exprNode st = exprData_getSingle (current->edata);
7140 uentry ue = exprNode_getUentry (st);
7142 if (uentry_isValid (ue))
7144 cstring cname = uentry_rawName (ue);
7146 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
7148 if (enumNameSList_member
7149 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
7152 (FLG_DUPLICATECASES,
7153 message ("Duplicate case in switch: %s",
7159 enumNameSList_addh (usedEnums, cname);
7166 message ("Case in switch not %s member: %s",
7167 ctype_unparse (ct), cname),
7174 if (inSwitch && !fallThrough)
7176 if (!thisReturn || canBreak)
7186 /*@switchbreak@*/ break;
7188 thisReturn = thisReturn || exprNode_mustEscape (current);
7189 canBreak = canBreak || current->canBreak;
7190 if (canBreak) fallThrough = FALSE;
7193 } end_exprNodeSList_elements;
7195 if (inSwitch) /* check the last one! */
7197 if (!thisReturn || canBreak)
7206 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
7207 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
7209 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
7211 voptgenerror (FLG_MISSCASE,
7212 message ("Missing case%s in switch: %q",
7213 cstring_makeLiteralTemp
7214 ((enumNameSList_size (unused) > 1) ? "s" : ""),
7215 enumNameSList_unparse (unused)),
7218 enumNameSList_free (unused);
7219 *allpaths = FALSE; /* evans 2002-01-01 */
7223 hasAllMembers = TRUE;
7227 enumNameSList_free (usedEnums);
7231 *allpaths = hasDefault;
7234 exprNodeSList_free (el);
7235 return ((hasDefault || hasAllMembers) && mustReturn);
7238 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
7240 exprNode ret = exprNode_createPartialCopy (e);
7243 DPRINTF (("Switch: %s", exprNode_unparse (s)));
7245 ret->kind = XPR_SWITCH;
7246 ret->edata = exprData_makePair (e, s);
7248 if (!exprNode_isError (s))
7250 exprNode fs = exprNode_firstStatement (s);
7251 ret->loc = fileloc_update (ret->loc, s->loc);
7253 if (exprNode_isUndefined (fs)
7254 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
7255 || exprNode_isDefaultMarker (fs)) {
7258 voptgenerror (FLG_FIRSTCASE,
7260 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
7265 if (!exprNode_isError (e))
7267 if (checkSwitchExpr (e, s, &allpaths))
7269 ret->exitCode = XK_MUSTRETURN;
7273 ret->exitCode = e->exitCode;
7276 ret->canBreak = e->canBreak;
7277 ret->mustBreak = e->mustBreak;
7281 ** exprNode.c:3883,32: Variable allpaths used before definition
7288 DPRINTF (("Context exit switch!"));
7289 context_exitSwitch (ret, allpaths);
7290 DPRINTF (("Context exit switch done!"));
7295 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
7296 /*@notnull@*/ exprNode body)
7298 sRefSet tuses = test->uses;
7300 if (!sRefSet_isEmpty (test->uses))
7302 sRefSet sets = sRefSet_newCopy (body->sets);
7303 bool hasError = TRUE;
7304 bool innerState = FALSE;
7305 sRefSet tuncon = sRefSet_undefined;
7307 sets = sRefSet_union (sets, test->sets);
7308 sets = sRefSet_union (sets, body->msets);
7309 sets = sRefSet_union (sets, test->msets);
7311 sRefSet_allElements (tuses, el)
7313 if (sRef_isUnconstrained (el))
7315 tuncon = sRefSet_insert (tuncon, el);
7319 if (sRefSet_member (sets, el))
7326 if (sRef_isInternalState (el)
7327 || sRef_isFileStatic (sRef_getRootBase (el)))
7331 } end_sRefSet_allElements ;
7335 sRefSet suncon = sRefSet_undefined;
7336 bool sinner = FALSE;
7338 sRefSet_allElements (sets, el)
7340 if (sRef_isUnconstrained (el))
7342 suncon = sRefSet_insert (suncon, el);
7344 else if (sRef_isInternalState (el))
7352 } end_sRefSet_allElements ;
7354 if (sinner && innerState)
7358 else if (sRefSet_isEmpty (tuncon)
7359 && sRefSet_isEmpty (suncon))
7364 ("Suspected infinite loop. No value used in loop test (%q) "
7365 "is modified by test or loop body.",
7366 sRefSet_unparsePlain (tuses)),
7371 if (sRefSet_isEmpty (tuncon))
7375 message ("Suspected infinite loop. No condition values "
7376 "modified. Modification possible through "
7377 "unconstrained calls: %q",
7378 sRefSet_unparsePlain (suncon)),
7385 message ("Suspected infinite loop. No condition values "
7386 "modified. Possible undetected dependency through "
7387 "unconstrained calls in loop test: %q",
7388 sRefSet_unparsePlain (tuncon)),
7394 sRefSet_free (sets);
7398 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7401 bool emptyErr = FALSE;
7403 if (context_maybeSet (FLG_WHILEEMPTY))
7405 if (exprNode_isEmptyStatement (b))
7407 emptyErr = optgenerror
7410 ("Body of while statement is empty"),
7415 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7417 if (exprNode_isDefined (b)
7418 && !exprNode_isBlock (b))
7420 if (context_inIterDef ()
7421 && (b->kind == XPR_STMTLIST
7422 || b->kind == XPR_TOK))
7428 voptgenerror (FLG_WHILEBLOCK,
7430 ("Body of while statement is not a block: %s",
7431 exprNode_unparse (b)),
7437 if (exprNode_isError (t))
7439 if (exprNode_isError (b))
7441 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7445 ret = exprNode_createPartialCopy (b);
7452 ret = exprNode_createPartialCopy (t);
7454 llassert (t->kind == XPR_WHILEPRED);
7456 test = exprData_getSingle (t->edata);
7458 if (!exprNode_isError (b) && exprNode_isDefined (test))
7460 if (context_maybeSet (FLG_INFLOOPS)
7461 || context_maybeSet (FLG_INFLOOPSUNCON))
7464 ** check that some variable in the predicate is set by the body
7465 ** if the predicate uses any variables
7468 checkInfiniteLoop (test, b);
7471 exprNode_mergeUSs (ret, b);
7473 if (exprNode_isDefined (b))
7475 ret->exitCode = exitkind_makeConditional (b->exitCode);
7480 ret->edata = exprData_makePair (t, b);
7481 ret->kind = XPR_WHILE;
7483 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7487 message ("Predicate always exits: %s", exprNode_unparse (t)),
7491 ret->exitCode = XK_NEVERESCAPE;
7494 ** If loop is infinite, and there is no break inside,
7495 ** exit code is never reach.
7498 if (exprNode_knownIntValue (t))
7500 if (!exprNode_isZero (t))
7502 if (exprNode_isDefined (b))
7506 /* Really, it means never reached. */
7507 ret->exitCode = XK_MUSTEXIT;
7517 ret->canBreak = FALSE;
7518 ret->mustBreak = FALSE;
7524 ** do { b } while (t);
7526 ** note: body passed as first argument
7529 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7533 DPRINTF (("Do while: %s / %s",
7534 exprNode_unparse (b), exprNode_unparse (t)));
7536 if (exprNode_isError (t))
7538 if (exprNode_isError (b))
7540 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7544 ret = exprNode_createPartialCopy (b);
7546 ret->exitCode = exitkind_makeConditional (b->exitCode);
7547 exprNode_checkUse (ret, b->sref, b->loc);
7548 ret->exitCode = b->exitCode;
7549 ret->canBreak = b->canBreak;
7550 ret->mustBreak = FALSE;
7555 DPRINTF (("Do while: %s / %s",
7556 exitkind_unparse (t->exitCode),
7557 exitkind_unparse (b->exitCode)));
7559 ret = exprNode_createPartialCopy (t);
7560 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7562 if (!exprNode_isError (b))
7565 ** forgot the copy's --- why wasn't this detected??
7568 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7569 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7570 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
7572 /* left this out --- causes and aliasing bug (infinite loop)
7573 should be detected?? */
7575 exprNode_checkUse (ret, b->sref, b->loc);
7576 exprNode_mergeUSs (ret, t);
7577 exprNode_checkUse (ret, t->sref, t->loc);
7579 /* evans 2001-10-05: while loop can break */
7580 ret->exitCode = exitkind_makeConditional (b->exitCode);
7582 DPRINTF (("Do while: %s",
7583 exitkind_unparse (ret->exitCode)));
7585 ret->canBreak = b->canBreak;
7587 /* Always FALSE for doWhile loops - break's when test is false */
7588 ret->mustBreak = FALSE; /* b->mustBreak; */
7592 context_exitDoWhileClause (t);
7594 ret->kind = XPR_DOWHILE;
7595 ret->edata = exprData_makePair (t, b);
7599 bool exprNode_loopMustExec (exprNode forPred)
7602 ** Returns true if it is obvious that the loop always executes at least once
7604 ** For now, we only identify the most obvious cases. Should be true anytime
7605 ** we can prove init => !test.
7608 if (exprNode_isDefined (forPred))
7610 exprNode init, test, inc;
7613 llassert (forPred->kind == XPR_FORPRED);
7615 edata = forPred->edata;
7616 init = exprData_getTripleInit (edata);
7617 test = exprData_getTripleTest (edata);
7618 inc = exprData_getTripleInc (edata);
7620 if (exprNode_isAssign (init))
7622 exprNode loopVar = exprData_getOpA (init->edata);
7623 exprNode loopInit = exprData_getOpB (init->edata);
7625 if (exprNode_isDefined (test) && test->kind == XPR_OP)
7627 exprNode testVar = exprData_getOpA (test->edata);
7628 exprNode testVal = exprData_getOpB (test->edata);
7629 lltok comp = exprData_getOpTok (test->edata);
7630 int opid = lltok_getTok (comp);
7632 DPRINTF (("Same storage: %s / %s", exprNode_unparse (loopVar),
7633 exprNode_unparse (testVar)));
7635 if (exprNode_sameStorage (loopVar, testVar))
7637 multiVal valinit = exprNode_getValue (loopInit);
7638 multiVal valtest = exprNode_getValue (testVal);
7640 DPRINTF (("Values: %s / %s", multiVal_unparse (valinit),
7641 multiVal_unparse (valtest)));
7643 if (multiVal_isInt (valinit) && multiVal_isInt (valtest))
7645 long v1 = multiVal_forceInt (valinit);
7646 long v2 = multiVal_forceInt (valtest);
7648 DPRINTF (("Here: %ld %ld", v1, v2));
7650 if ((opid == EQ_OP && v1 < v2)
7651 || (opid == NE_OP && v1 != v2)
7652 || (opid == TLT && v1 <= v2)
7653 || (opid == TGT && v1 >= v2)
7654 || (opid == LE_OP && v1 < v2)
7655 || (opid == GE_OP && v1 > v2))
7657 DPRINTF (("mustexec if inc"));
7666 DPRINTF (("loop must exec: FALSE"));
7670 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7673 bool emptyErr = FALSE;
7675 if (context_maybeSet (FLG_FOREMPTY))
7677 if (exprNode_isEmptyStatement (body))
7679 emptyErr = optgenerror
7682 ("Body of for statement is empty"),
7683 exprNode_loc (body));
7687 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7689 if (exprNode_isDefined (body)
7690 && !exprNode_isBlock (body))
7692 if (context_inIterDef ()
7693 && (body->kind == XPR_STMTLIST
7694 || body->kind == XPR_TOK))
7700 voptgenerror (FLG_FORBLOCK,
7702 ("Body of for statement is not a block: %s",
7703 exprNode_unparse (body)),
7704 exprNode_loc (body));
7710 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7713 if (exprNode_isError (body))
7715 ret = exprNode_createPartialCopy (inc);
7719 ret = exprNode_createPartialCopy (body);
7721 ret->exitCode = exitkind_makeConditional (body->exitCode);
7723 exprNode_mergeUSs (inc, body);
7725 if (exprNode_isDefined (inc))
7729 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7731 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7732 exprNode_freeShallow (tmp);
7734 context_clearMessageAnnote ();
7735 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7737 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7738 exprNode_freeShallow (tmp);
7740 context_clearMessageAnnote ();
7742 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7743 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7744 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7748 ret->kind = XPR_FOR;
7749 ret->edata = exprData_makePair (inc, body);
7751 if (exprNode_isDefined (inc)) {
7752 exprNode test = exprData_getTripleTest (inc->edata);
7754 if (exprNode_isUndefined (test)) {
7755 if (exprNode_isDefined (body)) {
7756 if (!body->canBreak) {
7757 /* Really, it means never reached. */
7758 ret->exitCode = XK_MUSTEXIT;
7768 ** for (init; test; inc)
7771 ** while (test) { body; inc; }
7773 ** Now: check use of init (may set vars for test)
7774 ** check use of test
7778 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7782 if (exprNode_isError (pred)) return guardSet_undefined;
7784 llassert (pred->kind == XPR_FORPRED);
7786 test = exprData_getTripleTest (pred->edata);
7788 if (!exprNode_isError (test))
7790 return (test->guards);
7793 return guardSet_undefined;
7796 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7798 exprNode ret = exprNode_createSemiCopy (test);
7800 if (exprNode_isDefined (test))
7802 exprNode_copySets (ret, test);
7803 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7804 exprNode_checkUse (ret, test->sref, test->loc);
7806 exprNode_produceGuards (test);
7808 ret->guards = guardSet_copy (test->guards);
7811 ret->edata = exprData_makeSingle (test);
7812 ret->kind = XPR_WHILEPRED;
7816 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7817 /*@only@*/ exprNode inc)
7822 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7825 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7827 if (!exprNode_isError (inc))
7829 ret = exprNode_createPartialCopy (inc);
7833 if (!exprNode_isError (init))
7835 ret = exprNode_createPartialCopy (init);
7837 else if (!exprNode_isError (test))
7839 ret = exprNode_createPartialCopy (test);
7843 ret = exprNode_createUnknown ();
7847 exprNode_mergeUSs (ret, init);
7849 if (exprNode_isDefined (init))
7851 exprNode_checkUse (ret, init->sref, init->loc);
7854 exprNode_mergeUSs (ret, test);
7856 if (exprNode_isDefined (test))
7858 exprNode_checkUse (ret, test->sref, test->loc);
7861 ret->kind = XPR_FORPRED;
7862 ret->edata = exprData_makeFor (init, test, inc);
7866 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7868 exprNode ret = exprNode_createUnknown ();
7870 if (context_inMacro ())
7872 voptgenerror (FLG_MACROSTMT,
7873 message ("Macro %s uses goto (not functional)",
7874 context_inFunctionName ()),
7878 ret->kind = XPR_GOTO;
7879 ret->edata = exprData_makeLiteral (label);
7880 ret->mustBreak = TRUE;
7881 ret->exitCode = XK_GOTO;
7882 ret->canBreak = TRUE;
7886 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7888 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7890 ret->kind = XPR_CONTINUE;
7891 ret->edata = exprData_makeTok (l);
7892 ret->canBreak = TRUE;
7893 ret->mustBreak = TRUE;
7895 if (qcontinue == QSAFEBREAK)
7899 else if (qcontinue == QINNERCONTINUE)
7901 if (!context_inDeepLoop ())
7904 (FLG_LOOPLOOPCONTINUE,
7905 cstring_makeLiteral ("Continue statement marked with innercontinue "
7906 "is not inside a nested loop"),
7907 exprNode_loc (ret));
7910 else if (qcontinue == BADTOK)
7912 if (context_inDeepLoop ())
7915 (FLG_LOOPLOOPCONTINUE,
7916 cstring_makeLiteral ("Continue statement in nested loop"),
7917 exprNode_loc (ret));
7922 llbuglit ("exprNode_continue: bad qcontinue");
7928 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
7930 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7931 clause breakClause = context_breakClause ();
7933 ret->kind = XPR_BREAK;
7934 ret->edata = exprData_makeTok (l);
7935 ret->canBreak = TRUE;
7936 ret->mustBreak = TRUE;
7938 if (breakClause == NOCLAUSE)
7942 cstring_makeLiteral ("Break not inside while, for or switch statement"),
7943 exprNode_loc (ret));
7947 if (bqual != BADTOK)
7954 if (breakClause == SWITCHCLAUSE)
7956 if (!context_inDeepSwitch ())
7958 voptgenerror (FLG_SYNTAX,
7960 ("Break preceded by innerbreak is not in a deep switch"),
7961 exprNode_loc (ret));
7966 if (!context_inDeepLoop ())
7968 voptgenerror (FLG_SYNTAX,
7970 ("Break preceded by innerbreak is not in a deep loop"),
7971 exprNode_loc (ret));
7976 if (breakClause == SWITCHCLAUSE)
7978 voptgenerror (FLG_SYNTAX,
7980 ("Break preceded by loopbreak is breaking a switch"),
7981 exprNode_loc (ret));
7985 if (breakClause != SWITCHCLAUSE)
7989 message ("Break preceded by switchbreak is breaking %s",
7990 cstring_makeLiteralTemp
7991 ((breakClause == WHILECLAUSE
7992 || breakClause == DOWHILECLAUSE) ? "a while loop"
7993 : (breakClause == FORCLAUSE) ? "a for loop"
7994 : (breakClause == ITERCLAUSE) ? "an iterator"
7996 exprNode_loc (ret));
8004 if (breakClause == SWITCHCLAUSE)
8006 clause nextBreakClause = context_nextBreakClause ();
8008 switch (nextBreakClause)
8010 case NOCLAUSE: break;
8016 (FLG_LOOPSWITCHBREAK,
8017 cstring_makeLiteral ("Break statement in switch inside loop"),
8018 exprNode_loc (ret));
8022 (FLG_SWITCHSWITCHBREAK,
8023 cstring_makeLiteral ("Break statement in switch inside switch"),
8024 exprNode_loc (ret));
8031 if (context_inDeepLoop ())
8035 cstring_makeLiteral ("Break statement in nested loop"),
8036 exprNode_loc (ret));
8040 if (context_inDeepLoopSwitch ())
8043 (FLG_SWITCHLOOPBREAK,
8044 cstring_makeLiteral ("Break statement in loop inside switch"),
8045 exprNode_loc (ret));
8055 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
8057 fileloc loc = lltok_getLoc (t);
8058 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
8060 context_returnFunction ();
8061 exprChecks_checkNullReturn (loc);
8063 ret->kind = XPR_NULLRETURN;
8064 ret->edata = exprData_makeTok (t);
8065 ret->exitCode = XK_MUSTRETURN;
8069 exprNode exprNode_return (/*@only@*/ exprNode e)
8073 if (exprNode_isError (e))
8075 ret = exprNode_createUnknown ();
8079 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
8081 exprNode_checkUse (ret, e->sref, e->loc);
8082 exprNode_checkReturn (e);
8085 context_returnFunction ();
8086 ret->kind = XPR_RETURN;
8087 ret->edata = exprData_makeSingle (e);
8088 ret->exitCode = XK_MUSTRETURN;
8093 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
8097 if (exprNode_isError (e1))
8099 if (exprNode_isError (e2))
8101 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
8105 ret = exprNode_createPartialCopy (e2);
8106 exprNode_checkUse (ret, e2->sref, e2->loc);
8107 ret->sref = e2->sref;
8112 ret = exprNode_createPartialCopy (e1);
8114 exprNode_checkUse (ret, e1->sref, e1->loc);
8116 if (!exprNode_isError (e2))
8118 exprNode_mergeUSs (ret, e2);
8119 exprNode_checkUse (ret, e2->sref, e2->loc);
8120 ret->sref = e2->sref;
8124 ret->kind = XPR_COMMA;
8125 ret->edata = exprData_makePair (e1, e2);
8127 if (exprNode_isDefined (e1))
8129 if (exprNode_isDefined (e2))
8133 if (exprNode_mustEscape (e1) || e1->mustBreak)
8137 message ("Second clause of comma expression is unreachable: %s",
8138 exprNode_unparse (e2)),
8142 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
8143 ret->mustBreak = e1->mustBreak || e2->mustBreak;
8144 ret->canBreak = e1->canBreak || e2->canBreak;
8148 if (exprNode_mustEscape (e1) || e1->mustBreak)
8152 message ("Second clause of comma expression is unreachable: %s",
8153 exprNode_unparse (e2)),
8157 ret->exitCode = e1->exitCode;
8158 ret->canBreak = e1->canBreak;
8163 if (exprNode_isDefined (e2))
8165 ret->exitCode = e2->exitCode;
8166 ret->mustBreak = e2->mustBreak;
8167 ret->canBreak = e2->canBreak;
8174 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
8176 ctype t1 = exprNode_getType (el);
8177 ctype t2 = exprNode_getType (val);
8178 bool hasError = FALSE;
8180 DPRINTF (("Check one init: %s / %s",
8181 exprNode_unparse (el),
8182 exprNode_unparse (val)));
8184 if (ctype_isUnknown (t1))
8186 voptgenerror (FLG_IMPTYPE,
8187 message ("Variable has unknown (implicitly int) type: %s",
8188 exprNode_unparse (el)),
8192 el->typ = ctype_int;
8195 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
8197 exprNodeList vals = exprData_getArgs (val->edata);
8199 DPRINTF (("Check one init: %s", exprNodeList_unparse (vals)));
8200 DPRINTF (("Type: %s", ctype_unparse (t1)));
8202 if (ctype_isRealAP (t1))
8207 if (ctype_isFixedArray (t1))
8209 size_t nelements = ctype_getArraySize (t1);
8211 DPRINTF (("Checked array: %s / %d",
8212 ctype_unparse (t1), nelements));
8214 if (exprNode_isStringLiteral (val))
8216 exprNode_checkStringLiteralLength (t1, val);
8220 if (exprNodeList_size (vals) != size_toInt (nelements))
8222 hasError = optgenerror
8223 (exprNodeList_size (vals) > size_toInt (nelements)
8224 ? 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.
8596 exprNode_checkStringLiteralLength (ct, e);
8597 sRef_setDefState (ret->sref, SS_DEFINED, e->loc);
8598 ret->val = multiVal_copy (e->val);
8600 sRef_setNullTerminatedState (ret->sref);
8602 if (multiVal_isDefined (e->val))
8604 cstring slit = multiVal_forceString (e->val);
8605 sRef_setLen (ret->sref, cstring_length (slit) + 1);
8608 if (ctype_isFixedArray (ct))
8610 sRef_setSize (ret->sref, size_toInt (ctype_getArraySize (ct)));
8615 doAssign (ret, e, TRUE);
8618 if (uentry_isStatic (ue))
8620 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8624 if (context_inIterDef ())
8626 /* should check if it is yield */
8627 uentry_setUsed (ue, loc);
8634 exprNode_mergeUSs (ret, e);
8635 DPRINTF (("Ret: %s %p %p",
8636 exprNode_unparse (ret),
8637 ret->requiresConstraints,
8638 ret->ensuresConstraints));
8640 DPRINTF (("Ret: %s %s %s",
8641 exprNode_unparse (ret),
8642 constraintList_unparse (ret->requiresConstraints),
8643 constraintList_unparse (ret->ensuresConstraints)));
8647 exprNode exprNode_iter (/*@observer@*/ uentry name,
8648 /*@only@*/ exprNodeList alist,
8649 /*@only@*/ exprNode body,
8650 /*@observer@*/ uentry end)
8655 llassert (uentry_isValid (name));
8657 uentry_setUsed (name, exprNode_loc (body));
8659 ret = exprNode_createPartialCopy (body);
8660 iname = uentry_getName (name);
8662 if (uentry_isInvalid (end))
8664 llerror (FLG_ITERBALANCE,
8665 message ("Iter %s not balanced with end_%s", iname, iname));
8669 cstring ename = uentry_getName (end);
8671 if (!cstring_equalPrefixLit (ename, "end_"))
8673 llerror (FLG_ITERBALANCE, message ("Iter %s not balanced with end_%s: %s",
8674 iname, iname, ename));
8678 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8680 llerror (FLG_ITERBALANCE,
8681 message ("Iter %s not balanced with end_%s: %s",
8682 iname, iname, ename));
8686 cstring_free (ename);
8689 context_exitIterClause (body);
8691 ret->kind = XPR_ITER;
8692 ret->edata = exprData_makeIter (name, alist, body, end);
8694 if (uentry_isIter (name))
8696 (void) checkArgsReal (name, body,
8697 uentry_getParams (name), alist, TRUE, ret);
8700 cstring_free (iname);
8706 exprNode_iterNewId (/*@only@*/ cstring s)
8708 exprNode e = exprNode_new ();
8709 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8711 llassert (processingIterVars ());
8713 e->loc = context_getSaveLocation ();
8715 if (fileloc_isUndefined (e->loc))
8717 fileloc_free (e->loc);
8718 e->loc = fileloc_copy (g_currentloc);
8721 e->uses = sRefSet_new ();
8722 e->sets = sRefSet_new ();
8723 e->msets = sRefSet_new ();
8725 e->val = multiVal_unknown ();
8726 e->guards = guardSet_new ();
8727 e->sref = sRef_undefined;
8728 e->isJumpPoint = FALSE;
8729 e->exitCode = XK_NEVERESCAPE;
8731 /*> missing fields, detected by splint <*/
8732 e->canBreak = FALSE;
8733 e->mustBreak = FALSE;
8734 e->etext = cstring_undefined;
8736 if (uentry_isYield (ue))
8738 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8739 fileloc_copy (e->loc),
8743 uue = usymtab_supEntrySrefReturn (uue);
8745 sr = uentry_getSref (uue);
8746 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8747 sr = uentry_getSref (uue);
8748 sRef_setDefined (sr, e->loc);
8750 e->typ = uentry_getType (uue);
8752 e->edata = exprData_makeId (uue);
8753 uentry_setUsed (uue, g_currentloc);
8759 sRef_setGlobalScope ();
8760 uue = uentry_makeVariableLoc (s, ctype_unknown);
8762 e->typ = ctype_unknown;
8763 e->edata = exprData_makeId (uue);
8765 uentry_setUsed (uue, e->loc);
8766 uentry_setHasNameError (uue);
8768 if (context_getFlag (FLG_REPEATUNRECOG))
8770 uentry_markOwned (uue);
8774 usymtab_supGlobalEntry (uue);
8777 sRef_clearGlobalScope ();
8779 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8786 exprNode_defineConstraints(e);
8791 exprNode_iterExpr (/*@returned@*/ exprNode e)
8793 if (!processingIterVars ())
8795 llcontbuglit ("checkIterParam: not in iter");
8799 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8802 if (exprNode_isDefined (e))
8804 if (fileloc_isDefined (e->loc))
8808 message ("Yield parameter is not simple identifier: %s",
8809 exprNode_unparse (e)),
8816 message ("Yield parameter is not simple identifier: %s",
8817 exprNode_unparse (e)),
8827 exprNode_iterId (/*@observer@*/ uentry c)
8831 llassert (processingIterVars ());
8833 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8836 if (uentry_isYield (ue))
8838 ctype ct = uentry_getType (ue);
8839 exprNode e = exprNode_createPlain (ct);
8840 cstring name = uentry_getName (c);
8841 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8843 uentry_setUsed (ue, g_currentloc);
8844 uentry_setHasNameError (ue);
8846 cstring_free (name);
8849 e->edata = exprData_makeId (le);
8850 e->loc = context_getSaveLocation ();
8851 e->sref = uentry_getSref (le);
8853 usymtab_supEntrySref (le);
8855 if (!context_inHeader ())
8859 message ("Yield parameter shadows local declaration: %q",
8860 uentry_getName (c)),
8861 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8863 uentry_showWhereDeclared (c);
8870 return (exprNode_fromIdentifierAux (c));
8873 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8875 exprNode ret = exprNode_create (ctype_unknown);
8877 ret->kind = XPR_ITERCALL;
8878 ret->edata = exprData_makeIterCall (name, alist);
8880 if (uentry_isIter (name))
8882 uentryList params = uentry_getParams (name);
8884 if (context_inIterDef ()
8885 && uentryList_size (params) == exprNodeList_size (alist))
8889 exprNodeList_elements (alist, arg)
8891 uentry parg = uentryList_getN (params, i);
8893 if (uentry_isYield (parg))
8895 uentry ue = exprNode_getUentry (arg);
8897 if (uentry_isValid (ue))
8904 } end_exprNodeList_elements;
8907 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8908 checkUnspecCall (ret, params, alist);
8914 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8916 if (exprNode_isDefined (e))
8918 if (sRef_isInvalid (e->sref))
8921 e->sref = sRef_makeUnknown ();
8922 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8933 return sRef_undefined;
8937 /*@observer@*/ cstring
8938 exprNode_unparseFirst (exprNode e)
8940 if (exprNode_isDefined (e))
8944 if (e->kind == XPR_STMTLIST
8945 || e->kind == XPR_COMMA || e->kind == XPR_COND)
8947 exprNode first = exprData_getPairA (e->edata);
8949 if (exprNode_isDefined (first))
8951 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8955 return (cstring_makeLiteralTemp ("..."));
8959 ret = cstring_elide (exprNode_unparse (e), 20);
8960 cstring_markOwned (ret);
8966 return cstring_makeLiteralTemp ("<error>");
8970 /*@observer@*/ cstring
8971 exprNode_unparse (/*@temp@*/ exprNode e)
8973 if (exprNode_isError (e))
8975 return cstring_makeLiteralTemp ("<error>");
8978 if (cstring_isDefined (e->etext))
8984 cstring ret = exprNode_doUnparse (e);
8986 /*@-modifies@*/ /* benevolent */
8993 /*@observer@*/ fileloc
8994 exprNode_loc (exprNode e)
8996 if (exprNode_isError (e))
8998 return (g_currentloc);
9007 ** executes exprNode e
9008 ** recursively rexecutes as though in original parse using
9009 ** information in e->edata
9012 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
9014 exprNodeList ret = exprNodeList_new ();
9016 exprNodeList_elements (e, current)
9018 exprNodeList_addh (ret, exprNode_effect (current));
9019 } end_exprNodeList_elements;
9024 static /*@only@*/ exprNode exprNode_effect (exprNode e)
9025 /*@globals internalState@*/
9027 bool innerEffect = inEffect;
9033 context_clearJustPopped ();
9035 if (exprNode_isError (e))
9037 ret = exprNode_undefined;
9042 ** Turn off expose and dependent transfer checking.
9043 ** Need to pass exposed internal nodes,
9044 ** [ copying would be a waste! ]
9045 ** [ Actually, I think I wasted a lot more time than its worth ]
9046 ** [ trying to do this. ]
9050 /*@-observertrans@*/
9051 /*@-dependenttrans@*/
9058 ret = exprNode_addParens (exprData_getUopTok (data),
9059 exprNode_effect (exprData_getUopNode (data)));
9062 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
9063 exprNode_effect (exprData_getOpB (data)),
9064 exprData_getOpTok (data));
9067 ret = exprNode_undefined;
9070 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
9071 exprNodeList_effect (exprData_getArgs (data)));
9084 cstring id = exprData_getId (data);
9085 uentry ue = usymtab_lookupSafe (id);
9087 ret = exprNode_fromIdentifierAux (ue);
9088 ret->loc = fileloc_update (ret->loc, e->loc);
9095 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
9096 exprNode_effect (exprData_getPairB (data)));
9100 ** evans 2002-03-15: for && and ||, need to do the guards also
9101 ** this is what cgrammar.y does - should be
9102 ** able to avoid duplication, but need to
9103 ** time with grammar productions.
9106 DPRINTF (("Effect: %s", exprNode_unparse (e)));
9108 if (lltok_getTok (exprData_getOpTok (data)) == AND_OP)
9110 exprNode e1 = exprNode_effect (exprData_getOpA (data));
9112 exprNode_produceGuards (e1);
9113 context_enterAndClause (e1);
9114 e2 = exprNode_effect (exprData_getOpB (data));
9116 ret = exprNode_op (e1, e2,
9117 exprData_getOpTok (data));
9119 context_exitAndClause (ret, e2);
9121 else if (lltok_getTok (exprData_getOpTok (data)) == OR_OP)
9123 exprNode e1 = exprNode_effect (exprData_getOpA (data));
9125 exprNode_produceGuards (e1);
9126 context_enterOrClause (e1);
9127 e2 = exprNode_effect (exprData_getOpB (data));
9129 ret = exprNode_op (e1, e2,
9130 exprData_getOpTok (data));
9132 context_exitOrClause (ret, e2);
9136 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
9137 exprNode_effect (exprData_getOpB (data)),
9138 exprData_getOpTok (data));
9143 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
9144 exprData_getUopTok (data));
9147 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
9148 exprData_getUopTok (data));
9160 ret = exprNode_vaArg (exprData_getCastTok (data),
9161 exprNode_effect (exprData_getCastNode (data)),
9162 exprData_getCastType (data));
9166 ret = exprNode_cast (exprData_getCastTok (data),
9167 exprNode_effect (exprData_getCastNode (data)),
9168 exprData_getCastType (data));
9171 ret = exprNode_iterStart (exprData_getIterCallIter (data),
9173 (exprData_getIterCallArgs (data)));
9177 ret = exprNode_iter (exprData_getIterSname (data),
9178 exprNodeList_effect (exprData_getIterAlist (data)),
9179 exprNode_effect (exprData_getIterBody (data)),
9180 exprData_getIterEname (data));
9184 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
9185 exprNode_effect (exprData_getPairB (data)));
9189 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
9190 exprNode_effect (exprData_getTripleTest (data)),
9191 exprNode_effect (exprData_getTripleInc (data)));
9195 ret = exprNode_createTok (exprData_getTok (data));
9199 ret = exprNode_goto (exprData_getLiteral (data));
9200 ret->loc = fileloc_update (ret->loc, e->loc);
9204 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
9208 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
9212 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
9215 case XPR_NULLRETURN:
9216 ret = exprNode_nullReturn (exprData_getTok (data));
9220 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
9221 exprNode_effect (exprData_getPairB (data)));
9225 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
9226 exprNode_effect (exprData_getTripleTrue (data)),
9227 exprNode_effect (exprData_getTripleFalse (data)));
9230 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
9231 exprNode_effect (exprData_getPairB (data)));
9235 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
9236 exprNode_effect (exprData_getTripleTrue (data)),
9237 exprNode_effect (exprData_getTripleFalse (data)));
9240 ret = exprNode_whilePred (exprData_getSingle (data));
9244 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
9245 exprNode_effect (exprData_getPairB (data)));
9249 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
9250 exprNode_effect (exprData_getPairB (data)));
9254 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
9258 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
9259 exprData_getUopTok (data));
9263 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
9264 exprNode_effect (exprData_getPairB (data)));
9269 ret = exprNode_caseMarker
9270 (exprNode_effect (exprData_getSingle (data)),
9276 ret = exprNode_createTok (exprData_getTok (data));
9280 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
9281 exprNode_effect (exprData_getPairB (data)));
9285 ret = exprNode_makeInitialization
9286 (exprData_getInitId (data),
9287 exprNode_effect (exprData_getInitNode (data)));
9291 ret = exprNode_fieldAccessAux
9292 (exprNode_effect (exprData_getFieldNode (data)),
9293 exprNode_loc (exprData_getFieldNode (data)),
9294 cstring_copy (exprData_getFieldName (data)));
9298 ret = exprNode_arrowAccessAux
9299 (exprNode_effect (exprData_getFieldNode (data)),
9300 exprNode_loc (exprData_getFieldNode (data)),
9301 cstring_copy (exprData_getFieldName (data)));
9304 case XPR_STRINGLITERAL:
9318 /*@=observertrans@*/
9320 /*@=dependenttrans@*/
9331 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
9336 if (exprNode_isError (e))
9338 return cstring_undefined;
9346 ret = exprNode_rootVarName (exprData_getUopNode (data));
9349 ret = exprNode_rootVarName (exprData_getOpA (data));
9353 ret = exprData_getId (data);
9356 ret = idDecl_getName (exprData_getInitId (data));
9381 case XPR_NULLRETURN:
9403 case XPR_STRINGLITERAL:
9404 ret = cstring_undefined;
9411 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
9416 if (exprNode_isError (e))
9418 static /*@only@*/ cstring error = cstring_undefined;
9420 if (!cstring_isDefined (error))
9422 error = cstring_makeLiteral ("<error>");
9433 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
9436 ret = message ("%s %s %s",
9437 exprNode_unparse (exprData_getOpA (data)),
9438 lltok_unparse (exprData_getOpTok (data)),
9439 exprNode_unparse (exprData_getOpB (data)));
9442 ret = message ("%s(%q)",
9443 exprNode_unparse (exprData_getFcn (data)),
9444 exprNodeList_unparse (exprData_getArgs (data)));
9447 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
9450 ret = cstring_undefined;
9453 ret = message ("%s:", exprData_getId (data));
9457 ret = cstring_copy (exprData_getId (data));
9460 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
9461 exprNode_unparse (exprData_getPairB (data)));
9464 ret = message ("<body>");
9467 ret = message ("%s %s %s",
9468 exprNode_unparse (exprData_getOpA (data)),
9469 lltok_unparse (exprData_getOpTok (data)),
9470 exprNode_unparse (exprData_getOpB (data)));
9474 ret = message ("%s%s",
9475 lltok_unparse (exprData_getUopTok (data)),
9476 exprNode_unparse (exprData_getUopNode (data)));
9480 ret = message ("%s%s",
9481 exprNode_unparse (exprData_getUopNode (data)),
9482 lltok_unparse (exprData_getUopTok (data)));
9486 ret = message ("offsetof(%s,%q)",
9487 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
9488 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
9492 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9496 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
9500 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9504 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
9508 ret = message ("va_arg(%s, %q)",
9509 exprNode_unparse (exprData_getCastNode (data)),
9510 qtype_unparse (exprData_getCastType (data)));
9514 ret = message ("%q(%q)",
9515 uentry_getName (exprData_getIterCallIter (data)),
9516 exprNodeList_unparse (exprData_getIterCallArgs (data)));
9519 ret = message ("%q(%q) %s %q",
9520 uentry_getName (exprData_getIterSname (data)),
9521 exprNodeList_unparse (exprData_getIterAlist (data)),
9522 exprNode_unparse (exprData_getIterBody (data)),
9523 uentry_getName (exprData_getIterEname (data)));
9526 ret = message ("(%q)%s",
9527 qtype_unparse (exprData_getCastType (data)),
9528 exprNode_unparse (exprData_getCastNode (data)));
9532 ret = message ("%s %s",
9533 exprNode_unparse (exprData_getPairA (data)),
9534 exprNode_unparse (exprData_getPairB (data)));
9538 ret = message ("for (%s; %s; %s)",
9539 exprNode_unparse (exprData_getTripleInit (data)),
9540 exprNode_unparse (exprData_getTripleTest (data)),
9541 exprNode_unparse (exprData_getTripleInc (data)));
9545 ret = message ("goto %s", exprData_getLiteral (data));
9549 ret = cstring_makeLiteral ("continue");
9553 ret = cstring_makeLiteral ("break");
9557 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
9560 case XPR_NULLRETURN:
9561 ret = cstring_makeLiteral ("return");
9565 ret = message ("%s, %s",
9566 exprNode_unparse (exprData_getPairA (data)),
9567 exprNode_unparse (exprData_getPairB (data)));
9571 ret = message ("%s ? %s : %s",
9572 exprNode_unparse (exprData_getTriplePred (data)),
9573 exprNode_unparse (exprData_getTripleTrue (data)),
9574 exprNode_unparse (exprData_getTripleFalse (data)));
9577 ret = message ("if (%s) %s",
9578 exprNode_unparse (exprData_getPairA (data)),
9579 exprNode_unparse (exprData_getPairB (data)));
9583 ret = message ("if (%s) %s else %s",
9584 exprNode_unparse (exprData_getTriplePred (data)),
9585 exprNode_unparse (exprData_getTripleTrue (data)),
9586 exprNode_unparse (exprData_getTripleFalse (data)));
9589 ret = message ("while (%s) %s",
9590 exprNode_unparse (exprData_getPairA (data)),
9591 exprNode_unparse (exprData_getPairB (data)));
9595 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9599 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9603 ret = message ("do { %s } while (%s)",
9604 exprNode_unparse (exprData_getPairB (data)),
9605 exprNode_unparse (exprData_getPairA (data)));
9609 ret = message ("{ %s }", exprNode_unparse (exprData_getSingle (data)));
9610 /* evans 2002-02-20 was unparseFirst! */
9614 ret = message ("%s;", exprNode_unparse (exprData_getUopNode (data)));
9618 if (exprNode_isStatement (exprData_getPairA (data)))
9621 ** statement expressions already print the ;
9624 ret = message ("%s %s",
9625 exprNode_unparse (exprData_getPairA (data)),
9626 exprNode_unparse (exprData_getPairB (data)));
9630 ret = message ("%s; %s",
9631 exprNode_unparse (exprData_getPairA (data)),
9632 exprNode_unparse (exprData_getPairB (data)));
9638 ret = cstring_makeLiteral ("default:");
9642 ret = message ("switch (%s) %s",
9643 exprNode_unparse (exprData_getPairA (data)),
9644 exprNode_unparse (exprData_getPairB (data)));
9649 ret = message ("case %s:",
9650 exprNode_unparse (exprData_getSingle (data)));
9654 if (exprNode_isError (exprData_getInitNode (data)))
9656 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9660 ret = message ("%q = %s",
9661 idDecl_unparseC (exprData_getInitId (data)),
9662 exprNode_unparse (exprData_getInitNode (data)));
9667 ret = message ("%s.%s",
9668 exprNode_unparse (exprData_getFieldNode (data)),
9669 exprData_getFieldName (data));
9673 ret = message ("%s->%s",
9674 exprNode_unparse (exprData_getFieldNode (data)),
9675 exprData_getFieldName (data));
9678 case XPR_STRINGLITERAL:
9679 if (ctype_isWideString (e->typ))
9681 ret = message ("L\"%s\"", exprData_getLiteral (data));
9685 ret = message ("\"%s\"", exprData_getLiteral (data));
9690 ret = cstring_copy (exprData_getLiteral (data));
9694 ret = cstring_makeLiteral ("<node>");
9702 exprNode_isInitializer (exprNode e)
9704 return (exprNode_isDefined (e)
9705 && e->kind == XPR_INIT);
9709 exprNode_isCharLit (exprNode e)
9711 if (exprNode_isDefined (e))
9713 return (multiVal_isChar (exprNode_getValue (e)));
9722 exprNode_isNumLit (exprNode e)
9724 if (exprNode_isDefined (e))
9726 return (multiVal_isInt (exprNode_getValue (e)));
9735 exprNode_isFalseConstant (exprNode e)
9737 if (exprNode_isDefined (e))
9739 cstring s = exprNode_rootVarName (e);
9741 if (cstring_equal (s, context_getFalseName ()))
9751 exprNode_matchLiteral (ctype expected, exprNode e)
9753 if (exprNode_isDefined (e))
9755 multiVal m = exprNode_getValue (e);
9757 if (multiVal_isDefined (m))
9759 if (multiVal_isInt (m))
9761 long int val = multiVal_forceInt (m);
9763 if (ctype_isDirectBool (ctype_realishType (expected)))
9767 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9775 if (ctype_isRealInt (expected))
9778 ** unsigned <- [ constant >= 0 is okay ]
9781 if (ctype_isUnsigned (expected))
9790 ** No checks on sizes of integers...maybe add
9794 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9795 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9796 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9798 if (context_getFlag (FLG_NUMLITERAL)
9799 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9805 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9809 else if (ctype_isChar (expected))
9813 else if (ctype_isArrayPtr (expected))
9816 ** evans 2001-10-14: We allow 0 to match any pointer, but only if the type matches or is void *.
9821 if (ctype_match (exprNode_getType (e), expected)
9822 || ctype_isVoidPointer (exprNode_getType (e)))
9832 else if (ctype_isAnyFloat (expected))
9834 return (context_getFlag (FLG_NUMLITERAL));
9841 else if (multiVal_isDouble (m))
9843 if (ctype_isAnyFloat (expected))
9848 else if (multiVal_isChar (m))
9850 char val = multiVal_forceChar (m);
9852 if (ctype_isChar (expected))
9854 if (ctype_isUnsigned (expected) && ((int)val) < 0)
9875 exprNode_matchType (ctype expected, exprNode e)
9879 if (!exprNode_isDefined (e)) return TRUE;
9881 actual = ctype_realishType (exprNode_getType (e));
9883 if (ctype_match (ctype_realishType (expected), actual))
9888 llassert (!exprNode_isError (e));
9889 return (exprNode_matchLiteral (expected, e));
9893 exprNode_matchTypes (exprNode e1, exprNode e2)
9898 if (!exprNode_isDefined (e1)) return TRUE;
9899 if (!exprNode_isDefined (e2)) return TRUE;
9902 ** realish type --- keep bools, bools
9905 t1 = ctype_realishType (exprNode_getType (e1));
9906 t2 = ctype_realishType (exprNode_getType (e2));
9908 if (ctype_match (t1, t2))
9913 DPRINTF (("Matching literal! %s %s %s %s",
9914 ctype_unparse (t1), exprNode_unparse (e2),
9915 ctype_unparse (t2), exprNode_unparse (e1)));
9917 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9925 exprNode_matchArgType (ctype ct, exprNode e)
9929 if (!exprNode_isDefined (e))
9934 et = ctype_realType (exprNode_getType (e));
9936 if (ctype_matchArg (ct, et)) return TRUE;
9938 llassert (!exprNode_isError (e));
9939 return (exprNode_matchLiteral (ct, e));
9942 static /*@only@*/ exprNodeSList
9943 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9945 if (exprNode_isDefined (e))
9947 if (e->kind == XPR_STMTLIST)
9949 return (exprNodeSList_append
9950 (exprNode_flatten (exprData_getPairA (e->edata)),
9951 exprNode_flatten (exprData_getPairB (e->edata))));
9953 else if (e->kind == XPR_BLOCK)
9955 return (exprNode_flatten (exprData_getSingle (e->edata)));
9959 return (exprNodeSList_singleton (e));
9963 return exprNodeSList_new ();
9966 static /*@exposed@*/ exprNode
9967 exprNode_lastStatement (/*@returned@*/ exprNode e)
9969 if (exprNode_isDefined (e))
9971 if (e->kind == XPR_STMTLIST)
9973 exprNode b = exprData_getPairB (e->edata);
9975 if (exprNode_isDefined (b))
9977 return exprNode_lastStatement (b);
9981 return exprNode_lastStatement (exprData_getPairA (e->edata));
9984 else if (e->kind == XPR_BLOCK)
9986 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
9994 return exprNode_undefined;
9997 static /*@exposed@*/ exprNode
9998 exprNode_firstStatement (/*@returned@*/ exprNode e)
10000 if (exprNode_isDefined (e))
10002 if (e->kind == XPR_STMTLIST)
10004 exprNode b = exprData_getPairA (e->edata);
10006 if (exprNode_isDefined (b))
10008 return exprNode_firstStatement (b);
10012 return exprNode_firstStatement (exprData_getPairB (e->edata));
10015 else if (e->kind == XPR_BLOCK)
10017 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
10025 return exprNode_undefined;
10029 exprNode_mergeUSs (exprNode res, exprNode other)
10031 if (exprNode_isDefined (res) && exprNode_isDefined (other))
10033 res->msets = sRefSet_union (res->msets, other->msets);
10034 res->sets = sRefSet_union (res->sets, other->sets);
10035 res->uses = sRefSet_union (res->uses, other->uses);
10040 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
10042 if (exprNode_isDefined (res))
10044 if (exprNode_isDefined (other1))
10046 res->sets = sRefSet_union (res->sets, other1->sets);
10047 res->msets = sRefSet_union (res->msets, other1->msets);
10048 res->uses = sRefSet_union (res->uses, other1->uses);
10050 if (exprNode_isDefined (other2))
10052 res->sets = sRefSet_union (res->sets, other2->sets);
10053 res->msets = sRefSet_union (res->msets, other2->msets);
10054 res->uses = sRefSet_union (res->uses, other2->uses);
10060 ** modifies e->uses
10062 ** Reports errors is s is not defined.
10066 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
10068 if (exprNode_isDefined (e))
10070 e->uses = sRefSet_insert (e->uses, s);
10075 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
10077 if (sRef_isKnown (s) && !sRef_isConst (s))
10080 ** need to check all outer types are useable
10083 DPRINTF (("Check use: %s / %s",
10084 exprNode_unparse (e), sRef_unparse (s)));
10086 exprNode_addUse (e, s);
10088 if (!context_inProtectVars ())
10091 ** only report the deepest error
10094 sRef errorRef = sRef_undefined;
10095 sRef lastRef = sRef_undefined;
10096 bool deadRef = FALSE;
10097 bool unuseable = FALSE;
10098 bool errorMaybe = FALSE;
10100 while (sRef_isValid (s) && sRef_isKnown (s))
10102 ynm readable = sRef_isValidLvalue (s);
10104 DPRINTF (("Readable: %s / %s",
10105 sRef_unparseFull (s), ynm_unparse (readable)));
10107 if (!(ynm_toBoolStrict (readable)))
10109 if (ynm_isMaybe (readable))
10111 lastRef = errorRef;
10113 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
10114 deadRef = sRef_isPossiblyDead (errorRef);
10115 unuseable = sRef_isUnuseable (errorRef);
10120 lastRef = errorRef;
10122 deadRef = sRef_isDead (errorRef);
10123 unuseable = sRef_isUnuseable (errorRef);
10124 errorMaybe = FALSE;
10127 if (!sRef_isPartial (s))
10129 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
10130 sRef_setDefined (s, fileloc_undefined);
10134 s = sRef_getBaseSafe (s);
10137 if (sRef_isValid (errorRef))
10139 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
10140 && sRef_isPointer (errorRef))
10142 errorRef = lastRef;
10147 if (sRef_isThroughArrayFetch (errorRef))
10150 (FLG_STRICTUSERELEASED,
10151 message ("%q %q may be used after being released",
10152 sRef_unparseKindNamePlain (errorRef),
10153 sRef_unparse (errorRef)),
10156 sRef_showRefKilled (errorRef);
10158 if (sRef_isKept (errorRef))
10160 sRef_clearAliasState (errorRef, loc);
10166 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
10170 message ("%q %q %qused after being released",
10171 sRef_unparseKindNamePlain (errorRef),
10172 sRef_unparse (errorRef),
10173 cstring_makeLiteral (errorMaybe
10174 ? "may be " : "")),
10177 sRef_showRefKilled (errorRef);
10179 if (sRef_isKept (errorRef))
10181 sRef_clearAliasState (errorRef, loc);
10186 else if (unuseable)
10190 message ("%q %q%qused in inconsistent state",
10191 sRef_unparseKindName (errorRef),
10192 sRef_unparseOpt (errorRef),
10193 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10196 sRef_showStateInconsistent (errorRef);
10201 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
10205 message ("%q %q%qused before definition",
10206 sRef_unparseKindName (errorRef),
10207 sRef_unparseOpt (errorRef),
10208 cstring_makeLiteral (errorMaybe ? "may be " : "")),
10211 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
10214 sRef_setDefined (errorRef, loc);
10216 if (sRef_isAddress (errorRef))
10218 sRef_setDefined (sRef_getRootBase (errorRef), loc);
10220 } /* end is error */
10228 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
10230 if (exprNode_isDefined (e) && sRef_isKnown (s))
10232 e->uses = sRefSet_insert (e->uses, s);
10237 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
10239 if (exprNode_isDefined (e))
10241 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
10246 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
10248 sRef defines = sRef_undefined;
10250 if (sRef_isValid (s) && !sRef_isNothing (s))
10252 uentry ue = sRef_getBaseUentry (s);
10254 if (uentry_isValid (ue))
10256 uentry_setLset (ue);
10259 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10261 voptgenerror (FLG_USEDEF,
10262 message ("Attempt to set unuseable storage: %q",
10267 if (sRef_isMeaningful (s))
10269 if (sRef_isDead (s))
10271 sRef base = sRef_getBaseSafe (s);
10273 if (sRef_isValid (base)
10274 && sRef_isDead (base))
10276 sRef_setPartial (s, exprNode_loc (e));
10279 defines = s; /* okay - modifies for only param */
10281 else if (sRef_isPartial (s))
10283 sRef eref = exprNode_getSref (e);
10285 if (!sRef_isPartial (eref))
10288 ** should do something different here???
10291 sRef_setDefinedComplete (eref, exprNode_loc (e));
10295 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
10298 if (sRef_isMeaningful (eref))
10307 else if (sRef_isAllocated (s))
10309 sRef eref = exprNode_getSref (e);
10312 if (!sRef_isAllocated (eref))
10314 sRef_setDefinedComplete (eref, exprNode_loc (e));
10318 sRef base = sRef_getBaseSafe (eref);
10320 if (sRef_isValid (base))
10322 sRef_setPdefined (base, exprNode_loc (e));
10330 sRef_setDefinedNCComplete (s, exprNode_loc (e));
10335 else /* not meaningful...but still need to insert it */
10341 if (exprNode_isDefined (e) && sRef_isValid (defines))
10343 e->sets = sRefSet_insert (e->sets, defines);
10348 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
10350 if (sRef_isValid (s) && !sRef_isNothing (s))
10352 uentry ue = sRef_getBaseUentry (s);
10354 if (uentry_isValid (ue))
10356 uentry_setLset (ue);
10359 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
10361 voptgenerror (FLG_USEDEF,
10362 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
10366 if (sRef_isMeaningful (s))
10368 sRef_setDefinedComplete (s, exprNode_loc (e));
10371 if (exprNode_isDefined (e))
10373 e->msets = sRefSet_insert (e->msets, s);
10379 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
10381 checkAnyCall (fcn, cstring_undefined, params, args,
10382 FALSE, sRefSet_undefined, FALSE, 0);
10386 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
10387 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
10391 if (uentry_isYield (ucurrent))
10393 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
10394 exprNode_checkSet (current, current->sref);
10398 if (uentry_isSefParam (ucurrent))
10400 sRefSet sets = current->sets;
10401 sRef ref = exprNode_getSref (current);
10403 if (sRef_isMacroParamRef (ref))
10405 uentry ue = sRef_getUentry (ref);
10407 if (!uentry_isSefParam (ue))
10412 ("Parameter %d to %s is declared sef, but "
10413 "the argument is a macro parameter declared "
10415 argno, exprNode_unparse (fcn),
10416 exprNode_unparse (current)),
10417 exprNode_loc (current));
10421 if (!sRefSet_isEmpty (sets))
10423 sRefSet reported = sRefSet_undefined;
10425 sRefSet_realElements (current->sets, el)
10427 if (sRefSet_isSameNameMember (reported, el))
10429 ; /* don't report again */
10433 if (sRef_isUnconstrained (el))
10438 ("Parameter %d to %s is declared sef, but "
10439 "the argument calls unconstrained function %s "
10440 "(no guarantee it will not modify something): %s",
10441 argno, exprNode_unparse (fcn),
10442 sRef_unconstrainedName (el),
10443 exprNode_unparse (current)),
10444 exprNode_loc (current));
10451 ("Parameter %d to %s is declared sef, but "
10452 "the argument may modify %q: %s",
10453 argno, exprNode_unparse (fcn),
10455 exprNode_unparse (current)),
10456 exprNode_loc (current));
10459 } end_sRefSet_realElements;
10463 transferChecks_passParam (current, ucurrent, isSpec, fcn, argno, totargs);
10464 exprNode_mergeUSs (fcn, current);
10469 checkAnyCall (/*@dependent@*/ exprNode fcn,
10470 /*@dependent@*/ cstring fname,
10473 bool hasMods, sRefSet mods,
10478 int nargs = exprNodeList_size (args);
10483 ** concat all args ud's to f, add each arg sref as a use unless
10484 ** it was specified as "out", in which case it is a def.
10487 uentryList_reset (pn);
10490 ** aliasing checks:
10492 ** if paramn is only or unique, no other arg may alias argn
10495 exprNodeList_elements (args, current)
10499 if (exprNode_isDefined (current))
10501 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
10503 uentry ucurrent = uentryList_current (pn);
10505 if (specialArgs == 0
10506 || (paramno < specialArgs))
10508 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
10510 if (context_maybeSet (FLG_ALIASUNIQUE))
10512 if (uentry_isOnly (ucurrent)
10513 || uentry_isUnique (ucurrent))
10515 checkUniqueParams (fcn, current, args,
10516 paramno, ucurrent);
10521 else /* uentry is undefined */
10523 if (specialArgs == 0)
10525 exprNode_checkUseParam (current);
10528 exprNode_mergeUSs (fcn, current);
10531 uentryList_advanceSafe (pn);
10532 } end_exprNodeList_elements;
10538 sRefSet_allElements (mods, s)
10541 sRef rb = sRef_getRootBase (s);
10543 if (sRef_isFileOrGlobalScope (rb))
10545 context_usedGlobal (rb);
10548 fb = sRef_fixBaseParam (s, args);
10550 if (!sRef_isMacroParamRef (fb))
10552 if (sRef_isNothing (fb))
10558 if (sRef_isValid (fb))
10560 uentry ue = sRef_getBaseUentry (s);
10562 if (uentry_isValid (ue))
10564 uentry_setLset (ue);
10568 fcn->sets = sRefSet_insert (fcn->sets, fb);
10571 sRef_clearDerivedComplete (s);
10572 } end_sRefSet_allElements;
10578 if (context_hasMods ())
10580 if (context_maybeSet (FLG_MODUNCON))
10584 message ("Undetected modification possible "
10585 "from call to unconstrained function %s: %s",
10587 exprNode_unparse (fcn)),
10588 exprNode_loc (fcn));
10593 if (context_maybeSet (FLG_MODUNCONNOMODS)
10594 && !(context_inIterDef () || context_inIterEnd ()))
10597 (FLG_MODUNCONNOMODS,
10598 message ("Undetected modification possible "
10599 "from call to unconstrained function %s: %s",
10601 exprNode_unparse (fcn)),
10602 exprNode_loc (fcn));
10606 exprNode_checkSetAny (fcn, fname);
10610 void exprNode_checkUseParam (exprNode current)
10612 if (exprNode_isDefined (current))
10614 exprNode_checkUse (current, current->sref, current->loc);
10619 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10620 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10625 if (!ctype_match (tr1, tr2))
10627 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10628 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10630 DPRINTF (("No error: [%s] %s / [%s] %s",
10631 exprNode_unparse (e1), ctype_unparse (tr1),
10632 exprNode_unparse (e2), ctype_unparse (tr2)));
10636 (void) gentypeerror
10638 message ("Incompatible types for %s (%s, %s): %s %s %s",
10639 lltok_unparse (op),
10640 ctype_unparse (te1),
10641 ctype_unparse (te2),
10642 exprNode_unparse (e1), lltok_unparse (op),
10643 exprNode_unparse (e2)),
10646 ret = ctype_unknown;
10650 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
10652 ret = ctype_resolveNumerics (tr1, tr2);
10654 else if (!context_msgStrictOps ())
10656 if (ctype_isPointer (tr1))
10658 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10662 else if (ctype_isInt (tr2))
10668 ret = ctype_unknown;
10671 else if (ctype_isPointer (tr2))
10673 if (ctype_isPointer (tr1))
10677 else if (ctype_isInt (tr1))
10683 ret = ctype_unknown;
10688 ret = ctype_resolveNumerics (tr1, tr2);
10693 int opid = lltok_getTok (op);
10694 bool comparop = (opid == EQ_OP || opid == NE_OP
10695 || opid == TLT || opid == TGT
10696 || opid == LE_OP || opid == GE_OP);
10698 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10701 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10702 || (ctype_isBool (tr1) && ctype_isBool (tr2))
10703 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10709 if (ctype_sameName (te1, te2))
10713 message ("Operands of %s are non-numeric (%t): %s %s %s",
10714 lltok_unparse (op), te1,
10715 exprNode_unparse (e1), lltok_unparse (op),
10716 exprNode_unparse (e2)),
10723 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10724 lltok_unparse (op), te1, te2,
10725 exprNode_unparse (e1), lltok_unparse (op),
10726 exprNode_unparse (e2)),
10731 else if (!ctype_isNumeric (tr1))
10735 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10736 lltok_unparse (op), te1,
10737 exprNode_unparse (e1), lltok_unparse (op),
10738 exprNode_unparse (e2)),
10743 if (!ctype_isNumeric (tr2))
10747 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10748 lltok_unparse (op), te2,
10749 exprNode_unparse (e1), lltok_unparse (op),
10750 exprNode_unparse (e2)),
10755 ret = ctype_unknown;
10763 abstractOpError (ctype tr1, ctype tr2, lltok op,
10764 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10765 fileloc loc1, fileloc loc2)
10767 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10769 if (ctype_match (tr1, tr2))
10773 message ("Operands of %s are abstract type (%t): %s %s %s",
10774 lltok_unparse (op), tr1,
10775 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10782 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10783 lltok_unparse (op), tr1, tr2,
10784 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10788 else if (ctype_isRealAbstract (tr1))
10792 message ("Left operand of %s is abstract type (%t): %s %s %s",
10793 lltok_unparse (op), tr1,
10794 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10799 if (ctype_isRealAbstract (tr2))
10803 message ("Right operand of %s is abstract type (%t): %s %s %s",
10804 lltok_unparse (op), tr2,
10805 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10814 ** requies e1 and e2 and not error exprNode's.
10818 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10819 ** the rep of the abstract type is exposed.
10821 ** The order is very important:
10823 ** check rep expose (move into check transfer)
10829 ** This isn't really a sensible procedure, but the indententation
10830 ** was getting too deep.
10834 checkOneRepExpose (sRef ysr, sRef base,
10835 /*@notnull@*/ exprNode e1,
10836 /*@notnull@*/ exprNode e2, ctype ct,
10839 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
10840 || sRef_isOwned (ysr)
10841 || sRef_isExposed (ysr)))
10843 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10844 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10847 if (sRef_isIReference (ysr))
10849 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10854 ("Assignment of mutable component of parameter %q "
10855 "to component of abstract "
10856 "type %s exposes rep: %s = %s",
10857 sRef_unparse (base),
10858 ctype_unparse (ct),
10859 exprNode_unparse (e1), exprNode_unparse (e2)),
10867 ("Assignment of mutable component of parameter %q "
10868 "(through alias %q) to component of abstract "
10869 "type %s exposes rep: %s = %s",
10870 sRef_unparse (base),
10871 sRef_unparse (e2->sref),
10872 ctype_unparse (ct),
10873 exprNode_unparse (e1), exprNode_unparse (e2)),
10879 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10883 message ("Assignment of mutable parameter %q "
10884 "to component of abstract type %s "
10885 "exposes rep: %s = %s",
10886 sRef_unparse (base),
10887 ctype_unparse (ct),
10888 exprNode_unparse (e1),
10889 exprNode_unparse (e2)),
10896 message ("Assignment of mutable parameter %q "
10897 "(through alias %q) to "
10898 "component of abstract type %s exposes "
10900 sRef_unparse (base),
10901 sRef_unparse (e2->sref),
10902 ctype_unparse (ct),
10903 exprNode_unparse (e1),
10904 exprNode_unparse (e2)),
10910 if (sRef_isFileOrGlobalScope (s2b))
10912 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10916 message ("Assignment of global %q "
10918 "abstract type %s exposes rep: %s = %s",
10919 sRef_unparse (base),
10920 ctype_unparse (ct),
10921 exprNode_unparse (e1), exprNode_unparse (e2)),
10928 message ("Assignment of global %q (through alias %q) "
10930 "abstract type %s exposes rep: %s = %s",
10931 sRef_unparse (base),
10932 sRef_unparse (e2->sref),
10933 ctype_unparse (ct),
10934 exprNode_unparse (e1), exprNode_unparse (e2)),
10942 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
10944 DPRINTF (("Do assign: %s <- %s",
10945 exprNode_unparse (e1), exprNode_unparse (e2)));
10946 DPRINTF (("Ctype: %s", ctype_unparse (exprNode_getType (e1))));
10948 if (ctype_isRealFunction (exprNode_getType (e1))
10949 && !ctype_isRealPointer (exprNode_getType (e1)))
10953 message ("Invalid left-hand side of assignment (function type %s): %s",
10954 ctype_unparse (exprNode_getType (e1)),
10955 exprNode_unparse (e1)),
10959 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
10961 ctype t2 = exprNode_getType (e2);
10962 sRef sr = sRef_getRootBase (e1->sref);
10963 ctype ct = sRef_getType (sr);
10965 if (ctype_isAbstract (t2)
10966 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
10968 /* it is immutable, okay to reference */
10969 goto donerepexpose;
10972 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
10974 sRef s2b = sRef_getRootBase (e2->sref);
10975 sRef s1 = e1->sref;
10976 sRef s1b = sRef_getRootBase (s1);
10979 aliases = usymtab_canAlias (e2->sref);
10981 if (!sRef_similar (s2b, s1b)
10982 && !sRef_isExposed (s1)
10983 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
10985 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
10986 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
10987 && !sRef_isExposed (s2b))
10989 if (sRef_isIReference (e2->sref))
10994 ("Assignment of mutable component of parameter %q "
10995 "to component of abstract type %s exposes rep: %s = %s",
10996 sRef_unparse (s2b),
10997 ctype_unparse (ct),
10998 exprNode_unparse (e1), exprNode_unparse (e2)),
11005 message ("Assignment of mutable parameter %q to "
11006 "component of abstract type %s exposes rep: %s = %s",
11007 sRef_unparse (s2b),
11008 ctype_unparse (ct),
11009 exprNode_unparse (e1), exprNode_unparse (e2)),
11014 if (sRef_isFileOrGlobalScope (s2b))
11018 message ("Assignment of global %q to component of "
11019 "abstract type %s exposes rep: %s = %s",
11020 sRef_unparse (s2b),
11021 ctype_unparse (ct),
11022 exprNode_unparse (e1), exprNode_unparse (e2)),
11026 sRefSet_realElements (aliases, ysr)
11028 sRef base = sRef_getRootBase (ysr);
11030 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
11031 || sRef_sameName (base, s1b))
11033 ; /* error already reported or same sref */
11037 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
11039 } end_sRefSet_realElements;
11041 sRefSet_free (aliases);
11048 ** function variables don't really work...
11051 if (!ctype_isFunction (ctype_realType (e2->typ)))
11055 DPRINTF (("Check init: %s / %s",
11056 exprNode_unparse (e1), exprNode_unparse (e2)));
11057 transferChecks_initialization (e1, e2);
11061 transferChecks_assign (e1, e2);
11066 sRef fref = e2->sref;
11068 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
11069 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
11071 /* Need to typecheck the annotation on the parameters */
11073 if (ctype_isRealFunction (e1->typ)) {
11074 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
11075 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
11077 if (!uentryList_isMissingParams (e1p)
11078 && !uentryList_isMissingParams (e2p)
11079 && uentryList_size (e1p) > 0) {
11080 if (uentryList_size (e1p) == uentryList_size (e2p)) {
11083 uentryList_elements (e1p, el1) {
11086 el2 = uentryList_getN (e2p, n);
11088 uentry_checkMatchParam (el1, el2, n, e2);
11089 } end_uentryList_elements;
11095 if (exprNode_isStringLiteral (e2))
11097 exprNode_checkStringLiteralLength (exprNode_getType (e1), e2);
11100 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
11106 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
11107 updateAliases (e1, e2);
11112 checkMacroParen (exprNode e)
11114 if (exprNode_isError (e) || e->kind == XPR_CAST)
11120 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
11124 message ("Macro parameter used without parentheses: %s",
11125 exprNode_unparse (e)),
11132 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
11136 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
11140 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
11147 ** if e2 is a parameter or global derived location which
11148 ** can be modified (that is, e2 is a mutable abstract type,
11149 ** or a derived pointer), then e1 can alias e2.
11151 ** e1 can alias everything which e2 can alias.
11153 ** Also, if e1 is guarded, remove from guard sets!
11156 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
11158 if (!context_inProtectVars ())
11161 ** depends on types of e1 and e2
11164 sRef s1 = e1->sref;
11165 sRef s2 = e2->sref;
11166 ctype t1 = exprNode_getType (e1);
11168 /* handle pointer sRefs, record fields, arrays, etc... */
11170 if (!ctype_isRealSU (t1))
11172 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
11173 sRef_copyRealDerivedComplete (s1, s2);
11178 ** Fields should alias
11181 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
11184 if (ctype_isMutable (t1) && sRef_isKnown (s1))
11186 usymtab_clearAlias (s1);
11187 usymtab_addMustAlias (s1, s2);
11188 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
11192 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
11195 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
11197 usymtab_unguard (s1);
11202 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
11204 if (exprNode_isDefined (e))
11206 e->loc = fileloc_update (e->loc, loc);
11210 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
11216 static void checkUniqueParams (exprNode fcn,
11217 /*@notnull@*/ exprNode current,
11219 int paramno, uentry ucurrent)
11222 sRef thisref = exprNode_getSref (current);
11225 ** Check if any argument could match this argument.
11228 exprNodeList_elements (args, icurrent)
11232 if (iparamno != paramno)
11234 sRef sr = exprNode_getSref (icurrent);
11236 if (sRef_similarRelaxed (thisref, sr))
11238 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
11243 ("Parameter %d (%s) to function %s is declared %s but "
11244 "is aliased by parameter %d (%s)",
11246 exprNode_unparse (current),
11247 exprNode_unparse (fcn),
11248 alkind_unparse (uentry_getAliasKind (ucurrent)),
11249 iparamno, exprNode_unparse (icurrent)),
11255 sRefSet aliases = usymtab_canAlias (sr);
11257 sRefSet_allElements (aliases, asr)
11259 if (ctype_isUnknown (sRef_getType (thisref)))
11261 sRef_setType (thisref, uentry_getType (ucurrent));
11264 if (sRef_similarRelaxed (thisref, asr))
11266 if (sRef_isExternal (asr))
11268 if (sRef_isLocalState (thisref))
11274 sRef base = sRef_getRootBase (asr);
11276 if (!sRef_similar (sRef_getBase (asr), thisref))
11278 if (sRef_isUnique (base) || sRef_isOnly (base)
11279 || sRef_isKept (base)
11280 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
11281 || (sRef_isAddress (thisref)
11282 && sRef_isLocalVar (sRef_getRootBase (thisref))))
11284 ; /* okay, no error */
11289 (FLG_MAYALIASUNIQUE,
11291 ("Parameter %d (%s) to function %s is declared %s but "
11292 "may be aliased externally by parameter %d (%s)",
11294 exprNode_unparse (current),
11295 exprNode_unparse (fcn),
11296 alkind_unparse (uentry_getAliasKind (ucurrent)),
11297 iparamno, exprNode_unparse (icurrent)),
11308 ("Parameter %d (%s) to function %s is declared %s but "
11309 "is aliased externally by parameter %d (%s) through "
11312 exprNode_unparse (current),
11313 exprNode_unparse (fcn),
11314 alkind_unparse (uentry_getAliasKind (ucurrent)),
11315 iparamno, exprNode_unparse (icurrent),
11316 sRef_unparse (asr)),
11320 } end_sRefSet_allElements;
11321 sRefSet_free (aliases);
11324 } end_exprNodeList_elements;
11327 long exprNode_getLongValue (exprNode e) {
11330 if (exprNode_hasValue (e)
11331 && multiVal_isInt (exprNode_getValue (e)))
11333 value = multiVal_forceInt (exprNode_getValue (e));
11344 /*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
11346 if (exprNode_isDefined (p_e) )
11347 return ( p_e->loc );
11349 return fileloc_undefined;
11352 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
11355 ** Returns the location of the sequence point following e.
11357 ** Only works for statements (for now).
11360 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
11361 lltok t = exprData_getUopTok (e->edata);
11362 return fileloc_copy(lltok_getLoc (t));
11364 /* drl possible problem : warning fix
11365 llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
11367 return fileloc_undefined;
11371 exprNode exprNode_createNew(ctype c)
11375 ret = exprNode_createPlain (c);
11380 bool exprNode_isInitBlock (exprNode e)
11382 return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);