2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
28 # include <ctype.h> /* for isdigit */
29 # include "lclintMacros.nf"
31 # include "cgrammar.h"
32 # include "cgrammar_tokens.h"
34 # include "exprChecks.h"
35 # include "transferChecks.h"
36 # include "exprNodeSList.h"
38 static bool exprNode_isEmptyStatement (exprNode p_e);
39 static /*@exposed@*/ exprNode exprNode_firstStatement (/*@returned@*/ exprNode p_e);
40 static bool exprNode_isFalseConstant (exprNode p_e) /*@*/ ;
41 static bool exprNode_isBlock (exprNode p_e);
42 static void checkGlobUse (uentry p_glob, bool p_isCall, /*@notnull@*/ exprNode p_e);
43 static void exprNode_addUse (exprNode p_e, /*@exposed@*/ sRef p_s);
44 static bool exprNode_matchArgType (ctype p_ct, exprNode p_e);
45 static exprNode exprNode_fakeCopy (exprNode p_e) /*@*/ ;
46 static exprNode exprNode_statementError (/*@only@*/ exprNode p_e, /*@only@*/ lltok p_t);
47 static bool exprNode_matchTypes (exprNode p_e1, exprNode p_e2);
48 static void checkUniqueParams (exprNode p_fcn,
49 /*@notnull@*/ exprNode p_current, exprNodeList p_args,
50 int p_paramno, uentry p_ucurrent);
51 static void updateAliases (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2);
52 static void abstractOpError (ctype p_tr1, ctype p_tr2, lltok p_op,
53 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2,
54 fileloc p_loc1, fileloc p_loc2);
55 static ctype checkNumerics (ctype p_tr1, ctype p_tr2, ctype p_te1, ctype p_te2,
56 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, lltok p_op);
57 static void doAssign (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, bool p_isInit);
58 static void checkSafeUse (exprNode p_e, /*@exposed@*/ sRef p_s);
59 static void reflectNullTest (/*@notnull@*/ exprNode p_e, bool p_isnull);
60 static void checkMacroParen (exprNode p_e);
61 static exprNodeSList exprNode_flatten (/*@dependent@*/ exprNode p_e);
62 static void exprNode_checkSetAny (exprNode p_e, /*@dependent@*/ cstring p_name);
63 static void exprNode_checkUse (exprNode p_e, /*@exposed@*/ sRef p_s, fileloc p_loc);
64 static void exprNode_mergeUSs (exprNode p_res, exprNode p_other);
65 static void exprNode_mergeCondUSs (exprNode p_res, exprNode p_other1, exprNode p_other2);
66 static /*@only@*/ /*@notnull@*/ exprNode exprNode_fromIdentifierAux (/*@observer@*/ uentry p_c);
67 static void checkAnyCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn,
68 /*@dependent@*/ cstring p_fname,
69 uentryList p_pn, exprNodeList p_args,
70 bool p_hasMods, sRefSet p_mods, bool p_isSpec,
72 static void checkOneArg (uentry p_ucurrent, /*@notnull@*/ exprNode p_current,
73 /*@dependent@*/ exprNode p_fcn, bool p_isSpec, int p_argno, int p_totargs);
75 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn, uentryList p_params, exprNodeList p_args);
77 static /*@only@*/ exprNode exprNode_effect (exprNode p_e)
78 /*@globals internalState@*/ ;
79 static /*@only@*/ cstring exprNode_doUnparse (exprNode p_e);
80 static /*@observer@*/ cstring exprNode_rootVarName (exprNode p_e);
81 static /*@exposed@*/ exprNode
82 exprNode_lastStatement (/*@returned@*/ exprNode p_e);
84 static /*@null@*/ sRef defref = sRef_undefined;
85 static /*@only@*/ exprNode 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 static void exprNode_defineConstraints(/*@sef@*/ /*@special@*/ /*@notnull@*/ exprNode e)
109 /*@defines e->requiresConstraints, e->ensuresConstraints,
110 e->trueEnsuresConstraints, e->falseEnsuresConstraints @*/
112 e->requiresConstraints = constraintList_makeNew ();
113 e->ensuresConstraints = constraintList_makeNew ();
114 e->trueEnsuresConstraints = constraintList_makeNew ();
115 e->falseEnsuresConstraints = constraintList_makeNew ();
119 ** must occur after library has been read
122 void exprNode_initMod (void)
123 /*@globals undef regArg, undef outArg, undef outStringArg,
124 undef csOnlyArg, undef csArg;
131 cstringType = ctype_unknown;
132 ctypeType = ctype_unknown;
133 filelocType = ctype_unknown;
135 defref = sRef_undefined;
137 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
139 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
142 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
144 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
147 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
149 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
152 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdin")))
154 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdin"));
156 else /* define stdin */
158 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdin"),
160 fileloc_getBuiltin (),
162 uentry_setHasNameError (ue);
163 ue = usymtab_supGlobalEntryReturn (ue);
166 stdinRef = sRef_makePointer (uentry_getSref (ue));
168 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdout")))
170 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdout"));
174 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdout"),
176 fileloc_getBuiltin (),
178 uentry_setHasNameError (ue);
179 ue = usymtab_supGlobalEntryReturn (ue);
182 stdoutRef = sRef_makePointer (uentry_getSref (ue));
184 tmp = idDecl_create (cstring_undefined, qtype_create (ctype_unknown));
186 regArg = uentry_makeParam (tmp, PARAMUNKNOWN);
189 qtype_addQual (qtype_create (ctype_makePointer (ctype_unknown)),
192 outArg = uentry_makeParam (tmp, PARAMUNKNOWN);
194 idDecl_setTyp (tmp, qtype_addQual (qtype_create (ctype_string),
197 outStringArg = uentry_makeParam (tmp, PARAMUNKNOWN);
199 idDecl_setTyp (tmp, qtype_addQual (qtype_addQual (qtype_create (cstringType),
201 qual_createNull ()));
203 csOnlyArg = uentry_makeParam (tmp, PARAMUNKNOWN);
205 idDecl_setTyp (tmp, qtype_addQual (qtype_create (cstringType), qual_createNull ()));
206 csArg = uentry_makeParam (tmp, PARAMUNKNOWN);
212 exprNode_destroyMod (void)
213 /*@globals killed regArg, killed outArg, killed outStringArg,
214 killed mustExitNode, initMod @*/
218 uentry_free (regArg);
219 uentry_free (outArg);
220 uentry_free (outStringArg);
222 exprNode_free (mustExitNode);
229 static void exprNode_resetSref (/*@notnull@*/ exprNode e)
234 exprNode exprNode_fakeCopy (exprNode e)
236 /*@-temptrans@*/ /*@-retalias@*/
238 /*@=temptrans@*/ /*@=retalias@*/
241 static bool isFlagKey (char key)
243 return (key == '-' || key == '+' || key == ' ' || key == '#');
246 static void exprNode_combineControl (/*@notnull@*/ exprNode ret,
247 /*@notnull@*/ exprNode ifclause,
248 /*@notnull@*/ exprNode elseclause)
250 ret->canBreak = ifclause->canBreak || elseclause->canBreak;
253 (ifclause->mustBreak || exprNode_mustEscape (ifclause))
254 && (elseclause->mustBreak || exprNode_mustEscape (elseclause));
256 ret->exitCode = exitkind_combine (ifclause->exitCode,
257 elseclause->exitCode);
262 ** For exprNode's returned by exprNode_effect.
265 static bool shallowKind (exprKind kind)
267 return (kind == XPR_STRINGLITERAL
268 || kind == XPR_NUMLIT
271 || kind == XPR_NODE);
275 exprNode_freeIniter (/*@only@*/ exprNode e)
277 if (!exprNode_isError (e))
283 ** Its a fake copy, don't free the field->rec and field->field
288 sfree (e->edata->field);
294 exprNode_free (e->edata->op->b);
295 /*@-compdestroy@*/ sfree (e->edata->op); /*@=compdestroy@*/
299 llbug (message ("other: %s", exprNode_unparse (e)));
302 multiVal_free (e->val);
303 cstring_free (e->etext);
304 fileloc_free (e->loc);
305 sRefSet_free (e->uses);
306 sRefSet_free (e->sets);
307 sRefSet_free (e->msets);
308 guardSet_free (e->guards);
310 constraintList_free(e->requiresConstraints);
311 constraintList_free(e->ensuresConstraints);
312 constraintList_free(e->trueEnsuresConstraints);
313 constraintList_free(e->falseEnsuresConstraints);
315 e->requiresConstraints = NULL;
316 e->ensuresConstraints = NULL;
317 e->trueEnsuresConstraints = NULL;
318 e->falseEnsuresConstraints = NULL;
325 exprNode_freeShallow (/*@only@*/ exprNode e)
327 if (!exprNode_isError (e))
329 if (shallowKind (e->kind))
336 if (e->kind == XPR_EMPTY
337 || e->kind == XPR_BODY
338 || e->kind == XPR_STRINGLITERAL
339 || e->kind == XPR_NUMLIT
340 || e->kind == XPR_NODE
341 || e->kind == XPR_OFFSETOF
342 || e->kind == XPR_ALIGNOFT
343 || e->kind == XPR_ALIGNOF
344 || e->kind == XPR_SIZEOFT
345 || e->kind == XPR_SIZEOF)
347 /* don't free anything */
351 /* multiVal_free (e->val); */
352 cstring_free (e->etext);
353 fileloc_free (e->loc);
354 sRefSet_free (e->uses);
355 sRefSet_free (e->sets);
356 sRefSet_free (e->msets);
357 guardSet_free (e->guards);
358 exprData_freeShallow (e->edata, e->kind);
360 /*@-compdestroy@*/ sfree (e); /*@=compdestroy@*/
369 exprNode_free (exprNode e)
371 if (!exprNode_isError (e))
375 multiVal_free (e->val);
376 cstring_free (e->etext);
377 fileloc_free (e->loc);
378 sRefSet_free (e->uses);
379 sRefSet_free (e->sets);
380 sRefSet_free (e->msets);
381 guardSet_free (e->guards);
382 exprData_free (e->edata, e->kind);
384 constraintList_free(e->requiresConstraints);
385 constraintList_free(e->ensuresConstraints);
386 constraintList_free(e->trueEnsuresConstraints);
387 constraintList_free(e->falseEnsuresConstraints);
389 e->requiresConstraints = NULL;
390 e->ensuresConstraints = NULL;
391 e->trueEnsuresConstraints = NULL;
392 e->falseEnsuresConstraints = NULL;
402 exprNode_makeError ()
404 return exprNode_undefined;
407 static /*@out@*/ /*@only@*/ /*@notnull@*/ exprNode
410 exprNode ret = (exprNode) dmalloc (sizeof (*ret));
411 /* static int lastexpnodes = 0; */
416 if (nowalloc > maxalloc)
424 static /*@notnull@*/ /*@special@*/ exprNode
425 exprNode_createPlain (ctype c)
427 /*@ensures isnull result->edata, result->loc, result->val, result->guards,
428 result->uses, result->sets, result->msets, result->etext @*/
431 exprNode e = exprNode_new ();
435 e->val = multiVal_undefined;
437 e->etext = cstring_undefined;
438 e->loc = fileloc_undefined;
439 e->guards = guardSet_undefined;
440 e->uses = sRefSet_undefined;
441 e->sets = sRefSet_undefined;
442 e->msets = sRefSet_undefined;
443 e->edata = exprData_undefined;
444 e->exitCode = XK_NEVERESCAPE;
446 e->mustBreak = FALSE;
447 e->isJumpPoint = FALSE;
449 exprNode_defineConstraints(e);
454 /*@observer@*/ exprNode exprNode_makeMustExit (void)
456 if (exprNode_isUndefined (mustExitNode))
458 mustExitNode = exprNode_createPlain (ctype_unknown);
459 mustExitNode->exitCode = XK_MUSTEXIT;
466 static /*@notnull@*/ /*@special@*/ exprNode exprNode_create (ctype c)
468 /*@post:isnull result->edata, result->guards, result->val,
469 result->uses, result->sets, result->msets@*/
472 exprNode e = exprNode_createPlain (c);
473 e->loc = fileloc_copy (g_currentloc);
477 static /*@notnull@*/ /*@special@*/ exprNode exprNode_createUnknown (void)
479 /*@post:isnull result->edata, result->guards,
480 result->uses, result->sets, result->msets@*/
483 return (exprNode_create (ctype_unknown));
486 static /*@notnull@*/ /*@special@*/ exprNode
487 exprNode_createLoc (ctype c, /*@keep@*/ fileloc loc)
489 /*@post:isnull result->edata, result->guards, result->val,
490 result->uses, result->sets, result->msets@*/
493 exprNode e = exprNode_createPlain (c);
499 exprNode_copySets (/*@special@*/ /*@notnull@*/ exprNode ret, exprNode e)
500 /*@defines ret->guards, ret->uses, ret->sets, ret->msets@*/
502 if (exprNode_isDefined (e))
504 ret->guards = guardSet_copy (e->guards);
505 ret->uses = sRefSet_newCopy (e->uses);
506 ret->sets = sRefSet_newCopy (e->sets);
507 ret->msets = sRefSet_newCopy (e->msets);
511 ret->guards = guardSet_undefined;
512 ret->uses = sRefSet_undefined;
513 ret->sets = sRefSet_undefined;
514 ret->msets = sRefSet_undefined;
518 static /*@notnull@*/ /*@special@*/ exprNode
519 exprNode_createPartialLocCopy (exprNode e, /*@only@*/ fileloc loc)
521 /*@post:isnull result->edata, result->etext@*/
524 exprNode ret = exprNode_new ();
526 if (exprNode_isError (e))
528 ret->typ = ctype_unknown;
529 ret->val = multiVal_undefined;
531 ret->guards = guardSet_undefined;
532 ret->uses = sRefSet_undefined;
533 ret->sets = sRefSet_undefined;
534 ret->msets = sRefSet_undefined;
539 ret->val = multiVal_copy (e->val);
541 ret->guards = guardSet_copy (e->guards);
542 ret->uses = sRefSet_newCopy (e->uses);
543 ret->sets = sRefSet_newCopy (e->sets);
544 ret->msets = sRefSet_newCopy (e->msets);
547 ret->kind = XPR_EMPTY;
549 ret->etext = cstring_undefined;
550 ret->exitCode = XK_NEVERESCAPE;
551 ret->canBreak = FALSE;
552 ret->mustBreak = FALSE;
553 ret->isJumpPoint = FALSE;
554 ret->edata = exprData_undefined;
556 exprNode_defineConstraints(ret);
562 static /*@notnull@*/ /*@special@*/ exprNode
563 exprNode_createPartialCopy (exprNode e)
565 /*@post:isnull result->edata, result->etext@*/
568 return (exprNode_createPartialLocCopy (e, fileloc_copy (exprNode_loc (e))));
571 static /*@notnull@*/ /*@special@*/ exprNode
572 exprNode_createPartialNVCopy (exprNode e)
574 /*@post:isnull result->edata, result->etext, result->val @*/
577 exprNode ret = exprNode_new ();
579 if (exprNode_isError (e))
581 ret->typ = ctype_unknown;
582 ret->loc = fileloc_undefined;
583 ret->guards = guardSet_undefined;
584 ret->uses = sRefSet_undefined;
585 ret->sets = sRefSet_undefined;
586 ret->msets = sRefSet_undefined;
591 ret->loc = fileloc_copy (e->loc);
592 ret->guards = guardSet_copy (e->guards);
593 ret->uses = sRefSet_newCopy (e->uses);
594 ret->sets = sRefSet_newCopy (e->sets);
595 ret->msets = sRefSet_newCopy (e->msets);
598 ret->val = multiVal_undefined;
599 ret->kind = XPR_EMPTY;
601 ret->etext = cstring_undefined;
602 ret->exitCode = XK_NEVERESCAPE;
603 ret->canBreak = FALSE;
604 ret->mustBreak = FALSE;
605 ret->isJumpPoint = FALSE;
606 ret->edata = exprData_undefined;
608 exprNode_defineConstraints(ret);
613 static /*@notnull@*/ /*@special@*/ exprNode
614 exprNode_createSemiCopy (exprNode e)
616 /*@post:isnull result->edata, result->etext, result->sets,
617 result->msets, result->uses, result->guards@*/
620 if (exprNode_isError (e))
622 return exprNode_createPlain (ctype_unknown);
626 exprNode ret = exprNode_new ();
629 ret->val = multiVal_copy (e->val);
630 ret->loc = fileloc_copy (e->loc);
631 ret->guards = guardSet_undefined;
632 ret->uses = sRefSet_undefined;
633 ret->sets = sRefSet_undefined;
634 ret->msets = sRefSet_undefined;
636 ret->kind = XPR_EMPTY;
638 ret->etext = cstring_undefined;
639 ret->exitCode = XK_NEVERESCAPE;
640 ret->canBreak = FALSE;
641 ret->mustBreak = FALSE;
642 ret->isJumpPoint = FALSE;
643 ret->edata = exprData_undefined;
645 exprNode_defineConstraints(ret);
652 exprNode_isNullValue (exprNode e)
654 if (exprNode_isDefined (e))
656 multiVal m = exprNode_getValue (e);
658 if (multiVal_isInt (m))
660 return (multiVal_forceInt (m) == 0);
668 exprNode_isUnknownConstant (/*@notnull@*/ exprNode e)
670 while (e->kind == XPR_PARENS)
672 e = exprData_getUopNode (e->edata);
673 llassert (exprNode_isDefined (e));
676 if (e->kind == XPR_CONST)
678 multiVal m = exprNode_getValue (e);
680 if (multiVal_isUnknown (m))
690 exprNode_numLiteral (ctype c, /*@temp@*/ cstring t,
691 /*@only@*/ fileloc loc, long val)
693 exprNode e = exprNode_createLoc (c, loc);
695 e->kind = XPR_NUMLIT;
697 llassert (multiVal_isUndefined (e->val));
698 e->val = multiVal_makeInt (val);
699 e->edata = exprData_makeLiteral (cstring_copy (t));
703 e->sref = sRef_makeUnknown ();
704 sRef_setDefNull (e->sref, e->loc);
707 DPRINTF (("Num lit: %s / %s", exprNode_unparse (e), ctype_unparse (exprNode_getType (e))));
712 exprNode_charLiteral (char c, cstring text, /*@only@*/ fileloc loc)
714 exprNode e = exprNode_createLoc (ctype_char, loc);
716 if (context_getFlag (FLG_CHARINTLITERAL))
718 e->typ = ctype_makeConj (ctype_char, ctype_int);
721 e->kind = XPR_NUMLIT;
722 e->val = multiVal_makeChar (c);
724 e->edata = exprData_makeLiteral (cstring_copy (text));
729 exprNode_floatLiteral (double d, ctype ct, cstring text, /*@only@*/ fileloc loc)
731 exprNode e = exprNode_createLoc (ct, loc);
733 e->kind = XPR_NUMLIT;
734 e->val = multiVal_makeDouble (d);
735 e->edata = exprData_makeLiteral (cstring_copy (text));
739 multiVal exprNode_getValue (exprNode e)
741 while (exprNode_isInParens (e)) {
742 if (e->edata != NULL) {
743 e = exprData_getUopNode (e->edata);
749 if (exprNode_isDefined (e)) {
752 return multiVal_undefined;
757 exprNode_combineLiterals (exprNode e, exprNode rest)
761 /* Both must be string literals. */
763 if (exprNode_isUndefined (rest) || exprNode_isUndefined (e))
765 exprNode_free (rest);
769 if (!exprNode_isStringLiteral (e))
773 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e),
774 exprNode_unparse (rest)),
776 exprNode_free (rest);
780 if (!exprNode_isStringLiteral (rest))
784 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e), exprNode_unparse (rest)),
787 exprNode_free (rest);
791 ns = cstring_concat (multiVal_forceString (exprNode_getValue (e)),
792 multiVal_forceString (exprNode_getValue (rest)));
794 multiVal_free (e->val);
795 exprData_free (e->edata, e->kind);
796 e->edata = exprData_makeLiteral (cstring_copy (ns));
797 e->val = multiVal_makeString (ns);
798 exprNode_free (rest);
803 exprNode_rawStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
805 exprNode e = exprNode_createLoc (ctype_string, loc);
806 int len = cstring_length (t);
808 if (context_getFlag (FLG_STRINGLITERALLEN))
810 if (len > context_getValue (FLG_STRINGLITERALLEN))
812 voptgenerror (FLG_STRINGLITERALLEN,
814 ("String literal length (%d) exceeds maximum "
815 "length (%d): \"%s\"",
817 context_getValue (FLG_STRINGLITERALLEN),
823 e->kind = XPR_STRINGLITERAL;
824 e->val = multiVal_makeString (cstring_copy (t));
825 e->edata = exprData_makeLiteral (t);
826 e->sref = sRef_makeType (ctype_string);
828 if (context_getFlag (FLG_READONLYSTRINGS))
830 sRef_setAliasKind (e->sref, AK_STATIC, fileloc_undefined);
831 sRef_setExKind (e->sref, XO_OBSERVER, loc);
835 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
838 return (e); /* s released */
842 exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
844 int len = cstring_length (t) - 2;
845 char *ts = cstring_toCharsSafe (t);
846 char *s = cstring_toCharsSafe (cstring_create (len + 1));
848 llassert (*ts == '\"' && *(ts + len + 1) == '\"');
849 strncpy (s, ts+1, size_fromInt (len));
852 return exprNode_rawStringLiteral (cstring_fromCharsO (s), loc);
855 exprNode exprNode_fromUIO (cstring c)
857 fileloc loc = context_getSaveLocation ();
858 exprNode e = exprNode_createPlain (ctype_unknown);
862 if (fileloc_isUndefined (loc))
864 loc = fileloc_copy (g_currentloc);
867 e->loc = loc; /* save loc was mangled */
870 if (usymtab_exists (c))
872 uentry ue = usymtab_lookupEither (c);
874 if (uentry_isDatatype (ue)
875 && uentry_isSpecified (ue))
878 (message ("%q: Specified datatype %s used in code, but not defined. "
879 "(Cannot continue reasonably from this error.)",
880 fileloc_unparse (e->loc), c));
888 llassertprint (!usymtab_exists (c), ("Entry exists: %s", c));
891 ** was supercedeGlobalEntry...is this better?
894 if (!context_inIterEnd ())
896 if (context_inMacro ())
898 if (context_getFlag (FLG_UNRECOG))
902 message ("Unrecognized identifier in macro definition: %s", c), e->loc);
906 flagcode_recordSuppressed (FLG_UNRECOG);
912 (FLG_UNRECOG, message ("Unrecognized identifier: %s", c), e->loc);
916 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
918 /* No alias errors for unrecognized identifiers */
919 sRef_setAliasKind (e->sref, AK_ERROR, loc);
924 exprNode exprNode_createId (/*@observer@*/ uentry c)
926 if (uentry_isValid (c))
928 exprNode e = exprNode_new ();
930 e->typ = uentry_getType (c);
932 if (uentry_isFunction (c)
933 && !sRef_isLocalVar (uentry_getSref (c)))
935 e->sref = sRef_undefined;
939 e->sref = uentry_getSref (c);
942 if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
944 sRef_setDefined (e->sref, fileloc_undefined);
948 ** yoikes! leaving this out was a heinous bug...that would have been
949 ** caught if i had lclint working first. gag!
952 e->etext = cstring_undefined;
954 if (uentry_isEitherConstant (c))
957 e->val = multiVal_copy (uentry_getConstantValue (c));
962 e->val = multiVal_unknown ();
965 e->edata = exprData_makeId (c);
966 e->loc = context_getSaveLocation ();
968 if (fileloc_isUndefined (e->loc))
970 fileloc_free (e->loc);
971 e->loc = fileloc_copy (g_currentloc);
974 e->guards = guardSet_new ();
975 e->sets = sRefSet_new ();
976 e->msets = sRefSet_new ();
977 e->uses = sRefSet_new ();
979 /*> missing fields, detected by lclint <*/
980 e->exitCode = XK_NEVERESCAPE;
981 e->isJumpPoint = FALSE;
983 e->mustBreak = FALSE;
985 exprNode_defineConstraints(e);
991 return exprNode_createUnknown ();
995 /*@notnull@*/ exprNode
996 exprNode_fromIdentifier (/*@observer@*/ uentry c)
1000 if (context_justPopped ()) /* watch out! c could be dead */
1002 uentry ce = usymtab_lookupSafe (LastIdentifier ());
1004 if (uentry_isValid (ce))
1010 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
1014 ret = exprNode_fromIdentifierAux (c);
1020 static /*@only@*/ /*@notnull@*/ exprNode
1021 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
1023 exprNode e = exprNode_createId (c);
1026 uentry_setUsed (c, e->loc);
1028 if (uentry_isVar (c) && sRef_isFileOrGlobalScope (sr))
1030 checkGlobUse (c, FALSE, e);
1037 exprNode_isZero (exprNode e)
1039 if (exprNode_isDefined (e))
1041 multiVal m = exprNode_getValue (e);
1043 if (multiVal_isInt (m))
1045 return (multiVal_forceInt (m) == 0);
1053 exprNode_isNonNegative (exprNode e)
1055 if (exprNode_isDefined (e))
1057 multiVal m = exprNode_getValue (e);
1059 if (multiVal_isInt (m))
1061 return (multiVal_forceInt (m) >= 0);
1069 ** a[x] - uses a but NOT a[]
1070 ** result sref = a[] (set/use in assignment)
1072 ** The syntax x[a] is also legal in C, and has the same
1073 ** semantics. If ind is an array, and arr is an int, flip
1078 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
1081 ** error in arr, error propagates (no new messages)
1082 ** error in ind, assume valid and continue
1085 if (exprNode_isError (e1))
1088 return (exprNode_makeError ());
1094 ctype carr = exprNode_getType (e1);
1095 ctype crarr = ctype_realType (carr);
1098 ** this sets up funny aliasing, that leads to spurious
1099 ** lclint errors. Hence, the i2 comments.
1102 if (!ctype_isRealArray (crarr)
1103 && ctype_isRealNumeric (crarr)
1104 && !exprNode_isError (e2)
1105 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1110 carr = exprNode_getType (arr);
1111 crarr = ctype_realType (carr);
1119 if (sRef_possiblyNull (arr->sref))
1121 if (!usymtab_isGuarded (arr->sref))
1123 if (optgenerror (FLG_NULLDEREF,
1124 message ("Index of %s pointer %q: %s",
1125 sRef_nullMessage (arr->sref),
1126 sRef_unparse (arr->sref),
1127 exprNode_unparse (arr)),
1130 sRef_showNullInfo (arr->sref);
1132 /* suppress future messages */
1133 sRef_setNullError (arr->sref);
1138 if (exprNode_isError (ind))
1140 if ((ctype_isArrayPtr (crarr)
1141 && !ctype_isFunction (crarr))
1142 || ctype_isUnknown (carr))
1144 exprNode ret = exprNode_createPartialCopy (arr);
1146 if (ctype_isKnown (carr))
1148 ret->typ = ctype_baseArrayPtr (crarr);
1152 ret->typ = ctype_unknown;
1155 ret->sref = sRef_makeArrayFetch (arr->sref);
1157 ret->kind = XPR_FETCH;
1160 ** Because of funny aliasing (when arr and ind are
1161 ** flipped) spurious errors would be reported here.
1164 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1165 checkSafeUse (ret, arr->sref);
1170 voptgenerror (FLG_TYPE,
1171 message ("Array fetch from non-array (%t): %s[%s]", carr,
1172 exprNode_unparse (e1), exprNode_unparse (e2)),
1174 exprNode_free (arr);
1175 return (exprNode_makeError ());
1180 if (!ctype_isForceRealInt (&(ind->typ)))
1182 ctype rt = ctype_realType (ind->typ);
1184 if (ctype_isChar (rt))
1188 message ("Array fetch using non-integer, %t: %s[%s]",
1190 exprNode_unparse (e1), exprNode_unparse (e2)),
1193 else if (ctype_isEnum (rt))
1197 message ("Array fetch using non-integer, %t: %s[%s]",
1199 exprNode_unparse (e1), exprNode_unparse (e2)),
1206 message ("Array fetch using non-integer, %t: %s[%s]",
1208 exprNode_unparse (e1), exprNode_unparse (e2)),
1212 multiVal_free (ind->val);
1213 ind->val = multiVal_unknown ();
1216 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1218 exprNode ret = exprNode_createSemiCopy (arr);
1219 multiVal m = exprNode_getValue (ind);
1221 ret->typ = ctype_baseArrayPtr (crarr);
1222 ret->kind = XPR_FETCH;
1224 if (multiVal_isInt (m))
1226 int i = (int) multiVal_forceInt (m);
1228 if (sRef_isValid (arr->sref)) {
1229 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1231 ret->sref = sRef_undefined;
1236 ret->sref = sRef_makeArrayFetch (arr->sref);
1239 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1240 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1241 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1243 /* (see comment on spurious errors above) */
1244 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1246 exprNode_checkUse (ret, ind->sref, ind->loc);
1247 exprNode_checkUse (ret, arr->sref, arr->loc);
1253 if (ctype_isUnknown (carr))
1255 exprNode ret = exprNode_createPartialCopy (arr);
1257 ret->kind = XPR_FETCH;
1258 ret->typ = ctype_unknown;
1259 ret->sets = sRefSet_union (ret->sets, ind->sets);
1260 ret->msets = sRefSet_union (ret->msets, ind->msets);
1261 ret->uses = sRefSet_union (ret->uses, ind->uses);
1263 /* (see comment on spurious errors above) */
1264 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1266 exprNode_checkUse (ret, ind->sref, ind->loc);
1267 exprNode_checkUse (ret, arr->sref, arr->loc);
1274 message ("Array fetch from non-array (%t): %s[%s]", carr,
1275 exprNode_unparse (e1), exprNode_unparse (e2)),
1278 exprNode_free (arr);
1279 exprNode_free (ind);
1281 return (exprNode_makeError ());
1291 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1292 exprNodeList args, exprNode ret)
1294 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1298 ** checkPrintfArgs --- checks arguments for printf-like functions
1299 ** Arguments before ... have already been checked.
1300 ** The argument before the ... is a char *.
1301 ** argno is the format string argument.
1305 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1306 exprNodeList args, exprNode ret, int argno)
1309 ** the last argument before the elips is the format string
1314 int nargs = exprNodeList_size (args);
1315 uentryList params = uentry_getParams (fcn);
1319 ** These should be ensured by checkSpecialFunction
1322 llassert (uentryList_size (params) == argno + 1);
1323 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1325 a = exprNodeList_getN (args, argno - 1);
1326 formatloc = fileloc_copy (exprNode_loc (a));
1328 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1329 && exprNode_knownStringValue (a))
1331 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1332 char *code = format;
1335 nargs = exprNodeList_size (args);
1337 while ((code = strchr (code, '%')) != NULL)
1339 char *origcode = code;
1340 cstring codetext = cstring_newEmpty ();
1341 char key = *(++code);
1342 ctype modtype = ctype_int;
1343 bool modified = FALSE;
1345 fileloc_addColumn (formatloc, code - ocode);
1347 codetext = cstring_appendChar (codetext, key);
1350 while (isFlagKey (key))
1353 codetext = cstring_appendChar (codetext, key);
1354 fileloc_incColumn (formatloc);
1357 if (key == 'm') /* skipped in syslog */
1362 /* ignore field width */
1363 while (isdigit ((int) key) != 0)
1366 codetext = cstring_appendChar (codetext, key);
1367 fileloc_incColumn (formatloc);
1370 /* ignore precision */
1374 codetext = cstring_appendChar (codetext, key);
1375 fileloc_incColumn (formatloc);
1378 ** In printf, '*' means: read the next arg as an int for the
1379 ** field width. This seems to be missing from my copy of the
1380 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1381 ** later) but never does.
1386 ; /* don't do anything --- handle later */
1390 while (isdigit ((int) key) != 0)
1393 codetext = cstring_appendChar (codetext, key);
1394 fileloc_incColumn (formatloc);
1401 modtype = ctype_sint; /* short */
1403 codetext = cstring_appendChar (codetext, key);
1404 fileloc_incColumn (formatloc);
1406 else if (key == 'l' || key == 'L')
1408 modtype = ctype_lint; /* long */
1410 codetext = cstring_appendChar (codetext, key);
1411 fileloc_incColumn (formatloc);
1413 if (key == 'l' || key == 'L') {
1414 modtype = ctype_llint; /* long long */
1416 codetext = cstring_appendChar (codetext, key);
1417 fileloc_incColumn (formatloc);
1425 /* now, key = type of conversion to apply */
1427 fileloc_incColumn (formatloc);
1435 message ("No argument corresponding to %q format "
1436 "code %d (%%%s): \"%s\"",
1437 uentry_getName (fcn),
1439 cstring_fromChars (format)),
1442 if (fileloc_isDefined (formatloc)
1443 && context_getFlag (FLG_SHOWCOL))
1445 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1453 a = exprNodeList_getN (args, i);
1456 if (!exprNode_isError (a))
1462 case '*': /* int argument for fieldwidth */
1463 expecttype = ctype_int;
1464 *(--code) = '%'; /* convert it for next code */
1465 fileloc_subColumn (formatloc, 1);
1466 /*@switchbreak@*/ break;
1469 expecttype = ctype_combine (ctype_uint, modtype);
1470 /*@switchbreak@*/ break;
1472 case 'i': /* int argument */
1474 expecttype = ctype_combine (ctype_int, modtype);
1475 /*@switchbreak@*/ break;
1477 case 'x': /* unsigned int */
1479 expecttype = ctype_combine (ctype_uint, modtype);
1481 /*@switchbreak@*/ break;
1487 case 'f': /* double */
1488 expecttype = ctype_combine (ctype_double, modtype);
1489 /*@switchbreak@*/ break;
1491 case 'c': /* int converted to char (check its a char?) */
1492 expecttype = ctype_makeConj (ctype_char, ctype_uchar);
1493 /*@switchbreak@*/ break;
1495 case 's': /* string */
1496 expecttype = ctype_string;
1497 /*@switchbreak@*/ break;
1500 while (((key = *(++code)) != ']')
1503 codetext = cstring_appendChar (codetext, key);
1504 fileloc_incColumn (formatloc);
1510 (message ("Bad character set format: %s",
1511 cstring_fromChars (origcode)));
1514 expecttype = ctype_string;
1515 /*@switchbreak@*/ break;
1517 case 'p': /* pointer */
1518 expecttype = ctype_makePointer (ctype_void);
1519 uentry_setDefState (regArg, SS_RELDEF); /* need not be defined */
1520 sRef_setPosNull (uentry_getSref (regArg), fileloc_undefined); /* could be null */
1521 /*@switchbreak@*/ break;
1523 case 'n': /* pointer to int, modified by call! */
1524 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1526 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1527 /*@switchbreak@*/ break;
1529 case 'm': /* in a syslog, it doesn't consume an argument */
1530 /* should check we're really doing syslog */
1532 /*@switchbreak@*/ break;
1536 expecttype = ctype_unknown;
1540 message ("Unrecognized format code: %s",
1541 cstring_fromChars (origcode)),
1542 fileloc_isDefined (formatloc)
1543 ? formatloc : g_currentloc);
1545 /*@switchbreak@*/ break;
1548 if (!(exprNode_matchArgType (expecttype, a)))
1550 if (ctype_isVoidPointer (expecttype)
1551 && ctype_isRealAbstract (a->typ)
1552 && (context_getFlag (FLG_ABSTVOIDP)))
1558 if (llgenformattypeerror
1559 (expecttype, exprNode_undefined,
1561 message ("Format argument %d to %q (%%%s) expects "
1564 uentry_getName (fcn),
1567 a->typ, exprNode_unparse (a)),
1570 if (fileloc_isDefined (formatloc)
1571 && context_getFlag (FLG_SHOWCOL))
1574 (cstring_makeLiteral
1575 ("Corresponding format code"),
1582 uentry_setType (regArg, expecttype);
1583 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1585 if (ctype_equal (expecttype, ctype_string))
1587 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1590 uentry_setType (regArg, ctype_unknown);
1591 uentry_fixupSref (regArg);
1595 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1606 cstring_free (codetext);
1611 voptgenerror (FLG_TYPE,
1612 message ("Format string for %q has %d arg%&, given %d",
1613 uentry_getName (fcn), i - argno, nargs - argno),
1619 /* no checking possible for compile-time unknown format strings */
1620 if (exprNode_isDefined (a))
1624 message ("Format string parameter to %s is not a compile-time constant: %s",
1625 exprNode_unparse (f),
1626 exprNode_unparse (a)),
1631 fileloc_free (formatloc);
1635 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1636 exprNodeList args, exprNode ret, int argno)
1640 int nargs = exprNodeList_size (args);
1641 uentryList params = uentry_getParams (fcn);
1645 ** These should be ensured by checkSpecialFunction
1648 llassert (uentryList_size (params) == argno + 1);
1649 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1651 a = exprNodeList_getN (args, argno - 1);
1652 formatloc = fileloc_copy (exprNode_loc (a));
1654 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1655 && exprNode_knownStringValue (a))
1657 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1658 char *code = format;
1661 nargs = exprNodeList_size (args);
1663 while ((code = strchr (code, '%')) != NULL)
1665 char *origcode = code;
1666 char key = *(++code);
1667 cstring codetext = cstring_newEmpty ();
1668 ctype modtype = ctype_int;
1669 char modifier = '\0';
1670 bool modified = TRUE;
1671 bool ignore = FALSE;
1673 codetext = cstring_appendChar (codetext, key);
1674 fileloc_addColumn (formatloc, code - ocode);
1677 ** this is based on ANSI standard library description of fscanf
1678 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1681 /* '*' suppresses assignment (does not need match argument) */
1686 codetext = cstring_appendChar (codetext, key);
1689 fileloc_incColumn (formatloc);
1692 /* ignore field width */
1693 while (isdigit ((int) key) != 0)
1696 codetext = cstring_appendChar (codetext, key);
1697 fileloc_incColumn (formatloc);
1702 modtype = ctype_sint; /* short */
1704 codetext = cstring_appendChar (codetext, key);
1705 fileloc_incColumn (formatloc);
1707 else if (key == 'l' || key == 'L')
1709 modtype = ctype_lint; /* long */
1713 codetext = cstring_appendChar (codetext, key);
1715 fileloc_incColumn (formatloc);
1717 if (key == 'l' || key == 'L') {
1718 modtype = ctype_llint; /* long long */
1720 codetext = cstring_appendChar (codetext, key);
1721 fileloc_incColumn (formatloc);
1729 /* now, key = type of conversion to apply */
1731 fileloc_incColumn (formatloc);
1745 message ("No argument corresponding to %q format "
1746 "code %d (%%%s): \"%s\"",
1747 uentry_getName (fcn),
1749 cstring_fromChars (format)),
1752 if (fileloc_isDefined (formatloc)
1753 && context_getFlag (FLG_SHOWCOL))
1756 (cstring_makeLiteral ("Corresponding format code"),
1764 a = exprNodeList_getN (args, i);
1767 if (!exprNode_isError (a))
1773 case '*': /* int argument for fieldwidth */
1774 expecttype = ctype_makePointer (ctype_int);
1775 *(--code) = '%'; /* convert it for next code */
1776 fileloc_subColumn (formatloc, 1);
1777 /*@switchbreak@*/ break;
1780 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1781 /*@switchbreak@*/ break;
1786 case 'X': /* unsigned int */
1787 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1788 /*@switchbreak@*/ break;
1795 /* printf is double, scanf is float! */
1797 if (modifier == 'l')
1799 expecttype = ctype_makePointer (ctype_double);
1801 else if (modifier == 'L')
1803 expecttype = ctype_makePointer (ctype_ldouble);
1807 llassert (modifier == '\0');
1808 expecttype = ctype_makePointer (ctype_float);
1810 /*@switchbreak@*/ break;
1812 case 'c': /* int converted to char (check its a char?) */
1813 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1814 /*@switchbreak@*/ break;
1816 case 's': /* string */
1817 expecttype = ctype_string;
1818 /*@switchbreak@*/ break;
1822 while (((key = *(++code)) != ']')
1825 codetext = cstring_appendChar (codetext, key);
1826 fileloc_incColumn (formatloc);
1832 (message ("Bad character set format: %s",
1833 cstring_fromChars (origcode)));
1836 expecttype = ctype_string;
1837 /*@switchbreak@*/ break;
1840 case 'p': /* pointer */
1843 message ("Format code should not be used in scanf: %s",
1844 cstring_fromChars (origcode)),
1845 fileloc_isDefined (formatloc)
1846 ? formatloc : g_currentloc);
1848 expecttype = ctype_unknown;
1849 /*@switchbreak@*/ break;
1851 case 'n': /* pointer to int, modified by call! */
1852 expecttype = ctype_makePointer (ctype_int);
1853 /*@switchbreak@*/ break;
1856 expecttype = ctype_unknown;
1860 message ("Unrecognized format code: %s",
1861 cstring_fromChars (origcode)),
1862 fileloc_isDefined (formatloc)
1863 ? formatloc : g_currentloc);
1865 /*@switchbreak@*/ break;
1868 if (!(exprNode_matchArgType (expecttype, a)))
1870 if (ctype_isVoidPointer (expecttype)
1871 && ctype_isRealAbstract (a->typ)
1872 && (context_getFlag (FLG_ABSTVOIDP)))
1878 if (llgenformattypeerror
1879 (expecttype, exprNode_undefined,
1881 message ("Format argument %d to %q (%%%s) expects "
1884 uentry_getName (fcn),
1885 codetext, expecttype,
1886 a->typ, exprNode_unparse (a)),
1889 if (fileloc_isDefined (formatloc)
1890 && context_getFlag (FLG_SHOWCOL))
1893 (cstring_makeLiteral
1894 ("Corresponding format code"),
1901 uentry_setType (outArg, expecttype);
1902 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
1903 uentry_setType (outArg, ctype_unknown);
1904 uentry_fixupSref (outArg);
1908 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1913 /* a->sref = defref; */
1920 cstring_free (codetext);
1925 voptgenerror (FLG_TYPE,
1926 message ("Format string for %q has %d arg%&, given %d",
1927 uentry_getName (fcn), i - argno, nargs - argno),
1933 /* no checking possible for compile-time unknown format strings */
1936 fileloc_free (formatloc);
1940 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
1943 /*@unused@*/ int argno)
1946 ** the last argument before the elips is the format string
1949 int nargs = exprNodeList_size (args);
1954 a = exprNodeList_getN (args, argno - 1);
1955 formatloc = fileloc_copy (exprNode_loc (a));
1957 if (ctype_isUnknown (cstringType)) {
1958 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
1960 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
1964 if (ctype_isUnknown (ctypeType)) {
1965 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
1967 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
1971 if (ctype_isUnknown (filelocType)) {
1972 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
1974 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
1978 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1979 && exprNode_knownStringValue (a))
1981 cstring format = multiVal_forceString (exprNode_getValue (a));
1982 char *code = cstring_toCharsSafe (format);
1985 nargs = exprNodeList_size (args);
1987 while ((code = strchr (code, '%')) != NULL)
1989 char *origcode = code;
1990 char key = *(++code);
1991 cstring codetext = cstring_newEmpty ();
1992 bool isOnly = FALSE;
1994 codetext = cstring_appendChar (codetext, key);
1996 fileloc_addColumn (formatloc, code - ocode);
1998 while (key >= '0' && key <= '9')
2001 codetext = cstring_appendChar (codetext, key);
2002 fileloc_incColumn (formatloc);
2006 fileloc_incColumn (formatloc);
2010 if (key == '&') /* plural marker */
2019 message ("Message missing format arg %d (%%%s): \"%s\"",
2020 i + 1, codetext, format),
2026 a = exprNodeList_getN (args, i);
2030 if (!exprNode_isError (a))
2034 /*@-loopswitchbreak@*/
2040 expecttype = ctype_char; break;
2042 expecttype = cstringType; break;
2044 expecttype = cstringType; isOnly = TRUE; break;
2046 expecttype = cstringType; isOnly = TRUE; break;
2047 case 'd': expecttype = ctype_int; break;
2048 case 'u': expecttype = ctype_uint; break;
2049 case 'w': expecttype = ctype_ulint; break;
2050 case 'f': expecttype = ctype_float; break;
2051 case 'b': expecttype = ctype_bool; break;
2052 case 't': expecttype = ctypeType; break;
2053 case 'l': expecttype = filelocType; break;
2054 case '&': /* a wee bit of a hack methinks */
2055 expecttype = ctype_int;
2057 case 'r': expecttype = ctype_bool; break;
2059 expecttype = ctype_unknown;
2062 message ("Unrecognized format code: %s",
2063 cstring_fromChars (origcode)),
2064 fileloc_isDefined (formatloc)
2065 ? formatloc : g_currentloc);
2068 /*@=loopswitchbreak@*/
2070 if (!(exprNode_matchArgType (expecttype, a)))
2072 if (ctype_isVoidPointer (expecttype)
2073 && ctype_isRealAbstract (a->typ)
2074 && (context_getFlag (FLG_ABSTVOIDP)))
2080 if (llgenformattypeerror
2081 (expecttype, exprNode_undefined,
2083 message ("Format argument %d to %q (%%%s) expects "
2086 uentry_getName (fcn),
2087 codetext, expecttype,
2088 a->typ, exprNode_unparse (a)),
2091 if (fileloc_isDefined (formatloc)
2092 && context_getFlag (FLG_SHOWCOL))
2095 (cstring_makeLiteral
2096 ("Corresponding format code"),
2103 if (ctype_equal (expecttype, cstringType))
2107 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2108 uentry_fixupSref (csOnlyArg);
2112 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2113 uentry_fixupSref (csArg);
2118 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2119 uentry_fixupSref (regArg);
2125 cstring_free (codetext);
2130 voptgenerror (FLG_TYPE,
2131 message ("Format string for %q has %d arg%&, given %d",
2132 uentry_getName (fcn), i - argno, nargs -argno),
2138 /* no checking possible for compile-time unknown format strings */
2141 fileloc_free (formatloc);
2145 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2146 /*@notnull@*/ exprNode e2,
2152 bool hadUncon = FALSE;
2154 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
2155 sRefSet_hasUnconstrained (sets2))
2158 (FLG_EVALORDERUNCON,
2160 ("Expression may have undefined behavior (%q used in right operand "
2161 "may set global variable %q used in left operand): %s %s %s",
2162 sRefSet_unparseUnconstrained (sets2),
2163 sRef_unparse (sRef_getRootBase (e1->sref)),
2164 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2168 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
2169 sRefSet_hasUnconstrained (sets1))
2172 (FLG_EVALORDERUNCON,
2174 ("Expression has undefined behavior (%q used in left operand "
2175 "may set global variable %q used in right operand): %s %s %s",
2176 sRefSet_unparseUnconstrained (sets1),
2177 sRef_unparse (e2->sref),
2178 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2182 sRefSet_realElements (e1->uses, sr)
2184 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2189 ("Expression has undefined behavior (left operand uses %q, "
2190 "modified by right operand): %s %s %s",
2192 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2195 } end_sRefSet_realElements;
2197 sRefSet_realElements (sets1, sr)
2199 if (sRef_isMeaningful (sr))
2201 if (sRef_same (sr, e2->sref))
2206 ("Expression has undefined behavior (value of right operand "
2207 "modified by left operand): %s %s %s",
2208 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2211 else if (sRefSet_member (e2->uses, sr))
2216 ("Expression has undefined behavior (left operand modifies %q, "
2217 "used by right operand): %s %s %s",
2219 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2224 if (sRefSet_member (sets2, sr))
2226 if (sRef_isUnconstrained (sr))
2234 hadUncon = optgenerror
2235 (FLG_EVALORDERUNCON,
2237 ("Expression may have undefined behavior. Left operand "
2238 "calls %q; right operand calls %q. The unconstrained "
2239 "functions may modify global state used by "
2240 "the other operand): %s %s %s",
2241 sRefSet_unparseUnconstrained (sets1),
2242 sRefSet_unparseUnconstrained (sets2),
2243 exprNode_unparse (e1), lltok_unparse (op),
2244 exprNode_unparse (e2)),
2253 ("Expression has undefined behavior (both "
2254 "operands modify %q): %s %s %s",
2256 exprNode_unparse (e1),
2257 lltok_unparse (op), exprNode_unparse (e2)),
2263 } end_sRefSet_realElements;
2266 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2268 bool hasError = FALSE;
2270 if (exprNode_isError (e1) || exprNode_isError (e2))
2275 if (sRefSet_member (e2->sets, e1->sref))
2277 if (e2->kind == XPR_CALL)
2283 hasError = optgenerror
2285 message ("Expression has undefined behavior "
2286 "(value of left operand is modified "
2287 "by right operand): %s %s %s",
2288 exprNode_unparse (e1), lltok_unparse (op),
2289 exprNode_unparse (e2)),
2294 if (context_getFlag (FLG_EVALORDERUNCON))
2296 if (sRefSet_member (e2->msets, e1->sref))
2298 if (e2->kind == XPR_CALL)
2304 hasError = optgenerror
2307 ("Expression has undefined behavior (value of left "
2308 "operand may be modified by right operand): %s %s %s",
2309 exprNode_unparse (e1), lltok_unparse (op),
2310 exprNode_unparse (e2)),
2318 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2320 if (context_maybeSet (FLG_EVALORDERUNCON))
2322 checkExpressionDefinedAux (e1, e2, e1->msets,
2323 e2->msets, op, FLG_EVALORDERUNCON);
2328 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2331 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2332 exprNodeList args, bool isIter, exprNode ret)
2336 if (!exprNode_isError (f))
2338 if (!uentryList_isMissingParams (cl))
2340 int nargs = exprNodeList_size (args);
2341 int expectargs = uentryList_size (cl);
2345 if (expectargs == 0)
2353 message ("Iter %q invoked with %d args, "
2355 uentry_getName (fcn),
2363 message ("Function %s called with %d args, "
2365 exprNode_unparse (f), nargs),
2372 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2374 exprNodeList_reset (args);
2376 uentryList_elements (cl, current)
2378 ctype ct = uentry_getType (current);
2381 if (ctype_isElips (ct))
2384 ** do special checking for printf/scanf library functions
2386 ** this is kludgey code, just for handling the special case
2390 if (uentry_isPrintfLike (fcn))
2392 checkPrintfArgs (f, fcn, args, ret, i);
2395 else if (uentry_isScanfLike (fcn))
2397 checkScanfArgs (f, fcn, args, ret, i);
2400 else if (uentry_isMessageLike (fcn))
2402 checkMessageArgs (f, fcn, args, i);
2407 llassert (!uentry_isSpecialFunction (fcn));
2410 nargs = expectargs; /* avoid errors */
2415 if (i >= nargs) break;
2417 a = exprNodeList_current (args);
2418 exprNodeList_advance (args);
2422 if (exprNode_isError (a))
2429 probably necessary? I'm not sure about this one
2430 checkMacroParen (a);
2433 f->guards = guardSet_union (f->guards, a->guards);
2435 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2437 if (!(exprNode_matchArgType (ct, a)))
2439 DPRINTF (("Args mismatch!"));
2441 if (ctype_isVoidPointer (ct)
2442 && (ctype_isPointer (a->typ)
2443 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2448 ("Pointer to abstract type (%t) used "
2450 "(arg %d to %q): %s",
2452 uentry_getName (fcn),
2453 exprNode_unparse (a)),
2461 (ct, exprNode_undefined,
2464 ("Iter %q expects arg %d to "
2465 "be %t gets %t: %s",
2466 uentry_getName (fcn),
2467 i, ct, a->typ, exprNode_unparse (a)),
2478 ("Function %q expects arg %d to be %t gets %t: %s",
2479 uentry_getName (fcn),
2480 i, ct, a->typ, exprNode_unparse (a)),
2483 DPRINTF (("Types: %s / %s",
2485 ctype_unparse (a->typ)));
2489 ** Clear null marker for abstract types.
2490 ** (It is not revealed, so suppress future messages.)
2493 if (ctype_isAbstract (a->typ))
2495 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2502 } end_uentryList_elements ;
2505 if (expectargs != nargs) /* note: not != since we may have ... */
2507 if (ctype_isElips (last))
2511 message ("Function %s called with %d args, expects at least %d",
2512 exprNode_unparse (f),
2513 nargs, expectargs - 1),
2522 message ("Iter %q invoked with %d args, expects %d",
2523 uentry_getName (fcn), nargs, expectargs),
2530 message ("Function %s called with %d args, expects %d",
2531 exprNode_unparse (f),
2544 ** Check for undefined code sequences in function arguments:
2546 ** one parameter sets something used by another parameter
2547 ** one parameter sets something set by another parameter
2551 checkSequencingOne (exprNode f, exprNodeList args,
2552 /*@notnull@*/ exprNode el, int argno)
2555 ** Do second loop, iff +undefunspec
2559 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2561 for (checkloop = 0; checkloop < numloops; checkloop++)
2567 thissets = el->sets;
2571 llassert (checkloop == 1);
2572 thissets = el->msets;
2575 sRefSet_realElements (thissets, thisset)
2579 /*@access exprNodeList@*/
2580 for (j = 0; j < args->nelements; j++)
2582 exprNode jl = args->elements[j];
2583 int thisargno = j + 1;
2585 if (thisargno != argno && exprNode_isDefined (jl))
2587 sRefSet otheruses = jl->uses;
2589 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
2590 sRefSet_hasUnconstrained (thissets))
2593 (FLG_EVALORDERUNCON,
2596 ("%q used in argument %d may set "
2597 "global variable %q used by argument %d: %s(%q)",
2598 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2601 sRef_unparse (sRef_getRootBase (jl->sref)),
2603 exprNode_unparse (f), exprNodeList_unparse (args)),
2607 if (sRefSet_member (otheruses, thisset))
2609 if (sRef_isUnconstrained (thisset))
2612 (FLG_EVALORDERUNCON,
2614 ("Unconstrained functions used in arguments %d (%q) "
2615 "and %d (%s) may modify "
2616 "or use global state in undefined way: %s(%q)",
2618 sRefSet_unparseUnconstrainedPlain (otheruses),
2620 sRef_unconstrainedName (thisset),
2621 exprNode_unparse (f),
2622 exprNodeList_unparse (args)),
2630 ("Argument %d modifies %q, used by argument %d "
2631 "(order of evaluation of actual parameters is "
2632 "undefined): %s(%q)",
2633 argno, sRef_unparse (thisset), thisargno,
2634 exprNode_unparse (f), exprNodeList_unparse (args)),
2640 sRefSet othersets = jl->sets;
2642 if (sRefSet_member (othersets, thisset))
2644 if (sRef_isUnconstrained (thisset))
2647 (FLG_EVALORDERUNCON,
2649 ("Unconstrained functions used in "
2650 "arguments %d (%q) and %d (%s) may modify "
2651 "or use global state in undefined way: %s(%q)",
2653 sRefSet_unparseUnconstrainedPlain (othersets),
2655 sRef_unconstrainedName (thisset),
2656 exprNode_unparse (f), exprNodeList_unparse (args)),
2664 ("Argument %d modifies %q, set by argument %d (order of"
2665 " evaluation of actual parameters is undefined): %s(%q)",
2666 argno, sRef_unparse (thisset), thisargno,
2667 exprNode_unparse (f), exprNodeList_unparse (args)),
2674 /*@noaccess exprNodeList@*/
2675 } end_sRefSet_realElements;
2680 checkSequencing (exprNode f, exprNodeList args)
2682 if (exprNodeList_size (args) > 1)
2687 /*@access exprNodeList*/
2689 for (i = 0; i < args->nelements; i++)
2691 el = args->elements[i];
2693 if (!exprNode_isError (el))
2695 checkSequencingOne (f, args, el, i + 1);
2698 /*@noaccess exprNodeList*/
2703 ** requires le = exprNode_getUentry (f)
2707 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2708 uentry le, exprNodeList args,
2709 /*@notnull@*/ exprNode ret, int specialArgs)
2711 bool isSpec = FALSE;
2712 bool hasMods = FALSE;
2714 globSet usesGlobs = globSet_undefined;
2715 sRefSet mods = sRefSet_undefined;
2716 bool freshMods = FALSE;
2717 uentryList params = uentryList_undefined;
2719 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2722 ** check globals and modifies
2727 if (!uentry_isValid (le))
2729 ctype fr = ctype_realType (f->typ);
2731 if (ctype_isFunction (fr))
2733 params = ctype_argsFunction (fr);
2737 params = uentryList_missingParams;
2740 if (!context_getFlag (FLG_MODNOMODS)
2741 && !context_getFlag (FLG_GLOBUNSPEC))
2743 checkUnspecCall (f, params, args);
2749 fname = uentry_rawName (le);
2753 if (uentry_isFunction (le))
2755 params = uentry_getParams (le);
2756 mods = uentry_getMods (le);
2757 hasMods = uentry_hasMods (le);
2758 usesGlobs = uentry_getGlobs (le);
2759 isSpec = uentry_isSpecified (le);
2761 else /* not a function */
2763 ctype ct = ctype_realType (uentry_getType (le));
2765 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2766 ("checkModGlobs: uentry not a function: %s",
2767 uentry_unparse (le)));
2769 params = ctype_argsFunction (ct);
2770 return; /*@32 ! remove this? */
2779 globSet_allElements (usesGlobs, el)
2781 if (sRef_isValid (el))
2783 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2785 context_usedGlobal (el);
2786 exprNode_checkUse (f, el, f->loc);
2788 if (context_checkInternalUse ())
2790 if (!context_globAccess (el))
2792 if (sRef_isSystemState (el)
2793 && !context_getFlag (FLG_MODFILESYSTEM))
2802 ("Called procedure %s may access %q, but "
2803 "globals list does not include globals %s",
2804 exprNode_unparse (f),
2806 cstring_makeLiteralTemp (sRef_isInternalState (el)
2814 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2820 uentry gle = sRef_getUentry (el);
2821 sRef sr = sRef_updateSref (el);
2823 if (sRef_isUndefGlob (el))
2825 sRef_setDefined (sr, f->loc);
2826 exprNode_checkSet (f, sr);
2834 if (sRef_isAllocated (el))
2836 exprNode_checkSet (f, sr);
2840 if (sRef_isStateUndefined (sr))
2845 ("%s %q used by function undefined before call: %s",
2846 sRef_getScopeName (sr),
2848 exprNode_unparse (f)),
2850 sRef_setDefined (sr, f->loc);
2852 exprNode_checkUse (f, sr, f->loc);
2855 checkGlobUse (gle, TRUE, f);
2858 if (sRef_isKilledGlob (el))
2860 sRef_kill (sr, f->loc);
2861 context_usedGlobal (sr);
2865 } end_globSet_allElements;
2871 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
2873 sRefSet smods = sRefSet_undefined;
2876 ** NEED to check for modifies anything
2880 ** check each sRef that called function modifies (ml), is
2886 sRefSet_allElements (mods, s) /* s is something which may be modified */
2888 DPRINTF (("Check modify: %s", sRef_unparse (s)));
2890 if (sRef_isKindSpecial (s))
2892 if (sRef_isSpecInternalState (s))
2894 if (context_getFlag (FLG_MODINTERNALSTRICT))
2896 exprNode_checkCallModifyVal (s, args, f, ret);
2900 sRefSet mmods = context_modList ();
2902 sRefSet_allElements (mmods, el)
2904 if (sRef_isInternalState (el))
2906 sRef_setModified (el);
2908 } end_sRefSet_allElements ;
2913 exprNode_checkCallModifyVal (s, args, f, ret);
2918 sRef rb = sRef_getRootBase (s);
2920 if (sRef_isFileOrGlobalScope (rb))
2922 context_usedGlobal (rb);
2925 if (sRef_isFileStatic (s)
2926 && !fileId_equal (fileloc_fileId (f->loc),
2927 fileloc_fileId (uentry_whereDefined (le))))
2929 smods = sRefSet_insert (smods, s);
2933 exprNode_checkCallModifyVal (s, args, f, ret);
2936 } end_sRefSet_allElements;
2941 ** Static elements in modifies set can have nasty consequences.
2942 ** (I think...have not been able to reproduce a possible bug.)
2945 if (!sRefSet_isDefined (smods))
2947 mods = sRefSet_newCopy (mods);
2950 sRefSet_allElements (smods, el)
2952 bool res = sRefSet_delete (mods, el);
2955 } end_sRefSet_allElements;
2957 sRefSet_free (smods);
2962 else if (sRefSet_isDefined (mods))
2963 { /* just check observers */
2966 sRefSet_allElements (mods, s) /* s is something which may be modified */
2968 sRef rb = sRef_getRootBase (s);
2972 if (sRef_isParam (rb))
2974 sRef b = sRef_fixBaseParam (s, args);
2976 if (sRef_isObserver (b))
2978 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
2982 message ("Function call may modify observer%q: %s",
2983 sRef_unparsePreOpt (b), exprNode_unparse (e)),
2986 sRef_showExpInfo (b);
2990 } end_sRefSet_allElements;
2994 if (!hasMods) /* no specified modifications */
2996 if (context_getFlag (FLG_MODOBSERVERUNCON))
2998 exprNodeList_elements (args, e)
3000 if (exprNode_isDefined (e))
3002 sRef s = exprNode_getSref (e);
3004 if (sRef_isObserver (s)
3005 && ctype_isMutable (sRef_getType (s)))
3008 (FLG_MODOBSERVERUNCON,
3010 ("Call to unconstrained function %s may modify observer%q: %s",
3011 exprNode_unparse (f),
3012 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3015 sRef_showExpInfo (s);
3019 } end_exprNodeList_elements;
3024 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3026 ret->uses = sRefSet_union (ret->uses, f->uses);
3027 ret->sets = sRefSet_union (ret->sets, f->sets);
3028 ret->msets = sRefSet_union (ret->msets, f->msets);
3033 ** Spurious errors reported, because lclint can't tell
3034 ** mods must be fresh if freshMods is true.
3037 /*@i@*/ sRefSet_free (mods);
3043 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3045 if (uentry_isVar (glob))
3047 if (context_inFunctionLike ())
3049 sRef sr = uentry_getSref (glob);
3051 context_usedGlobal (sr);
3053 if (context_checkGlobUse (glob))
3055 if (!context_globAccess (sr))
3061 message ("Called procedure %s may access %s %q",
3062 exprNode_unparse (e),
3063 sRef_unparseScope (sr),
3064 uentry_getName (glob)),
3071 message ("Undocumented use of %s %s",
3072 sRef_unparseScope (sr),
3073 exprNode_unparse (e)),
3082 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3087 reflectEnsuresClause (uentry le, exprNode f, exprNodeList args)
3089 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3090 exprNode_unparse (f), exprNodeList_unparse (args),
3091 uentry_unparseFull (le),
3092 stateClauseList_unparse (uentry_getStateClauseList (le))));
3094 if (uentry_isValid (le) && uentry_isFunction (le))
3096 stateClauseList sclauses = uentry_getStateClauseList (le);
3098 if (stateClauseList_isDefined (sclauses))
3100 DPRINTF (("Reflect ensures: %s / %s / %s",
3101 uentry_unparse (le),
3102 exprNode_unparse (f), exprNodeList_unparse (args)));
3104 stateClauseList_elements (sclauses, cl)
3106 if (stateClause_hasEnsures (cl))
3108 /* Same in usymtab.c:1904 */
3109 if (stateClause_setsMetaState (cl))
3111 qual q = stateClause_getMetaQual (cl);
3112 annotationInfo ainfo = qual_getAnnotationInfo (q);
3113 metaStateInfo minfo = annotationInfo_getState (ainfo);
3114 cstring key = metaStateInfo_getName (minfo);
3115 int mvalue = annotationInfo_getValue (ainfo);
3117 sRefSet osrs = sRefSet_undefined;
3120 if (stateClause_isGlobal (cl))
3122 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3127 srs = stateClause_getRefs (cl);
3130 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3133 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3135 sRefSet_elements (srs, sel)
3139 if (sRef_isResult (sRef_getRootBase (sel)))
3141 ; /*@i423 what do we do about results */
3145 s = sRef_fixBaseParam (sel, args);
3146 DPRINTF (("Reflecting state clause on: %s / %s",
3147 sRef_unparse (sel), sRef_unparse (s)));
3149 sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3151 } end_sRefSet_elements;
3153 sRefSet_free (osrs);
3157 sRefSet srs = stateClause_getRefs (cl);
3158 sRefModVal modf = stateClause_getEnsuresFunction (cl);
3159 int eparam = stateClause_getStateParameter (cl);
3161 DPRINTF (("Reflect after clause: %s / %s",
3162 stateClause_unparse (cl),
3163 sRefSet_unparse (srs)));
3165 sRefSet_elements (srs, sel)
3169 DPRINTF (("elements: %s", sRef_unparse (sel)));
3170 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3172 if (sRef_isResult (sRef_getRootBase (sel)))
3174 ; /*@i423 what do we do about results */
3178 s = sRef_fixBaseParam (sel, args);
3180 DPRINTF (("elements: %s", sRef_unparse (s)));
3181 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3183 DPRINTF (("Reflecting state clause on: %s / %s",
3184 sRef_unparse (sel), sRef_unparse (s)));
3186 modf (s, eparam, exprNode_loc (f));
3188 } end_sRefSet_elements;
3191 } end_stateClauseList_elements ;
3194 DPRINTF (("Here: %s / %s",
3195 uentry_unparseFull (le),
3196 bool_unparse (uentry_hasMetaStateEnsures (le))));
3198 if (uentry_hasMetaStateEnsures (le))
3200 metaStateConstraint msc = uentry_getMetaStateEnsures (le);
3202 TPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3203 metaStateConstraint_unparse (msc)));
3210 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3212 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3213 exprNode_unparse (f), exprNodeList_unparse (args),
3214 uentry_unparseFull (le),
3215 stateClauseList_unparse (uentry_getStateClauseList (le))));
3217 if (uentry_isValid (le) && uentry_isFunction (le))
3219 stateClauseList sclauses = uentry_getStateClauseList (le);
3221 if (stateClauseList_isDefined (sclauses))
3223 DPRINTF (("Check requires: %s / %s / %s",
3224 uentry_unparse (le),
3225 exprNode_unparse (f), exprNodeList_unparse (args)));
3227 stateClauseList_elements (sclauses, cl)
3229 DPRINTF (("Check clause: %s / %s",
3230 stateClause_unparse (cl),
3231 bool_unparse (stateClause_hasRequires (cl))));
3233 if (stateClause_hasRequires (cl))
3235 sRefSet osrs = sRefSet_undefined;
3238 if (stateClause_isGlobal (cl))
3240 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3245 srs = stateClause_getRefs (cl);
3248 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3250 if (stateClause_setsMetaState (cl))
3252 qual q = stateClause_getMetaQual (cl);
3253 annotationInfo ainfo = qual_getAnnotationInfo (q);
3254 metaStateInfo minfo = annotationInfo_getState (ainfo);
3255 cstring key = metaStateInfo_getName (minfo);
3256 int mvalue = annotationInfo_getValue (ainfo);
3258 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3260 sRefSet_elements (srs, sel)
3262 sRef s = sRef_fixBaseParam (sel, args);
3264 if (sRef_isResult (sRef_getRootBase (sel)))
3266 ; /*@i423 what do we do about results */
3270 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3271 sRef_unparseFull (sel), sRef_unparseFull (s),
3274 if (!sRef_checkMetaStateValue (s, key, mvalue))
3276 DPRINTF (("HERE: %s", sRef_unparse (s)));
3280 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3281 uentry_getName (le),
3282 sRef_isGlobalMarker (s)
3284 : message (" by %q", sRef_unparse (s)),
3285 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3287 stateClause_unparse (cl)),
3290 sRef_showAliasInfo (s);
3294 DPRINTF (("Error supressed!"));
3295 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3296 DPRINTF (("Context supress: %s",
3297 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3301 } end_sRefSet_elements;
3305 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3306 int eparam = stateClause_getStateParameter (cl);
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 s = sRef_fixBaseParam (sel, args);
3321 DPRINTF (("elements: %s", sRef_unparse (s)));
3322 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3324 if (sRef_isResult (sRef_getRootBase (sel)))
3326 ; /*@i423 what do we do about results */
3330 DPRINTF (("Reflecting state clause on: %s / %s",
3331 sRef_unparse (sel), sRef_unparse (s)));
3333 modf (s, eparam, exprNode_loc (f));
3335 } end_sRefSet_elements;
3338 sRefSet_free (osrs);
3340 } end_stateClauseList_elements ;
3345 static /*@only@*/ exprNode
3346 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3347 ctype t, /*@keep@*/ exprNodeList args)
3349 /* requires f is a non-error exprNode, with type function */
3350 cstring fname = exprNode_unparse (f);
3351 uentry le = exprNode_getUentry (f);
3352 exprNode ret = exprNode_createPartialCopy (f);
3357 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3359 ret->typ = ctype_getReturnType (t);
3360 ret->kind = XPR_CALL;
3362 ret->edata = exprData_makeCall (f, args);
3365 ** Order of these steps is very important!
3367 ** Must check for argument dependencies before messing up uses and sets.
3370 if (context_getFlag (FLG_EVALORDER))
3372 exprNodeList_elements (args, current)
3374 if (exprNode_isDefined (current))
3376 exprNode_addUse (current, current->sref);
3378 } end_exprNodeList_elements;
3380 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3382 checkSequencing (f, args);
3385 exprNodeList_elements (args, current)
3387 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3389 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3391 } end_exprNodeList_elements ;
3394 special = checkArgs (le, f, t, args, ret);
3395 checkGlobMods (f, le, args, ret, special);
3396 checkRequiresClause (le, f, args);
3399 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3400 reflectEnsuresClause (le, f, args);
3403 if (uentry_isValid (le)
3404 && (uentry_isFunction (le)
3405 || (uentry_isVariable (le)
3406 && ctype_isFunction (uentry_getType (le)))))
3408 exitkind exk = uentry_getExitCode (le);
3410 /* f->typ is already set to the return type */
3412 ret->sref = uentry_returnedRef (le, args);
3413 DPRINTF (("Returned: %s / %s",
3414 uentry_unparseFull (le),
3415 sRef_unparseFull (ret->sref)));
3417 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3419 qual nullPred = uentry_nullPred (le);
3421 if (qual_isTrueNull (nullPred))
3423 exprNode arg = exprNodeList_head (args);
3425 if (exprNode_isDefined (arg))
3427 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3430 else if (qual_isFalseNull (nullPred))
3432 exprNode arg = exprNodeList_head (args);
3434 if (exprNode_isDefined (arg))
3436 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3441 llassert (qual_isUnknown (nullPred));
3445 if (exitkind_isConditionalExit (exk))
3449 ** if (arg0) then { exit! } else { ; }
3451 ** if (arg0) then { ; } else { exit! }
3456 llassert (!exprNodeList_isEmpty (args));
3457 firstArg = exprNodeList_head (args);
3459 if (exprNode_isDefined (firstArg)
3460 && !guardSet_isEmpty (firstArg->guards))
3462 usymtab_trueBranch (guardSet_undefined);
3463 usymtab_altBranch (guardSet_undefined);
3465 if (exitkind_isTrueExit (exk))
3467 usymtab_popBranches (firstArg,
3468 exprNode_makeMustExit (),
3470 TRUE, TRUEEXITCLAUSE);
3474 usymtab_popBranches (firstArg,
3476 exprNode_makeMustExit (),
3477 TRUE, FALSEEXITCLAUSE);
3481 ret->exitCode = XK_MAYEXIT;
3483 else if (exitkind_mustExit (exk))
3485 ret->exitCode = XK_MUSTEXIT;
3487 else if (exitkind_couldExit (exk))
3489 ret->exitCode = XK_MAYEXIT;
3496 if (cstring_equalLit (fname, "exit"))
3498 if (exprNodeList_size (args) == 1)
3500 exprNode arg = exprNodeList_head (args);
3502 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3504 long int val = multiVal_forceInt (exprNode_getValue (arg));
3511 ("Argument to exit has implementation defined behavior: %s",
3512 exprNode_unparse (arg)),
3513 exprNode_loc (arg));
3522 exprNode_checkSetAny (ret, uentry_rawName (le));
3529 ** this is yucky! should keep the uentry as part of exprNode!
3532 /*@observer@*/ uentry
3533 exprNode_getUentry (exprNode e)
3535 if (exprNode_isError (e))
3537 return uentry_undefined;
3541 cstring s = exprNode_rootVarName (e);
3542 uentry ue = usymtab_lookupSafe (s);
3549 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3551 exprNode ret = exprNode_createPlain (ctype_unknown);
3553 ret->kind = XPR_INITBLOCK;
3554 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3555 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3561 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3567 if (exprNode_isUndefined (f))
3570 exprNodeList_free (args);
3571 return exprNode_undefined;
3574 t = exprNode_getType (f);
3576 if (sRef_isLocalVar (f->sref))
3578 exprNode_checkUse (f, f->sref, f->loc);
3580 if (sRef_possiblyNull (f->sref))
3582 if (!usymtab_isGuarded (f->sref))
3584 if (optgenerror (FLG_NULLDEREF,
3585 message ("Function call using %s pointer %q",
3586 sRef_nullMessage (f->sref),
3587 sRef_unparse (f->sref)),
3590 sRef_showNullInfo (f->sref);
3591 sRef_setNullError (f->sref);
3599 if (ctype_isRealFunction (t))
3601 exprNode ret = functionCallSafe (f, t, args);
3605 else if (ctype_isUnknown (t))
3607 exprNode ret = exprNode_createPartialCopy (f);
3613 exprNodeList_elements (args, current)
3615 if (exprNode_isDefined (current))
3617 exprNode_checkUse (ret, current->sref, ret->loc);
3620 ** also, anything derivable from current->sref may be used
3623 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3624 exprNode_mergeUSs (ret, current);
3626 } end_exprNodeList_elements;
3628 ret->edata = exprData_makeCall (f, args);
3629 ret->kind = XPR_CALL;
3631 tstring = cstring_copy (exprNode_unparse (f));
3633 cstring_markOwned (tstring);
3634 exprNode_checkSetAny (ret, tstring);
3640 voptgenerror (FLG_TYPE,
3641 message ("Call to non-function (type %t): %s", t,
3642 exprNode_unparse (f)),
3645 exprNodeList_free (args);
3647 return (exprNode_makeError ());
3652 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
3653 /*@only@*/ cstring f)
3655 exprNode ret = exprNode_createPartialCopy (s);
3657 ret->kind = XPR_FACCESS;
3659 if (exprNode_isError (s))
3661 ret->edata = exprData_makeField (s, f);
3666 ctype t = exprNode_getType (s);
3667 ctype tr = ctype_realType (t);
3669 checkMacroParen (s);
3671 ret->edata = exprData_makeField (s, f);
3673 if (ctype_isStructorUnion (tr))
3675 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
3677 if (uentry_isUndefined (tf))
3679 voptgenerror (FLG_TYPE,
3680 message ("Access non-existent field %s of %t: %s", f, t,
3681 exprNode_unparse (ret)),
3683 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
3688 uentry_setUsed (tf, exprNode_loc (ret));
3690 ret->typ = uentry_getType (tf);
3691 checkSafeUse (ret, s->sref);
3693 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
3694 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
3698 else /* isStructorUnion */
3700 if (ctype_isRealAbstract (tr))
3704 message ("Access field of abstract type (%t): %s.%s",
3705 t, exprNode_unparse (s), f),
3707 ret->typ = ctype_unknown;
3711 if (ctype_isKnown (tr))
3716 ("Access field of non-struct or union (%t): %s.%s",
3717 t, exprNode_unparse (s), f),
3720 ret->typ = ctype_unknown;
3724 cstring sn = cstring_copy (f);
3726 checkSafeUse (ret, s->sref);
3727 cstring_markOwned (sn);
3728 ret->sref = sRef_makeField (s->sref, sn);
3740 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
3741 /*@only@*/ cstring f)
3743 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
3744 lltok_release (dot);
3749 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
3751 exprNode ret = exprNode_createPartialCopy (e);
3753 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
3754 ret->kind = XPR_PARENS;
3755 ret->edata = exprData_makeUop (e, lpar);
3757 if (!exprNode_isError (e))
3759 ret->exitCode = e->exitCode;
3760 ret->canBreak = e->canBreak;
3761 ret->mustBreak = e->mustBreak;
3762 ret->isJumpPoint = e->isJumpPoint;
3763 ret->sref = e->sref;
3770 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
3771 /*@only@*/ cstring f)
3773 exprNode ret = exprNode_createPartialCopy (s);
3775 ret->edata = exprData_makeField (s, f);
3776 ret->kind = XPR_ARROW;
3778 if (exprNode_isError (s))
3784 ctype t = exprNode_getType (s);
3785 ctype tr = ctype_realType (t);
3787 checkMacroParen (s);
3789 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
3791 if (ctype_isRealPointer (tr))
3793 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
3795 if (ctype_isStructorUnion (b))
3797 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
3799 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
3801 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
3805 message ("Arrow access from %s pointer%q: %s",
3806 sRef_nullMessage (s->sref),
3807 sRef_unparsePreOpt (s->sref),
3808 exprNode_unparse (ret)),
3811 sRef_showNullInfo (s->sref);
3812 sRef_setNullError (s->sref);
3817 if (uentry_isUndefined (fentry))
3821 message ("Access non-existent field %s of %t: %s",
3822 f, t, exprNode_unparse (ret)),
3824 ret->typ = ctype_unknown;
3830 ** was safeUse: shouldn't be safe!
3833 ** rec must be defined,
3834 ** *rec must be allocated
3835 ** rec->field need only be defined it if is an rvalue
3838 uentry_setUsed (fentry, exprNode_loc (ret));
3839 ret->typ = uentry_getType (fentry);
3841 exprNode_checkUse (ret, s->sref, s->loc);
3843 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
3844 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
3848 else /* Pointer to something that is not a struct or union*/
3850 if (ctype_isRealAbstract (tr))
3852 ctype xrt = ctype_forceRealType (tr);
3856 message ("Arrow access field of abstract type (%t): %s->%s",
3857 t, exprNode_unparse (s), f),
3861 ** Set the state correctly, as if the abstraction is broken.
3864 if (ctype_isRealPointer (xrt) &&
3865 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
3866 ctype_isStructorUnion (b)))
3868 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
3869 ret->typ = uentry_getType (fentry);
3870 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
3874 ret->typ = ctype_unknown;
3875 ret->sref = sRef_undefined;
3878 else /* not a struct, union or abstract */
3880 if (ctype_isUnknown (tr)) {
3881 cstring sn = cstring_copy (f);
3883 DPRINTF (("Here: %s", exprNode_unparse (s)));
3885 exprNode_checkUse (ret, s->sref, s->loc);
3886 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
3888 cstring_markOwned (sn);
3889 ret->sref = sRef_makeArrow (s->sref, sn);
3891 ret->kind = XPR_ARROW;
3896 message ("Arrow access field of non-struct or union "
3897 "pointer (%t): %s->%s",
3898 t, exprNode_unparse (s), f),
3901 ret->typ = ctype_unknown;
3902 ret->sref = sRef_undefined;
3907 else /* its not a pointer */
3909 if (!ctype_isUnknown (tr))
3913 message ("Arrow access of non-pointer (%t): %s->%s",
3914 t, exprNode_unparse (s), f),
3917 ret->typ = ctype_unknown;
3918 ret->sref = sRef_undefined;
3922 cstring sn = cstring_copy (f);
3924 DPRINTF (("Here: %s", exprNode_unparse (s)));
3926 exprNode_checkUse (ret, s->sref, s->loc);
3927 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
3929 cstring_markOwned (sn);
3930 ret->sref = sRef_makeArrow (s->sref, sn);
3932 ret->kind = XPR_ARROW;
3943 exprNode_arrowAccess (/*@only@*/ exprNode s,
3944 /*@only@*/ lltok arrow,
3945 /*@only@*/ cstring f)
3947 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
3948 lltok_release (arrow);
3953 ** only postOp's in C: i++ and i--
3957 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
3959 /* check modification also */
3960 /* cstring opname = lltok_unparse (op);*/
3962 exprNode ret = exprNode_createPartialCopy (e);
3964 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
3965 ret->kind = XPR_POSTOP;
3966 ret->edata = exprData_makeUop (e, op);
3968 if (!exprNode_isDefined (e))
3973 checkMacroParen (e);
3975 exprNode_checkUse (ret, e->sref, e->loc);
3976 exprNode_checkSet (ret, e->sref);
3978 t = exprNode_getType (e);
3980 if (sRef_isUnsafe (e->sref))
3982 voptgenerror (FLG_MACROPARAMS,
3983 message ("Operand of %s is macro parameter (non-functional): %s%s",
3984 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
3986 sRef_makeSafe (e->sref);
3987 sRef_makeSafe (ret->sref);
3990 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
3996 if (ctype_isRealAbstract (t))
4000 message ("Operand of %s is abstract type (%t): %s",
4001 lltok_unparse (op), t, exprNode_unparse (e)),
4008 message ("Operand of %s is non-numeric (%t): %s",
4009 lltok_unparse (op), t, exprNode_unparse (e)),
4012 ret->typ = ctype_unknown;
4015 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4017 exprNode_checkModify (e, ret);
4019 /* added 7/11/2000 D.L */
4021 /*DRL 6/8/01 I decided to disable all LCLint Warning here since the code
4022 probably needs a rewrite any way */
4026 // updateEnvironmentForPostOp (e);
4028 /* start modifications */
4029 /* added by Seejo on 4/16/2000 */
4031 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4033 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4035 ret->sref = sRef_copy (e->sref);
4038 if (lltok_getTok (op) == INC_OP) {
4039 if (sRef_getSize(e->sref) > 0) {
4041 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4043 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4044 /* Assumption: there is only 1 \0 in the buffer */
4045 /* This will not be correct if there are 2 \0's in the buffer */
4046 sRef_setNotNullTerminatedState(ret->sref);
4047 sRef_resetLen(ret->sref);
4049 sRef_setNullTerminatedState(ret->sref);
4050 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4052 if (sRef_isNullTerminated (ret->sref))
4053 printf ("ret->sref is Null Terminated\n");
4054 else if (sRef_isPossiblyNullTerminated (ret->sref))
4055 printf ("ret->sref is Possibly Null Terminated\n");
4056 else if (sRef_isNotNullTerminated (ret->sref))
4057 printf ("ret->sref is Not Null Terminated\n");
4062 if (lltok_getTok (op) == DEC_OP) {
4063 if (sRef_getSize(e->sref) >= 0) {
4064 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4065 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4070 /* end modifications */
4076 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4078 bool checkMod = FALSE;
4080 int opid = lltok_getTok (op);
4081 exprNode ret = exprNode_createSemiCopy (e);
4083 exprNode_copySets (ret, e);
4085 multiVal_free (ret->val);
4086 ret->val = multiVal_undefined;
4087 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4088 ret->kind = XPR_PREOP;
4089 ret->edata = exprData_makeUop (e, op);
4091 if (exprNode_isError (e))
4096 checkMacroParen (e);
4098 te = exprNode_getType (e);
4099 tr = ctype_realType (te);
4101 if (opid != TAMPERSAND)
4103 exprNode_checkUse (ret, e->sref, e->loc);
4105 if (ctype_isRealAbstract (tr)
4106 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4108 if (optgenerror (FLG_ABSTRACT,
4109 message ("Operand of %s is abstract type (%t): %s",
4110 lltok_unparse (op), tr,
4111 exprNode_unparse (ret)),
4114 tr = te = ctype_unknown;
4115 ret->typ = ctype_unknown;
4116 sRef_setNullError (e->sref);
4124 case DEC_OP: /* should also check modification! */
4125 if (sRef_isMacroParamRef (e->sref))
4129 message ("Operand of %s is macro parameter (non-functional): %s",
4130 lltok_unparse (op), exprNode_unparse (ret)),
4135 exprNode_checkSet (ret, e->sref);
4138 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4143 if (context_msgStrictOps ())
4147 message ("Operand of %s is non-numeric (%t): %s",
4148 lltok_unparse (op), te, exprNode_unparse (ret)),
4151 ret->typ = ctype_int;
4154 /* start modifications */
4155 /* added by Seejo on 4/16/2000 */
4157 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4159 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4161 ret->sref = sRef_copy (e->sref);
4164 if (lltok_getTok (op) == INC_OP) {
4165 if (sRef_getSize(e->sref) > 0) {
4167 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4169 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4170 /* Assumption: there is only 1 \0 in the buffer */
4171 /* This will not be correct if there are 2 \0's in the buffer */
4172 sRef_setNotNullTerminatedState(ret->sref);
4173 sRef_resetLen (ret->sref);
4175 sRef_setNullTerminatedState(ret->sref);
4176 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4182 if (lltok_getTok (op) == DEC_OP) {
4183 if (sRef_getSize(e->sref) >= 0) {
4184 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4185 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4190 /* end modifications */
4197 if (ctype_isForceRealNumeric (&tr))
4201 ret->val = multiVal_invert (exprNode_getValue (e));
4205 ret->val = multiVal_copy (exprNode_getValue (e));
4210 if (context_msgStrictOps ())
4214 message ("Operand of %s is non-numeric (%t): %s",
4215 lltok_unparse (op), te, exprNode_unparse (ret)),
4219 ret->typ = ctype_int;
4223 case TEXCL: /* maybe this should be restricted */
4224 guardSet_flip (ret->guards);
4226 if (ctype_isRealBool (te) || ctype_isUnknown (te))
4232 if (ctype_isRealPointer (tr))
4234 if (sRef_isKnown (e->sref))
4236 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4240 (FLG_BOOLOPS, FLG_PTRNEGATE,
4241 message ("Operand of %s is non-boolean (%t): %s",
4242 lltok_unparse (op), te, exprNode_unparse (ret)),
4249 message ("Operand of %s is non-boolean (%t): %s",
4250 lltok_unparse (op), te, exprNode_unparse (ret)),
4254 ret->typ = ctype_bool;
4259 if (ctype_isForceRealInt (&tr))
4264 if (context_msgStrictOps ())
4268 message ("Operand of %s is non-integer (%t): %s",
4269 lltok_unparse (op), te, exprNode_unparse (ret)),
4273 if (ctype_isInt (e->typ))
4279 ret->typ = ctype_int;
4285 ret->typ = ctype_makePointer (e->typ);
4287 if (sRef_isKnown (e->sref))
4289 ret->sref = sRef_makeAddress (e->sref);
4296 if (ctype_isAP (tr))
4298 ret->typ = ctype_baseArrayPtr (e->typ);
4302 if (ctype_isKnown (te))
4304 if (ctype_isFunction (te))
4310 message ("Dereference of function type (%t): %s",
4311 te, exprNode_unparse (ret)),
4316 voptgenerror (FLG_TYPE,
4317 message ("Dereference of non-pointer (%t): %s",
4318 te, exprNode_unparse (ret)),
4320 ret->typ = ctype_unknown;
4325 ret->typ = ctype_unknown;
4330 if (sRef_isKnown (e->sref))
4332 if (sRef_possiblyNull (e->sref))
4334 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4338 message ("Dereference of %s pointer %q: %s",
4339 sRef_nullMessage (e->sref),
4340 sRef_unparse (e->sref),
4341 exprNode_unparse (ret)),
4344 sRef_showNullInfo (e->sref);
4345 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4350 ret->sref = sRef_makePointer (e->sref);
4355 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4360 exprNode_checkModify (e, ret);
4367 ** any reason to disallow sizeof (abstract type) ?
4371 ** used by both sizeof
4375 ctype sizeof_resultType (void)
4377 static ctype sizet = ctype_unknown;
4379 if (ctype_isUnknown (sizet))
4381 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4383 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4387 sizet = ctype_ulint;
4394 exprNode_sizeofType (/*@only@*/ qtype qt)
4396 exprNode ret = exprNode_create (sizeof_resultType ());
4397 ctype ct = qtype_getType (qt);
4399 ret->kind = XPR_SIZEOFT;
4400 ret->edata = exprData_makeSizeofType (qt);
4402 voptgenerror (FLG_SIZEOFTYPE,
4403 message ("Parameter to sizeof is type %s: %s",
4405 exprNode_unparse (ret)),
4412 exprNode_alignofType (/*@only@*/ qtype qt)
4414 exprNode ret = exprNode_create (sizeof_resultType ());
4415 ctype ct = qtype_getType (qt);
4417 ret->kind = XPR_ALIGNOFT;
4418 ret->edata = exprData_makeSizeofType (qt);
4420 voptgenerror (FLG_SIZEOFTYPE,
4421 message ("Parameter to alignof is type %s: %s",
4423 exprNode_unparse (ret)),
4429 exprNode exprNode_offsetof (qtype qt, cstringList s)
4431 exprNode ret = exprNode_create (sizeof_resultType ());
4432 ctype ct = qtype_getType (qt);
4434 ret->kind = XPR_OFFSETOF;
4435 ret->edata = exprData_makeOffsetof (qt, s);
4437 if (!ctype_isRealSU (ct))
4439 voptgenerror (FLG_TYPE,
4440 message ("First parameter to offsetof is not a "
4441 "struct or union type (type %s): %s",
4443 exprNode_unparse (ret)),
4450 cstringList_elements (s, el) {
4454 if (ctype_isUndefined (lt))
4458 else if (!ctype_isRealSU (lt))
4460 voptgenerror (FLG_TYPE,
4461 message ("Inner offsetof type is not a "
4462 "struct or union type (type %s before field %s): %s",
4463 ctype_unparse (lt), el,
4464 exprNode_unparse (ret)),
4470 fields = ctype_getFields (ctype_realType (lt));
4471 fld = uentryList_lookupField (fields, el);
4472 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4474 if (uentry_isUndefined (fld))
4476 if (ctype_equal (lt, ct)) {
4477 voptgenerror (FLG_TYPE,
4478 message ("Field %s in offsetof is not the "
4479 "name of a field of %s: %s",
4482 exprNode_unparse (ret)),
4485 voptgenerror (FLG_TYPE,
4486 message ("Deep field %s in offsetof is not the "
4487 "name of a field of %s: %s",
4490 exprNode_unparse (ret)),
4496 lt = uentry_getType (fld);
4499 } end_cstringList_elements;
4501 /* Should report error if its a bit field - behavior is undefined! */
4508 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4512 if (exprNode_isUndefined (e))
4514 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4515 ret->edata = exprData_makeSingle (e);
4516 ret->typ = sizeof_resultType ();
4517 ret->kind = XPR_SIZEOF;
4521 uentry u = exprNode_getUentry (e);
4523 ret = exprNode_createPartialCopy (e);
4524 ret->edata = exprData_makeSingle (e);
4526 ret->typ = sizeof_resultType ();
4527 ret->kind = XPR_SIZEOF;
4529 if (uentry_isValid (u)
4530 && uentry_isRefParam (u)
4531 && ctype_isRealArray (uentry_getType (u)))
4534 (FLG_SIZEOFFORMALARRAY,
4535 message ("Parameter to sizeof is an array-type function parameter: %s",
4536 exprNode_unparse (ret)),
4542 ** sizeof (x) doesn't "really" use x
4549 exprNode_alignofExpr (/*@only@*/ exprNode e)
4553 if (exprNode_isUndefined (e))
4555 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4559 ret = exprNode_createPartialCopy (e);
4562 ret->edata = exprData_makeSingle (e);
4563 ret->typ = sizeof_resultType ();
4564 ret->kind = XPR_ALIGNOF;
4567 ** sizeof (x) doesn't "really" use x
4574 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4580 if (exprNode_isError (e))
4583 lltok_release (tok);
4584 return exprNode_undefined;
4587 checkMacroParen (e);
4589 c = qtype_getType (q);
4590 t = exprNode_getType (e);
4592 ret = exprNode_createPartialCopy (e);
4594 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4596 ret->kind = XPR_CAST;
4597 ret->edata = exprData_makeCast (tok, e, q);
4599 if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
4602 ** This is a bit of a hack to avoid a problem
4603 ** when the code does,
4604 ** (some other struct) x
4609 ret->sref = sRef_copy (e->sref);
4610 usymtab_addForceMustAlias (ret->sref, e->sref);
4611 sRef_setTypeFull (ret->sref, c);
4612 DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
4613 sRef_unparseFull (ret->sref)));
4617 ret->sref = e->sref;
4618 sRef_setTypeFull (ret->sref, c);
4619 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
4626 ** void * <-> abstract * (if FLG_ABSTVOIDP)
4627 ** abstract * <-> void * (if FLG_ABSTVOIDP)
4630 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
4634 else if (ctype_isRealAP (c)) /* casting to array or pointer */
4636 ctype bc = ctype_getBaseType (c);
4637 ctype bt = ctype_getBaseType (t);
4638 ctype rt = ctype_realType (t);
4640 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
4641 && (ctype_isArrayPtr (rt)
4642 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4646 message ("Cast from function pointer type (%t) to "
4647 "non-function pointer (%t): %s",
4648 c, t, exprNode_unparse (ret)),
4652 if (!ctype_isFunction (ctype_baseArrayPtr (c))
4653 && (ctype_isArrayPtr (rt)
4654 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4658 message ("Cast from non-function pointer type (%t) to "
4659 "function pointer (%t): %s",
4660 c, t, exprNode_unparse (ret)),
4664 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
4665 !(ctype_isRealAbstract (bc)
4666 && context_hasAccess (ctype_typeId (bc))))
4668 ; /* okay to cast zero */
4672 if (ctype_isRealAbstract (bc)
4673 && !context_hasAccess (ctype_typeId (bc)))
4675 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
4679 message ("Cast to underlying abstract type %t: %s",
4680 c, exprNode_unparse (ret)),
4687 message ("Cast to underlying abstract type %t: %s",
4688 c, exprNode_unparse (ret)),
4693 if (ctype_isRealAbstract (bt)
4694 && !context_hasAccess (ctype_typeId (bt)))
4696 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
4700 message ("Cast from underlying abstract type %t: %s",
4701 t, exprNode_unparse (ret)),
4708 message ("Cast from underlying abstract type %t: %s",
4709 t, exprNode_unparse (ret)),
4717 ctype bt = ctype_realType (ctype_getBaseType (t));
4718 ctype bc = ctype_realType (ctype_getBaseType (c));
4720 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
4722 if (ctype_match (c, t))
4724 if (ctype_equal (c, t))
4728 message ("Redundant cast involving abstract type %t: %s",
4729 bt, exprNode_unparse (ret)),
4737 message ("Cast from abstract type %t: %s",
4738 bt, exprNode_unparse (ret)),
4743 if (ctype_isAbstract (bc)
4744 && !context_hasAccess (ctype_typeId (bc)))
4746 if (ctype_match (c, t))
4752 DPRINTF (("No access to: %s / %d",
4753 ctype_unparse (bc), ctype_typeId (bc)));
4754 DPRINTF (("Context %s %s",
4755 bool_unparse (context_inFunctionLike ()),
4756 context_unparse ()));
4759 message ("Cast to abstract type %t: %s", bc,
4760 exprNode_unparse (ret)),
4766 if (ctype_isAbstract (c))
4768 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
4770 /* okay, cast exposed to abstract */
4771 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
4775 if (ctype_isVisiblySharable (t)
4776 && sRef_isExternallyVisible (e->sref)
4777 && !(ctype_isAbstract (t)
4778 && context_hasAccess (ctype_typeId (t))))
4782 message ("Cast to abstract type from externally visible "
4783 "mutable storage exposes rep of %s: %s",
4785 exprNode_unparse (e)),
4795 evaluationOrderUndefined (lltok op)
4797 int opid = lltok_getTok (op);
4799 return (opid != AND_OP && opid != OR_OP);
4802 static bool checkIntegral (/*@notnull@*/ exprNode e1,
4803 /*@notnull@*/ exprNode e2,
4804 /*@notnull@*/ exprNode ret,
4809 ctype te1 = exprNode_getType (e1);
4810 ctype te2 = exprNode_getType (e2);
4812 ctype tr1 = ctype_realishType (te1);
4813 ctype tr2 = ctype_realishType (te2);
4815 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
4821 if (context_msgStrictOps ())
4823 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
4825 if (ctype_sameName (te1, te2))
4829 message ("Operands of %s are non-integer (%t): %s",
4830 lltok_unparse (op), te1,
4831 exprNode_unparse (ret)),
4838 message ("Operands of %s are non-integers (%t, %t): %s",
4839 lltok_unparse (op), te1, te2,
4840 exprNode_unparse (ret)),
4844 else if (!ctype_isInt (tr1))
4848 message ("Left operand of %s is non-integer (%t): %s",
4849 lltok_unparse (op), te1, exprNode_unparse (ret)),
4853 /* !ctype_isInt (te2) */
4857 message ("Right operand of %s is non-integer (%t): %s",
4858 lltok_unparse (op), te2, exprNode_unparse (ret)),
4868 ** returns exprNode representing e1 op e2
4870 ** uses msg if there are errors
4871 ** can be used for both assignment ops and regular ops
4876 static /*@only@*/ /*@notnull@*/ exprNode
4877 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
4878 /*@keep@*/ lltok op)
4880 ctype te1, te2, tr1, tr2, tret;
4881 int opid = lltok_getTok (op);
4882 bool hasError = FALSE;
4885 if (exprNode_isError (e1))
4887 ret = exprNode_createPartialNVCopy (e2);
4891 ret = exprNode_createPartialNVCopy (e1);
4894 ret->val = multiVal_undefined;
4896 ret->edata = exprData_makeOp (e1, e2, op);
4898 if (exprNode_isError (e1) || exprNode_isError (e2))
4900 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
4901 || opid == EQ_OP || opid == NE_OP
4902 || opid == AND_OP || opid == OR_OP)
4904 ret->typ = ctype_bool;
4907 if (exprNode_isDefined (e1))
4909 exprNode_checkUse (ret, e1->sref, e1->loc);
4912 if (exprNode_isDefined (e2))
4914 exprNode_mergeUSs (ret, e2);
4915 exprNode_checkUse (ret, e2->sref, e2->loc);
4921 tret = ctype_unknown;
4922 te1 = exprNode_getType (e1);
4923 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
4925 te2 = exprNode_getType (e2);
4927 tr1 = ctype_realishType (te1);
4928 tr2 = ctype_realishType (te2);
4932 ret->guards = guardSet_or (ret->guards, e2->guards);
4934 else if (opid == AND_OP)
4936 ret->guards = guardSet_and (ret->guards, e2->guards);
4943 if (opid == EQ_OP || opid == NE_OP)
4945 exprNode temp1 = e1, temp2 = e2;
4947 /* could do NULL == x */
4949 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
4951 temp1 = e2; temp2 = e1;
4954 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
4956 reflectNullTest (temp1, (opid == NE_OP));
4957 guardSet_free (ret->guards);
4958 ret->guards = guardSet_copy (temp1->guards);
4962 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
4963 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
4968 if (anyAbstract (tr1, tr2) &&
4969 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
4970 (opid == AND_OP || opid == OR_OP
4971 || opid == EQ_OP || opid == NE_OP))))
4973 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
4975 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
4977 /* unknown types, no comparisons possible */
4983 case TMULT: /* multiplication and division: */
4985 case MUL_ASSIGN: /* numeric, numeric -> numeric */
4986 case DIV_ASSIGN: /* */
4988 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
4991 case TPLUS: /* addition and subtraction: */
4992 case TMINUS: /* pointer, int -> pointer */
4993 case SUB_ASSIGN: /* int, pointer -> pointer */
4994 case ADD_ASSIGN: /* numeric, numeric -> numeric */
4996 tr1 = ctype_fixArrayPtr (tr1);
4998 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
4999 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5003 if (context_msgPointerArith ())
5007 message ("Pointer arithmetic (%t, %t): %s",
5008 te1, te2, exprNode_unparse (ret)),
5012 if (sRef_possiblyNull (e1->sref)
5013 && !usymtab_isGuarded (e1->sref))
5016 (FLG_NULLPOINTERARITH,
5017 message ("Pointer arithmetic involving possibly "
5018 "null pointer %s: %s",
5019 exprNode_unparse (e1),
5020 exprNode_unparse (ret)),
5024 ret->sref = sRef_copy (e1->sref);
5026 /* start modifications */
5027 /* added by Seejo on 4/16/2000 */
5029 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5031 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5032 //if (sRef_isKnown (e->sref)) {
5033 //ret->sref = sRef_makeAddress (e->sref);
5038 added ugly fixed to stop
5039 program from crashing on point + int +int
5040 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5042 if (!multiVal_isInt (e2->val) )
5046 val = (int) multiVal_forceInt (e2->val);
5048 /* Operator : + or += */
5049 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5050 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5051 val should not result in a
5052 size < 0 (size = 0 is ok !) */
5054 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5056 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5057 sRef_setNotNullTerminatedState(ret->sref);
5058 sRef_resetLen (ret->sref);
5060 sRef_setNullTerminatedState(ret->sref);
5061 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5066 /* Operator : - or -= */
5067 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5068 if (sRef_getSize(e1->sref) >= 0) {
5069 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5070 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5075 /* end modifications */
5077 sRef_setNullError (ret->sref);
5080 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5081 ** since is points to storage that should not be deallocated
5082 ** through this pointer.
5085 if (sRef_isOnly (ret->sref)
5086 || sRef_isFresh (ret->sref))
5088 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5093 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5094 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5096 if (context_msgPointerArith ())
5100 message ("Pointer arithmetic (%t, %t): %s",
5101 te1, te2, exprNode_unparse (ret)),
5105 if (sRef_possiblyNull (e1->sref)
5106 && !usymtab_isGuarded (e1->sref))
5109 (FLG_NULLPOINTERARITH,
5110 message ("Pointer arithmetic involving possibly "
5111 "null pointer %s: %s",
5112 exprNode_unparse (e2),
5113 exprNode_unparse (ret)),
5117 ret->sref = sRef_copy (e2->sref);
5119 /* start modifications */
5120 /* added by Seejo on 4/16/2000 */
5122 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5125 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5126 //if (sRef_isKnown (e->sref)) {
5127 //ret->sref = sRef_makeAddress (e->sref);
5130 int val = (int) multiVal_forceInt (e1->val);
5132 /* Operator : + or += */
5133 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5134 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5135 val should not result in a
5136 size < 0 (size = 0 is ok !) */
5138 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5140 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5141 sRef_setNotNullTerminatedState(ret->sref);
5142 sRef_resetLen (ret->sref);
5144 sRef_setNullTerminatedState(ret->sref);
5145 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5150 /* Operator : - or -= */
5151 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5152 if (sRef_getSize(e2->sref) >= 0) {
5153 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5154 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5159 /* end modifications */
5161 sRef_setNullError (ret->sref);
5164 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5165 ** since is points to storage that should not be deallocated
5166 ** through this pointer.
5169 if (sRef_isOnly (ret->sref)
5170 || sRef_isFresh (ret->sref)) {
5171 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5175 ret->sref = e2->sref;
5179 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5184 case LEFT_ASSIGN: /* Shifts: should be unsigned values */
5188 case TAMPERSAND: /* bitwise & */
5190 case TCIRC: /* ^ (XOR) */
5195 bool reported = FALSE;
5196 flagcode code = FLG_BITWISEOPS;
5198 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5199 || opid == RIGHT_OP || opid == RIGHT_ASSIGN) {
5200 code = FLG_SHIFTSIGNED;
5203 if (!ctype_isUnsigned (tr1))
5205 if (exprNode_isNonNegative (e1)) {
5208 reported = optgenerror
5210 message ("Left operand of %s is not unsigned value (%t): %s",
5211 lltok_unparse (op), te1,
5212 exprNode_unparse (ret)),
5222 /* right need not be signed for shifts */
5223 if (code != FLG_SHIFTSIGNED
5224 && !ctype_isUnsigned (tr2))
5226 if (!exprNode_isNonNegative (e2)) {
5227 reported = optgenerror
5229 message ("Right operand of %s is not unsigned value (%t): %s",
5230 lltok_unparse (op), te2,
5231 exprNode_unparse (ret)),
5239 if (!checkIntegral (e1, e2, ret, op)) {
5240 te1 = ctype_unknown;
5244 DPRINTF (("Set: %s", ctype_unparse (te1)));
5247 ** tret is the widest type of te1 and te2
5250 tret = ctype_widest (te1, te2);
5255 if (checkIntegral (e1, e2, ret, op)) {
5258 tret = ctype_unknown;
5263 case TLT: /* comparisons */
5264 case TGT: /* numeric, numeric -> bool */
5265 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5266 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5269 bool fepsilon = FALSE;
5271 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5276 if (opid == TLT || opid == TGT)
5278 uentry ue1 = exprNode_getUentry (e1);
5279 uentry ue2 = exprNode_getUentry (e2);
5282 ** FLT_EPSILON, etc. really is a variable, not
5286 if (uentry_isVariable (ue1))
5288 cstring uname = uentry_rawName (ue1);
5290 if (cstring_equalLit (uname, "FLT_EPSILON")
5291 || cstring_equalLit (uname, "DBL_EPSILON")
5292 || cstring_equalLit (uname, "LDBL_EPSILON"))
5298 if (uentry_isVariable (ue2))
5300 cstring uname = uentry_rawName (ue2);
5302 if (cstring_equalLit (uname, "FLT_EPSILON")
5303 || cstring_equalLit (uname, "DBL_EPSILON")
5304 || cstring_equalLit (uname, "LDBL_EPSILON"))
5313 ; /* Don't complain. */
5319 message ("Dangerous comparison involving %s types: %s",
5320 ctype_unparse (rtype),
5321 exprNode_unparse (ret)),
5330 ** Types should match.
5333 if (!exprNode_matchTypes (e1, e2))
5335 hasError = gentypeerror
5337 message ("Operands of %s have incompatible types (%t, %t): %s",
5338 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5344 || (ctype_isForceRealNumeric (&tr1)
5345 && ctype_isForceRealNumeric (&tr2)) ||
5346 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5352 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5353 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5357 message ("Comparison of pointer and numeric (%t, %t): %s",
5358 te1, te2, exprNode_unparse (ret)),
5363 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5368 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5370 if ((opid == EQ_OP || opid == NE_OP) &&
5371 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5374 ** is one a variable?
5377 if (uentry_isVariable (exprNode_getUentry (e1))
5378 || uentry_isVariable (exprNode_getUentry (e2)))
5381 ** comparisons with FALSE are okay
5384 if (exprNode_isFalseConstant (e1)
5385 || exprNode_isFalseConstant (e2))
5394 ("Use of %q with %s variables (risks inconsistency because "
5395 "of multiple true values): %s",
5396 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5397 context_printBoolName (), exprNode_unparse (ret)),
5404 case AND_OP: /* bool, bool -> bool */
5407 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5413 if (context_maybeSet (FLG_BOOLOPS))
5415 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5417 if (ctype_sameName (te1, te2))
5421 message ("Operands of %s are non-boolean (%t): %s",
5422 lltok_unparse (op), te1,
5423 exprNode_unparse (ret)),
5431 ("Operands of %s are non-booleans (%t, %t): %s",
5432 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5436 else if (!ctype_isRealBool (te1))
5440 message ("Left operand of %s is non-boolean (%t): %s",
5441 lltok_unparse (op), te1, exprNode_unparse (ret)),
5444 else if (!ctype_isRealBool (te2))
5448 message ("Right operand of %s is non-boolean (%t): %s",
5449 lltok_unparse (op), te2, exprNode_unparse (ret)),
5462 (cstring_makeLiteral
5463 ("There has been a problem in the parser. This is believed to result "
5464 "from a problem with bison v. 1.25. Please try rebuidling LCLint "
5465 "using the pre-compiled grammar files by commenting out the "
5466 "BISON= line in the top-level Makefile."));
5471 DPRINTF (("Return type: %s", ctype_unparse (tret)));
5474 exprNode_checkUse (ret, e1->sref, e1->loc);
5475 exprNode_mergeUSs (ret, e2);
5476 exprNode_checkUse (ret, e2->sref, e2->loc);
5482 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5483 /*@only@*/ lltok op)
5487 checkMacroParen (e1);
5488 checkMacroParen (e2);
5490 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5492 checkExpressionDefined (e1, e2, op);
5495 ret = exprNode_makeOp (e1, e2, op);
5500 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5503 ** This is somewhat bogus!
5505 ** Assigning to a nested observer in a non-observer datatype
5506 ** should not produce an error.
5509 sRef ref = exprNode_getSref (e1);
5511 DPRINTF (("Check assign mod: %s",
5512 sRef_unparseFull (ref)));
5514 if (sRef_isObserver (ref)
5515 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
5516 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5518 sRef base = sRef_getBase (ref);
5520 if (sRef_isValid (base) && sRef_isObserver (base))
5522 exprNode_checkModify (e1, ret);
5526 exprNode_checkModifyVal (e1, ret);
5531 exprNode_checkModify (e1, ret);
5536 exprNode_assign (/*@only@*/ exprNode e1,
5537 /*@only@*/ exprNode e2, /*@only@*/ lltok op)
5539 bool isalloc = FALSE;
5540 bool isjustalloc = FALSE;
5543 DPRINTF (("%s [%s] <- %s [%s]",
5544 exprNode_unparse (e1),
5545 ctype_unparse (e1->typ),
5546 exprNode_unparse (e2),
5547 ctype_unparse (e2->typ)));
5549 if (lltok_getTok (op) != TASSIGN)
5551 ret = exprNode_makeOp (e1, e2, op);
5555 ret = exprNode_createPartialCopy (e1);
5556 ret->kind = XPR_ASSIGN;
5557 ret->edata = exprData_makeOp (e1, e2, op);
5559 if (!exprNode_isError (e2))
5561 ret->sets = sRefSet_union (ret->sets, e2->sets);
5562 ret->msets = sRefSet_union (ret->msets, e2->msets);
5563 ret->uses = sRefSet_union (ret->uses, e2->uses);
5567 checkExpressionDefined (e1, e2, op);
5569 if (exprNode_isError (e1))
5571 if (!exprNode_isError (e2))
5573 ret->loc = fileloc_update (ret->loc, e2->loc);
5577 ret->loc = fileloc_update (ret->loc, g_currentloc);
5581 if (!exprNode_isError (e2))
5583 checkMacroParen (e2);
5586 if (exprNode_isDefined (e1))
5588 if (sRef_isMacroParamRef (e1->sref))
5590 if (context_inIterDef ())
5592 uentry ue = sRef_getUentry (e1->sref);
5594 if (uentry_isYield (ue))
5600 if (fileloc_isDefined (e1->loc))
5604 message ("Assignment to non-yield iter parameter: %q",
5605 sRef_unparse (e1->sref)),
5612 message ("Assignment to non-yield iter parameter: %q",
5613 sRef_unparse (e1->sref)),
5620 if (fileloc_isDefined (e1->loc))
5624 message ("Assignment to macro parameter: %q",
5625 sRef_unparse (e1->sref)),
5632 message ("Assignment to macro parameter: %q",
5633 sRef_unparse (e1->sref)),
5640 exprNode_checkAssignMod (e1, ret);
5643 if (exprNode_isDefined (e2))
5645 if (lltok_getTok (op) == TASSIGN)
5647 ctype te1 = exprNode_getType (e1);
5648 ctype te2 = exprNode_getType (e2);
5650 if (!ctype_forceMatch (te1, te2))
5652 if (exprNode_matchLiteral (te1, e2))
5660 message ("Assignment of %t to %t: %s %s %s",
5661 te2, te1, exprNode_unparse (e1),
5663 exprNode_unparse (e2)),
5669 exprNode_mergeUSs (ret, e2);
5670 exprNode_checkUse (ret, e2->sref, e2->loc);
5672 doAssign (e1, e2, FALSE);
5673 ret->sref = e1->sref;
5677 if (exprNode_isDefined (e2))
5679 exprNode_mergeUSs (ret, e2);
5680 exprNode_checkUse (ret, e2->sref, e2->loc);
5684 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
5686 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
5689 isjustalloc = sRef_isJustAllocated (e1->sref);
5690 isalloc = sRef_isAllocated (e1->sref);
5692 if (sRef_isField (e1->sref))
5694 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
5696 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
5698 exprNode_checkUse (ret, root, e1->loc);
5704 ** be careful! this defines e1->sref.
5707 if (!sRef_isMacroParamRef (e1->sref))
5709 exprNode_checkSet (ret, e1->sref);
5714 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
5715 ? e2->loc : e1->loc);
5721 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
5730 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
5731 /*@keep@*/ exprNode elseclause)
5735 if (!exprNode_isError (pred))
5737 ret = exprNode_createPartialCopy (pred);
5738 checkMacroParen (pred);
5739 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
5741 if (!exprNode_isError (ifclause))
5743 checkMacroParen (ifclause); /* update macro counts! */
5745 if (!exprNode_isError (elseclause))
5747 checkMacroParen (elseclause);
5749 if (!exprNode_matchTypes (ifclause, elseclause))
5752 (exprNode_getType (ifclause),
5754 exprNode_getType (elseclause),
5756 message ("Conditional clauses are not of same type: "
5758 exprNode_unparse (ifclause),
5759 exprNode_getType (ifclause),
5760 exprNode_unparse (elseclause),
5761 exprNode_getType (elseclause)),
5764 ret->sref = sRef_undefined;
5765 ret->typ = ctype_unknown;
5770 /* for now...should merge the states */
5771 ret->sref = ifclause->sref;
5772 ret->typ = ifclause->typ;
5774 if (exprNode_isNullValue (ifclause))
5776 ret->typ = elseclause->typ;
5780 exprNode_checkUse (ret, pred->sref, pred->loc);
5781 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
5782 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5784 exprNode_mergeCondUSs (ret, ifclause, elseclause);
5789 ret->typ = ifclause->typ;
5791 exprNode_checkUse (pred, pred->sref, pred->loc);
5792 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
5794 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
5799 if (!exprNode_isError (elseclause))
5801 ret->typ = elseclause->typ;
5803 exprNode_checkUse (pred, pred->sref, pred->loc);
5804 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5806 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
5810 else /* pred is error */
5812 if (!exprNode_isError (ifclause))
5814 ret = exprNode_createSemiCopy (ifclause);
5816 checkMacroParen (ifclause); /* update macro counts! */
5818 if (!exprNode_isError (elseclause))
5820 checkMacroParen (elseclause);
5822 ret->typ = ifclause->typ;
5824 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
5827 (exprNode_getType (ifclause),
5829 exprNode_getType (elseclause),
5831 message ("Conditional clauses are not of same type: "
5833 exprNode_unparse (ifclause),
5834 exprNode_getType (ifclause),
5835 exprNode_unparse (elseclause),
5836 exprNode_getType (elseclause)),
5839 ret->typ = ctype_unknown;
5843 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
5844 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5846 exprNode_mergeCondUSs (ret, ifclause, elseclause);
5849 else if (!exprNode_isError (elseclause)) /* pred, if errors */
5851 ret = exprNode_createSemiCopy (ifclause);
5853 ret->typ = elseclause->typ;
5854 checkMacroParen (elseclause);
5856 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5857 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
5859 else /* all errors! */
5861 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
5865 ret->kind = XPR_COND;
5866 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
5868 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
5870 exprNode_combineControl (ret, ifclause, elseclause);
5877 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
5879 ctype totype = qtype_getType (qt);
5881 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
5885 ** check use of va_arg : <valist>, type -> type
5888 if (exprNode_isError (arg))
5893 targ = exprNode_getType (arg);
5896 ** arg should have be a pointer
5899 if (!ctype_isUA (targ) ||
5900 (!usymId_equal (ctype_typeId (targ),
5901 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
5905 message ("First argument to va_arg is not a va_list (type %t): %s",
5906 targ, exprNode_unparse (arg)),
5910 exprNode_checkSet (ret, arg->sref);
5914 ** return type is totype
5918 ret->kind = XPR_VAARG;
5919 ret->edata = exprData_makeCast (tok, arg, qt);
5924 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
5926 exprNode ret = exprNode_createPlain (ctype_undefined);
5927 ret->kind = XPR_LABEL;
5928 ret->edata = exprData_makeLiteral (label);
5929 ret->isJumpPoint = TRUE;
5931 return (ret); /* for now, ignore label */
5934 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
5936 if (exprNode_isDefined (stmt))
5938 stmt->isJumpPoint = TRUE;
5940 /* This prevent stray no return path errors, etc. */
5941 stmt->exitCode = XK_MUSTEXIT;
5947 bool exprNode_isDefaultMarker (exprNode e)
5949 if (exprNode_isDefined (e))
5951 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
5957 bool exprNode_isCaseMarker (exprNode e)
5959 if (exprNode_isDefined (e))
5961 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
5967 bool exprNode_isLabelMarker (exprNode e)
5969 if (exprNode_isDefined (e))
5971 return (e->kind == XPR_LABEL);
5977 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
5979 exprNode ret = exprNode_createPartialCopy (test);
5981 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
5983 if (exprNode_isError (test)) {
5987 exprNode_checkUse (ret, test->sref, test->loc);
5989 usymtab_setExitCode (ret->exitCode);
5993 usymtab_setMustBreak ();
5996 ret->edata = exprData_makeSingle (test);
5997 ret->isJumpPoint = TRUE;
6003 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6005 exprNode ret = exprNode_createPartialCopy (test);
6007 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6008 ret->edata = exprData_makePair (test, stmt);
6009 ret->isJumpPoint = TRUE;
6011 if (exprNode_isError (test))
6016 exprNode_checkUse (ret, test->sref, test->loc);
6018 if (exprNode_isError (stmt))
6023 exprNode_mergeUSs (ret, stmt);
6025 ret->exitCode = stmt->exitCode;
6026 ret->mustBreak = stmt->mustBreak;
6027 ret->canBreak = stmt->canBreak;
6029 usymtab_setExitCode (ret->exitCode);
6033 usymtab_setMustBreak ();
6040 /*@notnull@*/ /*@only@*/ exprNode
6041 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6043 exprNode ret = exprNode_createTok (def);
6045 ret->isJumpPoint = TRUE;
6046 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6051 exprNode_mayEscape (exprNode e)
6053 if (exprNode_isDefined (e))
6055 return exitkind_couldEscape (e->exitCode);
6061 exprNode_mustBreak (exprNode e)
6063 if (exprNode_isDefined (e))
6065 return e->mustBreak;
6071 exprNode_mustEscape (exprNode e)
6073 if (exprNode_isDefined (e))
6075 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6082 exprNode_errorEscape (exprNode e)
6084 if (exprNode_isDefined (e))
6086 return exitkind_isError (e->exitCode);
6092 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6094 exprNode ret = exprNode_createPartialCopy (e1);
6096 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6098 ret->edata = exprData_makePair (e1, e2);
6099 ret->kind = XPR_STMTLIST;
6101 if (exprNode_isDefined (e1))
6103 ret->isJumpPoint = e1->isJumpPoint;
6104 ret->canBreak = e1->canBreak;
6108 if (exprNode_isDefined (e2))
6110 ret->loc = fileloc_update (ret->loc, e2->loc);
6114 if (exprNode_isDefined (e2))
6116 ret->exitCode = e2->exitCode;
6117 ret->mustBreak = e2->mustBreak;
6118 if (e2->canBreak) ret->canBreak = TRUE;
6122 ** if e1 must return, then e2 is unreachable!
6125 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6127 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6128 && !(e2->isJumpPoint))
6130 if (context_getFlag (FLG_UNREACHABLE))
6134 if (e2->kind == XPR_STMT)
6136 nr = exprData_getUopNode (e2->edata);
6139 if ((nr->kind == XPR_TOK
6140 && lltok_isSemi (exprData_getTok (nr->edata))))
6142 /* okay to have unreachable ";" */
6143 ret->exitCode = XK_MUSTEXIT;
6144 ret->canBreak = TRUE;
6148 if (optgenerror (FLG_UNREACHABLE,
6149 message ("Unreachable code: %s",
6150 exprNode_unparseFirst (nr)),
6153 ret->isJumpPoint = TRUE;
6154 ret->mustBreak = FALSE;
6155 ret->exitCode = XK_ERROR;
6156 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6160 ret->exitCode = XK_MUSTEXIT;
6161 ret->canBreak = TRUE;
6169 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6172 ** We want a warning anytime we have:
6174 ** yyy; <<<- no break or return
6178 exprNode lastStmt = exprNode_lastStatement (e1);
6180 if (exprNode_isDefined (lastStmt)
6181 && !exprNode_mustEscape (lastStmt)
6182 && !exprNode_mustBreak (lastStmt)
6183 && !exprNode_isCaseMarker (lastStmt)
6184 && !exprNode_isDefaultMarker (lastStmt)
6185 && !exprNode_isLabelMarker (lastStmt))
6187 voptgenerror (FLG_CASEBREAK,
6189 ("Fall through case (no preceeding break)"),
6196 exprNode_mergeUSs (ret, e2);
6198 usymtab_setExitCode (ret->exitCode);
6202 usymtab_setMustBreak ();
6208 exprNode exprNode_createTok (/*@only@*/ lltok t)
6210 exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6211 ret = exprNode_create (ctype_unknown);
6212 ret->kind = XPR_TOK;
6213 ret->edata = exprData_makeTok (t);
6217 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6219 if (!exprNode_isError (e))
6221 exprNode_checkStatement(e);
6224 return (exprNode_statementError (e, t));
6227 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6229 exprNode ret = exprNode_createPartialCopy (e);
6231 if (!exprNode_isError (e))
6233 if (e->kind != XPR_ASSIGN)
6235 exprNode_checkUse (ret, e->sref, e->loc);
6238 ret->exitCode = e->exitCode;
6239 ret->canBreak = e->canBreak;
6240 ret->mustBreak = e->mustBreak;
6243 ret->edata = exprData_makeUop (e, t);
6244 ret->kind = XPR_STMT;
6249 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6251 if (!exprNode_isError (e))
6253 if (e->kind != XPR_ASSIGN)
6255 exprNode_checkUse (e, e->sref, e->loc);
6262 void exprNode_produceGuards (exprNode pred)
6264 if (!exprNode_isError (pred))
6266 if (ctype_isRealPointer (pred->typ))
6268 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6271 exprNode_checkUse (pred, pred->sref, pred->loc);
6272 exprNode_resetSref (pred);
6276 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6278 exprNode ret = exprNode_createPartialCopy (e);
6280 if (!exprNode_isError (e))
6282 ret->exitCode = e->exitCode;
6283 ret->canBreak = e->canBreak;
6284 ret->mustBreak = e->mustBreak;
6287 ret->edata = exprData_makeSingle (e);
6288 ret->kind = XPR_BLOCK;
6292 bool exprNode_isBlock (exprNode e)
6294 return (exprNode_isDefined (e)
6295 && ((e)->kind == XPR_BLOCK));
6298 bool exprNode_isAssign (exprNode e)
6300 if (exprNode_isDefined (e))
6302 return (e->kind == XPR_ASSIGN);
6308 bool exprNode_isEmptyStatement (exprNode e)
6310 return (exprNode_isDefined (e)
6311 && (e->kind == XPR_TOK)
6312 && (lltok_isSemi (exprData_getTok (e->edata))));
6315 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6318 bool emptyErr = FALSE;
6320 if (context_maybeSet (FLG_IFEMPTY))
6322 if (exprNode_isEmptyStatement (tclause))
6324 emptyErr = optgenerror (FLG_IFEMPTY,
6326 ("Body of if statement is empty"),
6327 exprNode_loc (tclause));
6331 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6333 if (exprNode_isDefined (tclause)
6334 && !exprNode_isBlock (tclause))
6336 voptgenerror (FLG_IFBLOCK,
6338 ("Body of if statement is not a block: %s",
6339 exprNode_unparse (tclause)),
6340 exprNode_loc (tclause));
6344 if (exprNode_isError (pred))
6346 if (exprNode_isError (tclause))
6348 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6352 ret = exprNode_createPartialCopy (tclause);
6357 if (exprNode_mustEscape (pred))
6361 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6362 exprNode_loc (pred));
6365 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6366 exprNode_checkUse (pred, pred->sref, pred->loc);
6368 if (!exprNode_isError (tclause))
6370 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
6373 ret = exprNode_createPartialCopy (pred);
6377 ret->edata = exprData_makePair (pred, tclause);
6379 ret->exitCode = XK_UNKNOWN;
6381 if (exprNode_isDefined (tclause))
6383 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
6384 ret->canBreak = tclause->canBreak;
6385 ret->sets = sRefSet_union (ret->sets, tclause->sets);
6386 ret->msets = sRefSet_union (ret->msets, tclause->msets);
6387 ret->uses = sRefSet_union (ret->uses, tclause->uses);
6390 ret->mustBreak = FALSE;
6395 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
6396 /*@only@*/ exprNode tclause,
6397 /*@only@*/ exprNode eclause)
6400 bool tEmptyErr = FALSE;
6401 bool eEmptyErr = FALSE;
6403 if (context_maybeSet (FLG_IFEMPTY))
6405 if (exprNode_isEmptyStatement (tclause))
6407 tEmptyErr = optgenerror
6410 ("Body of if clause of if statement is empty"),
6411 exprNode_loc (tclause));
6414 if (exprNode_isEmptyStatement (eclause))
6416 eEmptyErr = optgenerror
6419 ("Body of else clause of if statement is empty"),
6420 exprNode_loc (eclause));
6424 if (context_maybeSet (FLG_IFBLOCK))
6427 && exprNode_isDefined (tclause)
6428 && !exprNode_isBlock (tclause))
6430 voptgenerror (FLG_IFBLOCK,
6432 ("Body of if clause of if statement is not a block: %s",
6433 exprNode_unparse (tclause)),
6434 exprNode_loc (tclause));
6438 && exprNode_isDefined (eclause)
6439 && !exprNode_isBlock (eclause)
6440 && !(eclause->kind == XPR_IF)
6441 && !(eclause->kind == XPR_IFELSE))
6446 ("Body of else clause of if statement is not a block: %s",
6447 exprNode_unparse (eclause)),
6448 exprNode_loc (eclause));
6452 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
6454 if (exprNode_isDefined (eclause)
6455 && (eclause->kind == XPR_IF))
6457 voptgenerror (FLG_ELSEIFCOMPLETE,
6458 message ("Incomplete else if logic (no final else): %s",
6459 exprNode_unparse (eclause)),
6460 exprNode_loc (eclause));
6464 if (exprNode_isError (pred))
6466 if (exprNode_isError (tclause))
6468 if (exprNode_isError (eclause))
6470 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6474 ret = exprNode_createPartialCopy (eclause);
6479 ret = exprNode_createPartialCopy (tclause);
6482 else /* pred is okay */
6484 ret = exprNode_createPartialCopy (pred);
6486 if (exprNode_mustEscape (pred))
6490 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6491 exprNode_loc (pred));
6494 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6495 exprNode_checkUse (ret, pred->sref, pred->loc);
6497 exprNode_mergeCondUSs (ret, tclause, eclause);
6500 ret->kind = XPR_IFELSE;
6501 ret->edata = exprData_makeCond (pred, tclause, eclause);
6503 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
6505 exprNode_combineControl (ret, tclause, eclause);
6506 ret->loc = fileloc_update (ret->loc, eclause->loc);
6513 ** *allpaths <- TRUE iff all executions paths must go through the switch
6517 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
6519 exprNodeSList el = exprNode_flatten (e);
6520 bool mustReturn = TRUE; /* find a branch that doesn't */
6521 bool thisReturn = FALSE;
6522 bool hasDefault = FALSE;
6523 bool hasAllMembers = FALSE;
6524 bool inSwitch = FALSE;
6525 bool isEnumSwitch = FALSE;
6526 bool canBreak = FALSE;
6527 bool fallThrough = FALSE;
6528 ctype ct = ctype_unknown;
6529 enumNameSList usedEnums;
6532 if (exprNode_isDefined (test))
6537 ttype = ctype_realType (ct);
6539 if (ctype_isEnum (ttype))
6541 isEnumSwitch = TRUE;
6542 enums = ctype_elist (ttype);
6543 usedEnums = enumNameSList_new ();
6547 exprNodeSList_elements (el, current)
6549 if (exprNode_isDefined (current))
6551 switch (current->kind)
6559 message ("Duplicate default cases in switch"),
6560 exprNode_loc (current));
6565 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
6573 exprNode st = exprData_getSingle (current->edata);
6574 uentry ue = exprNode_getUentry (st);
6576 if (uentry_isValid (ue))
6578 cstring cname = uentry_rawName (ue);
6580 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
6582 if (enumNameSList_member
6583 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
6587 message ("Duplicate case in switch: %s",
6593 enumNameSList_addh (usedEnums, cname);
6600 message ("Case in switch not %s member: %s",
6601 ctype_unparse (ct), cname),
6608 if (inSwitch && !fallThrough)
6610 if (!thisReturn || canBreak)
6620 /*@switchbreak@*/ break;
6622 thisReturn = thisReturn || exprNode_mustEscape (current);
6623 canBreak = canBreak || current->canBreak;
6624 if (canBreak) fallThrough = FALSE;
6627 } end_exprNodeSList_elements;
6629 if (inSwitch) /* check the last one! */
6631 if (!thisReturn || canBreak)
6640 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
6641 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
6643 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
6645 voptgenerror (FLG_MISSCASE,
6646 message ("Missing case%s in switch: %q",
6647 cstring_makeLiteralTemp
6648 ((enumNameSList_size (unused) > 1) ? "s" : ""),
6649 enumNameSList_unparse (unused)),
6652 enumNameSList_free (unused);
6656 hasAllMembers = TRUE;
6660 enumNameSList_free (usedEnums);
6664 *allpaths = hasDefault;
6667 exprNodeSList_free (el);
6668 return ((hasDefault || hasAllMembers) && mustReturn);
6671 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
6673 exprNode ret = exprNode_createPartialCopy (e);
6676 DPRINTF (("Switch: %s", exprNode_unparse (s)));
6678 ret->kind = XPR_SWITCH;
6679 ret->edata = exprData_makePair (e, s);
6681 if (!exprNode_isError (s))
6683 exprNode fs = exprNode_firstStatement (s);
6684 ret->loc = fileloc_update (ret->loc, s->loc);
6686 if (exprNode_isUndefined (fs)
6687 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
6688 || exprNode_isDefaultMarker (fs)) {
6691 voptgenerror (FLG_FIRSTCASE,
6693 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
6698 if (!exprNode_isError (e))
6700 if (checkSwitchExpr (e, s, &allpaths))
6702 ret->exitCode = XK_MUSTRETURN;
6706 ret->exitCode = e->exitCode;
6709 ret->canBreak = e->canBreak;
6710 ret->mustBreak = e->mustBreak;
6714 ** exprNode.c:3883,32: Variable allpaths used before definition
6721 DPRINTF (("Context exit switch!"));
6722 context_exitSwitch (ret, allpaths);
6723 DPRINTF (("Context exit switch done!"));
6728 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
6729 /*@notnull@*/ exprNode body)
6731 sRefSet tuses = test->uses;
6733 if (!sRefSet_isEmpty (test->uses))
6735 sRefSet sets = sRefSet_newCopy (body->sets);
6736 bool hasError = TRUE;
6737 bool innerState = FALSE;
6738 sRefSet tuncon = sRefSet_undefined;
6740 sets = sRefSet_union (sets, test->sets);
6741 sets = sRefSet_union (sets, body->msets);
6742 sets = sRefSet_union (sets, test->msets);
6744 sRefSet_allElements (tuses, el)
6746 if (sRef_isUnconstrained (el))
6748 tuncon = sRefSet_insert (tuncon, el);
6752 if (sRefSet_member (sets, el))
6759 if (sRef_isInternalState (el)
6760 || sRef_isFileStatic (sRef_getRootBase (el)))
6764 } end_sRefSet_allElements ;
6768 sRefSet suncon = sRefSet_undefined;
6769 bool sinner = FALSE;
6771 sRefSet_allElements (sets, el)
6773 if (sRef_isUnconstrained (el))
6775 suncon = sRefSet_insert (suncon, el);
6777 else if (sRef_isInternalState (el))
6785 } end_sRefSet_allElements ;
6787 if (sinner && innerState)
6791 else if (sRefSet_isEmpty (tuncon)
6792 && sRefSet_isEmpty (suncon))
6797 ("Suspected infinite loop. No value used in loop test (%q) "
6798 "is modified by test or loop body.",
6799 sRefSet_unparsePlain (tuses)),
6804 if (sRefSet_isEmpty (tuncon))
6808 message ("Suspected infinite loop. No condition values "
6809 "modified. Modification possible through "
6810 "unconstrained calls: %q",
6811 sRefSet_unparsePlain (suncon)),
6818 message ("Suspected infinite loop. No condition values "
6819 "modified. Possible undetected dependency through "
6820 "unconstrained calls in loop test: %q",
6821 sRefSet_unparsePlain (tuncon)),
6827 sRefSet_free (sets);
6831 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
6834 bool emptyErr = FALSE;
6836 if (context_maybeSet (FLG_WHILEEMPTY))
6838 if (exprNode_isEmptyStatement (b))
6840 emptyErr = optgenerror
6843 ("Body of while statement is empty"),
6848 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
6850 if (exprNode_isDefined (b)
6851 && !exprNode_isBlock (b))
6853 if (context_inIterDef ()
6854 && (b->kind == XPR_STMTLIST
6855 || b->kind == XPR_TOK))
6861 voptgenerror (FLG_WHILEBLOCK,
6863 ("Body of while statement is not a block: %s",
6864 exprNode_unparse (b)),
6870 if (exprNode_isError (t))
6872 if (exprNode_isError (b))
6874 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6878 ret = exprNode_createPartialCopy (b);
6885 ret = exprNode_createPartialCopy (t);
6887 llassert (t->kind == XPR_WHILEPRED);
6889 test = exprData_getSingle (t->edata);
6891 if (!exprNode_isError (b) && exprNode_isDefined (test))
6893 if (context_maybeSet (FLG_INFLOOPS)
6894 || context_maybeSet (FLG_INFLOOPSUNCON))
6897 ** check that some variable in the predicate is set by the body
6898 ** if the predicate uses any variables
6901 checkInfiniteLoop (test, b);
6904 exprNode_mergeUSs (ret, b);
6906 if (exprNode_isDefined (b))
6908 ret->exitCode = exitkind_makeConditional (b->exitCode);
6913 ret->edata = exprData_makePair (t, b);
6914 ret->kind = XPR_WHILE;
6916 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
6920 message ("Predicate always exits: %s", exprNode_unparse (t)),
6924 ret->exitCode = XK_NEVERESCAPE;
6927 ** If loop is infinite, and there is no break inside,
6928 ** exit code is never reach.
6931 if (exprNode_knownIntValue (t))
6933 if (!exprNode_isZero (t))
6935 if (exprNode_isDefined (b))
6939 /* Really, it means never reached. */
6940 ret->exitCode = XK_MUSTEXIT;
6950 ret->canBreak = FALSE;
6951 ret->mustBreak = FALSE;
6957 ** do { b } while (t);
6959 ** note: body passed as first argument
6962 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
6966 if (exprNode_isError (t))
6968 if (exprNode_isError (b))
6970 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6974 ret = exprNode_createPartialCopy (b);
6976 ret->exitCode = exitkind_makeConditional (b->exitCode);
6977 exprNode_checkUse (ret, b->sref, b->loc);
6978 ret->exitCode = b->exitCode;
6979 ret->canBreak = b->canBreak;
6980 ret->mustBreak = b->mustBreak;
6985 ret = exprNode_createPartialCopy (t);
6986 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
6988 if (!exprNode_isError (b))
6991 ** forgot the copy's --- why wasn't this detected??
6994 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
6995 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
6996 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
6998 /* left this out --- causes and aliasing bug (infinite loop)
6999 should be detected?? */
7001 exprNode_checkUse (ret, b->sref, b->loc);
7002 exprNode_mergeUSs (ret, t);
7003 exprNode_checkUse (ret, t->sref, t->loc);
7005 ret->exitCode = b->exitCode;
7006 ret->canBreak = b->canBreak;
7007 ret->mustBreak = b->mustBreak;
7011 context_exitDoWhileClause (t);
7013 ret->kind = XPR_DOWHILE;
7014 ret->edata = exprData_makePair (t, b);
7018 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7021 bool emptyErr = FALSE;
7023 if (context_maybeSet (FLG_FOREMPTY))
7025 if (exprNode_isEmptyStatement (body))
7027 emptyErr = optgenerror
7030 ("Body of for statement is empty"),
7031 exprNode_loc (body));
7035 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7037 if (exprNode_isDefined (body)
7038 && !exprNode_isBlock (body))
7040 if (context_inIterDef ()
7041 && (body->kind == XPR_STMTLIST
7042 || body->kind == XPR_TOK))
7048 voptgenerror (FLG_FORBLOCK,
7050 ("Body of for statement is not a block: %s",
7051 exprNode_unparse (body)),
7052 exprNode_loc (body));
7058 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7061 if (exprNode_isError (body))
7063 ret = exprNode_createPartialCopy (inc);
7067 ret = exprNode_createPartialCopy (body);
7069 ret->exitCode = exitkind_makeConditional (body->exitCode);
7071 exprNode_mergeUSs (inc, body);
7073 if (exprNode_isDefined (inc))
7077 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7080 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7081 exprNode_freeShallow (tmp);
7083 context_clearMessageAnnote ();
7084 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7086 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7087 exprNode_freeShallow (tmp);
7089 context_clearMessageAnnote ();
7091 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7092 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7093 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7097 ret->kind = XPR_FOR;
7098 ret->edata = exprData_makePair (inc, body);
7100 if (exprNode_isDefined (inc)) {
7101 exprNode test = exprData_getTripleTest (inc->edata);
7103 if (exprNode_isUndefined (test)) {
7104 if (exprNode_isDefined (body)) {
7105 if (!body->canBreak) {
7106 /* Really, it means never reached. */
7107 ret->exitCode = XK_MUSTEXIT;
7117 ** for (init; test; inc)
7120 ** while (test) { body; inc; }
7122 ** Now: check use of init (may set vars for test)
7123 ** check use of test
7127 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7131 if (exprNode_isError (pred)) return guardSet_undefined;
7133 llassert (pred->kind == XPR_FORPRED);
7135 test = exprData_getTripleTest (pred->edata);
7137 if (!exprNode_isError (test))
7139 return (test->guards);
7142 return guardSet_undefined;
7145 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7147 exprNode ret = exprNode_createSemiCopy (test);
7149 if (exprNode_isDefined (test))
7151 exprNode_copySets (ret, test);
7152 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7153 exprNode_checkUse (ret, test->sref, test->loc);
7155 exprNode_produceGuards (test);
7157 ret->guards = guardSet_copy (test->guards);
7160 ret->edata = exprData_makeSingle (test);
7161 ret->kind = XPR_WHILEPRED;
7165 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7166 /*@only@*/ exprNode inc)
7171 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7174 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7176 if (!exprNode_isError (inc))
7178 ret = exprNode_createPartialCopy (inc);
7182 if (!exprNode_isError (init))
7184 ret = exprNode_createPartialCopy (init);
7186 else if (!exprNode_isError (test))
7188 ret = exprNode_createPartialCopy (test);
7192 ret = exprNode_createUnknown ();
7196 exprNode_mergeUSs (ret, init);
7198 if (exprNode_isDefined (init))
7200 exprNode_checkUse (ret, init->sref, init->loc);
7203 exprNode_mergeUSs (ret, test);
7205 if (exprNode_isDefined (test))
7207 exprNode_checkUse (ret, test->sref, test->loc);
7210 ret->kind = XPR_FORPRED;
7211 ret->edata = exprData_makeFor (init, test, inc);
7215 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7217 exprNode ret = exprNode_createUnknown ();
7219 if (context_inMacro ())
7221 voptgenerror (FLG_MACROSTMT,
7222 message ("Macro %s uses goto (not functional)",
7223 context_inFunctionName ()),
7227 ret->kind = XPR_GOTO;
7228 ret->edata = exprData_makeLiteral (label);
7229 ret->mustBreak = TRUE;
7230 ret->exitCode = XK_GOTO;
7231 ret->canBreak = TRUE;
7235 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7237 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7239 ret->kind = XPR_CONTINUE;
7240 ret->edata = exprData_makeTok (l);
7241 ret->canBreak = TRUE;
7242 ret->mustBreak = TRUE;
7244 if (qcontinue == QSAFEBREAK)
7248 else if (qcontinue == QINNERCONTINUE)
7250 if (!context_inDeepLoop ())
7253 (FLG_LOOPLOOPCONTINUE,
7254 cstring_makeLiteral ("Continue statement marked with innercontinue "
7255 "is not inside a nested loop"),
7256 exprNode_loc (ret));
7259 else if (qcontinue == BADTOK)
7261 if (context_inDeepLoop ())
7264 (FLG_LOOPLOOPCONTINUE,
7265 cstring_makeLiteral ("Continue statement in nested loop"),
7266 exprNode_loc (ret));
7271 llbuglit ("exprNode_continue: bad qcontinue");
7277 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
7279 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7280 clause breakClause = context_breakClause ();
7282 ret->kind = XPR_BREAK;
7283 ret->edata = exprData_makeTok (l);
7284 ret->canBreak = TRUE;
7285 ret->mustBreak = TRUE;
7287 if (breakClause == NOCLAUSE)
7291 cstring_makeLiteral ("Break not inside while, for or switch statement"),
7292 exprNode_loc (ret));
7296 if (bqual != BADTOK)
7303 if (breakClause == SWITCHCLAUSE)
7305 if (!context_inDeepSwitch ())
7307 voptgenerror (FLG_SYNTAX,
7309 ("Break preceded by innerbreak is not in a deep switch"),
7310 exprNode_loc (ret));
7315 if (!context_inDeepLoop ())
7317 voptgenerror (FLG_SYNTAX,
7319 ("Break preceded by innerbreak is not in a deep loop"),
7320 exprNode_loc (ret));
7325 if (breakClause == SWITCHCLAUSE)
7327 voptgenerror (FLG_SYNTAX,
7329 ("Break preceded by loopbreak is breaking a switch"),
7330 exprNode_loc (ret));
7334 if (breakClause != SWITCHCLAUSE)
7338 message ("Break preceded by switchbreak is breaking %s",
7339 cstring_makeLiteralTemp
7340 ((breakClause == WHILECLAUSE
7341 || breakClause == DOWHILECLAUSE) ? "a while loop"
7342 : (breakClause == FORCLAUSE) ? "a for loop"
7343 : (breakClause == ITERCLAUSE) ? "an iterator"
7345 exprNode_loc (ret));
7353 if (breakClause == SWITCHCLAUSE)
7355 clause nextBreakClause = context_nextBreakClause ();
7357 switch (nextBreakClause)
7359 case NOCLAUSE: break;
7365 (FLG_LOOPSWITCHBREAK,
7366 cstring_makeLiteral ("Break statement in switch inside loop"),
7367 exprNode_loc (ret));
7371 (FLG_SWITCHSWITCHBREAK,
7372 cstring_makeLiteral ("Break statement in switch inside switch"),
7373 exprNode_loc (ret));
7380 if (context_inDeepLoop ())
7384 cstring_makeLiteral ("Break statement in nested loop"),
7385 exprNode_loc (ret));
7389 if (context_inDeepLoopSwitch ())
7392 (FLG_SWITCHLOOPBREAK,
7393 cstring_makeLiteral ("Break statement in loop inside switch"),
7394 exprNode_loc (ret));
7404 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
7406 fileloc loc = lltok_getLoc (t);
7407 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
7409 context_returnFunction ();
7410 exprChecks_checkNullReturn (loc);
7412 ret->kind = XPR_NULLRETURN;
7413 ret->edata = exprData_makeTok (t);
7414 ret->exitCode = XK_MUSTRETURN;
7418 exprNode exprNode_return (/*@only@*/ exprNode e)
7422 if (exprNode_isError (e))
7424 ret = exprNode_createUnknown ();
7428 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
7430 exprNode_checkUse (ret, e->sref, e->loc);
7431 exprNode_checkReturn (e);
7434 context_returnFunction ();
7435 ret->kind = XPR_RETURN;
7436 ret->edata = exprData_makeSingle (e);
7437 ret->exitCode = XK_MUSTRETURN;
7442 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
7446 if (exprNode_isError (e1))
7448 if (exprNode_isError (e2))
7450 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
7454 ret = exprNode_createPartialCopy (e2);
7455 exprNode_checkUse (ret, e2->sref, e2->loc);
7456 ret->sref = e2->sref;
7461 ret = exprNode_createPartialCopy (e1);
7463 exprNode_checkUse (ret, e1->sref, e1->loc);
7465 if (!exprNode_isError (e2))
7467 exprNode_mergeUSs (ret, e2);
7468 exprNode_checkUse (ret, e2->sref, e2->loc);
7469 ret->sref = e2->sref;
7473 ret->kind = XPR_COMMA;
7474 ret->edata = exprData_makePair (e1, e2);
7476 if (exprNode_isDefined (e1))
7478 if (exprNode_isDefined (e2))
7482 if (exprNode_mustEscape (e1) || e1->mustBreak)
7486 message ("Second clause of comma expression is unreachable: %s",
7487 exprNode_unparse (e2)),
7491 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
7492 ret->mustBreak = e1->mustBreak || e2->mustBreak;
7493 ret->canBreak = e1->canBreak || e2->canBreak;
7497 if (exprNode_mustEscape (e1) || e1->mustBreak)
7501 message ("Second clause of comma expression is unreachable: %s",
7502 exprNode_unparse (e2)),
7506 ret->exitCode = e1->exitCode;
7507 ret->canBreak = e1->canBreak;
7512 if (exprNode_isDefined (e2))
7514 ret->exitCode = e2->exitCode;
7515 ret->mustBreak = e2->mustBreak;
7516 ret->canBreak = e2->canBreak;
7523 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
7525 ctype t1 = exprNode_getType (el);
7526 ctype t2 = exprNode_getType (val);
7527 bool hasError = FALSE;
7529 if (ctype_isUnknown (t1))
7531 voptgenerror (FLG_IMPTYPE,
7532 message ("Variable has unknown (implicitly int) type: %s",
7533 exprNode_unparse (el)),
7537 el->typ = ctype_int;
7540 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
7542 exprNodeList vals = exprData_getArgs (val->edata);
7544 if (ctype_isRealAP (t1))
7549 exprNodeList_elements (vals, oneval)
7551 cstring istring = message ("%d", i);
7554 (exprNode_fakeCopy (el),
7555 exprNode_numLiteral (ctype_int, istring,
7556 fileloc_copy (el->loc), i));
7558 if (exprNode_isDefined (newel))
7560 if (exprNodeList_size (vals) == 1
7561 && ctype_isString (exprNode_getType (oneval))
7562 && ctype_isChar (exprNode_getType (newel)))
7564 exprNode_freeIniter (newel);
7568 if (exprNode_checkOneInit (newel, oneval))
7573 if (nerrors > 3 && exprNodeList_size (vals) > 6)
7576 (message ("Additional initialization errors "
7577 "for %s not reported",
7578 exprNode_unparse (el)),
7580 exprNode_freeIniter (newel);
7585 exprNode_freeIniter (newel);
7590 exprNode_freeIniter (newel);
7595 cstring_free (istring);
7598 } end_exprNodeList_elements;
7601 else if (ctype_isStruct (ctype_realType (t1)))
7603 uentryList fields = ctype_getFields (t1);
7606 if (uentryList_size (fields) != exprNodeList_size (vals))
7608 if (uentryList_size (fields) > exprNodeList_size (vals))
7610 hasError = optgenerror
7612 message ("Initializer block for "
7613 "%s has %d field%&, but %s has %d field%&: %q",
7614 exprNode_unparse (el),
7615 exprNodeList_size (vals),
7617 uentryList_size (fields),
7618 exprNodeList_unparse (vals)),
7623 hasError = optgenerror
7625 message ("Initializer block for "
7626 "%s has %d field%&, but %s has %d field%&: %q",
7627 exprNode_unparse (el),
7628 exprNodeList_size (vals),
7630 uentryList_size (fields),
7631 exprNodeList_unparse (vals)),
7637 exprNodeList_elements (vals, oneval)
7639 uentry thisfield = uentryList_getN (fields, i);
7641 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
7643 uentry_getName (thisfield));
7645 if (exprNode_isDefined (newel))
7647 if (exprNode_checkOneInit (newel, oneval))
7652 exprNode_freeIniter (newel);
7656 } end_exprNodeList_elements;
7661 hasError = optgenerror
7663 message ("Initializer block used for "
7664 "%s where %t is expected: %s",
7665 exprNode_unparse (el), t1, exprNode_unparse (val)),
7671 if (exprNode_isDefined (val))
7673 doAssign (el, val, TRUE);
7675 if (!exprNode_matchType (t1, val))
7677 hasError = gentypeerror
7679 message ("Initial value of %s is type %t, "
7681 exprNode_unparse (el),
7682 t2, t1, exprNode_unparse (val)),
7692 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
7696 if (usymtab_exists (idDecl_observeId (t)))
7698 uentry ue = usymtab_lookup (idDecl_observeId (t));
7699 ret = exprNode_createId (ue);
7701 /*@i723 don't do this...but why? */
7703 ct = ctype_realishType (ret->typ);
7705 DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
7707 if (ctype_isUnknown (ct))
7709 if (uentry_isAnyTag (ue))
7713 message ("%s used but not previously declared: %s",
7714 uentry_ekindName (ue),
7715 idDecl_getName (t)),
7723 message ("Variable has unknown (implicitly int) type: %s",
7724 idDecl_getName (t)),
7734 uentry ue = uentry_makeUnrecognized (idDecl_observeId (t),
7736 ret = exprNode_fromIdentifierAux (ue);
7739 ** No error - this happens in old style declarations:
7743 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
7750 exprData_free (ret->edata, ret->kind);
7751 ret->edata = exprData_undefined;
7752 ret->exitCode = XK_NEVERESCAPE;
7753 ret->mustBreak = FALSE;
7754 ret->kind = XPR_INIT;
7758 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
7760 exprNode ret = exprNode_makeInitializationAux (t);
7761 llassert (ret->edata == exprData_undefined);
7762 ret->edata = exprData_makeInit (t, exprNode_undefined);
7766 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
7767 /*@only@*/ exprNode e)
7769 uentry ue = usymtab_lookup (idDecl_observeId (t));
7770 exprNode ret = exprNode_makeInitializationAux (t);
7771 fileloc loc = exprNode_loc (e);
7773 if (exprNode_isError (e))
7775 e = exprNode_createUnknown ();
7778 /* error: assume initializer is defined */
7779 sRef_setDefined (ret->sref, g_currentloc);
7783 ctype ct = ctype_realishType (ret->typ);
7788 ** was addSafeUse --- what's the problem?
7790 ** int x = 3, y = x ?
7793 exprData_free (ret->edata, ret->kind);
7794 ret->edata = exprData_makeInit (t, e);
7796 exprNode_checkUse (ret, e->sref, e->loc);
7798 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
7800 exprNode lhs = exprNode_createId (ue);
7803 ** static storage should be undefined before initializing
7806 if (uentry_isStatic (ue))
7808 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
7811 (void) exprNode_checkOneInit (lhs, e);
7813 if (uentry_isStatic (ue))
7815 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
7818 exprNode_free (lhs);
7822 if (!exprNode_matchType (ct, e))
7824 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
7831 (exprNode_getType (e), e, exprNode_getType (ret), ret,
7833 ("Variable %q initialized to type %t, expects %t: %s",
7834 uentry_getName (ue), exprNode_getType (e),
7835 exprNode_getType (ret),
7836 exprNode_unparse (e)),
7842 if (uentry_isStatic (ue))
7844 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
7847 doAssign (ret, e, TRUE);
7849 if (uentry_isStatic (ue))
7851 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
7855 if (context_inIterDef ())
7857 /* should check if it is yield */
7858 uentry_setUsed (ue, loc);
7865 exprNode_mergeUSs (ret, e);
7869 exprNode exprNode_iter (/*@observer@*/ uentry name,
7870 /*@only@*/ exprNodeList alist,
7871 /*@only@*/ exprNode body,
7872 /*@observer@*/ uentry end)
7877 llassert (uentry_isValid (name));
7879 uentry_setUsed (name, exprNode_loc (body));
7881 ret = exprNode_createPartialCopy (body);
7882 iname = uentry_getName (name);
7884 if (uentry_isInvalid (end))
7887 message ("Iter %s not balanced with end_%s", iname, iname));
7891 cstring ename = uentry_getName (end);
7893 if (!cstring_equalPrefix (ename, "end_"))
7895 llerror (FLG_ITER, message ("Iter %s not balanced with end_%s: %s",
7896 iname, iname, ename));
7900 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
7903 message ("Iter %s not balanced with end_%s: %s",
7904 iname, iname, ename));
7908 cstring_free (ename);
7911 context_exitIterClause (body);
7913 ret->kind = XPR_ITER;
7914 ret->edata = exprData_makeIter (name, alist, body, end);
7916 if (uentry_isIter (name))
7918 (void) checkArgsReal (name, body,
7919 uentry_getParams (name), alist, TRUE, ret);
7922 cstring_free (iname);
7928 exprNode_iterNewId (/*@only@*/ cstring s)
7930 exprNode e = exprNode_new ();
7931 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
7933 llassert (processingIterVars ());
7935 e->loc = context_getSaveLocation ();
7937 if (fileloc_isUndefined (e->loc))
7939 fileloc_free (e->loc);
7940 e->loc = fileloc_copy (g_currentloc);
7943 e->uses = sRefSet_new ();
7944 e->sets = sRefSet_new ();
7945 e->msets = sRefSet_new ();
7947 e->val = multiVal_unknown ();
7948 e->guards = guardSet_new ();
7950 e->isJumpPoint = FALSE;
7951 e->exitCode = XK_NEVERESCAPE;
7953 /*> missing fields, detected by lclint <*/
7954 e->canBreak = FALSE;
7955 e->mustBreak = FALSE;
7956 e->etext = cstring_undefined;
7958 if (uentry_isYield (ue))
7960 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
7961 fileloc_copy (e->loc),
7965 uue = usymtab_supEntrySrefReturn (uue);
7967 sr = uentry_getSref (uue);
7968 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
7969 sr = uentry_getSref (uue);
7970 sRef_setDefined (sr, e->loc);
7972 e->typ = uentry_getType (uue);
7974 e->edata = exprData_makeId (uue);
7975 uentry_setUsed (uue, g_currentloc);
7981 sRef_setGlobalScope ();
7982 uue = uentry_makeVariableLoc (s, ctype_unknown);
7984 e->typ = ctype_unknown;
7985 e->edata = exprData_makeId (uue);
7987 uentry_setUsed (uue, e->loc);
7988 uentry_setHasNameError (uue);
7990 if (context_getFlag (FLG_REPEATUNRECOG))
7992 uentry_markOwned (uue);
7996 usymtab_supGlobalEntry (uue);
7999 sRef_clearGlobalScope ();
8001 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8008 exprNode_defineConstraints(e);
8013 exprNode_iterExpr (/*@returned@*/ exprNode e)
8015 if (!processingIterVars ())
8017 llcontbuglit ("checkIterParam: not in iter");
8021 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8024 if (exprNode_isDefined (e))
8026 if (fileloc_isDefined (e->loc))
8030 message ("Yield parameter is not simple identifier: %s",
8031 exprNode_unparse (e)),
8038 message ("Yield parameter is not simple identifier: %s",
8039 exprNode_unparse (e)),
8049 exprNode_iterId (/*@observer@*/ uentry c)
8053 llassert (processingIterVars ());
8055 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8058 if (uentry_isYield (ue))
8060 ctype ct = uentry_getType (ue);
8061 exprNode e = exprNode_createPlain (ct);
8062 cstring name = uentry_getName (c);
8063 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8065 uentry_setUsed (ue, g_currentloc);
8066 uentry_setHasNameError (ue);
8068 cstring_free (name);
8071 e->edata = exprData_makeId (le);
8072 e->loc = context_getSaveLocation ();
8073 e->sref = uentry_getSref (le);
8075 usymtab_supEntrySref (le);
8077 if (!context_inHeader ())
8081 message ("Yield parameter shadows local declaration: %q",
8082 uentry_getName (c)),
8083 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8085 uentry_showWhereDeclared (c);
8092 return (exprNode_fromIdentifierAux (c));
8095 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8097 exprNode ret = exprNode_create (ctype_unknown);
8099 ret->kind = XPR_ITERCALL;
8100 ret->edata = exprData_makeIterCall (name, alist);
8102 if (uentry_isIter (name))
8104 uentryList params = uentry_getParams (name);
8106 if (context_inIterDef ()
8107 && uentryList_size (params) == exprNodeList_size (alist))
8111 exprNodeList_elements (alist, arg)
8113 uentry parg = uentryList_getN (params, i);
8115 if (uentry_isYield (parg))
8117 uentry ue = exprNode_getUentry (arg);
8119 if (uentry_isValid (ue))
8126 } end_exprNodeList_elements;
8129 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8130 checkUnspecCall (ret, params, alist);
8136 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8138 if (exprNode_isDefined (e))
8141 if (e->sref == defref) /*@noaccess sRef@*/
8144 e->sref = sRef_makeUnknown ();
8145 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8156 return sRef_undefined;
8160 /*@observer@*/ cstring
8161 exprNode_unparseFirst (exprNode e)
8163 if (exprNode_isDefined (e))
8167 if (e->kind == XPR_STMTLIST
8168 || e->kind == XPR_COMMA || e->kind == XPR_COND)
8170 exprNode first = exprData_getPairA (e->edata);
8172 if (exprNode_isDefined (first))
8174 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8178 return (cstring_makeLiteralTemp ("..."));
8182 ret = cstring_elide (exprNode_unparse (e), 20);
8183 cstring_markOwned (ret);
8189 return cstring_makeLiteralTemp ("<error>");
8193 /*@observer@*/ cstring
8194 exprNode_unparse (/*@temp@*/ exprNode e)
8196 if (exprNode_isError (e))
8198 return cstring_makeLiteralTemp ("<error>");
8201 if (cstring_isDefined (e->etext))
8207 cstring ret = exprNode_doUnparse (e);
8209 /*@-modifies@*/ /* benevolent */
8216 /*@observer@*/ fileloc
8217 exprNode_loc (exprNode e)
8219 if (exprNode_isError (e))
8221 return (g_currentloc);
8230 ** executes exprNode e
8231 ** recursively rexecutes as though in original parse using
8232 ** information in e->edata
8235 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
8237 exprNodeList ret = exprNodeList_new ();
8239 exprNodeList_elements (e, current)
8241 exprNodeList_addh (ret, exprNode_effect (current));
8242 } end_exprNodeList_elements;
8247 static /*@only@*/ exprNode exprNode_effect (exprNode e)
8248 /*@globals internalState@*/
8250 bool innerEffect = inEffect;
8256 context_clearJustPopped ();
8258 if (exprNode_isError (e))
8260 ret = exprNode_undefined;
8265 ** Turn off expose and dependent transfer checking.
8266 ** Need to pass exposed internal nodes,
8267 ** [ copying would be a waste! ]
8268 ** [ Actually, I think I wasted a lot more time than its worth ]
8269 ** [ trying to do this. ]
8273 /*@-observertrans@*/
8274 /*@-dependenttrans@*/
8281 ret = exprNode_addParens (exprData_getUopTok (data),
8282 exprNode_effect (exprData_getUopNode (data)));
8285 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
8286 exprNode_effect (exprData_getOpB (data)),
8287 exprData_getOpTok (data));
8290 ret = exprNode_undefined;
8293 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
8294 exprNodeList_effect (exprData_getArgs (data)));
8307 cstring id = exprData_getId (data);
8308 uentry ue = usymtab_lookupSafe (id);
8310 ret = exprNode_fromIdentifierAux (ue);
8311 ret->loc = fileloc_update (ret->loc, e->loc);
8318 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
8319 exprNode_effect (exprData_getPairB (data)));
8322 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
8323 exprNode_effect (exprData_getOpB (data)),
8324 exprData_getOpTok (data));
8328 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
8329 exprData_getUopTok (data));
8332 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
8333 exprData_getUopTok (data));
8345 ret = exprNode_vaArg (exprData_getCastTok (data),
8346 exprNode_effect (exprData_getCastNode (data)),
8347 exprData_getCastType (data));
8351 ret = exprNode_cast (exprData_getCastTok (data),
8352 exprNode_effect (exprData_getCastNode (data)),
8353 exprData_getCastType (data));
8356 ret = exprNode_iterStart (exprData_getIterCallIter (data),
8358 (exprData_getIterCallArgs (data)));
8362 ret = exprNode_iter (exprData_getIterSname (data),
8363 exprNodeList_effect (exprData_getIterAlist (data)),
8364 exprNode_effect (exprData_getIterBody (data)),
8365 exprData_getIterEname (data));
8369 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
8370 exprNode_effect (exprData_getPairB (data)));
8374 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
8375 exprNode_effect (exprData_getTripleTest (data)),
8376 exprNode_effect (exprData_getTripleInc (data)));
8380 ret = exprNode_createTok (exprData_getTok (data));
8384 ret = exprNode_goto (exprData_getLiteral (data));
8385 ret->loc = fileloc_update (ret->loc, e->loc);
8389 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
8393 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
8397 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
8400 case XPR_NULLRETURN:
8401 ret = exprNode_nullReturn (exprData_getTok (data));
8405 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
8406 exprNode_effect (exprData_getPairB (data)));
8410 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
8411 exprNode_effect (exprData_getTripleTrue (data)),
8412 exprNode_effect (exprData_getTripleFalse (data)));
8415 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
8416 exprNode_effect (exprData_getPairB (data)));
8420 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
8421 exprNode_effect (exprData_getTripleTrue (data)),
8422 exprNode_effect (exprData_getTripleFalse (data)));
8425 ret = exprNode_whilePred (exprData_getSingle (data));
8429 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
8430 exprNode_effect (exprData_getPairB (data)));
8434 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
8435 exprNode_effect (exprData_getPairB (data)));
8439 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
8443 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
8444 exprData_getUopTok (data));
8448 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
8449 exprNode_effect (exprData_getPairB (data)));
8454 ret = exprNode_caseMarker
8455 (exprNode_effect (exprData_getSingle (data)),
8461 ret = exprNode_createTok (exprData_getTok (data));
8465 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
8466 exprNode_effect (exprData_getPairB (data)));
8470 ret = exprNode_makeInitialization
8471 (exprData_getInitId (data),
8472 exprNode_effect (exprData_getInitNode (data)));
8476 ret = exprNode_fieldAccessAux
8477 (exprNode_effect (exprData_getFieldNode (data)),
8478 exprNode_loc (exprData_getFieldNode (data)),
8479 cstring_copy (exprData_getFieldName (data)));
8483 ret = exprNode_arrowAccessAux
8484 (exprNode_effect (exprData_getFieldNode (data)),
8485 exprNode_loc (exprData_getFieldNode (data)),
8486 cstring_copy (exprData_getFieldName (data)));
8489 case XPR_STRINGLITERAL:
8503 /*@=observertrans@*/
8505 /*@=dependenttrans@*/
8516 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
8521 if (exprNode_isError (e))
8523 return cstring_undefined;
8531 ret = exprNode_rootVarName (exprData_getUopNode (data));
8534 ret = exprNode_rootVarName (exprData_getOpA (data));
8538 ret = exprData_getId (data);
8563 case XPR_NULLRETURN:
8586 case XPR_STRINGLITERAL:
8587 ret = cstring_undefined;
8594 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
8599 if (exprNode_isError (e))
8601 static /*@only@*/ cstring error = cstring_undefined;
8603 if (!cstring_isDefined (error))
8605 error = cstring_makeLiteral ("<error>");
8616 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
8619 ret = message ("%s %s %s",
8620 exprNode_unparse (exprData_getOpA (data)),
8621 lltok_unparse (exprData_getOpTok (data)),
8622 exprNode_unparse (exprData_getOpB (data)));
8625 ret = message ("%s(%q)",
8626 exprNode_unparse (exprData_getFcn (data)),
8627 exprNodeList_unparse (exprData_getArgs (data)));
8630 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
8633 ret = cstring_undefined;
8636 ret = message ("%s:", exprData_getId (data));
8640 ret = cstring_copy (exprData_getId (data));
8643 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
8644 exprNode_unparse (exprData_getPairB (data)));
8647 ret = message ("<body>");
8650 ret = message ("%s %s %s",
8651 exprNode_unparse (exprData_getOpA (data)),
8652 lltok_unparse (exprData_getOpTok (data)),
8653 exprNode_unparse (exprData_getOpB (data)));
8657 ret = message ("%s%s",
8658 lltok_unparse (exprData_getUopTok (data)),
8659 exprNode_unparse (exprData_getUopNode (data)));
8663 ret = message ("%s%s",
8664 exprNode_unparse (exprData_getUopNode (data)),
8665 lltok_unparse (exprData_getUopTok (data)));
8669 ret = message ("offsetof(%s,%q)",
8670 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
8671 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
8675 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8679 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
8683 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8687 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
8691 ret = message ("va_arg(%s, %q)",
8692 exprNode_unparse (exprData_getCastNode (data)),
8693 qtype_unparse (exprData_getCastType (data)));
8697 ret = message ("%q(%q)",
8698 uentry_getName (exprData_getIterCallIter (data)),
8699 exprNodeList_unparse (exprData_getIterCallArgs (data)));
8702 ret = message ("%q(%q) %s %q",
8703 uentry_getName (exprData_getIterSname (data)),
8704 exprNodeList_unparse (exprData_getIterAlist (data)),
8705 exprNode_unparse (exprData_getIterBody (data)),
8706 uentry_getName (exprData_getIterEname (data)));
8709 ret = message ("(%q)%s",
8710 qtype_unparse (exprData_getCastType (data)),
8711 exprNode_unparse (exprData_getCastNode (data)));
8715 ret = message ("%s %s",
8716 exprNode_unparse (exprData_getPairA (data)),
8717 exprNode_unparse (exprData_getPairB (data)));
8721 ret = message ("for (%s; %s; %s)",
8722 exprNode_unparse (exprData_getTripleInit (data)),
8723 exprNode_unparse (exprData_getTripleTest (data)),
8724 exprNode_unparse (exprData_getTripleInc (data)));
8728 ret = message ("goto %s", exprData_getLiteral (data));
8732 ret = cstring_makeLiteral ("continue");
8736 ret = cstring_makeLiteral ("break");
8740 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
8743 case XPR_NULLRETURN:
8744 ret = cstring_makeLiteral ("return");
8748 ret = message ("%s, %s",
8749 exprNode_unparse (exprData_getPairA (data)),
8750 exprNode_unparse (exprData_getPairB (data)));
8754 ret = message ("%s ? %s : %s",
8755 exprNode_unparse (exprData_getTriplePred (data)),
8756 exprNode_unparse (exprData_getTripleTrue (data)),
8757 exprNode_unparse (exprData_getTripleFalse (data)));
8760 ret = message ("if (%s) %s",
8761 exprNode_unparse (exprData_getPairA (data)),
8762 exprNode_unparse (exprData_getPairB (data)));
8766 ret = message ("if (%s) %s else %s",
8767 exprNode_unparse (exprData_getTriplePred (data)),
8768 exprNode_unparse (exprData_getTripleTrue (data)),
8769 exprNode_unparse (exprData_getTripleFalse (data)));
8772 ret = message ("while (%s) %s",
8773 exprNode_unparse (exprData_getPairA (data)),
8774 exprNode_unparse (exprData_getPairB (data)));
8778 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
8782 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
8786 ret = message ("do { %s } while (%s)",
8787 exprNode_unparse (exprData_getPairB (data)),
8788 exprNode_unparse (exprData_getPairA (data)));
8792 ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
8796 ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
8800 ret = message ("%s; %s",
8801 exprNode_unparse (exprData_getPairA (data)),
8802 exprNode_unparse (exprData_getPairB (data)));
8807 ret = cstring_makeLiteral ("default:");
8811 ret = message ("switch (%s) %s",
8812 exprNode_unparse (exprData_getPairA (data)),
8813 exprNode_unparse (exprData_getPairB (data)));
8818 ret = message ("case %s:",
8819 exprNode_unparse (exprData_getSingle (data)));
8823 if (exprNode_isError (exprData_getInitNode (data)))
8825 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
8829 ret = message ("%q = %s",
8830 idDecl_unparseC (exprData_getInitId (data)),
8831 exprNode_unparse (exprData_getInitNode (data)));
8836 ret = message ("%s.%s",
8837 exprNode_unparse (exprData_getFieldNode (data)),
8838 exprData_getFieldName (data));
8842 ret = message ("%s->%s",
8843 exprNode_unparse (exprData_getFieldNode (data)),
8844 exprData_getFieldName (data));
8847 case XPR_STRINGLITERAL:
8848 ret = message ("\"%s\"", exprData_getLiteral (data));
8852 ret = cstring_copy (exprData_getLiteral (data));
8856 ret = cstring_makeLiteral ("<node>");
8864 exprNode_isInitializer (exprNode e)
8866 return (exprNode_isDefined (e)
8867 && e->kind == XPR_INIT);
8871 exprNode_isCharLit (exprNode e)
8873 if (exprNode_isDefined (e))
8875 return (multiVal_isChar (exprNode_getValue (e)));
8884 exprNode_isNumLit (exprNode e)
8886 if (exprNode_isDefined (e))
8888 return (multiVal_isInt (exprNode_getValue (e)));
8897 exprNode_isFalseConstant (exprNode e)
8899 if (exprNode_isDefined (e))
8901 cstring s = exprNode_rootVarName (e);
8903 if (cstring_equal (s, context_getFalseName ()))
8913 exprNode_matchLiteral (ctype expected, exprNode e)
8915 if (exprNode_isDefined (e))
8917 multiVal m = exprNode_getValue (e);
8919 if (multiVal_isDefined (m))
8921 if (multiVal_isInt (m))
8923 long int val = multiVal_forceInt (m);
8925 if (ctype_isDirectBool (ctype_realishType (expected)))
8929 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
8937 if (ctype_isRealInt (expected))
8940 ** unsigned <- [ constant >= 0 is okay ]
8943 if (ctype_isUnsigned (expected))
8952 ** No checks on sizes of integers...maybe add
8956 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
8957 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
8958 bool_unparse (ctype_isInt (exprNode_getType (e)))));
8960 if (context_getFlag (FLG_NUMLITERAL)
8961 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
8967 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
8971 else if (ctype_isChar (expected))
8975 else if (ctype_isArrayPtr (expected))
8979 else if (ctype_isAnyFloat (expected))
8981 return (context_getFlag (FLG_NUMLITERAL));
8988 else if (multiVal_isDouble (m))
8990 if (ctype_isAnyFloat (expected))
8995 else if (multiVal_isChar (m))
8997 char val = multiVal_forceChar (m);
8999 if (ctype_isChar (expected))
9001 if (ctype_isUnsigned (expected) && ((int)val) < 0)
9022 exprNode_matchType (ctype expected, exprNode e)
9026 if (!exprNode_isDefined (e)) return TRUE;
9028 actual = ctype_realishType (exprNode_getType (e));
9030 if (ctype_match (ctype_realishType (expected), actual))
9035 llassert (!exprNode_isError (e));
9036 return (exprNode_matchLiteral (expected, e));
9040 exprNode_matchTypes (exprNode e1, exprNode e2)
9045 if (!exprNode_isDefined (e1)) return TRUE;
9046 if (!exprNode_isDefined (e2)) return TRUE;
9049 ** realish type --- keep bools, bools
9052 t1 = ctype_realishType (exprNode_getType (e1));
9053 t2 = ctype_realishType (exprNode_getType (e2));
9055 if (ctype_match (t1, t2))
9060 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9068 exprNode_matchArgType (ctype ct, exprNode e)
9072 if (!exprNode_isDefined (e))
9077 et = ctype_realType (exprNode_getType (e));
9079 if (ctype_matchArg (ct, et)) return TRUE;
9081 llassert (!exprNode_isError (e));
9082 return (exprNode_matchLiteral (ct, e));
9085 static /*@only@*/ exprNodeSList
9086 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9088 if (exprNode_isDefined (e))
9090 if (e->kind == XPR_STMTLIST)
9092 return (exprNodeSList_append
9093 (exprNode_flatten (exprData_getPairA (e->edata)),
9094 exprNode_flatten (exprData_getPairB (e->edata))));
9096 else if (e->kind == XPR_BLOCK)
9098 return (exprNode_flatten (exprData_getSingle (e->edata)));
9102 return (exprNodeSList_singleton (e));
9106 return exprNodeSList_new ();
9109 static /*@exposed@*/ exprNode
9110 exprNode_lastStatement (/*@returned@*/ exprNode e)
9112 if (exprNode_isDefined (e))
9114 if (e->kind == XPR_STMTLIST)
9116 exprNode b = exprData_getPairB (e->edata);
9118 if (exprNode_isDefined (b))
9120 return exprNode_lastStatement (b);
9124 return exprNode_lastStatement (exprData_getPairA (e->edata));
9127 else if (e->kind == XPR_BLOCK)
9129 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
9137 return exprNode_undefined;
9140 static /*@exposed@*/ exprNode
9141 exprNode_firstStatement (/*@returned@*/ exprNode e)
9143 if (exprNode_isDefined (e))
9145 if (e->kind == XPR_STMTLIST)
9147 exprNode b = exprData_getPairA (e->edata);
9149 if (exprNode_isDefined (b))
9151 return exprNode_firstStatement (b);
9155 return exprNode_firstStatement (exprData_getPairB (e->edata));
9158 else if (e->kind == XPR_BLOCK)
9160 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
9168 return exprNode_undefined;
9172 exprNode_mergeUSs (exprNode res, exprNode other)
9174 if (exprNode_isDefined (res) && exprNode_isDefined (other))
9176 res->msets = sRefSet_union (res->msets, other->msets);
9177 res->sets = sRefSet_union (res->sets, other->sets);
9178 res->uses = sRefSet_union (res->uses, other->uses);
9183 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
9185 if (exprNode_isDefined (res))
9187 if (exprNode_isDefined (other1))
9189 res->sets = sRefSet_union (res->sets, other1->sets);
9190 res->msets = sRefSet_union (res->msets, other1->msets);
9191 res->uses = sRefSet_union (res->uses, other1->uses);
9193 if (exprNode_isDefined (other2))
9195 res->sets = sRefSet_union (res->sets, other2->sets);
9196 res->msets = sRefSet_union (res->msets, other2->msets);
9197 res->uses = sRefSet_union (res->uses, other2->uses);
9205 ** Reports errors is s is not defined.
9209 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
9211 if (exprNode_isDefined (e))
9213 e->uses = sRefSet_insert (e->uses, s);
9218 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
9220 if (sRef_isKnown (s) && !sRef_isConst (s))
9223 ** need to check all outer types are useable
9226 DPRINTF (("Check use: %s / %s",
9227 exprNode_unparse (e), sRef_unparse (s)));
9229 exprNode_addUse (e, s);
9231 if (!context_inProtectVars ())
9234 ** only report the deepest error
9237 sRef errorRef = sRef_undefined;
9238 sRef lastRef = sRef_undefined;
9239 bool deadRef = FALSE;
9240 bool unuseable = FALSE;
9241 bool errorMaybe = FALSE;
9243 while (sRef_isValid (s) && sRef_isKnown (s))
9245 ynm readable = sRef_isReadable (s);
9247 DPRINTF (("Readable: %s / %s",
9248 sRef_unparseFull (s), ynm_unparse (readable)));
9250 if (!(ynm_toBoolStrict (readable)))
9252 if (ynm_isMaybe (readable))
9256 deadRef = sRef_isPossiblyDead (errorRef);
9257 unuseable = sRef_isUnuseable (errorRef);
9264 deadRef = sRef_isDead (errorRef);
9265 unuseable = sRef_isUnuseable (errorRef);
9269 if (!sRef_isPartial (s))
9271 sRef_setDefined (s, fileloc_undefined);
9275 s = sRef_getBaseSafe (s);
9278 if (sRef_isValid (errorRef))
9280 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
9281 && sRef_isPointer (errorRef))
9288 if (sRef_isThroughArrayFetch (errorRef))
9291 (FLG_STRICTUSERELEASED,
9292 message ("%q %q may be used after being released",
9293 sRef_unparseKindNamePlain (errorRef),
9294 sRef_unparse (errorRef)),
9297 sRef_showRefKilled (errorRef);
9299 if (sRef_isKept (errorRef))
9301 sRef_clearAliasState (errorRef, loc);
9307 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
9311 message ("%q %q %qused after being released",
9312 sRef_unparseKindNamePlain (errorRef),
9313 sRef_unparse (errorRef),
9314 cstring_makeLiteral (errorMaybe
9318 sRef_showRefKilled (errorRef);
9320 if (sRef_isKept (errorRef))
9322 sRef_clearAliasState (errorRef, loc);
9331 message ("%q %q%qused in inconsistent state",
9332 sRef_unparseKindName (errorRef),
9333 sRef_unparseOpt (errorRef),
9334 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9337 sRef_showStateInconsistent (errorRef);
9342 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
9346 message ("%q %q%qused before definition",
9347 sRef_unparseKindName (errorRef),
9348 sRef_unparseOpt (errorRef),
9349 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9353 sRef_setDefined (errorRef, loc);
9355 if (sRef_isAddress (errorRef))
9357 sRef_setDefined (sRef_getRootBase (errorRef), loc);
9359 } /* end is error */
9367 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
9369 if (exprNode_isDefined (e) && sRef_isKnown (s))
9371 e->uses = sRefSet_insert (e->uses, s);
9376 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
9378 if (exprNode_isDefined (e))
9380 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
9385 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
9387 sRef defines = sRef_undefined;
9389 if (sRef_isValid (s) && !sRef_isNothing (s))
9391 uentry ue = sRef_getBaseUentry (s);
9393 if (uentry_isValid (ue))
9395 uentry_setLset (ue);
9398 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9400 voptgenerror (FLG_USEDEF,
9401 message ("Attempt to set unuseable storage: %q",
9406 if (sRef_isMeaningful (s))
9409 if (sRef_isDead (s))
9411 sRef base = sRef_getBaseSafe (s);
9413 if (sRef_isValid (base)
9414 && sRef_isDead (base))
9416 sRef_setPartial (s, exprNode_loc (e));
9419 defines = s; /* okay - modifies for only param */
9421 else if (sRef_isPartial (s))
9423 sRef eref = exprNode_getSref (e);
9425 if (!sRef_isPartial (eref))
9428 ** should do something different here???
9431 sRef_setDefinedComplete (eref, exprNode_loc (e));
9435 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
9438 if (sRef_isMeaningful (eref))
9447 else if (sRef_isAllocated (s))
9449 sRef eref = exprNode_getSref (e);
9452 if (!sRef_isAllocated (eref))
9454 sRef_setDefinedComplete (eref, exprNode_loc (e));
9458 sRef base = sRef_getBaseSafe (eref);
9460 if (sRef_isValid (base))
9462 sRef_setPdefined (base, exprNode_loc (e));
9470 sRef_setDefinedNCComplete (s, exprNode_loc (e));
9475 else /* not meaningful...but still need to insert it */
9481 if (exprNode_isDefined (e) && sRef_isValid (defines))
9483 e->sets = sRefSet_insert (e->sets, defines);
9488 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
9490 if (sRef_isValid (s) && !sRef_isNothing (s))
9492 uentry ue = sRef_getBaseUentry (s);
9494 if (uentry_isValid (ue))
9496 uentry_setLset (ue);
9499 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9501 voptgenerror (FLG_USEDEF,
9502 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
9506 if (sRef_isMeaningful (s))
9508 sRef_setDefinedComplete (s, exprNode_loc (e));
9511 if (exprNode_isDefined (e))
9513 e->msets = sRefSet_insert (e->msets, s);
9519 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
9521 checkAnyCall (fcn, cstring_undefined, params, args,
9522 FALSE, sRefSet_undefined, FALSE, 0);
9526 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
9527 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
9531 if (uentry_isYield (ucurrent))
9533 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
9534 exprNode_checkSet (current, current->sref);
9538 if (uentry_isSefParam (ucurrent))
9540 sRefSet sets = current->sets;
9541 sRef ref = exprNode_getSref (current);
9543 if (sRef_isMacroParamRef (ref))
9545 uentry ue = sRef_getUentry (ref);
9547 if (!uentry_isSefParam (ue))
9552 ("Parameter %d to %s is declared sef, but "
9553 "the argument is a macro parameter declared "
9555 argno, exprNode_unparse (fcn),
9556 exprNode_unparse (current)),
9557 exprNode_loc (current));
9561 if (!sRefSet_isEmpty (sets))
9563 sRefSet reported = sRefSet_undefined;
9565 sRefSet_realElements (current->sets, el)
9567 if (sRefSet_isSameNameMember (reported, el))
9569 ; /* don't report again */
9573 if (sRef_isUnconstrained (el))
9578 ("Parameter %d to %s is declared sef, but "
9579 "the argument calls unconstrained function %s "
9580 "(no guarantee it will not modify something): %s",
9581 argno, exprNode_unparse (fcn),
9582 sRef_unconstrainedName (el),
9583 exprNode_unparse (current)),
9584 exprNode_loc (current));
9591 ("Parameter %d to %s is declared sef, but "
9592 "the argument may modify %q: %s",
9593 argno, exprNode_unparse (fcn),
9595 exprNode_unparse (current)),
9596 exprNode_loc (current));
9599 } end_sRefSet_realElements;
9603 checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs);
9604 exprNode_mergeUSs (fcn, current);
9609 checkAnyCall (/*@dependent@*/ exprNode fcn,
9610 /*@dependent@*/ cstring fname,
9613 bool hasMods, sRefSet mods,
9618 int nargs = exprNodeList_size (args);
9623 ** concat all args ud's to f, add each arg sref as a use unless
9624 ** it was specified as "out", in which case it is a def.
9627 uentryList_reset (pn);
9632 ** if paramn is only or unique, no other arg may alias argn
9635 exprNodeList_elements (args, current)
9639 if (exprNode_isDefined (current))
9641 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
9643 uentry ucurrent = uentryList_current (pn);
9645 if (specialArgs == 0
9646 || (paramno < specialArgs))
9648 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
9650 if (context_maybeSet (FLG_ALIASUNIQUE))
9652 if (uentry_isOnly (ucurrent)
9653 || uentry_isUnique (ucurrent))
9655 checkUniqueParams (fcn, current, args,
9661 else /* uentry is undefined */
9663 if (specialArgs == 0)
9665 exprNode_checkUseParam (current);
9668 exprNode_mergeUSs (fcn, current);
9671 uentryList_advanceSafe (pn);
9672 } end_exprNodeList_elements;
9678 sRefSet_allElements (mods, s)
9681 sRef rb = sRef_getRootBase (s);
9683 if (sRef_isFileOrGlobalScope (rb))
9685 context_usedGlobal (rb);
9688 fb = sRef_fixBaseParam (s, args);
9690 if (!sRef_isMacroParamRef (fb))
9692 if (sRef_isNothing (fb))
9698 if (sRef_isValid (fb))
9700 uentry ue = sRef_getBaseUentry (s);
9702 if (uentry_isValid (ue))
9704 uentry_setLset (ue);
9708 fcn->sets = sRefSet_insert (fcn->sets, fb);
9711 sRef_clearDerivedComplete (s);
9712 } end_sRefSet_allElements;
9718 if (context_hasMods ())
9720 if (context_maybeSet (FLG_MODUNCON))
9724 message ("Undetected modification possible "
9725 "from call to unconstrained function %s: %s",
9727 exprNode_unparse (fcn)),
9728 exprNode_loc (fcn));
9733 if (context_maybeSet (FLG_MODUNCONNOMODS)
9734 && !(context_inIterDef () || context_inIterEnd ()))
9737 (FLG_MODUNCONNOMODS,
9738 message ("Undetected modification possible "
9739 "from call to unconstrained function %s: %s",
9741 exprNode_unparse (fcn)),
9742 exprNode_loc (fcn));
9746 exprNode_checkSetAny (fcn, fname);
9750 void exprNode_checkUseParam (exprNode current)
9752 if (exprNode_isDefined (current))
9754 exprNode_checkUse (current, current->sref, current->loc);
9759 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
9760 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
9765 if (!ctype_match (tr1, tr2))
9767 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
9768 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
9776 message ("Incompatible types for %s (%s, %s): %s %s %s",
9778 ctype_unparse (te1),
9779 ctype_unparse (te2),
9780 exprNode_unparse (e1), lltok_unparse (op),
9781 exprNode_unparse (e2)),
9784 ret = ctype_unknown;
9788 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
9790 ret = ctype_resolveNumerics (tr1, tr2);
9792 else if (!context_msgStrictOps ())
9794 if (ctype_isPointer (tr1))
9796 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
9800 else if (ctype_isInt (tr2))
9806 ret = ctype_unknown;
9809 else if (ctype_isPointer (tr2))
9811 if (ctype_isPointer (tr1))
9815 else if (ctype_isInt (tr1))
9821 ret = ctype_unknown;
9826 ret = ctype_resolveNumerics (tr1, tr2);
9831 int opid = lltok_getTok (op);
9832 bool comparop = (opid == EQ_OP || opid == NE_OP
9833 || opid == TLT || opid == TGT
9834 || opid == LE_OP || opid == GE_OP);
9836 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
9839 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
9840 || (ctype_isBool (tr1) && ctype_isBool (tr2))
9841 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
9847 if (ctype_sameName (te1, te2))
9851 message ("Operands of %s are non-numeric (%t): %s %s %s",
9852 lltok_unparse (op), te1,
9853 exprNode_unparse (e1), lltok_unparse (op),
9854 exprNode_unparse (e2)),
9861 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
9862 lltok_unparse (op), te1, te2,
9863 exprNode_unparse (e1), lltok_unparse (op),
9864 exprNode_unparse (e2)),
9869 else if (!ctype_isNumeric (tr1))
9873 message ("Right operand of %s is non-numeric (%t): %s %s %s",
9874 lltok_unparse (op), te1,
9875 exprNode_unparse (e1), lltok_unparse (op),
9876 exprNode_unparse (e2)),
9881 if (!ctype_isNumeric (tr2))
9885 message ("Left operand of %s is non-numeric (%t): %s %s %s",
9886 lltok_unparse (op), te2,
9887 exprNode_unparse (e1), lltok_unparse (op),
9888 exprNode_unparse (e2)),
9893 ret = ctype_unknown;
9901 abstractOpError (ctype tr1, ctype tr2, lltok op,
9902 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
9903 fileloc loc1, fileloc loc2)
9905 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
9907 if (ctype_match (tr1, tr2))
9911 message ("Operands of %s are abstract type (%t): %s %s %s",
9912 lltok_unparse (op), tr1,
9913 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9920 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
9921 lltok_unparse (op), tr1, tr2,
9922 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9926 else if (ctype_isRealAbstract (tr1))
9930 message ("Left operand of %s is abstract type (%t): %s %s %s",
9931 lltok_unparse (op), tr1,
9932 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9937 if (ctype_isRealAbstract (tr2))
9941 message ("Right operand of %s is abstract type (%t): %s %s %s",
9942 lltok_unparse (op), tr2,
9943 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9952 ** requies e1 and e2 and not error exprNode's.
9956 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
9957 ** the rep of the abstract type is exposed.
9959 ** The order is very important:
9961 ** check rep expose (move into check transfer)
9967 ** This isn't really a sensible procedure, but the indententation
9968 ** was getting too deep.
9972 checkOneRepExpose (sRef ysr, sRef base,
9973 /*@notnull@*/ exprNode e1,
9974 /*@notnull@*/ exprNode e2, ctype ct,
9977 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
9978 || sRef_isOwned (ysr)
9979 || sRef_isExposed (ysr)))
9981 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
9982 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
9985 if (sRef_isIReference (ysr))
9987 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
9992 ("Assignment of mutable component of parameter %q "
9993 "to component of abstract "
9994 "type %s exposes rep: %s = %s",
9995 sRef_unparse (base),
9997 exprNode_unparse (e1), exprNode_unparse (e2)),
10005 ("Assignment of mutable component of parameter %q "
10006 "(through alias %q) to component of abstract "
10007 "type %s exposes rep: %s = %s",
10008 sRef_unparse (base),
10009 sRef_unparse (e2->sref),
10010 ctype_unparse (ct),
10011 exprNode_unparse (e1), exprNode_unparse (e2)),
10017 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10021 message ("Assignment of mutable parameter %q "
10022 "to component of abstract type %s "
10023 "exposes rep: %s = %s",
10024 sRef_unparse (base),
10025 ctype_unparse (ct),
10026 exprNode_unparse (e1),
10027 exprNode_unparse (e2)),
10034 message ("Assignment of mutable parameter %q "
10035 "(through alias %q) to "
10036 "component of abstract type %s exposes "
10038 sRef_unparse (base),
10039 sRef_unparse (e2->sref),
10040 ctype_unparse (ct),
10041 exprNode_unparse (e1),
10042 exprNode_unparse (e2)),
10048 if (sRef_isFileOrGlobalScope (s2b))
10050 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10054 message ("Assignment of global %q "
10056 "abstract type %s exposes rep: %s = %s",
10057 sRef_unparse (base),
10058 ctype_unparse (ct),
10059 exprNode_unparse (e1), exprNode_unparse (e2)),
10066 message ("Assignment of global %q (through alias %q) "
10068 "abstract type %s exposes rep: %s = %s",
10069 sRef_unparse (base),
10070 sRef_unparse (e2->sref),
10071 ctype_unparse (ct),
10072 exprNode_unparse (e1), exprNode_unparse (e2)),
10080 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
10082 if (ctype_isRealFunction (exprNode_getType (e1))
10083 && !ctype_isRealPointer (exprNode_getType (e1)))
10087 message ("Invalid left-hand side of assignment (function type %s): %s",
10088 ctype_unparse (exprNode_getType (e1)),
10089 exprNode_unparse (e1)),
10093 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
10095 ctype t2 = exprNode_getType (e2);
10096 sRef sr = sRef_getRootBase (e1->sref);
10097 ctype ct = sRef_getType (sr);
10099 if (ctype_isAbstract (t2)
10100 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
10102 /* it is immutable, okay to reference */
10103 goto donerepexpose;
10106 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
10108 sRef s2b = sRef_getRootBase (e2->sref);
10109 sRef s1 = e1->sref;
10110 sRef s1b = sRef_getRootBase (s1);
10113 aliases = usymtab_canAlias (e2->sref);
10115 if (!sRef_similar (s2b, s1b)
10116 && !sRef_isExposed (s1)
10117 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
10119 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
10120 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
10121 && !sRef_isExposed (s2b))
10123 if (sRef_isIReference (e2->sref))
10128 ("Assignment of mutable component of parameter %q "
10129 "to component of abstract type %s exposes rep: %s = %s",
10130 sRef_unparse (s2b),
10131 ctype_unparse (ct),
10132 exprNode_unparse (e1), exprNode_unparse (e2)),
10139 message ("Assignment of mutable parameter %q to "
10140 "component of abstract type %s exposes rep: %s = %s",
10141 sRef_unparse (s2b),
10142 ctype_unparse (ct),
10143 exprNode_unparse (e1), exprNode_unparse (e2)),
10148 if (sRef_isFileOrGlobalScope (s2b))
10152 message ("Assignment of global %q to component of "
10153 "abstract type %s exposes rep: %s = %s",
10154 sRef_unparse (s2b),
10155 ctype_unparse (ct),
10156 exprNode_unparse (e1), exprNode_unparse (e2)),
10160 sRefSet_realElements (aliases, ysr)
10162 sRef base = sRef_getRootBase (ysr);
10164 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
10165 || sRef_sameName (base, s1b))
10167 ; /* error already reported or same sref */
10171 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
10173 } end_sRefSet_realElements;
10175 sRefSet_free (aliases);
10182 ** function variables don't really work...
10185 if (!ctype_isFunction (ctype_realType (e2->typ)))
10189 DPRINTF (("Check init: %s / %s",
10190 exprNode_unparse (e1), exprNode_unparse (e2)));
10191 checkInitTransfer (e1, e2);
10195 checkAssignTransfer (e1, e2);
10200 sRef fref = e2->sref;
10202 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
10203 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
10205 /* Need to typecheck the annotation on the parameters */
10207 if (ctype_isRealFunction (e1->typ)) {
10208 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
10209 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
10211 if (!uentryList_isMissingParams (e1p)
10212 && !uentryList_isMissingParams (e2p)
10213 && uentryList_size (e1p) > 0) {
10214 if (uentryList_size (e1p) == uentryList_size (e2p)) {
10217 uentryList_elements (e1p, el1) {
10220 el2 = uentryList_getN (e2p, n);
10222 uentry_checkMatchParam (el1, el2, n, e2);
10223 } end_uentryList_elements;
10229 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
10235 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
10236 updateAliases (e1, e2);
10241 checkMacroParen (exprNode e)
10243 if (exprNode_isError (e) || e->kind == XPR_CAST)
10249 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
10253 message ("Macro parameter used without parentheses: %s",
10254 exprNode_unparse (e)),
10261 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
10265 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
10269 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
10276 ** if e2 is a parameter or global derived location which
10277 ** can be modified (that is, e2 is a mutable abstract type,
10278 ** or a derived pointer), then e1 can alias e2.
10280 ** e1 can alias everything which e2 can alias.
10282 ** Also, if e1 is guarded, remove from guard sets!
10285 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
10287 if (!context_inProtectVars ())
10290 ** depends on types of e1 and e2
10293 sRef s1 = e1->sref;
10294 sRef s2 = e2->sref;
10295 ctype t1 = exprNode_getType (e1);
10297 /* handle pointer sRefs, record fields, arrays, etc... */
10299 if (!ctype_isRealSU (t1))
10301 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
10302 sRef_copyRealDerivedComplete (s1, s2);
10307 ** Fields should alias
10310 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
10313 if (ctype_isMutable (t1) && sRef_isKnown (s1))
10315 usymtab_clearAlias (s1);
10316 usymtab_addMustAlias (s1, s2);
10317 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
10321 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
10324 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
10326 usymtab_unguard (s1);
10331 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
10333 if (exprNode_isDefined (e))
10335 e->loc = fileloc_update (e->loc, loc);
10339 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
10345 static void checkUniqueParams (exprNode fcn,
10346 /*@notnull@*/ exprNode current,
10348 int paramno, uentry ucurrent)
10351 sRef thisref = exprNode_getSref (current);
10354 ** Check if any argument could match this argument.
10357 exprNodeList_elements (args, icurrent)
10361 if (iparamno != paramno)
10363 sRef sr = exprNode_getSref (icurrent);
10365 if (sRef_similarRelaxed (thisref, sr))
10367 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
10372 ("Parameter %d (%s) to function %s is declared %s but "
10373 "is aliased by parameter %d (%s)",
10375 exprNode_unparse (current),
10376 exprNode_unparse (fcn),
10377 alkind_unparse (uentry_getAliasKind (ucurrent)),
10378 iparamno, exprNode_unparse (icurrent)),
10384 sRefSet aliases = usymtab_canAlias (sr);
10386 sRefSet_allElements (aliases, asr)
10388 if (ctype_isUnknown (sRef_getType (thisref)))
10390 sRef_setType (thisref, uentry_getType (ucurrent));
10393 if (sRef_similarRelaxed (thisref, asr))
10395 if (sRef_isExternal (asr))
10397 if (sRef_isLocalState (thisref))
10403 sRef base = sRef_getRootBase (asr);
10405 if (!sRef_similar (sRef_getBase (asr), thisref))
10407 if (sRef_isUnique (base) || sRef_isOnly (base)
10408 || sRef_isKept (base)
10409 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
10410 || (sRef_isAddress (thisref)
10411 && sRef_isLocalVar (sRef_getRootBase (thisref))))
10413 ; /* okay, no error */
10418 (FLG_MAYALIASUNIQUE,
10420 ("Parameter %d (%s) to function %s is declared %s but "
10421 "may be aliased externally by parameter %d (%s)",
10423 exprNode_unparse (current),
10424 exprNode_unparse (fcn),
10425 alkind_unparse (uentry_getAliasKind (ucurrent)),
10426 iparamno, exprNode_unparse (icurrent)),
10437 ("Parameter %d (%s) to function %s is declared %s but "
10438 "is aliased externally by parameter %d (%s) through "
10441 exprNode_unparse (current),
10442 exprNode_unparse (fcn),
10443 alkind_unparse (uentry_getAliasKind (ucurrent)),
10444 iparamno, exprNode_unparse (icurrent),
10445 sRef_unparse (asr)),
10449 } end_sRefSet_allElements;
10450 sRefSet_free (aliases);
10453 } end_exprNodeList_elements;
10456 long exprNode_getLongValue (exprNode e) {
10459 if (exprNode_hasValue (e)
10460 && multiVal_isInt (exprNode_getValue (e)))
10462 value = multiVal_forceInt (exprNode_getValue (e));
10472 /*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
10474 if (exprNode_isDefined (p_e) )
10475 return ( p_e->loc );
10477 return fileloc_undefined;
10480 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
10483 ** Returns the location of the sequence point following e.
10485 ** Only works for statements (for now).
10488 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
10489 lltok t = exprData_getUopTok (e->edata);
10490 return fileloc_copy(lltok_getLoc (t));
10492 //drl possible problem : warning fix
10493 // llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
10494 return fileloc_undefined;
10498 exprNode exprNode_createNew(ctype c)
10502 ret = exprNode_createPlain (c);