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 "mtincludes.h"
32 # include "cgrammar.h"
33 # include "cgrammar_tokens.h"
35 # include "exprChecks.h"
36 # include "transferChecks.h"
37 # include "exprNodeSList.h"
39 static bool exprNode_isEmptyStatement (exprNode p_e);
40 static /*@exposed@*/ exprNode exprNode_firstStatement (/*@returned@*/ exprNode p_e);
41 static bool exprNode_isFalseConstant (exprNode p_e) /*@*/ ;
42 static bool exprNode_isBlock (exprNode p_e);
43 static void checkGlobUse (uentry p_glob, bool p_isCall, /*@notnull@*/ exprNode p_e);
44 static void exprNode_addUse (exprNode p_e, /*@exposed@*/ sRef p_s);
45 static bool exprNode_matchArgType (ctype p_ct, exprNode p_e);
46 static exprNode exprNode_fakeCopy (exprNode p_e) /*@*/ ;
47 static exprNode exprNode_statementError (/*@only@*/ exprNode p_e, /*@only@*/ lltok p_t);
48 static bool exprNode_matchTypes (exprNode p_e1, exprNode p_e2);
49 static void checkUniqueParams (exprNode p_fcn,
50 /*@notnull@*/ exprNode p_current, exprNodeList p_args,
51 int p_paramno, uentry p_ucurrent);
52 static void updateAliases (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2);
53 static void abstractOpError (ctype p_tr1, ctype p_tr2, lltok p_op,
54 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2,
55 fileloc p_loc1, fileloc p_loc2);
56 static ctype checkNumerics (ctype p_tr1, ctype p_tr2, ctype p_te1, ctype p_te2,
57 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, lltok p_op);
58 static void doAssign (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, bool p_isInit);
59 static void checkSafeUse (exprNode p_e, /*@exposed@*/ sRef p_s);
60 static void reflectNullTest (/*@notnull@*/ exprNode p_e, bool p_isnull);
61 static void checkMacroParen (exprNode p_e);
62 static exprNodeSList exprNode_flatten (/*@dependent@*/ exprNode p_e);
63 static void exprNode_checkSetAny (exprNode p_e, /*@dependent@*/ cstring p_name);
64 static void exprNode_checkUse (exprNode p_e, /*@exposed@*/ sRef p_s, fileloc p_loc);
65 static void exprNode_mergeUSs (exprNode p_res, exprNode p_other);
66 static void exprNode_mergeCondUSs (exprNode p_res, exprNode p_other1, exprNode p_other2);
67 static /*@only@*/ /*@notnull@*/ exprNode exprNode_fromIdentifierAux (/*@observer@*/ uentry p_c);
68 static void checkAnyCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn,
69 /*@dependent@*/ cstring p_fname,
70 uentryList p_pn, exprNodeList p_args,
71 bool p_hasMods, sRefSet p_mods, bool p_isSpec,
73 static void checkOneArg (uentry p_ucurrent, /*@notnull@*/ exprNode p_current,
74 /*@dependent@*/ exprNode p_fcn, bool p_isSpec, int p_argno, int p_totargs);
76 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn, uentryList p_params, exprNodeList p_args);
78 static /*@only@*/ exprNode exprNode_effect (exprNode p_e)
79 /*@globals internalState@*/ ;
80 static /*@only@*/ cstring exprNode_doUnparse (exprNode p_e);
81 static /*@observer@*/ cstring exprNode_rootVarName (exprNode p_e);
82 static /*@exposed@*/ exprNode
83 exprNode_lastStatement (/*@returned@*/ exprNode p_e);
85 static /*@null@*/ sRef defref = sRef_undefined;
86 static /*@only@*/ exprNode mustExitNode = exprNode_undefined;
88 static int checkArgsReal (uentry p_fcn, /*@dependent@*/ exprNode p_f,
90 exprNodeList p_args, bool p_isIter, exprNode p_ret);
92 static bool inEffect = FALSE;
93 static int nowalloc = 0;
94 static int totalloc = 0;
95 static int maxalloc = 0;
97 static /*@only@*/ uentry regArg;
98 static /*@only@*/ uentry outArg;
99 static /*@only@*/ uentry outStringArg;
100 static /*@exposed@*/ sRef stdinRef;
101 static /*@exposed@*/ sRef stdoutRef;
102 static /*@only@*/ uentry csArg;
103 static /*@only@*/ uentry csOnlyArg;
104 static ctype cstringType;
105 static ctype ctypeType;
106 static ctype filelocType;
107 static bool initMod = FALSE;
109 static void exprNode_defineConstraints(/*@sef@*/ /*@special@*/ /*@notnull@*/ exprNode e)
110 /*@defines e->requiresConstraints, e->ensuresConstraints,
111 e->trueEnsuresConstraints, e->falseEnsuresConstraints @*/
113 e->requiresConstraints = constraintList_makeNew ();
114 e->ensuresConstraints = constraintList_makeNew ();
115 e->trueEnsuresConstraints = constraintList_makeNew ();
116 e->falseEnsuresConstraints = constraintList_makeNew ();
120 ** must occur after library has been read
123 void exprNode_initMod (void)
124 /*@globals undef regArg, undef outArg, undef outStringArg,
125 undef csOnlyArg, undef csArg;
132 cstringType = ctype_unknown;
133 ctypeType = ctype_unknown;
134 filelocType = ctype_unknown;
136 defref = sRef_undefined;
138 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
140 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
143 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
145 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
148 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
150 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
153 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdin")))
155 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdin"));
157 else /* define stdin */
159 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdin"),
161 fileloc_getBuiltin (),
163 uentry_setHasNameError (ue);
164 ue = usymtab_supGlobalEntryReturn (ue);
167 stdinRef = sRef_makePointer (uentry_getSref (ue));
169 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdout")))
171 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdout"));
175 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdout"),
177 fileloc_getBuiltin (),
179 uentry_setHasNameError (ue);
180 ue = usymtab_supGlobalEntryReturn (ue);
183 stdoutRef = sRef_makePointer (uentry_getSref (ue));
185 tmp = idDecl_create (cstring_undefined, qtype_create (ctype_unknown));
187 regArg = uentry_makeParam (tmp, PARAMUNKNOWN);
190 qtype_addQual (qtype_create (ctype_makePointer (ctype_unknown)),
193 outArg = uentry_makeParam (tmp, PARAMUNKNOWN);
195 idDecl_setTyp (tmp, qtype_addQual (qtype_create (ctype_string),
198 outStringArg = uentry_makeParam (tmp, PARAMUNKNOWN);
200 idDecl_setTyp (tmp, qtype_addQual (qtype_addQual (qtype_create (cstringType),
202 qual_createNull ()));
204 csOnlyArg = uentry_makeParam (tmp, PARAMUNKNOWN);
206 idDecl_setTyp (tmp, qtype_addQual (qtype_create (cstringType), qual_createNull ()));
207 csArg = uentry_makeParam (tmp, PARAMUNKNOWN);
213 exprNode_destroyMod (void)
214 /*@globals killed regArg, killed outArg, killed outStringArg,
215 killed mustExitNode, initMod @*/
219 uentry_free (regArg);
220 uentry_free (outArg);
221 uentry_free (outStringArg);
223 exprNode_free (mustExitNode);
230 static void exprNode_resetSref (/*@notnull@*/ exprNode e)
235 exprNode exprNode_fakeCopy (exprNode e)
237 /*@-temptrans@*/ /*@-retalias@*/
239 /*@=temptrans@*/ /*@=retalias@*/
242 static bool isFlagKey (char key)
244 return (key == '-' || key == '+' || key == ' ' || key == '#');
247 static void exprNode_combineControl (/*@notnull@*/ exprNode ret,
248 /*@notnull@*/ exprNode ifclause,
249 /*@notnull@*/ exprNode elseclause)
251 ret->canBreak = ifclause->canBreak || elseclause->canBreak;
254 (ifclause->mustBreak || exprNode_mustEscape (ifclause))
255 && (elseclause->mustBreak || exprNode_mustEscape (elseclause));
257 ret->exitCode = exitkind_combine (ifclause->exitCode,
258 elseclause->exitCode);
263 ** For exprNode's returned by exprNode_effect.
266 static bool shallowKind (exprKind kind)
268 return (kind == XPR_STRINGLITERAL
269 || kind == XPR_NUMLIT
272 || kind == XPR_NODE);
276 exprNode_freeIniter (/*@only@*/ exprNode e)
278 if (!exprNode_isError (e))
284 ** Its a fake copy, don't free the field->rec and field->field
289 sfree (e->edata->field);
295 exprNode_free (e->edata->op->b);
296 /*@-compdestroy@*/ sfree (e->edata->op); /*@=compdestroy@*/
300 llbug (message ("other: %s", exprNode_unparse (e)));
303 multiVal_free (e->val);
304 cstring_free (e->etext);
305 fileloc_free (e->loc);
306 sRefSet_free (e->uses);
307 sRefSet_free (e->sets);
308 sRefSet_free (e->msets);
309 guardSet_free (e->guards);
311 constraintList_free(e->requiresConstraints);
312 constraintList_free(e->ensuresConstraints);
313 constraintList_free(e->trueEnsuresConstraints);
314 constraintList_free(e->falseEnsuresConstraints);
316 e->requiresConstraints = NULL;
317 e->ensuresConstraints = NULL;
318 e->trueEnsuresConstraints = NULL;
319 e->falseEnsuresConstraints = NULL;
326 exprNode_freeShallow (/*@only@*/ exprNode e)
328 if (!exprNode_isError (e))
330 if (shallowKind (e->kind))
337 if (e->kind == XPR_EMPTY
338 || e->kind == XPR_BODY
339 || e->kind == XPR_STRINGLITERAL
340 || e->kind == XPR_NUMLIT
341 || e->kind == XPR_NODE
342 || e->kind == XPR_OFFSETOF
343 || e->kind == XPR_ALIGNOFT
344 || e->kind == XPR_ALIGNOF
345 || e->kind == XPR_SIZEOFT
346 || e->kind == XPR_SIZEOF)
348 /* don't free anything */
352 /* multiVal_free (e->val); */
353 cstring_free (e->etext);
354 fileloc_free (e->loc);
355 sRefSet_free (e->uses);
356 sRefSet_free (e->sets);
357 sRefSet_free (e->msets);
358 guardSet_free (e->guards);
359 exprData_freeShallow (e->edata, e->kind);
361 /*@-compdestroy@*/ sfree (e); /*@=compdestroy@*/
370 exprNode_free (exprNode e)
372 if (!exprNode_isError (e))
376 multiVal_free (e->val);
377 cstring_free (e->etext);
378 fileloc_free (e->loc);
379 sRefSet_free (e->uses);
380 sRefSet_free (e->sets);
381 sRefSet_free (e->msets);
382 guardSet_free (e->guards);
383 exprData_free (e->edata, e->kind);
385 constraintList_free(e->requiresConstraints);
386 constraintList_free(e->ensuresConstraints);
387 constraintList_free(e->trueEnsuresConstraints);
388 constraintList_free(e->falseEnsuresConstraints);
390 e->requiresConstraints = NULL;
391 e->ensuresConstraints = NULL;
392 e->trueEnsuresConstraints = NULL;
393 e->falseEnsuresConstraints = NULL;
403 exprNode_makeError ()
405 return exprNode_undefined;
408 static /*@out@*/ /*@only@*/ /*@notnull@*/ exprNode
411 exprNode ret = (exprNode) dmalloc (sizeof (*ret));
412 /* static int lastexpnodes = 0; */
417 if (nowalloc > maxalloc)
425 static /*@notnull@*/ /*@special@*/ exprNode
426 exprNode_createPlain (ctype c)
428 /*@ensures isnull result->edata, result->loc, result->val, result->guards,
429 result->uses, result->sets, result->msets, result->etext @*/
432 exprNode e = exprNode_new ();
436 e->val = multiVal_undefined;
438 e->etext = cstring_undefined;
439 e->loc = fileloc_undefined;
440 e->guards = guardSet_undefined;
441 e->uses = sRefSet_undefined;
442 e->sets = sRefSet_undefined;
443 e->msets = sRefSet_undefined;
444 e->edata = exprData_undefined;
445 e->exitCode = XK_NEVERESCAPE;
447 e->mustBreak = FALSE;
448 e->isJumpPoint = FALSE;
450 exprNode_defineConstraints(e);
455 /*@observer@*/ exprNode exprNode_makeMustExit (void)
457 if (exprNode_isUndefined (mustExitNode))
459 mustExitNode = exprNode_createPlain (ctype_unknown);
460 mustExitNode->exitCode = XK_MUSTEXIT;
467 static /*@notnull@*/ /*@special@*/ exprNode exprNode_create (ctype c)
469 /*@post:isnull result->edata, result->guards, result->val,
470 result->uses, result->sets, result->msets@*/
473 exprNode e = exprNode_createPlain (c);
474 e->loc = fileloc_copy (g_currentloc);
478 static /*@notnull@*/ /*@special@*/ exprNode exprNode_createUnknown (void)
480 /*@post:isnull result->edata, result->guards,
481 result->uses, result->sets, result->msets@*/
484 return (exprNode_create (ctype_unknown));
487 static /*@notnull@*/ /*@special@*/ exprNode
488 exprNode_createLoc (ctype c, /*@keep@*/ fileloc loc)
490 /*@post:isnull result->edata, result->guards, result->val,
491 result->uses, result->sets, result->msets@*/
494 exprNode e = exprNode_createPlain (c);
500 exprNode_copySets (/*@special@*/ /*@notnull@*/ exprNode ret, exprNode e)
501 /*@defines ret->guards, ret->uses, ret->sets, ret->msets@*/
503 if (exprNode_isDefined (e))
505 ret->guards = guardSet_copy (e->guards);
506 ret->uses = sRefSet_newCopy (e->uses);
507 ret->sets = sRefSet_newCopy (e->sets);
508 ret->msets = sRefSet_newCopy (e->msets);
512 ret->guards = guardSet_undefined;
513 ret->uses = sRefSet_undefined;
514 ret->sets = sRefSet_undefined;
515 ret->msets = sRefSet_undefined;
519 static /*@notnull@*/ /*@special@*/ exprNode
520 exprNode_createPartialLocCopy (exprNode e, /*@only@*/ fileloc loc)
522 /*@post:isnull result->edata, result->etext@*/
525 exprNode ret = exprNode_new ();
527 if (exprNode_isError (e))
529 ret->typ = ctype_unknown;
530 ret->val = multiVal_undefined;
532 ret->guards = guardSet_undefined;
533 ret->uses = sRefSet_undefined;
534 ret->sets = sRefSet_undefined;
535 ret->msets = sRefSet_undefined;
540 ret->val = multiVal_copy (e->val);
542 ret->guards = guardSet_copy (e->guards);
543 ret->uses = sRefSet_newCopy (e->uses);
544 ret->sets = sRefSet_newCopy (e->sets);
545 ret->msets = sRefSet_newCopy (e->msets);
548 ret->kind = XPR_EMPTY;
550 ret->etext = cstring_undefined;
551 ret->exitCode = XK_NEVERESCAPE;
552 ret->canBreak = FALSE;
553 ret->mustBreak = FALSE;
554 ret->isJumpPoint = FALSE;
555 ret->edata = exprData_undefined;
557 exprNode_defineConstraints(ret);
563 static /*@notnull@*/ /*@special@*/ exprNode
564 exprNode_createPartialCopy (exprNode e)
566 /*@post:isnull result->edata, result->etext@*/
569 return (exprNode_createPartialLocCopy (e, fileloc_copy (exprNode_loc (e))));
572 static /*@notnull@*/ /*@special@*/ exprNode
573 exprNode_createPartialNVCopy (exprNode e)
575 /*@post:isnull result->edata, result->etext, result->val @*/
578 exprNode ret = exprNode_new ();
580 if (exprNode_isError (e))
582 ret->typ = ctype_unknown;
583 ret->loc = fileloc_undefined;
584 ret->guards = guardSet_undefined;
585 ret->uses = sRefSet_undefined;
586 ret->sets = sRefSet_undefined;
587 ret->msets = sRefSet_undefined;
592 ret->loc = fileloc_copy (e->loc);
593 ret->guards = guardSet_copy (e->guards);
594 ret->uses = sRefSet_newCopy (e->uses);
595 ret->sets = sRefSet_newCopy (e->sets);
596 ret->msets = sRefSet_newCopy (e->msets);
599 ret->val = multiVal_undefined;
600 ret->kind = XPR_EMPTY;
602 ret->etext = cstring_undefined;
603 ret->exitCode = XK_NEVERESCAPE;
604 ret->canBreak = FALSE;
605 ret->mustBreak = FALSE;
606 ret->isJumpPoint = FALSE;
607 ret->edata = exprData_undefined;
609 exprNode_defineConstraints(ret);
614 static /*@notnull@*/ /*@special@*/ exprNode
615 exprNode_createSemiCopy (exprNode e)
617 /*@post:isnull result->edata, result->etext, result->sets,
618 result->msets, result->uses, result->guards@*/
621 if (exprNode_isError (e))
623 return exprNode_createPlain (ctype_unknown);
627 exprNode ret = exprNode_new ();
630 ret->val = multiVal_copy (e->val);
631 ret->loc = fileloc_copy (e->loc);
632 ret->guards = guardSet_undefined;
633 ret->uses = sRefSet_undefined;
634 ret->sets = sRefSet_undefined;
635 ret->msets = sRefSet_undefined;
637 ret->kind = XPR_EMPTY;
639 ret->etext = cstring_undefined;
640 ret->exitCode = XK_NEVERESCAPE;
641 ret->canBreak = FALSE;
642 ret->mustBreak = FALSE;
643 ret->isJumpPoint = FALSE;
644 ret->edata = exprData_undefined;
646 exprNode_defineConstraints(ret);
653 exprNode_isNullValue (exprNode e)
655 if (exprNode_isDefined (e))
657 multiVal m = exprNode_getValue (e);
659 if (multiVal_isInt (m))
661 return (multiVal_forceInt (m) == 0);
669 exprNode_isUnknownConstant (/*@notnull@*/ exprNode e)
671 while (e->kind == XPR_PARENS)
673 e = exprData_getUopNode (e->edata);
674 llassert (exprNode_isDefined (e));
677 if (e->kind == XPR_CONST)
679 multiVal m = exprNode_getValue (e);
681 if (multiVal_isUnknown (m))
691 exprNode_numLiteral (ctype c, /*@temp@*/ cstring t,
692 /*@only@*/ fileloc loc, long val)
694 exprNode e = exprNode_createLoc (c, loc);
696 e->kind = XPR_NUMLIT;
698 llassert (multiVal_isUndefined (e->val));
699 e->val = multiVal_makeInt (val);
700 e->edata = exprData_makeLiteral (cstring_copy (t));
704 e->sref = sRef_makeUnknown ();
705 sRef_setDefNull (e->sref, e->loc);
708 DPRINTF (("Num lit: %s / %s", exprNode_unparse (e), ctype_unparse (exprNode_getType (e))));
713 exprNode_charLiteral (char c, cstring text, /*@only@*/ fileloc loc)
715 exprNode e = exprNode_createLoc (ctype_char, loc);
717 if (context_getFlag (FLG_CHARINTLITERAL))
719 e->typ = ctype_makeConj (ctype_char, ctype_int);
722 e->kind = XPR_NUMLIT;
723 e->val = multiVal_makeChar (c);
725 e->edata = exprData_makeLiteral (cstring_copy (text));
730 exprNode_floatLiteral (double d, ctype ct, cstring text, /*@only@*/ fileloc loc)
732 exprNode e = exprNode_createLoc (ct, loc);
734 e->kind = XPR_NUMLIT;
735 e->val = multiVal_makeDouble (d);
736 e->edata = exprData_makeLiteral (cstring_copy (text));
740 multiVal exprNode_getValue (exprNode e)
742 while (exprNode_isInParens (e)) {
743 if (e->edata != NULL) {
744 e = exprData_getUopNode (e->edata);
750 if (exprNode_isDefined (e)) {
753 return multiVal_undefined;
758 exprNode_combineLiterals (exprNode e, exprNode rest)
762 /* Both must be string literals. */
764 if (exprNode_isUndefined (rest) || exprNode_isUndefined (e))
766 exprNode_free (rest);
770 if (!exprNode_isStringLiteral (e))
774 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e),
775 exprNode_unparse (rest)),
777 exprNode_free (rest);
781 if (!exprNode_isStringLiteral (rest))
785 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e), exprNode_unparse (rest)),
788 exprNode_free (rest);
792 ns = cstring_concat (multiVal_forceString (exprNode_getValue (e)),
793 multiVal_forceString (exprNode_getValue (rest)));
795 multiVal_free (e->val);
796 exprData_free (e->edata, e->kind);
797 e->edata = exprData_makeLiteral (cstring_copy (ns));
798 e->val = multiVal_makeString (ns);
799 exprNode_free (rest);
804 exprNode_rawStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
806 exprNode e = exprNode_createLoc (ctype_string, loc);
807 int len = cstring_length (t);
809 if (context_getFlag (FLG_STRINGLITERALLEN))
811 if (len > context_getValue (FLG_STRINGLITERALLEN))
813 voptgenerror (FLG_STRINGLITERALLEN,
815 ("String literal length (%d) exceeds maximum "
816 "length (%d): \"%s\"",
818 context_getValue (FLG_STRINGLITERALLEN),
824 e->kind = XPR_STRINGLITERAL;
825 e->val = multiVal_makeString (cstring_copy (t));
826 e->edata = exprData_makeLiteral (t);
827 e->sref = sRef_makeType (ctype_string);
829 if (context_getFlag (FLG_READONLYSTRINGS))
831 sRef_setAliasKind (e->sref, AK_STATIC, fileloc_undefined);
832 sRef_setExKind (e->sref, XO_OBSERVER, loc);
836 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
839 return (e); /* s released */
843 exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
845 int len = cstring_length (t) - 2;
846 char *ts = cstring_toCharsSafe (t);
847 char *s = cstring_toCharsSafe (cstring_create (len + 1));
849 llassert (*ts == '\"' && *(ts + len + 1) == '\"');
850 strncpy (s, ts+1, size_fromInt (len));
853 return exprNode_rawStringLiteral (cstring_fromCharsO (s), loc);
856 exprNode exprNode_fromUIO (cstring c)
858 fileloc loc = context_getSaveLocation ();
859 exprNode e = exprNode_createPlain (ctype_unknown);
863 if (fileloc_isUndefined (loc))
865 loc = fileloc_copy (g_currentloc);
868 e->loc = loc; /* save loc was mangled */
871 if (usymtab_exists (c))
873 uentry ue = usymtab_lookupEither (c);
875 if (uentry_isDatatype (ue)
876 && uentry_isSpecified (ue))
879 (message ("%q: Specified datatype %s used in code, but not defined. "
880 "(Cannot continue reasonably from this error.)",
881 fileloc_unparse (e->loc), c));
889 llassertprint (!usymtab_exists (c), ("Entry exists: %s", c));
892 ** was supercedeGlobalEntry...is this better?
895 if (!context_inIterEnd ())
897 if (context_inMacro ())
899 if (context_getFlag (FLG_UNRECOG))
903 message ("Unrecognized identifier in macro definition: %s", c), e->loc);
907 flagcode_recordSuppressed (FLG_UNRECOG);
913 (FLG_UNRECOG, message ("Unrecognized identifier: %s", c), e->loc);
917 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
919 /* No alias errors for unrecognized identifiers */
920 sRef_setAliasKind (e->sref, AK_ERROR, loc);
925 exprNode exprNode_createId (/*@observer@*/ uentry c)
927 if (uentry_isValid (c))
929 exprNode e = exprNode_new ();
931 e->typ = uentry_getType (c);
933 if (uentry_isFunction (c)
934 && !sRef_isLocalVar (uentry_getSref (c)))
936 e->sref = sRef_undefined;
940 e->sref = uentry_getSref (c);
943 if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
945 sRef_setDefined (e->sref, fileloc_undefined);
949 ** yoikes! leaving this out was a heinous bug...that would have been
950 ** caught if i had lclint working first. gag!
953 e->etext = cstring_undefined;
955 if (uentry_isEitherConstant (c))
958 e->val = multiVal_copy (uentry_getConstantValue (c));
963 e->val = multiVal_unknown ();
966 e->edata = exprData_makeId (c);
967 e->loc = context_getSaveLocation ();
969 if (fileloc_isUndefined (e->loc))
971 fileloc_free (e->loc);
972 e->loc = fileloc_copy (g_currentloc);
975 e->guards = guardSet_new ();
976 e->sets = sRefSet_new ();
977 e->msets = sRefSet_new ();
978 e->uses = sRefSet_new ();
980 /*> missing fields, detected by lclint <*/
981 e->exitCode = XK_NEVERESCAPE;
982 e->isJumpPoint = FALSE;
984 e->mustBreak = FALSE;
986 exprNode_defineConstraints(e);
992 return exprNode_createUnknown ();
996 /*@notnull@*/ exprNode
997 exprNode_fromIdentifier (/*@observer@*/ uentry c)
1001 if (context_justPopped ()) /* watch out! c could be dead */
1003 uentry ce = usymtab_lookupSafe (LastIdentifier ());
1005 if (uentry_isValid (ce))
1011 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
1015 ret = exprNode_fromIdentifierAux (c);
1021 static /*@only@*/ /*@notnull@*/ exprNode
1022 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
1024 exprNode e = exprNode_createId (c);
1027 uentry_setUsed (c, e->loc);
1029 if (uentry_isVar (c) && sRef_isFileOrGlobalScope (sr))
1031 checkGlobUse (c, FALSE, e);
1038 exprNode_isZero (exprNode e)
1040 if (exprNode_isDefined (e))
1042 multiVal m = exprNode_getValue (e);
1044 if (multiVal_isInt (m))
1046 return (multiVal_forceInt (m) == 0);
1054 exprNode_isNonNegative (exprNode e)
1056 if (exprNode_isDefined (e))
1058 multiVal m = exprNode_getValue (e);
1060 if (multiVal_isInt (m))
1062 return (multiVal_forceInt (m) >= 0);
1070 ** a[x] - uses a but NOT a[]
1071 ** result sref = a[] (set/use in assignment)
1073 ** The syntax x[a] is also legal in C, and has the same
1074 ** semantics. If ind is an array, and arr is an int, flip
1079 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
1082 ** error in arr, error propagates (no new messages)
1083 ** error in ind, assume valid and continue
1086 if (exprNode_isError (e1))
1089 return (exprNode_makeError ());
1095 ctype carr = exprNode_getType (e1);
1096 ctype crarr = ctype_realType (carr);
1099 ** this sets up funny aliasing, that leads to spurious
1100 ** lclint errors. Hence, the i2 comments.
1103 if (!ctype_isRealArray (crarr)
1104 && ctype_isRealNumeric (crarr)
1105 && !exprNode_isError (e2)
1106 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1111 carr = exprNode_getType (arr);
1112 crarr = ctype_realType (carr);
1120 if (sRef_possiblyNull (arr->sref))
1122 if (!usymtab_isGuarded (arr->sref))
1124 if (optgenerror (FLG_NULLDEREF,
1125 message ("Index of %s pointer %q: %s",
1126 sRef_nullMessage (arr->sref),
1127 sRef_unparse (arr->sref),
1128 exprNode_unparse (arr)),
1131 sRef_showNullInfo (arr->sref);
1133 /* suppress future messages */
1134 sRef_setNullError (arr->sref);
1139 if (exprNode_isError (ind))
1141 if ((ctype_isArrayPtr (crarr)
1142 && !ctype_isFunction (crarr))
1143 || ctype_isUnknown (carr))
1145 exprNode ret = exprNode_createPartialCopy (arr);
1147 if (ctype_isKnown (carr))
1149 ret->typ = ctype_baseArrayPtr (crarr);
1153 ret->typ = ctype_unknown;
1156 ret->sref = sRef_makeArrayFetch (arr->sref);
1158 ret->kind = XPR_FETCH;
1161 ** Because of funny aliasing (when arr and ind are
1162 ** flipped) spurious errors would be reported here.
1165 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1166 checkSafeUse (ret, arr->sref);
1171 voptgenerror (FLG_TYPE,
1172 message ("Array fetch from non-array (%t): %s[%s]", carr,
1173 exprNode_unparse (e1), exprNode_unparse (e2)),
1175 exprNode_free (arr);
1176 return (exprNode_makeError ());
1181 if (!ctype_isForceRealInt (&(ind->typ)))
1183 ctype rt = ctype_realType (ind->typ);
1185 if (ctype_isChar (rt))
1189 message ("Array fetch using non-integer, %t: %s[%s]",
1191 exprNode_unparse (e1), exprNode_unparse (e2)),
1194 else if (ctype_isEnum (rt))
1198 message ("Array fetch using non-integer, %t: %s[%s]",
1200 exprNode_unparse (e1), exprNode_unparse (e2)),
1207 message ("Array fetch using non-integer, %t: %s[%s]",
1209 exprNode_unparse (e1), exprNode_unparse (e2)),
1213 multiVal_free (ind->val);
1214 ind->val = multiVal_unknown ();
1217 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1219 exprNode ret = exprNode_createSemiCopy (arr);
1220 multiVal m = exprNode_getValue (ind);
1222 ret->typ = ctype_baseArrayPtr (crarr);
1223 ret->kind = XPR_FETCH;
1225 if (multiVal_isInt (m))
1227 int i = (int) multiVal_forceInt (m);
1229 if (sRef_isValid (arr->sref)) {
1230 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1232 ret->sref = sRef_undefined;
1237 ret->sref = sRef_makeArrayFetch (arr->sref);
1240 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1241 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1242 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1244 /* (see comment on spurious errors above) */
1245 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1247 exprNode_checkUse (ret, ind->sref, ind->loc);
1248 exprNode_checkUse (ret, arr->sref, arr->loc);
1254 if (ctype_isUnknown (carr))
1256 exprNode ret = exprNode_createPartialCopy (arr);
1258 ret->kind = XPR_FETCH;
1259 ret->typ = ctype_unknown;
1260 ret->sets = sRefSet_union (ret->sets, ind->sets);
1261 ret->msets = sRefSet_union (ret->msets, ind->msets);
1262 ret->uses = sRefSet_union (ret->uses, ind->uses);
1264 /* (see comment on spurious errors above) */
1265 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1267 exprNode_checkUse (ret, ind->sref, ind->loc);
1268 exprNode_checkUse (ret, arr->sref, arr->loc);
1275 message ("Array fetch from non-array (%t): %s[%s]", carr,
1276 exprNode_unparse (e1), exprNode_unparse (e2)),
1279 exprNode_free (arr);
1280 exprNode_free (ind);
1282 return (exprNode_makeError ());
1292 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1293 exprNodeList args, exprNode ret)
1295 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1299 ** checkPrintfArgs --- checks arguments for printf-like functions
1300 ** Arguments before ... have already been checked.
1301 ** The argument before the ... is a char *.
1302 ** argno is the format string argument.
1306 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1307 exprNodeList args, exprNode ret, int argno)
1310 ** the last argument before the elips is the format string
1315 int nargs = exprNodeList_size (args);
1316 uentryList params = uentry_getParams (fcn);
1320 ** These should be ensured by checkSpecialFunction
1323 llassert (uentryList_size (params) == argno + 1);
1324 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1326 a = exprNodeList_getN (args, argno - 1);
1327 formatloc = fileloc_copy (exprNode_loc (a));
1329 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1330 && exprNode_knownStringValue (a))
1332 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1333 char *code = format;
1336 nargs = exprNodeList_size (args);
1338 while ((code = strchr (code, '%')) != NULL)
1340 char *origcode = code;
1341 cstring codetext = cstring_newEmpty ();
1342 char key = *(++code);
1343 ctype modtype = ctype_int;
1344 bool modified = FALSE;
1346 fileloc_addColumn (formatloc, code - ocode);
1348 codetext = cstring_appendChar (codetext, key);
1351 while (isFlagKey (key))
1354 codetext = cstring_appendChar (codetext, key);
1355 fileloc_incColumn (formatloc);
1358 if (key == 'm') /* skipped in syslog */
1363 /* ignore field width */
1364 while (isdigit ((int) key) != 0)
1367 codetext = cstring_appendChar (codetext, key);
1368 fileloc_incColumn (formatloc);
1371 /* ignore precision */
1375 codetext = cstring_appendChar (codetext, key);
1376 fileloc_incColumn (formatloc);
1379 ** In printf, '*' means: read the next arg as an int for the
1380 ** field width. This seems to be missing from my copy of the
1381 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1382 ** later) but never does.
1387 ; /* don't do anything --- handle later */
1391 while (isdigit ((int) key) != 0)
1394 codetext = cstring_appendChar (codetext, key);
1395 fileloc_incColumn (formatloc);
1402 modtype = ctype_sint; /* short */
1404 codetext = cstring_appendChar (codetext, key);
1405 fileloc_incColumn (formatloc);
1407 else if (key == 'l' || key == 'L')
1409 modtype = ctype_lint; /* long */
1411 codetext = cstring_appendChar (codetext, key);
1412 fileloc_incColumn (formatloc);
1414 if (key == 'l' || key == 'L') {
1415 modtype = ctype_llint; /* long long */
1417 codetext = cstring_appendChar (codetext, key);
1418 fileloc_incColumn (formatloc);
1426 /* now, key = type of conversion to apply */
1428 fileloc_incColumn (formatloc);
1436 message ("No argument corresponding to %q format "
1437 "code %d (%%%s): \"%s\"",
1438 uentry_getName (fcn),
1440 cstring_fromChars (format)),
1443 if (fileloc_isDefined (formatloc)
1444 && context_getFlag (FLG_SHOWCOL))
1446 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1454 a = exprNodeList_getN (args, i);
1457 if (!exprNode_isError (a))
1463 case '*': /* int argument for fieldwidth */
1464 expecttype = ctype_int;
1465 *(--code) = '%'; /* convert it for next code */
1466 fileloc_subColumn (formatloc, 1);
1467 /*@switchbreak@*/ break;
1470 expecttype = ctype_combine (ctype_uint, modtype);
1471 /*@switchbreak@*/ break;
1473 case 'i': /* int argument */
1475 expecttype = ctype_combine (ctype_int, modtype);
1476 /*@switchbreak@*/ break;
1478 case 'x': /* unsigned int */
1480 expecttype = ctype_combine (ctype_uint, modtype);
1482 /*@switchbreak@*/ break;
1488 case 'f': /* double */
1489 expecttype = ctype_combine (ctype_double, modtype);
1490 /*@switchbreak@*/ break;
1492 case 'c': /* int converted to char (check its a char?) */
1493 expecttype = ctype_makeConj (ctype_char, ctype_uchar);
1494 /*@switchbreak@*/ break;
1496 case 's': /* string */
1497 expecttype = ctype_string;
1498 /*@switchbreak@*/ break;
1501 while (((key = *(++code)) != ']')
1504 codetext = cstring_appendChar (codetext, key);
1505 fileloc_incColumn (formatloc);
1511 (message ("Bad character set format: %s",
1512 cstring_fromChars (origcode)));
1515 expecttype = ctype_string;
1516 /*@switchbreak@*/ break;
1518 case 'p': /* pointer */
1519 expecttype = ctype_makePointer (ctype_void);
1520 uentry_setDefState (regArg, SS_RELDEF); /* need not be defined */
1521 sRef_setPosNull (uentry_getSref (regArg), fileloc_undefined); /* could be null */
1522 /*@switchbreak@*/ break;
1524 case 'n': /* pointer to int, modified by call! */
1525 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1527 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1528 /*@switchbreak@*/ break;
1530 case 'm': /* in a syslog, it doesn't consume an argument */
1531 /* should check we're really doing syslog */
1533 /*@switchbreak@*/ break;
1537 expecttype = ctype_unknown;
1541 message ("Unrecognized format code: %s",
1542 cstring_fromChars (origcode)),
1543 fileloc_isDefined (formatloc)
1544 ? formatloc : g_currentloc);
1546 /*@switchbreak@*/ break;
1549 if (!(exprNode_matchArgType (expecttype, a)))
1551 if (ctype_isVoidPointer (expecttype)
1552 && ctype_isRealAbstract (a->typ)
1553 && (context_getFlag (FLG_ABSTVOIDP)))
1559 if (llgenformattypeerror
1560 (expecttype, exprNode_undefined,
1562 message ("Format argument %d to %q (%%%s) expects "
1565 uentry_getName (fcn),
1568 a->typ, exprNode_unparse (a)),
1571 if (fileloc_isDefined (formatloc)
1572 && context_getFlag (FLG_SHOWCOL))
1575 (cstring_makeLiteral
1576 ("Corresponding format code"),
1583 uentry_setType (regArg, expecttype);
1584 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1586 if (ctype_equal (expecttype, ctype_string))
1588 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1591 uentry_setType (regArg, ctype_unknown);
1592 uentry_fixupSref (regArg);
1596 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1607 cstring_free (codetext);
1612 voptgenerror (FLG_TYPE,
1613 message ("Format string for %q has %d arg%&, given %d",
1614 uentry_getName (fcn), i - argno, nargs - argno),
1620 /* no checking possible for compile-time unknown format strings */
1621 if (exprNode_isDefined (a))
1625 message ("Format string parameter to %s is not a compile-time constant: %s",
1626 exprNode_unparse (f),
1627 exprNode_unparse (a)),
1632 fileloc_free (formatloc);
1636 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1637 exprNodeList args, exprNode ret, int argno)
1641 int nargs = exprNodeList_size (args);
1642 uentryList params = uentry_getParams (fcn);
1646 ** These should be ensured by checkSpecialFunction
1649 llassert (uentryList_size (params) == argno + 1);
1650 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1652 a = exprNodeList_getN (args, argno - 1);
1653 formatloc = fileloc_copy (exprNode_loc (a));
1655 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1656 && exprNode_knownStringValue (a))
1658 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1659 char *code = format;
1662 nargs = exprNodeList_size (args);
1664 while ((code = strchr (code, '%')) != NULL)
1666 char *origcode = code;
1667 char key = *(++code);
1668 cstring codetext = cstring_newEmpty ();
1669 ctype modtype = ctype_int;
1670 char modifier = '\0';
1671 bool modified = TRUE;
1672 bool ignore = FALSE;
1674 codetext = cstring_appendChar (codetext, key);
1675 fileloc_addColumn (formatloc, code - ocode);
1678 ** this is based on ANSI standard library description of fscanf
1679 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1682 /* '*' suppresses assignment (does not need match argument) */
1687 codetext = cstring_appendChar (codetext, key);
1690 fileloc_incColumn (formatloc);
1693 /* ignore field width */
1694 while (isdigit ((int) key) != 0)
1697 codetext = cstring_appendChar (codetext, key);
1698 fileloc_incColumn (formatloc);
1703 modtype = ctype_sint; /* short */
1705 codetext = cstring_appendChar (codetext, key);
1706 fileloc_incColumn (formatloc);
1708 else if (key == 'l' || key == 'L')
1710 modtype = ctype_lint; /* long */
1714 codetext = cstring_appendChar (codetext, key);
1716 fileloc_incColumn (formatloc);
1718 if (key == 'l' || key == 'L') {
1719 modtype = ctype_llint; /* long long */
1721 codetext = cstring_appendChar (codetext, key);
1722 fileloc_incColumn (formatloc);
1730 /* now, key = type of conversion to apply */
1732 fileloc_incColumn (formatloc);
1746 message ("No argument corresponding to %q format "
1747 "code %d (%%%s): \"%s\"",
1748 uentry_getName (fcn),
1750 cstring_fromChars (format)),
1753 if (fileloc_isDefined (formatloc)
1754 && context_getFlag (FLG_SHOWCOL))
1757 (cstring_makeLiteral ("Corresponding format code"),
1765 a = exprNodeList_getN (args, i);
1768 if (!exprNode_isError (a))
1774 case '*': /* int argument for fieldwidth */
1775 expecttype = ctype_makePointer (ctype_int);
1776 *(--code) = '%'; /* convert it for next code */
1777 fileloc_subColumn (formatloc, 1);
1778 /*@switchbreak@*/ break;
1781 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1782 /*@switchbreak@*/ break;
1787 case 'X': /* unsigned int */
1788 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1789 /*@switchbreak@*/ break;
1796 /* printf is double, scanf is float! */
1798 if (modifier == 'l')
1800 expecttype = ctype_makePointer (ctype_double);
1802 else if (modifier == 'L')
1804 expecttype = ctype_makePointer (ctype_ldouble);
1808 llassert (modifier == '\0');
1809 expecttype = ctype_makePointer (ctype_float);
1811 /*@switchbreak@*/ break;
1813 case 'c': /* int converted to char (check its a char?) */
1814 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1815 /*@switchbreak@*/ break;
1817 case 's': /* string */
1818 expecttype = ctype_string;
1819 /*@switchbreak@*/ break;
1823 while (((key = *(++code)) != ']')
1826 codetext = cstring_appendChar (codetext, key);
1827 fileloc_incColumn (formatloc);
1833 (message ("Bad character set format: %s",
1834 cstring_fromChars (origcode)));
1837 expecttype = ctype_string;
1838 /*@switchbreak@*/ break;
1841 case 'p': /* pointer */
1844 message ("Format code should not be used in scanf: %s",
1845 cstring_fromChars (origcode)),
1846 fileloc_isDefined (formatloc)
1847 ? formatloc : g_currentloc);
1849 expecttype = ctype_unknown;
1850 /*@switchbreak@*/ break;
1852 case 'n': /* pointer to int, modified by call! */
1853 expecttype = ctype_makePointer (ctype_int);
1854 /*@switchbreak@*/ break;
1857 expecttype = ctype_unknown;
1861 message ("Unrecognized format code: %s",
1862 cstring_fromChars (origcode)),
1863 fileloc_isDefined (formatloc)
1864 ? formatloc : g_currentloc);
1866 /*@switchbreak@*/ break;
1869 if (!(exprNode_matchArgType (expecttype, a)))
1871 if (ctype_isVoidPointer (expecttype)
1872 && ctype_isRealAbstract (a->typ)
1873 && (context_getFlag (FLG_ABSTVOIDP)))
1879 if (llgenformattypeerror
1880 (expecttype, exprNode_undefined,
1882 message ("Format argument %d to %q (%%%s) expects "
1885 uentry_getName (fcn),
1886 codetext, expecttype,
1887 a->typ, exprNode_unparse (a)),
1890 if (fileloc_isDefined (formatloc)
1891 && context_getFlag (FLG_SHOWCOL))
1894 (cstring_makeLiteral
1895 ("Corresponding format code"),
1902 uentry_setType (outArg, expecttype);
1903 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
1904 uentry_setType (outArg, ctype_unknown);
1905 uentry_fixupSref (outArg);
1909 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1914 /* a->sref = defref; */
1921 cstring_free (codetext);
1926 voptgenerror (FLG_TYPE,
1927 message ("Format string for %q has %d arg%&, given %d",
1928 uentry_getName (fcn), i - argno, nargs - argno),
1934 /* no checking possible for compile-time unknown format strings */
1937 fileloc_free (formatloc);
1941 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
1944 /*@unused@*/ int argno)
1947 ** the last argument before the elips is the format string
1950 int nargs = exprNodeList_size (args);
1955 a = exprNodeList_getN (args, argno - 1);
1956 formatloc = fileloc_copy (exprNode_loc (a));
1958 if (ctype_isUnknown (cstringType)) {
1959 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
1961 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
1965 if (ctype_isUnknown (ctypeType)) {
1966 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
1968 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
1972 if (ctype_isUnknown (filelocType)) {
1973 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
1975 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
1979 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1980 && exprNode_knownStringValue (a))
1982 cstring format = multiVal_forceString (exprNode_getValue (a));
1983 char *code = cstring_toCharsSafe (format);
1986 nargs = exprNodeList_size (args);
1988 while ((code = strchr (code, '%')) != NULL)
1990 char *origcode = code;
1991 char key = *(++code);
1992 cstring codetext = cstring_newEmpty ();
1993 bool isOnly = FALSE;
1995 codetext = cstring_appendChar (codetext, key);
1997 fileloc_addColumn (formatloc, code - ocode);
1999 while (key >= '0' && key <= '9')
2002 codetext = cstring_appendChar (codetext, key);
2003 fileloc_incColumn (formatloc);
2007 fileloc_incColumn (formatloc);
2011 if (key == '&') /* plural marker */
2020 message ("Message missing format arg %d (%%%s): \"%s\"",
2021 i + 1, codetext, format),
2027 a = exprNodeList_getN (args, i);
2031 if (!exprNode_isError (a))
2035 /*@-loopswitchbreak@*/
2041 expecttype = ctype_char; break;
2043 expecttype = cstringType; break;
2045 expecttype = cstringType; isOnly = TRUE; break;
2047 expecttype = cstringType; isOnly = TRUE; break;
2048 case 'd': expecttype = ctype_int; break;
2049 case 'u': expecttype = ctype_uint; break;
2050 case 'w': expecttype = ctype_ulint; break;
2051 case 'f': expecttype = ctype_float; break;
2052 case 'b': expecttype = ctype_bool; break;
2053 case 't': expecttype = ctypeType; break;
2054 case 'l': expecttype = filelocType; break;
2055 case '&': /* a wee bit of a hack methinks */
2056 expecttype = ctype_int;
2058 case 'r': expecttype = ctype_bool; break;
2060 expecttype = ctype_unknown;
2063 message ("Unrecognized format code: %s",
2064 cstring_fromChars (origcode)),
2065 fileloc_isDefined (formatloc)
2066 ? formatloc : g_currentloc);
2069 /*@=loopswitchbreak@*/
2071 if (!(exprNode_matchArgType (expecttype, a)))
2073 if (ctype_isVoidPointer (expecttype)
2074 && ctype_isRealAbstract (a->typ)
2075 && (context_getFlag (FLG_ABSTVOIDP)))
2081 if (llgenformattypeerror
2082 (expecttype, exprNode_undefined,
2084 message ("Format argument %d to %q (%%%s) expects "
2087 uentry_getName (fcn),
2088 codetext, expecttype,
2089 a->typ, exprNode_unparse (a)),
2092 if (fileloc_isDefined (formatloc)
2093 && context_getFlag (FLG_SHOWCOL))
2096 (cstring_makeLiteral
2097 ("Corresponding format code"),
2104 if (ctype_equal (expecttype, cstringType))
2108 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2109 uentry_fixupSref (csOnlyArg);
2113 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2114 uentry_fixupSref (csArg);
2119 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2120 uentry_fixupSref (regArg);
2126 cstring_free (codetext);
2131 voptgenerror (FLG_TYPE,
2132 message ("Format string for %q has %d arg%&, given %d",
2133 uentry_getName (fcn), i - argno, nargs -argno),
2139 /* no checking possible for compile-time unknown format strings */
2142 fileloc_free (formatloc);
2146 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2147 /*@notnull@*/ exprNode e2,
2153 bool hadUncon = FALSE;
2155 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
2156 sRefSet_hasUnconstrained (sets2))
2159 (FLG_EVALORDERUNCON,
2161 ("Expression may have undefined behavior (%q used in right operand "
2162 "may set global variable %q used in left operand): %s %s %s",
2163 sRefSet_unparseUnconstrained (sets2),
2164 sRef_unparse (sRef_getRootBase (e1->sref)),
2165 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2169 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
2170 sRefSet_hasUnconstrained (sets1))
2173 (FLG_EVALORDERUNCON,
2175 ("Expression has undefined behavior (%q used in left operand "
2176 "may set global variable %q used in right operand): %s %s %s",
2177 sRefSet_unparseUnconstrained (sets1),
2178 sRef_unparse (e2->sref),
2179 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2183 sRefSet_realElements (e1->uses, sr)
2185 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2190 ("Expression has undefined behavior (left operand uses %q, "
2191 "modified by right operand): %s %s %s",
2193 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2196 } end_sRefSet_realElements;
2198 sRefSet_realElements (sets1, sr)
2200 if (sRef_isMeaningful (sr))
2202 if (sRef_same (sr, e2->sref))
2207 ("Expression has undefined behavior (value of right operand "
2208 "modified by left operand): %s %s %s",
2209 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2212 else if (sRefSet_member (e2->uses, sr))
2217 ("Expression has undefined behavior (left operand modifies %q, "
2218 "used by right operand): %s %s %s",
2220 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2225 if (sRefSet_member (sets2, sr))
2227 if (sRef_isUnconstrained (sr))
2235 hadUncon = optgenerror
2236 (FLG_EVALORDERUNCON,
2238 ("Expression may have undefined behavior. Left operand "
2239 "calls %q; right operand calls %q. The unconstrained "
2240 "functions may modify global state used by "
2241 "the other operand): %s %s %s",
2242 sRefSet_unparseUnconstrained (sets1),
2243 sRefSet_unparseUnconstrained (sets2),
2244 exprNode_unparse (e1), lltok_unparse (op),
2245 exprNode_unparse (e2)),
2254 ("Expression has undefined behavior (both "
2255 "operands modify %q): %s %s %s",
2257 exprNode_unparse (e1),
2258 lltok_unparse (op), exprNode_unparse (e2)),
2264 } end_sRefSet_realElements;
2267 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2269 bool hasError = FALSE;
2271 if (exprNode_isError (e1) || exprNode_isError (e2))
2276 if (sRefSet_member (e2->sets, e1->sref))
2278 if (e2->kind == XPR_CALL)
2284 hasError = optgenerror
2286 message ("Expression has undefined behavior "
2287 "(value of left operand is modified "
2288 "by right operand): %s %s %s",
2289 exprNode_unparse (e1), lltok_unparse (op),
2290 exprNode_unparse (e2)),
2295 if (context_getFlag (FLG_EVALORDERUNCON))
2297 if (sRefSet_member (e2->msets, e1->sref))
2299 if (e2->kind == XPR_CALL)
2305 hasError = optgenerror
2308 ("Expression has undefined behavior (value of left "
2309 "operand may be modified by right operand): %s %s %s",
2310 exprNode_unparse (e1), lltok_unparse (op),
2311 exprNode_unparse (e2)),
2319 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2321 if (context_maybeSet (FLG_EVALORDERUNCON))
2323 checkExpressionDefinedAux (e1, e2, e1->msets,
2324 e2->msets, op, FLG_EVALORDERUNCON);
2329 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2332 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2333 exprNodeList args, bool isIter, exprNode ret)
2337 if (!exprNode_isError (f))
2339 if (!uentryList_isMissingParams (cl))
2341 int nargs = exprNodeList_size (args);
2342 int expectargs = uentryList_size (cl);
2346 if (expectargs == 0)
2354 message ("Iter %q invoked with %d args, "
2356 uentry_getName (fcn),
2364 message ("Function %s called with %d args, "
2366 exprNode_unparse (f), nargs),
2373 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2375 exprNodeList_reset (args);
2377 uentryList_elements (cl, current)
2379 ctype ct = uentry_getType (current);
2382 if (ctype_isElips (ct))
2385 ** do special checking for printf/scanf library functions
2387 ** this is kludgey code, just for handling the special case
2391 if (uentry_isPrintfLike (fcn))
2393 checkPrintfArgs (f, fcn, args, ret, i);
2396 else if (uentry_isScanfLike (fcn))
2398 checkScanfArgs (f, fcn, args, ret, i);
2401 else if (uentry_isMessageLike (fcn))
2403 checkMessageArgs (f, fcn, args, i);
2408 llassert (!uentry_isSpecialFunction (fcn));
2411 nargs = expectargs; /* avoid errors */
2416 if (i >= nargs) break;
2418 a = exprNodeList_current (args);
2419 exprNodeList_advance (args);
2423 if (exprNode_isError (a))
2430 probably necessary? I'm not sure about this one
2431 checkMacroParen (a);
2434 f->guards = guardSet_union (f->guards, a->guards);
2436 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2438 if (!(exprNode_matchArgType (ct, a)))
2440 DPRINTF (("Args mismatch!"));
2442 if (ctype_isVoidPointer (ct)
2443 && (ctype_isPointer (a->typ)
2444 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2449 ("Pointer to abstract type (%t) used "
2451 "(arg %d to %q): %s",
2453 uentry_getName (fcn),
2454 exprNode_unparse (a)),
2462 (ct, exprNode_undefined,
2465 ("Iter %q expects arg %d to "
2466 "be %t gets %t: %s",
2467 uentry_getName (fcn),
2468 i, ct, a->typ, exprNode_unparse (a)),
2479 ("Function %q expects arg %d to be %t gets %t: %s",
2480 uentry_getName (fcn),
2481 i, ct, a->typ, exprNode_unparse (a)),
2484 DPRINTF (("Types: %s / %s",
2486 ctype_unparse (a->typ)));
2490 ** Clear null marker for abstract types.
2491 ** (It is not revealed, so suppress future messages.)
2494 if (ctype_isAbstract (a->typ))
2496 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2503 } end_uentryList_elements ;
2506 if (expectargs != nargs) /* note: not != since we may have ... */
2508 if (ctype_isElips (last))
2512 message ("Function %s called with %d args, expects at least %d",
2513 exprNode_unparse (f),
2514 nargs, expectargs - 1),
2523 message ("Iter %q invoked with %d args, expects %d",
2524 uentry_getName (fcn), nargs, expectargs),
2531 message ("Function %s called with %d args, expects %d",
2532 exprNode_unparse (f),
2545 ** Check for undefined code sequences in function arguments:
2547 ** one parameter sets something used by another parameter
2548 ** one parameter sets something set by another parameter
2552 checkSequencingOne (exprNode f, exprNodeList args,
2553 /*@notnull@*/ exprNode el, int argno)
2556 ** Do second loop, iff +undefunspec
2560 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2562 for (checkloop = 0; checkloop < numloops; checkloop++)
2568 thissets = el->sets;
2572 llassert (checkloop == 1);
2573 thissets = el->msets;
2576 sRefSet_realElements (thissets, thisset)
2580 /*@access exprNodeList@*/
2581 for (j = 0; j < args->nelements; j++)
2583 exprNode jl = args->elements[j];
2584 int thisargno = j + 1;
2586 if (thisargno != argno && exprNode_isDefined (jl))
2588 sRefSet otheruses = jl->uses;
2590 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
2591 sRefSet_hasUnconstrained (thissets))
2594 (FLG_EVALORDERUNCON,
2597 ("%q used in argument %d may set "
2598 "global variable %q used by argument %d: %s(%q)",
2599 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2602 sRef_unparse (sRef_getRootBase (jl->sref)),
2604 exprNode_unparse (f), exprNodeList_unparse (args)),
2608 if (sRefSet_member (otheruses, thisset))
2610 if (sRef_isUnconstrained (thisset))
2613 (FLG_EVALORDERUNCON,
2615 ("Unconstrained functions used in arguments %d (%q) "
2616 "and %d (%s) may modify "
2617 "or use global state in undefined way: %s(%q)",
2619 sRefSet_unparseUnconstrainedPlain (otheruses),
2621 sRef_unconstrainedName (thisset),
2622 exprNode_unparse (f),
2623 exprNodeList_unparse (args)),
2631 ("Argument %d modifies %q, used by argument %d "
2632 "(order of evaluation of actual parameters is "
2633 "undefined): %s(%q)",
2634 argno, sRef_unparse (thisset), thisargno,
2635 exprNode_unparse (f), exprNodeList_unparse (args)),
2641 sRefSet othersets = jl->sets;
2643 if (sRefSet_member (othersets, thisset))
2645 if (sRef_isUnconstrained (thisset))
2648 (FLG_EVALORDERUNCON,
2650 ("Unconstrained functions used in "
2651 "arguments %d (%q) and %d (%s) may modify "
2652 "or use global state in undefined way: %s(%q)",
2654 sRefSet_unparseUnconstrainedPlain (othersets),
2656 sRef_unconstrainedName (thisset),
2657 exprNode_unparse (f), exprNodeList_unparse (args)),
2665 ("Argument %d modifies %q, set by argument %d (order of"
2666 " evaluation of actual parameters is undefined): %s(%q)",
2667 argno, sRef_unparse (thisset), thisargno,
2668 exprNode_unparse (f), exprNodeList_unparse (args)),
2675 /*@noaccess exprNodeList@*/
2676 } end_sRefSet_realElements;
2681 checkSequencing (exprNode f, exprNodeList args)
2683 if (exprNodeList_size (args) > 1)
2688 /*@access exprNodeList*/
2690 for (i = 0; i < args->nelements; i++)
2692 el = args->elements[i];
2694 if (!exprNode_isError (el))
2696 checkSequencingOne (f, args, el, i + 1);
2699 /*@noaccess exprNodeList*/
2704 ** requires le = exprNode_getUentry (f)
2708 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2709 uentry le, exprNodeList args,
2710 /*@notnull@*/ exprNode ret, int specialArgs)
2712 bool isSpec = FALSE;
2713 bool hasMods = FALSE;
2715 globSet usesGlobs = globSet_undefined;
2716 sRefSet mods = sRefSet_undefined;
2717 bool freshMods = FALSE;
2718 uentryList params = uentryList_undefined;
2720 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2723 ** check globals and modifies
2728 if (!uentry_isValid (le))
2730 ctype fr = ctype_realType (f->typ);
2732 if (ctype_isFunction (fr))
2734 params = ctype_argsFunction (fr);
2738 params = uentryList_missingParams;
2741 if (!context_getFlag (FLG_MODNOMODS)
2742 && !context_getFlag (FLG_GLOBUNSPEC))
2744 checkUnspecCall (f, params, args);
2750 fname = uentry_rawName (le);
2754 if (uentry_isFunction (le))
2756 params = uentry_getParams (le);
2757 mods = uentry_getMods (le);
2758 hasMods = uentry_hasMods (le);
2759 usesGlobs = uentry_getGlobs (le);
2760 isSpec = uentry_isSpecified (le);
2762 else /* not a function */
2764 ctype ct = ctype_realType (uentry_getType (le));
2766 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2767 ("checkModGlobs: uentry not a function: %s",
2768 uentry_unparse (le)));
2770 params = ctype_argsFunction (ct);
2771 return; /*@32 ! remove this? */
2780 globSet_allElements (usesGlobs, el)
2782 if (sRef_isValid (el))
2784 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2786 context_usedGlobal (el);
2787 exprNode_checkUse (f, el, f->loc);
2789 if (context_checkInternalUse ())
2791 if (!context_globAccess (el))
2793 if (sRef_isSystemState (el)
2794 && !context_getFlag (FLG_MODFILESYSTEM))
2803 ("Called procedure %s may access %q, but "
2804 "globals list does not include globals %s",
2805 exprNode_unparse (f),
2807 cstring_makeLiteralTemp (sRef_isInternalState (el)
2815 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2821 uentry gle = sRef_getUentry (el);
2822 sRef sr = sRef_updateSref (el);
2824 if (sRef_isUndefGlob (el))
2826 sRef_setDefined (sr, f->loc);
2827 exprNode_checkSet (f, sr);
2835 if (sRef_isAllocated (el))
2837 exprNode_checkSet (f, sr);
2841 if (sRef_isStateUndefined (sr))
2846 ("%s %q used by function undefined before call: %s",
2847 sRef_getScopeName (sr),
2849 exprNode_unparse (f)),
2851 sRef_setDefined (sr, f->loc);
2853 exprNode_checkUse (f, sr, f->loc);
2856 checkGlobUse (gle, TRUE, f);
2859 if (sRef_isKilledGlob (el))
2861 sRef_kill (sr, f->loc);
2862 context_usedGlobal (sr);
2866 } end_globSet_allElements;
2872 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
2874 sRefSet smods = sRefSet_undefined;
2877 ** NEED to check for modifies anything
2881 ** check each sRef that called function modifies (ml), is
2887 sRefSet_allElements (mods, s) /* s is something which may be modified */
2889 DPRINTF (("Check modify: %s", sRef_unparse (s)));
2891 if (sRef_isKindSpecial (s))
2893 if (sRef_isSpecInternalState (s))
2895 if (context_getFlag (FLG_MODINTERNALSTRICT))
2897 exprNode_checkCallModifyVal (s, args, f, ret);
2901 sRefSet mmods = context_modList ();
2903 sRefSet_allElements (mmods, el)
2905 if (sRef_isInternalState (el))
2907 sRef_setModified (el);
2909 } end_sRefSet_allElements ;
2914 exprNode_checkCallModifyVal (s, args, f, ret);
2919 sRef rb = sRef_getRootBase (s);
2921 if (sRef_isFileOrGlobalScope (rb))
2923 context_usedGlobal (rb);
2926 if (sRef_isFileStatic (s)
2927 && !fileId_equal (fileloc_fileId (f->loc),
2928 fileloc_fileId (uentry_whereDefined (le))))
2930 smods = sRefSet_insert (smods, s);
2934 exprNode_checkCallModifyVal (s, args, f, ret);
2937 } end_sRefSet_allElements;
2942 ** Static elements in modifies set can have nasty consequences.
2943 ** (I think...have not been able to reproduce a possible bug.)
2946 if (!sRefSet_isDefined (smods))
2948 mods = sRefSet_newCopy (mods);
2951 sRefSet_allElements (smods, el)
2953 bool res = sRefSet_delete (mods, el);
2956 } end_sRefSet_allElements;
2958 sRefSet_free (smods);
2963 else if (sRefSet_isDefined (mods))
2964 { /* just check observers */
2967 sRefSet_allElements (mods, s) /* s is something which may be modified */
2969 sRef rb = sRef_getRootBase (s);
2973 if (sRef_isParam (rb))
2975 sRef b = sRef_fixBaseParam (s, args);
2977 if (sRef_isObserver (b))
2979 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
2983 message ("Function call may modify observer%q: %s",
2984 sRef_unparsePreOpt (b), exprNode_unparse (e)),
2987 sRef_showExpInfo (b);
2991 } end_sRefSet_allElements;
2995 if (!hasMods) /* no specified modifications */
2997 if (context_getFlag (FLG_MODOBSERVERUNCON))
2999 exprNodeList_elements (args, e)
3001 if (exprNode_isDefined (e))
3003 sRef s = exprNode_getSref (e);
3005 if (sRef_isObserver (s)
3006 && ctype_isMutable (sRef_getType (s)))
3009 (FLG_MODOBSERVERUNCON,
3011 ("Call to unconstrained function %s may modify observer%q: %s",
3012 exprNode_unparse (f),
3013 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3016 sRef_showExpInfo (s);
3020 } end_exprNodeList_elements;
3025 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3027 ret->uses = sRefSet_union (ret->uses, f->uses);
3028 ret->sets = sRefSet_union (ret->sets, f->sets);
3029 ret->msets = sRefSet_union (ret->msets, f->msets);
3034 ** Spurious errors reported, because lclint can't tell
3035 ** mods must be fresh if freshMods is true.
3038 /*@i@*/ sRefSet_free (mods);
3044 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3046 if (uentry_isVar (glob))
3048 if (context_inFunctionLike ())
3050 sRef sr = uentry_getSref (glob);
3052 context_usedGlobal (sr);
3054 if (context_checkGlobUse (glob))
3056 if (!context_globAccess (sr))
3062 message ("Called procedure %s may access %s %q",
3063 exprNode_unparse (e),
3064 sRef_unparseScope (sr),
3065 uentry_getName (glob)),
3072 message ("Undocumented use of %s %s",
3073 sRef_unparseScope (sr),
3074 exprNode_unparse (e)),
3083 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3088 reflectEnsuresClause (uentry le, exprNode f, exprNodeList args)
3090 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3091 exprNode_unparse (f), exprNodeList_unparse (args),
3092 uentry_unparseFull (le),
3093 stateClauseList_unparse (uentry_getStateClauseList (le))));
3095 if (uentry_isValid (le) && uentry_isFunction (le))
3097 stateClauseList sclauses = uentry_getStateClauseList (le);
3099 if (stateClauseList_isDefined (sclauses))
3101 DPRINTF (("Reflect ensures: %s / %s / %s",
3102 uentry_unparse (le),
3103 exprNode_unparse (f), exprNodeList_unparse (args)));
3105 stateClauseList_elements (sclauses, cl)
3107 if (stateClause_hasEnsures (cl))
3109 /* Same in usymtab.c:1904 */
3110 if (stateClause_setsMetaState (cl))
3112 qual q = stateClause_getMetaQual (cl);
3113 annotationInfo ainfo = qual_getAnnotationInfo (q);
3114 metaStateInfo minfo = annotationInfo_getState (ainfo);
3115 cstring key = metaStateInfo_getName (minfo);
3116 int mvalue = annotationInfo_getValue (ainfo);
3118 sRefSet osrs = sRefSet_undefined;
3121 if (stateClause_isGlobal (cl))
3123 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3128 srs = stateClause_getRefs (cl);
3131 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3134 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3136 sRefSet_elements (srs, sel)
3140 if (sRef_isResult (sRef_getRootBase (sel)))
3142 ; /*@i423 what do we do about results */
3146 s = sRef_fixBaseParam (sel, args);
3147 DPRINTF (("Reflecting state clause on: %s / %s",
3148 sRef_unparse (sel), sRef_unparse (s)));
3150 sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3152 } end_sRefSet_elements;
3154 sRefSet_free (osrs);
3158 sRefSet srs = stateClause_getRefs (cl);
3159 sRefModVal modf = stateClause_getEnsuresFunction (cl);
3160 int eparam = stateClause_getStateParameter (cl);
3162 DPRINTF (("Reflect after clause: %s / %s",
3163 stateClause_unparse (cl),
3164 sRefSet_unparse (srs)));
3166 sRefSet_elements (srs, sel)
3170 DPRINTF (("elements: %s", sRef_unparse (sel)));
3171 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3173 if (sRef_isResult (sRef_getRootBase (sel)))
3175 ; /*@i423 what do we do about results */
3179 s = sRef_fixBaseParam (sel, args);
3181 DPRINTF (("elements: %s", sRef_unparse (s)));
3182 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3184 DPRINTF (("Reflecting state clause on: %s / %s",
3185 sRef_unparse (sel), sRef_unparse (s)));
3187 modf (s, eparam, exprNode_loc (f));
3189 } end_sRefSet_elements;
3192 } end_stateClauseList_elements ;
3195 DPRINTF (("Here: %s / %s",
3196 uentry_unparseFull (le),
3197 bool_unparse (uentry_hasMetaStateEnsures (le))));
3199 if (uentry_hasMetaStateEnsures (le))
3201 metaStateConstraint msc = uentry_getMetaStateEnsures (le);
3202 metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3203 metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3204 metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
3205 cstring key = metaStateInfo_getName (msinfo);
3206 sRef mlsr = metaStateSpecifier_getSref (msspec);
3208 stateValue sval = stateValue_undefined;
3210 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3211 metaStateConstraint_unparse (msc)));
3212 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3214 if (sRef_isResult (sRef_getRootBase (mlsr)))
3216 s = sRef_undefined; /*@i423 what about results? */
3220 s = sRef_fixBaseParam (mlsr, args);
3221 DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3224 /* while (metaStateExpression_isDefined (msexpr)) */
3226 metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
3227 sRef msr = metaStateSpecifier_getSref (ms);
3228 metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
3231 if (metaStateInfo_isDefined (msi))
3233 /* Must match lhs state */
3234 llassert (metaStateInfo_equal (msinfo, msi));
3237 llassert (sRef_isParam (sRef_getRootBase (msr)));
3238 fs = sRef_fixBaseParam (msr, args);
3240 sval = sRef_getMetaStateValue (fs, key);
3243 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3244 sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), exprNode_loc (f));
3250 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3252 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3253 exprNode_unparse (f), exprNodeList_unparse (args),
3254 uentry_unparseFull (le),
3255 stateClauseList_unparse (uentry_getStateClauseList (le))));
3257 if (uentry_isValid (le) && uentry_isFunction (le))
3259 stateClauseList sclauses = uentry_getStateClauseList (le);
3261 if (stateClauseList_isDefined (sclauses))
3263 DPRINTF (("Check requires: %s / %s / %s",
3264 uentry_unparse (le),
3265 exprNode_unparse (f), exprNodeList_unparse (args)));
3267 stateClauseList_elements (sclauses, cl)
3269 DPRINTF (("Check clause: %s / %s",
3270 stateClause_unparse (cl),
3271 bool_unparse (stateClause_hasRequires (cl))));
3273 if (stateClause_hasRequires (cl))
3275 sRefSet osrs = sRefSet_undefined;
3278 if (stateClause_isGlobal (cl))
3280 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3285 srs = stateClause_getRefs (cl);
3288 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3290 if (stateClause_setsMetaState (cl))
3292 qual q = stateClause_getMetaQual (cl);
3293 annotationInfo ainfo = qual_getAnnotationInfo (q);
3294 metaStateInfo minfo = annotationInfo_getState (ainfo);
3295 cstring key = metaStateInfo_getName (minfo);
3296 int mvalue = annotationInfo_getValue (ainfo);
3298 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3300 sRefSet_elements (srs, sel)
3302 sRef s = sRef_fixBaseParam (sel, args);
3304 if (sRef_isResult (sRef_getRootBase (sel)))
3306 ; /*@i423 what do we do about results */
3310 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3311 sRef_unparseFull (sel), sRef_unparseFull (s),
3314 if (!sRef_checkMetaStateValue (s, key, mvalue))
3316 DPRINTF (("HERE: %s", sRef_unparse (s)));
3320 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3321 uentry_getName (le),
3322 sRef_isGlobalMarker (s)
3324 : message (" by %q", sRef_unparse (s)),
3325 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3327 stateClause_unparse (cl)),
3330 sRef_showAliasInfo (s);
3334 DPRINTF (("Error supressed!"));
3335 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3336 DPRINTF (("Context supress: %s",
3337 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3341 } end_sRefSet_elements;
3345 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3346 int eparam = stateClause_getStateParameter (cl);
3348 DPRINTF (("Reflect after clause: %s / %s",
3349 stateClause_unparse (cl),
3350 sRefSet_unparse (srs)));
3352 sRefSet_elements (srs, sel)
3356 DPRINTF (("elements: %s", sRef_unparse (sel)));
3357 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3359 s = sRef_fixBaseParam (sel, args);
3361 DPRINTF (("elements: %s", sRef_unparse (s)));
3362 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3364 if (sRef_isResult (sRef_getRootBase (sel)))
3366 ; /*@i423 what do we do about results */
3370 DPRINTF (("Reflecting state clause on: %s / %s",
3371 sRef_unparse (sel), sRef_unparse (s)));
3373 modf (s, eparam, exprNode_loc (f));
3375 } end_sRefSet_elements;
3378 sRefSet_free (osrs);
3380 } end_stateClauseList_elements ;
3385 static /*@only@*/ exprNode
3386 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3387 ctype t, /*@keep@*/ exprNodeList args)
3389 /* requires f is a non-error exprNode, with type function */
3390 cstring fname = exprNode_unparse (f);
3391 uentry le = exprNode_getUentry (f);
3392 exprNode ret = exprNode_createPartialCopy (f);
3397 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3399 ret->typ = ctype_getReturnType (t);
3400 ret->kind = XPR_CALL;
3402 ret->edata = exprData_makeCall (f, args);
3405 ** Order of these steps is very important!
3407 ** Must check for argument dependencies before messing up uses and sets.
3410 if (context_getFlag (FLG_EVALORDER))
3412 exprNodeList_elements (args, current)
3414 if (exprNode_isDefined (current))
3416 exprNode_addUse (current, current->sref);
3418 } end_exprNodeList_elements;
3420 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3422 checkSequencing (f, args);
3425 exprNodeList_elements (args, current)
3427 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3429 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3431 } end_exprNodeList_elements ;
3434 special = checkArgs (le, f, t, args, ret);
3435 checkGlobMods (f, le, args, ret, special);
3436 checkRequiresClause (le, f, args);
3439 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3440 reflectEnsuresClause (le, f, args);
3443 if (uentry_isValid (le)
3444 && (uentry_isFunction (le)
3445 || (uentry_isVariable (le)
3446 && ctype_isFunction (uentry_getType (le)))))
3448 exitkind exk = uentry_getExitCode (le);
3450 /* f->typ is already set to the return type */
3452 ret->sref = uentry_returnedRef (le, args);
3453 DPRINTF (("Returned: %s / %s",
3454 uentry_unparseFull (le),
3455 sRef_unparseFull (ret->sref)));
3457 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3459 qual nullPred = uentry_nullPred (le);
3461 if (qual_isTrueNull (nullPred))
3463 exprNode arg = exprNodeList_head (args);
3465 if (exprNode_isDefined (arg))
3467 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3470 else if (qual_isFalseNull (nullPred))
3472 exprNode arg = exprNodeList_head (args);
3474 if (exprNode_isDefined (arg))
3476 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3481 llassert (qual_isUnknown (nullPred));
3485 if (exitkind_isConditionalExit (exk))
3489 ** if (arg0) then { exit! } else { ; }
3491 ** if (arg0) then { ; } else { exit! }
3496 llassert (!exprNodeList_isEmpty (args));
3497 firstArg = exprNodeList_head (args);
3499 if (exprNode_isDefined (firstArg)
3500 && !guardSet_isEmpty (firstArg->guards))
3502 usymtab_trueBranch (guardSet_undefined);
3503 usymtab_altBranch (guardSet_undefined);
3505 if (exitkind_isTrueExit (exk))
3507 usymtab_popBranches (firstArg,
3508 exprNode_makeMustExit (),
3510 TRUE, TRUEEXITCLAUSE);
3514 usymtab_popBranches (firstArg,
3516 exprNode_makeMustExit (),
3517 TRUE, FALSEEXITCLAUSE);
3521 ret->exitCode = XK_MAYEXIT;
3523 else if (exitkind_mustExit (exk))
3525 ret->exitCode = XK_MUSTEXIT;
3527 else if (exitkind_couldExit (exk))
3529 ret->exitCode = XK_MAYEXIT;
3536 if (cstring_equalLit (fname, "exit"))
3538 if (exprNodeList_size (args) == 1)
3540 exprNode arg = exprNodeList_head (args);
3542 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3544 long int val = multiVal_forceInt (exprNode_getValue (arg));
3551 ("Argument to exit has implementation defined behavior: %s",
3552 exprNode_unparse (arg)),
3553 exprNode_loc (arg));
3562 exprNode_checkSetAny (ret, uentry_rawName (le));
3569 ** this is yucky! should keep the uentry as part of exprNode!
3572 /*@observer@*/ uentry
3573 exprNode_getUentry (exprNode e)
3575 if (exprNode_isError (e))
3577 return uentry_undefined;
3581 cstring s = exprNode_rootVarName (e);
3582 uentry ue = usymtab_lookupSafe (s);
3589 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3591 exprNode ret = exprNode_createPlain (ctype_unknown);
3593 ret->kind = XPR_INITBLOCK;
3594 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3595 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3601 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3607 if (exprNode_isUndefined (f))
3610 exprNodeList_free (args);
3611 return exprNode_undefined;
3614 t = exprNode_getType (f);
3616 if (sRef_isLocalVar (f->sref))
3618 exprNode_checkUse (f, f->sref, f->loc);
3620 if (sRef_possiblyNull (f->sref))
3622 if (!usymtab_isGuarded (f->sref))
3624 if (optgenerror (FLG_NULLDEREF,
3625 message ("Function call using %s pointer %q",
3626 sRef_nullMessage (f->sref),
3627 sRef_unparse (f->sref)),
3630 sRef_showNullInfo (f->sref);
3631 sRef_setNullError (f->sref);
3639 if (ctype_isRealFunction (t))
3641 exprNode ret = functionCallSafe (f, t, args);
3645 else if (ctype_isUnknown (t))
3647 exprNode ret = exprNode_createPartialCopy (f);
3653 exprNodeList_elements (args, current)
3655 if (exprNode_isDefined (current))
3657 exprNode_checkUse (ret, current->sref, ret->loc);
3660 ** also, anything derivable from current->sref may be used
3663 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3664 exprNode_mergeUSs (ret, current);
3666 } end_exprNodeList_elements;
3668 ret->edata = exprData_makeCall (f, args);
3669 ret->kind = XPR_CALL;
3671 tstring = cstring_copy (exprNode_unparse (f));
3673 cstring_markOwned (tstring);
3674 exprNode_checkSetAny (ret, tstring);
3680 voptgenerror (FLG_TYPE,
3681 message ("Call to non-function (type %t): %s", t,
3682 exprNode_unparse (f)),
3685 exprNodeList_free (args);
3687 return (exprNode_makeError ());
3692 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
3693 /*@only@*/ cstring f)
3695 exprNode ret = exprNode_createPartialCopy (s);
3697 ret->kind = XPR_FACCESS;
3699 if (exprNode_isError (s))
3701 ret->edata = exprData_makeField (s, f);
3706 ctype t = exprNode_getType (s);
3707 ctype tr = ctype_realType (t);
3709 checkMacroParen (s);
3711 ret->edata = exprData_makeField (s, f);
3713 if (ctype_isStructorUnion (tr))
3715 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
3717 if (uentry_isUndefined (tf))
3719 voptgenerror (FLG_TYPE,
3720 message ("Access non-existent field %s of %t: %s", f, t,
3721 exprNode_unparse (ret)),
3723 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
3728 uentry_setUsed (tf, exprNode_loc (ret));
3730 ret->typ = uentry_getType (tf);
3731 checkSafeUse (ret, s->sref);
3733 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
3734 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
3738 else /* isStructorUnion */
3740 if (ctype_isRealAbstract (tr))
3744 message ("Access field of abstract type (%t): %s.%s",
3745 t, exprNode_unparse (s), f),
3747 ret->typ = ctype_unknown;
3751 if (ctype_isKnown (tr))
3756 ("Access field of non-struct or union (%t): %s.%s",
3757 t, exprNode_unparse (s), f),
3760 ret->typ = ctype_unknown;
3764 cstring sn = cstring_copy (f);
3766 checkSafeUse (ret, s->sref);
3767 cstring_markOwned (sn);
3768 ret->sref = sRef_makeField (s->sref, sn);
3780 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
3781 /*@only@*/ cstring f)
3783 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
3784 lltok_release (dot);
3789 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
3791 exprNode ret = exprNode_createPartialCopy (e);
3793 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
3794 ret->kind = XPR_PARENS;
3795 ret->edata = exprData_makeUop (e, lpar);
3797 if (!exprNode_isError (e))
3799 ret->exitCode = e->exitCode;
3800 ret->canBreak = e->canBreak;
3801 ret->mustBreak = e->mustBreak;
3802 ret->isJumpPoint = e->isJumpPoint;
3803 ret->sref = e->sref;
3810 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
3811 /*@only@*/ cstring f)
3813 exprNode ret = exprNode_createPartialCopy (s);
3815 ret->edata = exprData_makeField (s, f);
3816 ret->kind = XPR_ARROW;
3818 if (exprNode_isError (s))
3824 ctype t = exprNode_getType (s);
3825 ctype tr = ctype_realType (t);
3827 checkMacroParen (s);
3829 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
3831 if (ctype_isRealPointer (tr))
3833 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
3835 if (ctype_isStructorUnion (b))
3837 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
3839 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
3841 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
3845 message ("Arrow access from %s pointer%q: %s",
3846 sRef_nullMessage (s->sref),
3847 sRef_unparsePreOpt (s->sref),
3848 exprNode_unparse (ret)),
3851 sRef_showNullInfo (s->sref);
3852 sRef_setNullError (s->sref);
3857 if (uentry_isUndefined (fentry))
3861 message ("Access non-existent field %s of %t: %s",
3862 f, t, exprNode_unparse (ret)),
3864 ret->typ = ctype_unknown;
3870 ** was safeUse: shouldn't be safe!
3873 ** rec must be defined,
3874 ** *rec must be allocated
3875 ** rec->field need only be defined it if is an rvalue
3878 uentry_setUsed (fentry, exprNode_loc (ret));
3879 ret->typ = uentry_getType (fentry);
3881 exprNode_checkUse (ret, s->sref, s->loc);
3883 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
3884 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
3888 else /* Pointer to something that is not a struct or union*/
3890 if (ctype_isRealAbstract (tr))
3892 ctype xrt = ctype_forceRealType (tr);
3896 message ("Arrow access field of abstract type (%t): %s->%s",
3897 t, exprNode_unparse (s), f),
3901 ** Set the state correctly, as if the abstraction is broken.
3904 if (ctype_isRealPointer (xrt) &&
3905 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
3906 ctype_isStructorUnion (b)))
3908 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
3909 ret->typ = uentry_getType (fentry);
3910 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
3914 ret->typ = ctype_unknown;
3915 ret->sref = sRef_undefined;
3918 else /* not a struct, union or abstract */
3920 if (ctype_isUnknown (tr)) {
3921 cstring sn = cstring_copy (f);
3923 DPRINTF (("Here: %s", exprNode_unparse (s)));
3925 exprNode_checkUse (ret, s->sref, s->loc);
3926 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
3928 cstring_markOwned (sn);
3929 ret->sref = sRef_makeArrow (s->sref, sn);
3931 ret->kind = XPR_ARROW;
3936 message ("Arrow access field of non-struct or union "
3937 "pointer (%t): %s->%s",
3938 t, exprNode_unparse (s), f),
3941 ret->typ = ctype_unknown;
3942 ret->sref = sRef_undefined;
3947 else /* its not a pointer */
3949 if (!ctype_isUnknown (tr))
3953 message ("Arrow access of non-pointer (%t): %s->%s",
3954 t, exprNode_unparse (s), f),
3957 ret->typ = ctype_unknown;
3958 ret->sref = sRef_undefined;
3962 cstring sn = cstring_copy (f);
3964 DPRINTF (("Here: %s", exprNode_unparse (s)));
3966 exprNode_checkUse (ret, s->sref, s->loc);
3967 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
3969 cstring_markOwned (sn);
3970 ret->sref = sRef_makeArrow (s->sref, sn);
3972 ret->kind = XPR_ARROW;
3983 exprNode_arrowAccess (/*@only@*/ exprNode s,
3984 /*@only@*/ lltok arrow,
3985 /*@only@*/ cstring f)
3987 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
3988 lltok_release (arrow);
3993 ** only postOp's in C: i++ and i--
3997 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
3999 /* check modification also */
4000 /* cstring opname = lltok_unparse (op);*/
4002 exprNode ret = exprNode_createPartialCopy (e);
4004 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4005 ret->kind = XPR_POSTOP;
4006 ret->edata = exprData_makeUop (e, op);
4008 if (!exprNode_isDefined (e))
4013 checkMacroParen (e);
4015 exprNode_checkUse (ret, e->sref, e->loc);
4016 exprNode_checkSet (ret, e->sref);
4018 t = exprNode_getType (e);
4020 if (sRef_isUnsafe (e->sref))
4022 voptgenerror (FLG_MACROPARAMS,
4023 message ("Operand of %s is macro parameter (non-functional): %s%s",
4024 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4026 sRef_makeSafe (e->sref);
4027 sRef_makeSafe (ret->sref);
4030 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4036 if (ctype_isRealAbstract (t))
4040 message ("Operand of %s is abstract type (%t): %s",
4041 lltok_unparse (op), t, exprNode_unparse (e)),
4048 message ("Operand of %s is non-numeric (%t): %s",
4049 lltok_unparse (op), t, exprNode_unparse (e)),
4052 ret->typ = ctype_unknown;
4055 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4057 exprNode_checkModify (e, ret);
4059 /* added 7/11/2000 D.L */
4061 /*DRL 6/8/01 I decided to disable all LCLint Warning here since the code
4062 probably needs a rewrite any way */
4066 // updateEnvironmentForPostOp (e);
4068 /* start modifications */
4069 /* added by Seejo on 4/16/2000 */
4071 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4073 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4075 ret->sref = sRef_copy (e->sref);
4078 if (lltok_getTok (op) == INC_OP) {
4079 if (sRef_getSize(e->sref) > 0) {
4081 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4083 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4084 /* Assumption: there is only 1 \0 in the buffer */
4085 /* This will not be correct if there are 2 \0's in the buffer */
4086 sRef_setNotNullTerminatedState(ret->sref);
4087 sRef_resetLen(ret->sref);
4089 sRef_setNullTerminatedState(ret->sref);
4090 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4092 if (sRef_isNullTerminated (ret->sref))
4093 printf ("ret->sref is Null Terminated\n");
4094 else if (sRef_isPossiblyNullTerminated (ret->sref))
4095 printf ("ret->sref is Possibly Null Terminated\n");
4096 else if (sRef_isNotNullTerminated (ret->sref))
4097 printf ("ret->sref is Not Null Terminated\n");
4102 if (lltok_getTok (op) == DEC_OP) {
4103 if (sRef_getSize(e->sref) >= 0) {
4104 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4105 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4110 /* end modifications */
4116 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4118 bool checkMod = FALSE;
4120 int opid = lltok_getTok (op);
4121 exprNode ret = exprNode_createSemiCopy (e);
4123 exprNode_copySets (ret, e);
4125 multiVal_free (ret->val);
4126 ret->val = multiVal_undefined;
4127 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4128 ret->kind = XPR_PREOP;
4129 ret->edata = exprData_makeUop (e, op);
4131 if (exprNode_isError (e))
4136 checkMacroParen (e);
4138 te = exprNode_getType (e);
4139 tr = ctype_realType (te);
4141 if (opid != TAMPERSAND)
4143 exprNode_checkUse (ret, e->sref, e->loc);
4145 if (ctype_isRealAbstract (tr)
4146 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4148 if (optgenerror (FLG_ABSTRACT,
4149 message ("Operand of %s is abstract type (%t): %s",
4150 lltok_unparse (op), tr,
4151 exprNode_unparse (ret)),
4154 tr = te = ctype_unknown;
4155 ret->typ = ctype_unknown;
4156 sRef_setNullError (e->sref);
4164 case DEC_OP: /* should also check modification! */
4165 if (sRef_isMacroParamRef (e->sref))
4169 message ("Operand of %s is macro parameter (non-functional): %s",
4170 lltok_unparse (op), exprNode_unparse (ret)),
4175 exprNode_checkSet (ret, e->sref);
4178 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4183 if (context_msgStrictOps ())
4187 message ("Operand of %s is non-numeric (%t): %s",
4188 lltok_unparse (op), te, exprNode_unparse (ret)),
4191 ret->typ = ctype_int;
4194 /* start modifications */
4195 /* added by Seejo on 4/16/2000 */
4197 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4199 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4201 ret->sref = sRef_copy (e->sref);
4204 if (lltok_getTok (op) == INC_OP) {
4205 if (sRef_getSize(e->sref) > 0) {
4207 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4209 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4210 /* Assumption: there is only 1 \0 in the buffer */
4211 /* This will not be correct if there are 2 \0's in the buffer */
4212 sRef_setNotNullTerminatedState(ret->sref);
4213 sRef_resetLen (ret->sref);
4215 sRef_setNullTerminatedState(ret->sref);
4216 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4222 if (lltok_getTok (op) == DEC_OP) {
4223 if (sRef_getSize(e->sref) >= 0) {
4224 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4225 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4230 /* end modifications */
4237 if (ctype_isForceRealNumeric (&tr))
4241 ret->val = multiVal_invert (exprNode_getValue (e));
4245 ret->val = multiVal_copy (exprNode_getValue (e));
4250 if (context_msgStrictOps ())
4254 message ("Operand of %s is non-numeric (%t): %s",
4255 lltok_unparse (op), te, exprNode_unparse (ret)),
4259 ret->typ = ctype_int;
4263 case TEXCL: /* maybe this should be restricted */
4264 guardSet_flip (ret->guards);
4266 if (ctype_isRealBool (te) || ctype_isUnknown (te))
4272 if (ctype_isRealPointer (tr))
4274 if (sRef_isKnown (e->sref))
4276 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4280 (FLG_BOOLOPS, FLG_PTRNEGATE,
4281 message ("Operand of %s is non-boolean (%t): %s",
4282 lltok_unparse (op), te, exprNode_unparse (ret)),
4289 message ("Operand of %s is non-boolean (%t): %s",
4290 lltok_unparse (op), te, exprNode_unparse (ret)),
4294 ret->typ = ctype_bool;
4299 if (ctype_isForceRealInt (&tr))
4304 if (context_msgStrictOps ())
4308 message ("Operand of %s is non-integer (%t): %s",
4309 lltok_unparse (op), te, exprNode_unparse (ret)),
4313 if (ctype_isInt (e->typ))
4319 ret->typ = ctype_int;
4325 ret->typ = ctype_makePointer (e->typ);
4327 if (sRef_isKnown (e->sref))
4329 ret->sref = sRef_makeAddress (e->sref);
4336 if (ctype_isAP (tr))
4338 ret->typ = ctype_baseArrayPtr (e->typ);
4342 if (ctype_isKnown (te))
4344 if (ctype_isFunction (te))
4350 message ("Dereference of function type (%t): %s",
4351 te, exprNode_unparse (ret)),
4356 voptgenerror (FLG_TYPE,
4357 message ("Dereference of non-pointer (%t): %s",
4358 te, exprNode_unparse (ret)),
4360 ret->typ = ctype_unknown;
4365 ret->typ = ctype_unknown;
4370 if (sRef_isKnown (e->sref))
4372 if (sRef_possiblyNull (e->sref))
4374 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4378 message ("Dereference of %s pointer %q: %s",
4379 sRef_nullMessage (e->sref),
4380 sRef_unparse (e->sref),
4381 exprNode_unparse (ret)),
4384 sRef_showNullInfo (e->sref);
4385 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4390 ret->sref = sRef_makePointer (e->sref);
4395 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4400 exprNode_checkModify (e, ret);
4407 ** any reason to disallow sizeof (abstract type) ?
4411 ** used by both sizeof
4415 ctype sizeof_resultType (void)
4417 static ctype sizet = ctype_unknown;
4419 if (ctype_isUnknown (sizet))
4421 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4423 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4427 sizet = ctype_ulint;
4434 exprNode_sizeofType (/*@only@*/ qtype qt)
4436 exprNode ret = exprNode_create (sizeof_resultType ());
4437 ctype ct = qtype_getType (qt);
4439 ret->kind = XPR_SIZEOFT;
4440 ret->edata = exprData_makeSizeofType (qt);
4442 voptgenerror (FLG_SIZEOFTYPE,
4443 message ("Parameter to sizeof is type %s: %s",
4445 exprNode_unparse (ret)),
4452 exprNode_alignofType (/*@only@*/ qtype qt)
4454 exprNode ret = exprNode_create (sizeof_resultType ());
4455 ctype ct = qtype_getType (qt);
4457 ret->kind = XPR_ALIGNOFT;
4458 ret->edata = exprData_makeSizeofType (qt);
4460 voptgenerror (FLG_SIZEOFTYPE,
4461 message ("Parameter to alignof is type %s: %s",
4463 exprNode_unparse (ret)),
4469 exprNode exprNode_offsetof (qtype qt, cstringList s)
4471 exprNode ret = exprNode_create (sizeof_resultType ());
4472 ctype ct = qtype_getType (qt);
4474 ret->kind = XPR_OFFSETOF;
4475 ret->edata = exprData_makeOffsetof (qt, s);
4477 if (!ctype_isRealSU (ct))
4479 voptgenerror (FLG_TYPE,
4480 message ("First parameter to offsetof is not a "
4481 "struct or union type (type %s): %s",
4483 exprNode_unparse (ret)),
4490 cstringList_elements (s, el) {
4494 if (ctype_isUndefined (lt))
4498 else if (!ctype_isRealSU (lt))
4500 voptgenerror (FLG_TYPE,
4501 message ("Inner offsetof type is not a "
4502 "struct or union type (type %s before field %s): %s",
4503 ctype_unparse (lt), el,
4504 exprNode_unparse (ret)),
4510 fields = ctype_getFields (ctype_realType (lt));
4511 fld = uentryList_lookupField (fields, el);
4512 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4514 if (uentry_isUndefined (fld))
4516 if (ctype_equal (lt, ct)) {
4517 voptgenerror (FLG_TYPE,
4518 message ("Field %s in offsetof is not the "
4519 "name of a field of %s: %s",
4522 exprNode_unparse (ret)),
4525 voptgenerror (FLG_TYPE,
4526 message ("Deep field %s in offsetof is not the "
4527 "name of a field of %s: %s",
4530 exprNode_unparse (ret)),
4536 lt = uentry_getType (fld);
4539 } end_cstringList_elements;
4541 /* Should report error if its a bit field - behavior is undefined! */
4548 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4552 if (exprNode_isUndefined (e))
4554 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4555 ret->edata = exprData_makeSingle (e);
4556 ret->typ = sizeof_resultType ();
4557 ret->kind = XPR_SIZEOF;
4561 uentry u = exprNode_getUentry (e);
4563 ret = exprNode_createPartialCopy (e);
4564 ret->edata = exprData_makeSingle (e);
4566 ret->typ = sizeof_resultType ();
4567 ret->kind = XPR_SIZEOF;
4569 if (uentry_isValid (u)
4570 && uentry_isRefParam (u)
4571 && ctype_isRealArray (uentry_getType (u)))
4574 (FLG_SIZEOFFORMALARRAY,
4575 message ("Parameter to sizeof is an array-type function parameter: %s",
4576 exprNode_unparse (ret)),
4582 ** sizeof (x) doesn't "really" use x
4589 exprNode_alignofExpr (/*@only@*/ exprNode e)
4593 if (exprNode_isUndefined (e))
4595 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4599 ret = exprNode_createPartialCopy (e);
4602 ret->edata = exprData_makeSingle (e);
4603 ret->typ = sizeof_resultType ();
4604 ret->kind = XPR_ALIGNOF;
4607 ** sizeof (x) doesn't "really" use x
4614 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4620 if (exprNode_isError (e))
4623 lltok_release (tok);
4624 return exprNode_undefined;
4627 checkMacroParen (e);
4629 c = qtype_getType (q);
4630 t = exprNode_getType (e);
4632 ret = exprNode_createPartialCopy (e);
4634 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4636 ret->kind = XPR_CAST;
4637 ret->edata = exprData_makeCast (tok, e, q);
4639 if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
4642 ** This is a bit of a hack to avoid a problem
4643 ** when the code does,
4644 ** (some other struct) x
4649 ret->sref = sRef_copy (e->sref);
4650 usymtab_addForceMustAlias (ret->sref, e->sref);
4651 sRef_setTypeFull (ret->sref, c);
4652 DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
4653 sRef_unparseFull (ret->sref)));
4657 ret->sref = e->sref;
4658 sRef_setTypeFull (ret->sref, c);
4659 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
4666 ** void * <-> abstract * (if FLG_ABSTVOIDP)
4667 ** abstract * <-> void * (if FLG_ABSTVOIDP)
4670 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
4674 else if (ctype_isRealAP (c)) /* casting to array or pointer */
4676 ctype bc = ctype_getBaseType (c);
4677 ctype bt = ctype_getBaseType (t);
4678 ctype rt = ctype_realType (t);
4680 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
4681 && (ctype_isArrayPtr (rt)
4682 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4686 message ("Cast from function pointer type (%t) to "
4687 "non-function pointer (%t): %s",
4688 c, t, exprNode_unparse (ret)),
4692 if (!ctype_isFunction (ctype_baseArrayPtr (c))
4693 && (ctype_isArrayPtr (rt)
4694 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4698 message ("Cast from non-function pointer type (%t) to "
4699 "function pointer (%t): %s",
4700 c, t, exprNode_unparse (ret)),
4704 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
4705 !(ctype_isRealAbstract (bc)
4706 && context_hasAccess (ctype_typeId (bc))))
4708 ; /* okay to cast zero */
4712 if (ctype_isRealAbstract (bc)
4713 && !context_hasAccess (ctype_typeId (bc)))
4715 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
4719 message ("Cast to underlying abstract type %t: %s",
4720 c, exprNode_unparse (ret)),
4727 message ("Cast to underlying abstract type %t: %s",
4728 c, exprNode_unparse (ret)),
4733 if (ctype_isRealAbstract (bt)
4734 && !context_hasAccess (ctype_typeId (bt)))
4736 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
4740 message ("Cast from underlying abstract type %t: %s",
4741 t, exprNode_unparse (ret)),
4748 message ("Cast from underlying abstract type %t: %s",
4749 t, exprNode_unparse (ret)),
4757 ctype bt = ctype_realType (ctype_getBaseType (t));
4758 ctype bc = ctype_realType (ctype_getBaseType (c));
4760 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
4762 if (ctype_match (c, t))
4764 if (ctype_equal (c, t))
4768 message ("Redundant cast involving abstract type %t: %s",
4769 bt, exprNode_unparse (ret)),
4777 message ("Cast from abstract type %t: %s",
4778 bt, exprNode_unparse (ret)),
4783 if (ctype_isAbstract (bc)
4784 && !context_hasAccess (ctype_typeId (bc)))
4786 if (ctype_match (c, t))
4792 DPRINTF (("No access to: %s / %d",
4793 ctype_unparse (bc), ctype_typeId (bc)));
4794 DPRINTF (("Context %s %s",
4795 bool_unparse (context_inFunctionLike ()),
4796 context_unparse ()));
4799 message ("Cast to abstract type %t: %s", bc,
4800 exprNode_unparse (ret)),
4806 if (ctype_isAbstract (c))
4808 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
4810 /* okay, cast exposed to abstract */
4811 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
4815 if (ctype_isVisiblySharable (t)
4816 && sRef_isExternallyVisible (e->sref)
4817 && !(ctype_isAbstract (t)
4818 && context_hasAccess (ctype_typeId (t))))
4822 message ("Cast to abstract type from externally visible "
4823 "mutable storage exposes rep of %s: %s",
4825 exprNode_unparse (e)),
4835 evaluationOrderUndefined (lltok op)
4837 int opid = lltok_getTok (op);
4839 return (opid != AND_OP && opid != OR_OP);
4842 static bool checkIntegral (/*@notnull@*/ exprNode e1,
4843 /*@notnull@*/ exprNode e2,
4844 /*@notnull@*/ exprNode ret,
4849 ctype te1 = exprNode_getType (e1);
4850 ctype te2 = exprNode_getType (e2);
4852 ctype tr1 = ctype_realishType (te1);
4853 ctype tr2 = ctype_realishType (te2);
4855 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
4861 if (context_msgStrictOps ())
4863 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
4865 if (ctype_sameName (te1, te2))
4869 message ("Operands of %s are non-integer (%t): %s",
4870 lltok_unparse (op), te1,
4871 exprNode_unparse (ret)),
4878 message ("Operands of %s are non-integers (%t, %t): %s",
4879 lltok_unparse (op), te1, te2,
4880 exprNode_unparse (ret)),
4884 else if (!ctype_isInt (tr1))
4888 message ("Left operand of %s is non-integer (%t): %s",
4889 lltok_unparse (op), te1, exprNode_unparse (ret)),
4893 /* !ctype_isInt (te2) */
4897 message ("Right operand of %s is non-integer (%t): %s",
4898 lltok_unparse (op), te2, exprNode_unparse (ret)),
4908 ** returns exprNode representing e1 op e2
4910 ** uses msg if there are errors
4911 ** can be used for both assignment ops and regular ops
4916 static /*@only@*/ /*@notnull@*/ exprNode
4917 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
4918 /*@keep@*/ lltok op)
4920 ctype te1, te2, tr1, tr2, tret;
4921 int opid = lltok_getTok (op);
4922 bool hasError = FALSE;
4925 if (exprNode_isError (e1))
4927 ret = exprNode_createPartialNVCopy (e2);
4931 ret = exprNode_createPartialNVCopy (e1);
4934 ret->val = multiVal_undefined;
4936 ret->edata = exprData_makeOp (e1, e2, op);
4938 if (exprNode_isError (e1) || exprNode_isError (e2))
4940 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
4941 || opid == EQ_OP || opid == NE_OP
4942 || opid == AND_OP || opid == OR_OP)
4944 ret->typ = ctype_bool;
4947 if (exprNode_isDefined (e1))
4949 exprNode_checkUse (ret, e1->sref, e1->loc);
4952 if (exprNode_isDefined (e2))
4954 exprNode_mergeUSs (ret, e2);
4955 exprNode_checkUse (ret, e2->sref, e2->loc);
4961 tret = ctype_unknown;
4962 te1 = exprNode_getType (e1);
4963 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
4965 te2 = exprNode_getType (e2);
4967 tr1 = ctype_realishType (te1);
4968 tr2 = ctype_realishType (te2);
4972 ret->guards = guardSet_or (ret->guards, e2->guards);
4974 else if (opid == AND_OP)
4976 ret->guards = guardSet_and (ret->guards, e2->guards);
4983 if (opid == EQ_OP || opid == NE_OP)
4985 exprNode temp1 = e1, temp2 = e2;
4987 /* could do NULL == x */
4989 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
4991 temp1 = e2; temp2 = e1;
4994 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
4996 reflectNullTest (temp1, (opid == NE_OP));
4997 guardSet_free (ret->guards);
4998 ret->guards = guardSet_copy (temp1->guards);
5002 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5003 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5008 if (anyAbstract (tr1, tr2) &&
5009 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
5010 (opid == AND_OP || opid == OR_OP
5011 || opid == EQ_OP || opid == NE_OP))))
5013 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
5015 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5017 /* unknown types, no comparisons possible */
5023 case TMULT: /* multiplication and division: */
5025 case MUL_ASSIGN: /* numeric, numeric -> numeric */
5026 case DIV_ASSIGN: /* */
5028 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5031 case TPLUS: /* addition and subtraction: */
5032 case TMINUS: /* pointer, int -> pointer */
5033 case SUB_ASSIGN: /* int, pointer -> pointer */
5034 case ADD_ASSIGN: /* numeric, numeric -> numeric */
5036 tr1 = ctype_fixArrayPtr (tr1);
5038 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5039 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5043 if (context_msgPointerArith ())
5047 message ("Pointer arithmetic (%t, %t): %s",
5048 te1, te2, exprNode_unparse (ret)),
5052 if (sRef_possiblyNull (e1->sref)
5053 && !usymtab_isGuarded (e1->sref))
5056 (FLG_NULLPOINTERARITH,
5057 message ("Pointer arithmetic involving possibly "
5058 "null pointer %s: %s",
5059 exprNode_unparse (e1),
5060 exprNode_unparse (ret)),
5064 ret->sref = sRef_copy (e1->sref);
5066 /* start modifications */
5067 /* added by Seejo on 4/16/2000 */
5069 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5071 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5072 //if (sRef_isKnown (e->sref)) {
5073 //ret->sref = sRef_makeAddress (e->sref);
5078 added ugly fixed to stop
5079 program from crashing on point + int +int
5080 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5082 if (!multiVal_isInt (e2->val) )
5086 val = (int) multiVal_forceInt (e2->val);
5088 /* Operator : + or += */
5089 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5090 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5091 val should not result in a
5092 size < 0 (size = 0 is ok !) */
5094 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5096 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5097 sRef_setNotNullTerminatedState(ret->sref);
5098 sRef_resetLen (ret->sref);
5100 sRef_setNullTerminatedState(ret->sref);
5101 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5106 /* Operator : - or -= */
5107 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5108 if (sRef_getSize(e1->sref) >= 0) {
5109 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5110 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5115 /* end modifications */
5117 sRef_setNullError (ret->sref);
5120 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5121 ** since is points to storage that should not be deallocated
5122 ** through this pointer.
5125 if (sRef_isOnly (ret->sref)
5126 || sRef_isFresh (ret->sref))
5128 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5133 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5134 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5136 if (context_msgPointerArith ())
5140 message ("Pointer arithmetic (%t, %t): %s",
5141 te1, te2, exprNode_unparse (ret)),
5145 if (sRef_possiblyNull (e1->sref)
5146 && !usymtab_isGuarded (e1->sref))
5149 (FLG_NULLPOINTERARITH,
5150 message ("Pointer arithmetic involving possibly "
5151 "null pointer %s: %s",
5152 exprNode_unparse (e2),
5153 exprNode_unparse (ret)),
5157 ret->sref = sRef_copy (e2->sref);
5159 /* start modifications */
5160 /* added by Seejo on 4/16/2000 */
5162 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5165 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5166 //if (sRef_isKnown (e->sref)) {
5167 //ret->sref = sRef_makeAddress (e->sref);
5170 int val = (int) multiVal_forceInt (e1->val);
5172 /* Operator : + or += */
5173 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5174 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5175 val should not result in a
5176 size < 0 (size = 0 is ok !) */
5178 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5180 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5181 sRef_setNotNullTerminatedState(ret->sref);
5182 sRef_resetLen (ret->sref);
5184 sRef_setNullTerminatedState(ret->sref);
5185 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5190 /* Operator : - or -= */
5191 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5192 if (sRef_getSize(e2->sref) >= 0) {
5193 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5194 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5199 /* end modifications */
5201 sRef_setNullError (ret->sref);
5204 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5205 ** since is points to storage that should not be deallocated
5206 ** through this pointer.
5209 if (sRef_isOnly (ret->sref)
5210 || sRef_isFresh (ret->sref)) {
5211 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5215 ret->sref = e2->sref;
5219 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5224 case LEFT_ASSIGN: /* Shifts: should be unsigned values */
5228 case TAMPERSAND: /* bitwise & */
5230 case TCIRC: /* ^ (XOR) */
5235 bool reported = FALSE;
5236 flagcode code = FLG_BITWISEOPS;
5238 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5239 || opid == RIGHT_OP || opid == RIGHT_ASSIGN) {
5240 code = FLG_SHIFTSIGNED;
5243 if (!ctype_isUnsigned (tr1))
5245 if (exprNode_isNonNegative (e1)) {
5248 reported = optgenerror
5250 message ("Left operand of %s is not unsigned value (%t): %s",
5251 lltok_unparse (op), te1,
5252 exprNode_unparse (ret)),
5262 /* right need not be signed for shifts */
5263 if (code != FLG_SHIFTSIGNED
5264 && !ctype_isUnsigned (tr2))
5266 if (!exprNode_isNonNegative (e2)) {
5267 reported = optgenerror
5269 message ("Right operand of %s is not unsigned value (%t): %s",
5270 lltok_unparse (op), te2,
5271 exprNode_unparse (ret)),
5279 if (!checkIntegral (e1, e2, ret, op)) {
5280 te1 = ctype_unknown;
5284 DPRINTF (("Set: %s", ctype_unparse (te1)));
5287 ** tret is the widest type of te1 and te2
5290 tret = ctype_widest (te1, te2);
5295 if (checkIntegral (e1, e2, ret, op)) {
5298 tret = ctype_unknown;
5303 case TLT: /* comparisons */
5304 case TGT: /* numeric, numeric -> bool */
5305 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5306 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5309 bool fepsilon = FALSE;
5311 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5316 if (opid == TLT || opid == TGT)
5318 uentry ue1 = exprNode_getUentry (e1);
5319 uentry ue2 = exprNode_getUentry (e2);
5322 ** FLT_EPSILON, etc. really is a variable, not
5326 if (uentry_isVariable (ue1))
5328 cstring uname = uentry_rawName (ue1);
5330 if (cstring_equalLit (uname, "FLT_EPSILON")
5331 || cstring_equalLit (uname, "DBL_EPSILON")
5332 || cstring_equalLit (uname, "LDBL_EPSILON"))
5338 if (uentry_isVariable (ue2))
5340 cstring uname = uentry_rawName (ue2);
5342 if (cstring_equalLit (uname, "FLT_EPSILON")
5343 || cstring_equalLit (uname, "DBL_EPSILON")
5344 || cstring_equalLit (uname, "LDBL_EPSILON"))
5353 ; /* Don't complain. */
5359 message ("Dangerous comparison involving %s types: %s",
5360 ctype_unparse (rtype),
5361 exprNode_unparse (ret)),
5370 ** Types should match.
5373 if (!exprNode_matchTypes (e1, e2))
5375 hasError = gentypeerror
5377 message ("Operands of %s have incompatible types (%t, %t): %s",
5378 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5384 || (ctype_isForceRealNumeric (&tr1)
5385 && ctype_isForceRealNumeric (&tr2)) ||
5386 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5392 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5393 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5397 message ("Comparison of pointer and numeric (%t, %t): %s",
5398 te1, te2, exprNode_unparse (ret)),
5403 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5408 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5410 if ((opid == EQ_OP || opid == NE_OP) &&
5411 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5414 ** is one a variable?
5417 if (uentry_isVariable (exprNode_getUentry (e1))
5418 || uentry_isVariable (exprNode_getUentry (e2)))
5421 ** comparisons with FALSE are okay
5424 if (exprNode_isFalseConstant (e1)
5425 || exprNode_isFalseConstant (e2))
5434 ("Use of %q with %s variables (risks inconsistency because "
5435 "of multiple true values): %s",
5436 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5437 context_printBoolName (), exprNode_unparse (ret)),
5444 case AND_OP: /* bool, bool -> bool */
5447 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5453 if (context_maybeSet (FLG_BOOLOPS))
5455 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5457 if (ctype_sameName (te1, te2))
5461 message ("Operands of %s are non-boolean (%t): %s",
5462 lltok_unparse (op), te1,
5463 exprNode_unparse (ret)),
5471 ("Operands of %s are non-booleans (%t, %t): %s",
5472 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5476 else if (!ctype_isRealBool (te1))
5480 message ("Left operand of %s is non-boolean (%t): %s",
5481 lltok_unparse (op), te1, exprNode_unparse (ret)),
5484 else if (!ctype_isRealBool (te2))
5488 message ("Right operand of %s is non-boolean (%t): %s",
5489 lltok_unparse (op), te2, exprNode_unparse (ret)),
5502 (cstring_makeLiteral
5503 ("There has been a problem in the parser. This is believed to result "
5504 "from a problem with bison v. 1.25. Please try rebuidling LCLint "
5505 "using the pre-compiled grammar files by commenting out the "
5506 "BISON= line in the top-level Makefile."));
5511 DPRINTF (("Return type: %s", ctype_unparse (tret)));
5514 exprNode_checkUse (ret, e1->sref, e1->loc);
5515 exprNode_mergeUSs (ret, e2);
5516 exprNode_checkUse (ret, e2->sref, e2->loc);
5522 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5523 /*@only@*/ lltok op)
5527 checkMacroParen (e1);
5528 checkMacroParen (e2);
5530 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5532 checkExpressionDefined (e1, e2, op);
5535 ret = exprNode_makeOp (e1, e2, op);
5540 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5543 ** This is somewhat bogus!
5545 ** Assigning to a nested observer in a non-observer datatype
5546 ** should not produce an error.
5549 sRef ref = exprNode_getSref (e1);
5551 DPRINTF (("Check assign mod: %s",
5552 sRef_unparseFull (ref)));
5554 if (sRef_isObserver (ref)
5555 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
5556 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5558 sRef base = sRef_getBase (ref);
5560 if (sRef_isValid (base) && sRef_isObserver (base))
5562 exprNode_checkModify (e1, ret);
5566 exprNode_checkModifyVal (e1, ret);
5571 exprNode_checkModify (e1, ret);
5576 exprNode_assign (/*@only@*/ exprNode e1,
5577 /*@only@*/ exprNode e2, /*@only@*/ lltok op)
5579 bool isalloc = FALSE;
5580 bool isjustalloc = FALSE;
5583 DPRINTF (("%s [%s] <- %s [%s]",
5584 exprNode_unparse (e1),
5585 ctype_unparse (e1->typ),
5586 exprNode_unparse (e2),
5587 ctype_unparse (e2->typ)));
5589 if (lltok_getTok (op) != TASSIGN)
5591 ret = exprNode_makeOp (e1, e2, op);
5595 ret = exprNode_createPartialCopy (e1);
5596 ret->kind = XPR_ASSIGN;
5597 ret->edata = exprData_makeOp (e1, e2, op);
5599 if (!exprNode_isError (e2))
5601 ret->sets = sRefSet_union (ret->sets, e2->sets);
5602 ret->msets = sRefSet_union (ret->msets, e2->msets);
5603 ret->uses = sRefSet_union (ret->uses, e2->uses);
5607 checkExpressionDefined (e1, e2, op);
5609 if (exprNode_isError (e1))
5611 if (!exprNode_isError (e2))
5613 ret->loc = fileloc_update (ret->loc, e2->loc);
5617 ret->loc = fileloc_update (ret->loc, g_currentloc);
5621 if (!exprNode_isError (e2))
5623 checkMacroParen (e2);
5626 if (exprNode_isDefined (e1))
5628 if (sRef_isMacroParamRef (e1->sref))
5630 if (context_inIterDef ())
5632 uentry ue = sRef_getUentry (e1->sref);
5634 if (uentry_isYield (ue))
5640 if (fileloc_isDefined (e1->loc))
5644 message ("Assignment to non-yield iter parameter: %q",
5645 sRef_unparse (e1->sref)),
5652 message ("Assignment to non-yield iter parameter: %q",
5653 sRef_unparse (e1->sref)),
5660 if (fileloc_isDefined (e1->loc))
5664 message ("Assignment to macro parameter: %q",
5665 sRef_unparse (e1->sref)),
5672 message ("Assignment to macro parameter: %q",
5673 sRef_unparse (e1->sref)),
5680 exprNode_checkAssignMod (e1, ret);
5683 if (exprNode_isDefined (e2))
5685 if (lltok_getTok (op) == TASSIGN)
5687 ctype te1 = exprNode_getType (e1);
5688 ctype te2 = exprNode_getType (e2);
5690 if (!ctype_forceMatch (te1, te2))
5692 if (exprNode_matchLiteral (te1, e2))
5700 message ("Assignment of %t to %t: %s %s %s",
5701 te2, te1, exprNode_unparse (e1),
5703 exprNode_unparse (e2)),
5709 exprNode_mergeUSs (ret, e2);
5710 exprNode_checkUse (ret, e2->sref, e2->loc);
5712 doAssign (e1, e2, FALSE);
5713 ret->sref = e1->sref;
5717 if (exprNode_isDefined (e2))
5719 exprNode_mergeUSs (ret, e2);
5720 exprNode_checkUse (ret, e2->sref, e2->loc);
5724 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
5726 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
5729 isjustalloc = sRef_isJustAllocated (e1->sref);
5730 isalloc = sRef_isAllocated (e1->sref);
5732 if (sRef_isField (e1->sref))
5734 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
5736 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
5738 exprNode_checkUse (ret, root, e1->loc);
5744 ** be careful! this defines e1->sref.
5747 if (!sRef_isMacroParamRef (e1->sref))
5749 exprNode_checkSet (ret, e1->sref);
5754 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
5755 ? e2->loc : e1->loc);
5761 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
5770 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
5771 /*@keep@*/ exprNode elseclause)
5775 if (!exprNode_isError (pred))
5777 ret = exprNode_createPartialCopy (pred);
5778 checkMacroParen (pred);
5779 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
5781 if (!exprNode_isError (ifclause))
5783 checkMacroParen (ifclause); /* update macro counts! */
5785 if (!exprNode_isError (elseclause))
5787 checkMacroParen (elseclause);
5789 if (!exprNode_matchTypes (ifclause, elseclause))
5792 (exprNode_getType (ifclause),
5794 exprNode_getType (elseclause),
5796 message ("Conditional clauses are not of same type: "
5798 exprNode_unparse (ifclause),
5799 exprNode_getType (ifclause),
5800 exprNode_unparse (elseclause),
5801 exprNode_getType (elseclause)),
5804 ret->sref = sRef_undefined;
5805 ret->typ = ctype_unknown;
5810 /* for now...should merge the states */
5811 ret->sref = ifclause->sref;
5812 ret->typ = ifclause->typ;
5814 if (exprNode_isNullValue (ifclause))
5816 ret->typ = elseclause->typ;
5820 exprNode_checkUse (ret, pred->sref, pred->loc);
5821 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
5822 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5824 exprNode_mergeCondUSs (ret, ifclause, elseclause);
5829 ret->typ = ifclause->typ;
5831 exprNode_checkUse (pred, pred->sref, pred->loc);
5832 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
5834 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
5839 if (!exprNode_isError (elseclause))
5841 ret->typ = elseclause->typ;
5843 exprNode_checkUse (pred, pred->sref, pred->loc);
5844 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5846 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
5850 else /* pred is error */
5852 if (!exprNode_isError (ifclause))
5854 ret = exprNode_createSemiCopy (ifclause);
5856 checkMacroParen (ifclause); /* update macro counts! */
5858 if (!exprNode_isError (elseclause))
5860 checkMacroParen (elseclause);
5862 ret->typ = ifclause->typ;
5864 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
5867 (exprNode_getType (ifclause),
5869 exprNode_getType (elseclause),
5871 message ("Conditional clauses are not of same type: "
5873 exprNode_unparse (ifclause),
5874 exprNode_getType (ifclause),
5875 exprNode_unparse (elseclause),
5876 exprNode_getType (elseclause)),
5879 ret->typ = ctype_unknown;
5883 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
5884 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5886 exprNode_mergeCondUSs (ret, ifclause, elseclause);
5889 else if (!exprNode_isError (elseclause)) /* pred, if errors */
5891 ret = exprNode_createSemiCopy (ifclause);
5893 ret->typ = elseclause->typ;
5894 checkMacroParen (elseclause);
5896 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
5897 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
5899 else /* all errors! */
5901 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
5905 ret->kind = XPR_COND;
5906 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
5908 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
5910 exprNode_combineControl (ret, ifclause, elseclause);
5917 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
5919 ctype totype = qtype_getType (qt);
5921 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
5925 ** check use of va_arg : <valist>, type -> type
5928 if (exprNode_isError (arg))
5933 targ = exprNode_getType (arg);
5936 ** arg should have be a pointer
5939 if (!ctype_isUA (targ) ||
5940 (!usymId_equal (ctype_typeId (targ),
5941 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
5945 message ("First argument to va_arg is not a va_list (type %t): %s",
5946 targ, exprNode_unparse (arg)),
5950 exprNode_checkSet (ret, arg->sref);
5954 ** return type is totype
5958 ret->kind = XPR_VAARG;
5959 ret->edata = exprData_makeCast (tok, arg, qt);
5964 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
5966 exprNode ret = exprNode_createPlain (ctype_undefined);
5967 ret->kind = XPR_LABEL;
5968 ret->edata = exprData_makeLiteral (label);
5969 ret->isJumpPoint = TRUE;
5971 return (ret); /* for now, ignore label */
5974 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
5976 if (exprNode_isDefined (stmt))
5978 stmt->isJumpPoint = TRUE;
5980 /* This prevent stray no return path errors, etc. */
5981 stmt->exitCode = XK_MUSTEXIT;
5987 bool exprNode_isDefaultMarker (exprNode e)
5989 if (exprNode_isDefined (e))
5991 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
5997 bool exprNode_isCaseMarker (exprNode e)
5999 if (exprNode_isDefined (e))
6001 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6007 bool exprNode_isLabelMarker (exprNode e)
6009 if (exprNode_isDefined (e))
6011 return (e->kind == XPR_LABEL);
6017 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6019 exprNode ret = exprNode_createPartialCopy (test);
6021 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6023 if (exprNode_isError (test)) {
6027 exprNode_checkUse (ret, test->sref, test->loc);
6029 usymtab_setExitCode (ret->exitCode);
6033 usymtab_setMustBreak ();
6036 ret->edata = exprData_makeSingle (test);
6037 ret->isJumpPoint = TRUE;
6043 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6045 exprNode ret = exprNode_createPartialCopy (test);
6047 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6048 ret->edata = exprData_makePair (test, stmt);
6049 ret->isJumpPoint = TRUE;
6051 if (exprNode_isError (test))
6056 exprNode_checkUse (ret, test->sref, test->loc);
6058 if (exprNode_isError (stmt))
6063 exprNode_mergeUSs (ret, stmt);
6065 ret->exitCode = stmt->exitCode;
6066 ret->mustBreak = stmt->mustBreak;
6067 ret->canBreak = stmt->canBreak;
6069 usymtab_setExitCode (ret->exitCode);
6073 usymtab_setMustBreak ();
6080 /*@notnull@*/ /*@only@*/ exprNode
6081 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6083 exprNode ret = exprNode_createTok (def);
6085 ret->isJumpPoint = TRUE;
6086 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6091 exprNode_mayEscape (exprNode e)
6093 if (exprNode_isDefined (e))
6095 return exitkind_couldEscape (e->exitCode);
6101 exprNode_mustBreak (exprNode e)
6103 if (exprNode_isDefined (e))
6105 return e->mustBreak;
6111 exprNode_mustEscape (exprNode e)
6113 if (exprNode_isDefined (e))
6115 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6122 exprNode_errorEscape (exprNode e)
6124 if (exprNode_isDefined (e))
6126 return exitkind_isError (e->exitCode);
6132 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6134 exprNode ret = exprNode_createPartialCopy (e1);
6136 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6138 ret->edata = exprData_makePair (e1, e2);
6139 ret->kind = XPR_STMTLIST;
6141 if (exprNode_isDefined (e1))
6143 ret->isJumpPoint = e1->isJumpPoint;
6144 ret->canBreak = e1->canBreak;
6148 if (exprNode_isDefined (e2))
6150 ret->loc = fileloc_update (ret->loc, e2->loc);
6154 if (exprNode_isDefined (e2))
6156 ret->exitCode = e2->exitCode;
6157 ret->mustBreak = e2->mustBreak;
6158 if (e2->canBreak) ret->canBreak = TRUE;
6162 ** if e1 must return, then e2 is unreachable!
6165 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6167 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6168 && !(e2->isJumpPoint))
6170 if (context_getFlag (FLG_UNREACHABLE))
6174 if (e2->kind == XPR_STMT)
6176 nr = exprData_getUopNode (e2->edata);
6179 if ((nr->kind == XPR_TOK
6180 && lltok_isSemi (exprData_getTok (nr->edata))))
6182 /* okay to have unreachable ";" */
6183 ret->exitCode = XK_MUSTEXIT;
6184 ret->canBreak = TRUE;
6188 if (optgenerror (FLG_UNREACHABLE,
6189 message ("Unreachable code: %s",
6190 exprNode_unparseFirst (nr)),
6193 ret->isJumpPoint = TRUE;
6194 ret->mustBreak = FALSE;
6195 ret->exitCode = XK_ERROR;
6196 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6200 ret->exitCode = XK_MUSTEXIT;
6201 ret->canBreak = TRUE;
6209 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6212 ** We want a warning anytime we have:
6214 ** yyy; <<<- no break or return
6218 exprNode lastStmt = exprNode_lastStatement (e1);
6220 if (exprNode_isDefined (lastStmt)
6221 && !exprNode_mustEscape (lastStmt)
6222 && !exprNode_mustBreak (lastStmt)
6223 && !exprNode_isCaseMarker (lastStmt)
6224 && !exprNode_isDefaultMarker (lastStmt)
6225 && !exprNode_isLabelMarker (lastStmt))
6227 voptgenerror (FLG_CASEBREAK,
6229 ("Fall through case (no preceeding break)"),
6236 exprNode_mergeUSs (ret, e2);
6238 usymtab_setExitCode (ret->exitCode);
6242 usymtab_setMustBreak ();
6248 exprNode exprNode_createTok (/*@only@*/ lltok t)
6250 exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6251 ret = exprNode_create (ctype_unknown);
6252 ret->kind = XPR_TOK;
6253 ret->edata = exprData_makeTok (t);
6257 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6259 if (!exprNode_isError (e))
6261 exprNode_checkStatement(e);
6264 return (exprNode_statementError (e, t));
6267 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6269 exprNode ret = exprNode_createPartialCopy (e);
6271 if (!exprNode_isError (e))
6273 if (e->kind != XPR_ASSIGN)
6275 exprNode_checkUse (ret, e->sref, e->loc);
6278 ret->exitCode = e->exitCode;
6279 ret->canBreak = e->canBreak;
6280 ret->mustBreak = e->mustBreak;
6283 ret->edata = exprData_makeUop (e, t);
6284 ret->kind = XPR_STMT;
6289 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6291 if (!exprNode_isError (e))
6293 if (e->kind != XPR_ASSIGN)
6295 exprNode_checkUse (e, e->sref, e->loc);
6302 void exprNode_produceGuards (exprNode pred)
6304 if (!exprNode_isError (pred))
6306 if (ctype_isRealPointer (pred->typ))
6308 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6311 exprNode_checkUse (pred, pred->sref, pred->loc);
6312 exprNode_resetSref (pred);
6316 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6318 exprNode ret = exprNode_createPartialCopy (e);
6320 if (!exprNode_isError (e))
6322 ret->exitCode = e->exitCode;
6323 ret->canBreak = e->canBreak;
6324 ret->mustBreak = e->mustBreak;
6327 ret->edata = exprData_makeSingle (e);
6328 ret->kind = XPR_BLOCK;
6332 bool exprNode_isBlock (exprNode e)
6334 return (exprNode_isDefined (e)
6335 && ((e)->kind == XPR_BLOCK));
6338 bool exprNode_isAssign (exprNode e)
6340 if (exprNode_isDefined (e))
6342 return (e->kind == XPR_ASSIGN);
6348 bool exprNode_isEmptyStatement (exprNode e)
6350 return (exprNode_isDefined (e)
6351 && (e->kind == XPR_TOK)
6352 && (lltok_isSemi (exprData_getTok (e->edata))));
6355 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6358 bool emptyErr = FALSE;
6360 if (context_maybeSet (FLG_IFEMPTY))
6362 if (exprNode_isEmptyStatement (tclause))
6364 emptyErr = optgenerror (FLG_IFEMPTY,
6366 ("Body of if statement is empty"),
6367 exprNode_loc (tclause));
6371 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6373 if (exprNode_isDefined (tclause)
6374 && !exprNode_isBlock (tclause))
6376 voptgenerror (FLG_IFBLOCK,
6378 ("Body of if statement is not a block: %s",
6379 exprNode_unparse (tclause)),
6380 exprNode_loc (tclause));
6384 if (exprNode_isError (pred))
6386 if (exprNode_isError (tclause))
6388 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6392 ret = exprNode_createPartialCopy (tclause);
6397 if (exprNode_mustEscape (pred))
6401 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6402 exprNode_loc (pred));
6405 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6406 exprNode_checkUse (pred, pred->sref, pred->loc);
6408 if (!exprNode_isError (tclause))
6410 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
6413 ret = exprNode_createPartialCopy (pred);
6417 ret->edata = exprData_makePair (pred, tclause);
6419 ret->exitCode = XK_UNKNOWN;
6421 if (exprNode_isDefined (tclause))
6423 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
6424 ret->canBreak = tclause->canBreak;
6425 ret->sets = sRefSet_union (ret->sets, tclause->sets);
6426 ret->msets = sRefSet_union (ret->msets, tclause->msets);
6427 ret->uses = sRefSet_union (ret->uses, tclause->uses);
6430 ret->mustBreak = FALSE;
6435 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
6436 /*@only@*/ exprNode tclause,
6437 /*@only@*/ exprNode eclause)
6440 bool tEmptyErr = FALSE;
6441 bool eEmptyErr = FALSE;
6443 if (context_maybeSet (FLG_IFEMPTY))
6445 if (exprNode_isEmptyStatement (tclause))
6447 tEmptyErr = optgenerror
6450 ("Body of if clause of if statement is empty"),
6451 exprNode_loc (tclause));
6454 if (exprNode_isEmptyStatement (eclause))
6456 eEmptyErr = optgenerror
6459 ("Body of else clause of if statement is empty"),
6460 exprNode_loc (eclause));
6464 if (context_maybeSet (FLG_IFBLOCK))
6467 && exprNode_isDefined (tclause)
6468 && !exprNode_isBlock (tclause))
6470 voptgenerror (FLG_IFBLOCK,
6472 ("Body of if clause of if statement is not a block: %s",
6473 exprNode_unparse (tclause)),
6474 exprNode_loc (tclause));
6478 && exprNode_isDefined (eclause)
6479 && !exprNode_isBlock (eclause)
6480 && !(eclause->kind == XPR_IF)
6481 && !(eclause->kind == XPR_IFELSE))
6486 ("Body of else clause of if statement is not a block: %s",
6487 exprNode_unparse (eclause)),
6488 exprNode_loc (eclause));
6492 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
6494 if (exprNode_isDefined (eclause)
6495 && (eclause->kind == XPR_IF))
6497 voptgenerror (FLG_ELSEIFCOMPLETE,
6498 message ("Incomplete else if logic (no final else): %s",
6499 exprNode_unparse (eclause)),
6500 exprNode_loc (eclause));
6504 if (exprNode_isError (pred))
6506 if (exprNode_isError (tclause))
6508 if (exprNode_isError (eclause))
6510 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6514 ret = exprNode_createPartialCopy (eclause);
6519 ret = exprNode_createPartialCopy (tclause);
6522 else /* pred is okay */
6524 ret = exprNode_createPartialCopy (pred);
6526 if (exprNode_mustEscape (pred))
6530 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6531 exprNode_loc (pred));
6534 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6535 exprNode_checkUse (ret, pred->sref, pred->loc);
6537 exprNode_mergeCondUSs (ret, tclause, eclause);
6540 ret->kind = XPR_IFELSE;
6541 ret->edata = exprData_makeCond (pred, tclause, eclause);
6543 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
6545 exprNode_combineControl (ret, tclause, eclause);
6546 ret->loc = fileloc_update (ret->loc, eclause->loc);
6553 ** *allpaths <- TRUE iff all executions paths must go through the switch
6557 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
6559 exprNodeSList el = exprNode_flatten (e);
6560 bool mustReturn = TRUE; /* find a branch that doesn't */
6561 bool thisReturn = FALSE;
6562 bool hasDefault = FALSE;
6563 bool hasAllMembers = FALSE;
6564 bool inSwitch = FALSE;
6565 bool isEnumSwitch = FALSE;
6566 bool canBreak = FALSE;
6567 bool fallThrough = FALSE;
6568 ctype ct = ctype_unknown;
6569 enumNameSList usedEnums;
6572 if (exprNode_isDefined (test))
6577 ttype = ctype_realType (ct);
6579 if (ctype_isEnum (ttype))
6581 isEnumSwitch = TRUE;
6582 enums = ctype_elist (ttype);
6583 usedEnums = enumNameSList_new ();
6587 exprNodeSList_elements (el, current)
6589 if (exprNode_isDefined (current))
6591 switch (current->kind)
6599 message ("Duplicate default cases in switch"),
6600 exprNode_loc (current));
6605 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
6613 exprNode st = exprData_getSingle (current->edata);
6614 uentry ue = exprNode_getUentry (st);
6616 if (uentry_isValid (ue))
6618 cstring cname = uentry_rawName (ue);
6620 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
6622 if (enumNameSList_member
6623 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
6627 message ("Duplicate case in switch: %s",
6633 enumNameSList_addh (usedEnums, cname);
6640 message ("Case in switch not %s member: %s",
6641 ctype_unparse (ct), cname),
6648 if (inSwitch && !fallThrough)
6650 if (!thisReturn || canBreak)
6660 /*@switchbreak@*/ break;
6662 thisReturn = thisReturn || exprNode_mustEscape (current);
6663 canBreak = canBreak || current->canBreak;
6664 if (canBreak) fallThrough = FALSE;
6667 } end_exprNodeSList_elements;
6669 if (inSwitch) /* check the last one! */
6671 if (!thisReturn || canBreak)
6680 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
6681 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
6683 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
6685 voptgenerror (FLG_MISSCASE,
6686 message ("Missing case%s in switch: %q",
6687 cstring_makeLiteralTemp
6688 ((enumNameSList_size (unused) > 1) ? "s" : ""),
6689 enumNameSList_unparse (unused)),
6692 enumNameSList_free (unused);
6696 hasAllMembers = TRUE;
6700 enumNameSList_free (usedEnums);
6704 *allpaths = hasDefault;
6707 exprNodeSList_free (el);
6708 return ((hasDefault || hasAllMembers) && mustReturn);
6711 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
6713 exprNode ret = exprNode_createPartialCopy (e);
6716 DPRINTF (("Switch: %s", exprNode_unparse (s)));
6718 ret->kind = XPR_SWITCH;
6719 ret->edata = exprData_makePair (e, s);
6721 if (!exprNode_isError (s))
6723 exprNode fs = exprNode_firstStatement (s);
6724 ret->loc = fileloc_update (ret->loc, s->loc);
6726 if (exprNode_isUndefined (fs)
6727 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
6728 || exprNode_isDefaultMarker (fs)) {
6731 voptgenerror (FLG_FIRSTCASE,
6733 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
6738 if (!exprNode_isError (e))
6740 if (checkSwitchExpr (e, s, &allpaths))
6742 ret->exitCode = XK_MUSTRETURN;
6746 ret->exitCode = e->exitCode;
6749 ret->canBreak = e->canBreak;
6750 ret->mustBreak = e->mustBreak;
6754 ** exprNode.c:3883,32: Variable allpaths used before definition
6761 DPRINTF (("Context exit switch!"));
6762 context_exitSwitch (ret, allpaths);
6763 DPRINTF (("Context exit switch done!"));
6768 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
6769 /*@notnull@*/ exprNode body)
6771 sRefSet tuses = test->uses;
6773 if (!sRefSet_isEmpty (test->uses))
6775 sRefSet sets = sRefSet_newCopy (body->sets);
6776 bool hasError = TRUE;
6777 bool innerState = FALSE;
6778 sRefSet tuncon = sRefSet_undefined;
6780 sets = sRefSet_union (sets, test->sets);
6781 sets = sRefSet_union (sets, body->msets);
6782 sets = sRefSet_union (sets, test->msets);
6784 sRefSet_allElements (tuses, el)
6786 if (sRef_isUnconstrained (el))
6788 tuncon = sRefSet_insert (tuncon, el);
6792 if (sRefSet_member (sets, el))
6799 if (sRef_isInternalState (el)
6800 || sRef_isFileStatic (sRef_getRootBase (el)))
6804 } end_sRefSet_allElements ;
6808 sRefSet suncon = sRefSet_undefined;
6809 bool sinner = FALSE;
6811 sRefSet_allElements (sets, el)
6813 if (sRef_isUnconstrained (el))
6815 suncon = sRefSet_insert (suncon, el);
6817 else if (sRef_isInternalState (el))
6825 } end_sRefSet_allElements ;
6827 if (sinner && innerState)
6831 else if (sRefSet_isEmpty (tuncon)
6832 && sRefSet_isEmpty (suncon))
6837 ("Suspected infinite loop. No value used in loop test (%q) "
6838 "is modified by test or loop body.",
6839 sRefSet_unparsePlain (tuses)),
6844 if (sRefSet_isEmpty (tuncon))
6848 message ("Suspected infinite loop. No condition values "
6849 "modified. Modification possible through "
6850 "unconstrained calls: %q",
6851 sRefSet_unparsePlain (suncon)),
6858 message ("Suspected infinite loop. No condition values "
6859 "modified. Possible undetected dependency through "
6860 "unconstrained calls in loop test: %q",
6861 sRefSet_unparsePlain (tuncon)),
6867 sRefSet_free (sets);
6871 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
6874 bool emptyErr = FALSE;
6876 if (context_maybeSet (FLG_WHILEEMPTY))
6878 if (exprNode_isEmptyStatement (b))
6880 emptyErr = optgenerror
6883 ("Body of while statement is empty"),
6888 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
6890 if (exprNode_isDefined (b)
6891 && !exprNode_isBlock (b))
6893 if (context_inIterDef ()
6894 && (b->kind == XPR_STMTLIST
6895 || b->kind == XPR_TOK))
6901 voptgenerror (FLG_WHILEBLOCK,
6903 ("Body of while statement is not a block: %s",
6904 exprNode_unparse (b)),
6910 if (exprNode_isError (t))
6912 if (exprNode_isError (b))
6914 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
6918 ret = exprNode_createPartialCopy (b);
6925 ret = exprNode_createPartialCopy (t);
6927 llassert (t->kind == XPR_WHILEPRED);
6929 test = exprData_getSingle (t->edata);
6931 if (!exprNode_isError (b) && exprNode_isDefined (test))
6933 if (context_maybeSet (FLG_INFLOOPS)
6934 || context_maybeSet (FLG_INFLOOPSUNCON))
6937 ** check that some variable in the predicate is set by the body
6938 ** if the predicate uses any variables
6941 checkInfiniteLoop (test, b);
6944 exprNode_mergeUSs (ret, b);
6946 if (exprNode_isDefined (b))
6948 ret->exitCode = exitkind_makeConditional (b->exitCode);
6953 ret->edata = exprData_makePair (t, b);
6954 ret->kind = XPR_WHILE;
6956 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
6960 message ("Predicate always exits: %s", exprNode_unparse (t)),
6964 ret->exitCode = XK_NEVERESCAPE;
6967 ** If loop is infinite, and there is no break inside,
6968 ** exit code is never reach.
6971 if (exprNode_knownIntValue (t))
6973 if (!exprNode_isZero (t))
6975 if (exprNode_isDefined (b))
6979 /* Really, it means never reached. */
6980 ret->exitCode = XK_MUSTEXIT;
6990 ret->canBreak = FALSE;
6991 ret->mustBreak = FALSE;
6997 ** do { b } while (t);
6999 ** note: body passed as first argument
7002 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7006 if (exprNode_isError (t))
7008 if (exprNode_isError (b))
7010 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
7014 ret = exprNode_createPartialCopy (b);
7016 ret->exitCode = exitkind_makeConditional (b->exitCode);
7017 exprNode_checkUse (ret, b->sref, b->loc);
7018 ret->exitCode = b->exitCode;
7019 ret->canBreak = b->canBreak;
7020 ret->mustBreak = b->mustBreak;
7025 ret = exprNode_createPartialCopy (t);
7026 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7028 if (!exprNode_isError (b))
7031 ** forgot the copy's --- why wasn't this detected??
7034 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7035 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7036 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
7038 /* left this out --- causes and aliasing bug (infinite loop)
7039 should be detected?? */
7041 exprNode_checkUse (ret, b->sref, b->loc);
7042 exprNode_mergeUSs (ret, t);
7043 exprNode_checkUse (ret, t->sref, t->loc);
7045 ret->exitCode = b->exitCode;
7046 ret->canBreak = b->canBreak;
7047 ret->mustBreak = b->mustBreak;
7051 context_exitDoWhileClause (t);
7053 ret->kind = XPR_DOWHILE;
7054 ret->edata = exprData_makePair (t, b);
7058 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7061 bool emptyErr = FALSE;
7063 if (context_maybeSet (FLG_FOREMPTY))
7065 if (exprNode_isEmptyStatement (body))
7067 emptyErr = optgenerror
7070 ("Body of for statement is empty"),
7071 exprNode_loc (body));
7075 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7077 if (exprNode_isDefined (body)
7078 && !exprNode_isBlock (body))
7080 if (context_inIterDef ()
7081 && (body->kind == XPR_STMTLIST
7082 || body->kind == XPR_TOK))
7088 voptgenerror (FLG_FORBLOCK,
7090 ("Body of for statement is not a block: %s",
7091 exprNode_unparse (body)),
7092 exprNode_loc (body));
7098 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7101 if (exprNode_isError (body))
7103 ret = exprNode_createPartialCopy (inc);
7107 ret = exprNode_createPartialCopy (body);
7109 ret->exitCode = exitkind_makeConditional (body->exitCode);
7111 exprNode_mergeUSs (inc, body);
7113 if (exprNode_isDefined (inc))
7117 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7120 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7121 exprNode_freeShallow (tmp);
7123 context_clearMessageAnnote ();
7124 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7126 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7127 exprNode_freeShallow (tmp);
7129 context_clearMessageAnnote ();
7131 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7132 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7133 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7137 ret->kind = XPR_FOR;
7138 ret->edata = exprData_makePair (inc, body);
7140 if (exprNode_isDefined (inc)) {
7141 exprNode test = exprData_getTripleTest (inc->edata);
7143 if (exprNode_isUndefined (test)) {
7144 if (exprNode_isDefined (body)) {
7145 if (!body->canBreak) {
7146 /* Really, it means never reached. */
7147 ret->exitCode = XK_MUSTEXIT;
7157 ** for (init; test; inc)
7160 ** while (test) { body; inc; }
7162 ** Now: check use of init (may set vars for test)
7163 ** check use of test
7167 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7171 if (exprNode_isError (pred)) return guardSet_undefined;
7173 llassert (pred->kind == XPR_FORPRED);
7175 test = exprData_getTripleTest (pred->edata);
7177 if (!exprNode_isError (test))
7179 return (test->guards);
7182 return guardSet_undefined;
7185 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7187 exprNode ret = exprNode_createSemiCopy (test);
7189 if (exprNode_isDefined (test))
7191 exprNode_copySets (ret, test);
7192 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7193 exprNode_checkUse (ret, test->sref, test->loc);
7195 exprNode_produceGuards (test);
7197 ret->guards = guardSet_copy (test->guards);
7200 ret->edata = exprData_makeSingle (test);
7201 ret->kind = XPR_WHILEPRED;
7205 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7206 /*@only@*/ exprNode inc)
7211 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7214 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7216 if (!exprNode_isError (inc))
7218 ret = exprNode_createPartialCopy (inc);
7222 if (!exprNode_isError (init))
7224 ret = exprNode_createPartialCopy (init);
7226 else if (!exprNode_isError (test))
7228 ret = exprNode_createPartialCopy (test);
7232 ret = exprNode_createUnknown ();
7236 exprNode_mergeUSs (ret, init);
7238 if (exprNode_isDefined (init))
7240 exprNode_checkUse (ret, init->sref, init->loc);
7243 exprNode_mergeUSs (ret, test);
7245 if (exprNode_isDefined (test))
7247 exprNode_checkUse (ret, test->sref, test->loc);
7250 ret->kind = XPR_FORPRED;
7251 ret->edata = exprData_makeFor (init, test, inc);
7255 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7257 exprNode ret = exprNode_createUnknown ();
7259 if (context_inMacro ())
7261 voptgenerror (FLG_MACROSTMT,
7262 message ("Macro %s uses goto (not functional)",
7263 context_inFunctionName ()),
7267 ret->kind = XPR_GOTO;
7268 ret->edata = exprData_makeLiteral (label);
7269 ret->mustBreak = TRUE;
7270 ret->exitCode = XK_GOTO;
7271 ret->canBreak = TRUE;
7275 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7277 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7279 ret->kind = XPR_CONTINUE;
7280 ret->edata = exprData_makeTok (l);
7281 ret->canBreak = TRUE;
7282 ret->mustBreak = TRUE;
7284 if (qcontinue == QSAFEBREAK)
7288 else if (qcontinue == QINNERCONTINUE)
7290 if (!context_inDeepLoop ())
7293 (FLG_LOOPLOOPCONTINUE,
7294 cstring_makeLiteral ("Continue statement marked with innercontinue "
7295 "is not inside a nested loop"),
7296 exprNode_loc (ret));
7299 else if (qcontinue == BADTOK)
7301 if (context_inDeepLoop ())
7304 (FLG_LOOPLOOPCONTINUE,
7305 cstring_makeLiteral ("Continue statement in nested loop"),
7306 exprNode_loc (ret));
7311 llbuglit ("exprNode_continue: bad qcontinue");
7317 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
7319 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7320 clause breakClause = context_breakClause ();
7322 ret->kind = XPR_BREAK;
7323 ret->edata = exprData_makeTok (l);
7324 ret->canBreak = TRUE;
7325 ret->mustBreak = TRUE;
7327 if (breakClause == NOCLAUSE)
7331 cstring_makeLiteral ("Break not inside while, for or switch statement"),
7332 exprNode_loc (ret));
7336 if (bqual != BADTOK)
7343 if (breakClause == SWITCHCLAUSE)
7345 if (!context_inDeepSwitch ())
7347 voptgenerror (FLG_SYNTAX,
7349 ("Break preceded by innerbreak is not in a deep switch"),
7350 exprNode_loc (ret));
7355 if (!context_inDeepLoop ())
7357 voptgenerror (FLG_SYNTAX,
7359 ("Break preceded by innerbreak is not in a deep loop"),
7360 exprNode_loc (ret));
7365 if (breakClause == SWITCHCLAUSE)
7367 voptgenerror (FLG_SYNTAX,
7369 ("Break preceded by loopbreak is breaking a switch"),
7370 exprNode_loc (ret));
7374 if (breakClause != SWITCHCLAUSE)
7378 message ("Break preceded by switchbreak is breaking %s",
7379 cstring_makeLiteralTemp
7380 ((breakClause == WHILECLAUSE
7381 || breakClause == DOWHILECLAUSE) ? "a while loop"
7382 : (breakClause == FORCLAUSE) ? "a for loop"
7383 : (breakClause == ITERCLAUSE) ? "an iterator"
7385 exprNode_loc (ret));
7393 if (breakClause == SWITCHCLAUSE)
7395 clause nextBreakClause = context_nextBreakClause ();
7397 switch (nextBreakClause)
7399 case NOCLAUSE: break;
7405 (FLG_LOOPSWITCHBREAK,
7406 cstring_makeLiteral ("Break statement in switch inside loop"),
7407 exprNode_loc (ret));
7411 (FLG_SWITCHSWITCHBREAK,
7412 cstring_makeLiteral ("Break statement in switch inside switch"),
7413 exprNode_loc (ret));
7420 if (context_inDeepLoop ())
7424 cstring_makeLiteral ("Break statement in nested loop"),
7425 exprNode_loc (ret));
7429 if (context_inDeepLoopSwitch ())
7432 (FLG_SWITCHLOOPBREAK,
7433 cstring_makeLiteral ("Break statement in loop inside switch"),
7434 exprNode_loc (ret));
7444 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
7446 fileloc loc = lltok_getLoc (t);
7447 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
7449 context_returnFunction ();
7450 exprChecks_checkNullReturn (loc);
7452 ret->kind = XPR_NULLRETURN;
7453 ret->edata = exprData_makeTok (t);
7454 ret->exitCode = XK_MUSTRETURN;
7458 exprNode exprNode_return (/*@only@*/ exprNode e)
7462 if (exprNode_isError (e))
7464 ret = exprNode_createUnknown ();
7468 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
7470 exprNode_checkUse (ret, e->sref, e->loc);
7471 exprNode_checkReturn (e);
7474 context_returnFunction ();
7475 ret->kind = XPR_RETURN;
7476 ret->edata = exprData_makeSingle (e);
7477 ret->exitCode = XK_MUSTRETURN;
7482 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
7486 if (exprNode_isError (e1))
7488 if (exprNode_isError (e2))
7490 ret = exprNode_createLoc (ctype_unknown, g_currentloc);
7494 ret = exprNode_createPartialCopy (e2);
7495 exprNode_checkUse (ret, e2->sref, e2->loc);
7496 ret->sref = e2->sref;
7501 ret = exprNode_createPartialCopy (e1);
7503 exprNode_checkUse (ret, e1->sref, e1->loc);
7505 if (!exprNode_isError (e2))
7507 exprNode_mergeUSs (ret, e2);
7508 exprNode_checkUse (ret, e2->sref, e2->loc);
7509 ret->sref = e2->sref;
7513 ret->kind = XPR_COMMA;
7514 ret->edata = exprData_makePair (e1, e2);
7516 if (exprNode_isDefined (e1))
7518 if (exprNode_isDefined (e2))
7522 if (exprNode_mustEscape (e1) || e1->mustBreak)
7526 message ("Second clause of comma expression is unreachable: %s",
7527 exprNode_unparse (e2)),
7531 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
7532 ret->mustBreak = e1->mustBreak || e2->mustBreak;
7533 ret->canBreak = e1->canBreak || e2->canBreak;
7537 if (exprNode_mustEscape (e1) || e1->mustBreak)
7541 message ("Second clause of comma expression is unreachable: %s",
7542 exprNode_unparse (e2)),
7546 ret->exitCode = e1->exitCode;
7547 ret->canBreak = e1->canBreak;
7552 if (exprNode_isDefined (e2))
7554 ret->exitCode = e2->exitCode;
7555 ret->mustBreak = e2->mustBreak;
7556 ret->canBreak = e2->canBreak;
7563 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
7565 ctype t1 = exprNode_getType (el);
7566 ctype t2 = exprNode_getType (val);
7567 bool hasError = FALSE;
7569 if (ctype_isUnknown (t1))
7571 voptgenerror (FLG_IMPTYPE,
7572 message ("Variable has unknown (implicitly int) type: %s",
7573 exprNode_unparse (el)),
7577 el->typ = ctype_int;
7580 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
7582 exprNodeList vals = exprData_getArgs (val->edata);
7584 if (ctype_isRealAP (t1))
7589 /*@i423 check number of entries int a[3] = { 1, 2, 3, 4 } ; */
7591 exprNodeList_elements (vals, oneval)
7593 cstring istring = message ("%d", i);
7596 (exprNode_fakeCopy (el),
7597 exprNode_numLiteral (ctype_int, istring,
7598 fileloc_copy (el->loc), i));
7600 if (exprNode_isDefined (newel))
7602 if (exprNodeList_size (vals) == 1
7603 && ctype_isString (exprNode_getType (oneval))
7604 && ctype_isChar (exprNode_getType (newel)))
7606 exprNode_freeIniter (newel);
7610 if (exprNode_checkOneInit (newel, oneval))
7615 if (nerrors > 3 && exprNodeList_size (vals) > 6)
7618 (message ("Additional initialization errors "
7619 "for %s not reported",
7620 exprNode_unparse (el)),
7622 exprNode_freeIniter (newel);
7627 exprNode_freeIniter (newel);
7632 exprNode_freeIniter (newel);
7637 cstring_free (istring);
7640 } end_exprNodeList_elements;
7643 else if (ctype_isStruct (ctype_realType (t1)))
7645 uentryList fields = ctype_getFields (t1);
7648 if (uentryList_size (fields) != exprNodeList_size (vals))
7650 if (uentryList_size (fields) > exprNodeList_size (vals))
7652 hasError = optgenerror
7654 message ("Initializer block for "
7655 "%s has %d field%&, but %s has %d field%&: %q",
7656 exprNode_unparse (el),
7657 exprNodeList_size (vals),
7659 uentryList_size (fields),
7660 exprNodeList_unparse (vals)),
7665 hasError = optgenerror
7667 message ("Initializer block for "
7668 "%s has %d field%&, but %s has %d field%&: %q",
7669 exprNode_unparse (el),
7670 exprNodeList_size (vals),
7672 uentryList_size (fields),
7673 exprNodeList_unparse (vals)),
7679 exprNodeList_elements (vals, oneval)
7681 uentry thisfield = uentryList_getN (fields, i);
7683 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
7685 uentry_getName (thisfield));
7687 if (exprNode_isDefined (newel))
7689 if (exprNode_checkOneInit (newel, oneval))
7694 exprNode_freeIniter (newel);
7698 } end_exprNodeList_elements;
7703 hasError = optgenerror
7705 message ("Initializer block used for "
7706 "%s where %t is expected: %s",
7707 exprNode_unparse (el), t1, exprNode_unparse (val)),
7713 if (exprNode_isDefined (val))
7715 doAssign (el, val, TRUE);
7717 if (!exprNode_matchType (t1, val))
7719 hasError = gentypeerror
7721 message ("Initial value of %s is type %t, "
7723 exprNode_unparse (el),
7724 t2, t1, exprNode_unparse (val)),
7734 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
7738 if (usymtab_exists (idDecl_observeId (t)))
7740 uentry ue = usymtab_lookup (idDecl_observeId (t));
7741 ret = exprNode_createId (ue);
7743 /*@i723 don't do this...but why? */
7745 ct = ctype_realishType (ret->typ);
7747 DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
7749 if (ctype_isUnknown (ct))
7751 if (uentry_isAnyTag (ue))
7755 message ("%s used but not previously declared: %s",
7756 uentry_ekindName (ue),
7757 idDecl_getName (t)),
7765 message ("Variable has unknown (implicitly int) type: %s",
7766 idDecl_getName (t)),
7776 uentry ue = uentry_makeUnrecognized (idDecl_observeId (t),
7778 ret = exprNode_fromIdentifierAux (ue);
7781 ** No error - this happens in old style declarations:
7785 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
7792 exprData_free (ret->edata, ret->kind);
7793 ret->edata = exprData_undefined;
7794 ret->exitCode = XK_NEVERESCAPE;
7795 ret->mustBreak = FALSE;
7796 ret->kind = XPR_INIT;
7800 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
7802 exprNode ret = exprNode_makeInitializationAux (t);
7803 llassert (ret->edata == exprData_undefined);
7804 ret->edata = exprData_makeInit (t, exprNode_undefined);
7808 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
7809 /*@only@*/ exprNode e)
7811 uentry ue = usymtab_lookup (idDecl_observeId (t));
7812 exprNode ret = exprNode_makeInitializationAux (t);
7813 fileloc loc = exprNode_loc (e);
7815 if (exprNode_isError (e))
7817 e = exprNode_createUnknown ();
7820 /* error: assume initializer is defined */
7821 sRef_setDefined (ret->sref, g_currentloc);
7825 ctype ct = ctype_realishType (ret->typ);
7830 ** was addSafeUse --- what's the problem?
7832 ** int x = 3, y = x ?
7835 exprData_free (ret->edata, ret->kind);
7836 ret->edata = exprData_makeInit (t, e);
7838 exprNode_checkUse (ret, e->sref, e->loc);
7840 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
7842 exprNode lhs = exprNode_createId (ue);
7845 ** static storage should be undefined before initializing
7848 if (uentry_isStatic (ue))
7850 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
7853 (void) exprNode_checkOneInit (lhs, e);
7855 if (uentry_isStatic (ue))
7857 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
7860 exprNode_free (lhs);
7864 if (!exprNode_matchType (ct, e))
7866 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
7873 (exprNode_getType (e), e, exprNode_getType (ret), ret,
7875 ("Variable %q initialized to type %t, expects %t: %s",
7876 uentry_getName (ue), exprNode_getType (e),
7877 exprNode_getType (ret),
7878 exprNode_unparse (e)),
7884 if (uentry_isStatic (ue))
7886 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
7889 doAssign (ret, e, TRUE);
7891 if (uentry_isStatic (ue))
7893 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
7897 if (context_inIterDef ())
7899 /* should check if it is yield */
7900 uentry_setUsed (ue, loc);
7907 exprNode_mergeUSs (ret, e);
7911 exprNode exprNode_iter (/*@observer@*/ uentry name,
7912 /*@only@*/ exprNodeList alist,
7913 /*@only@*/ exprNode body,
7914 /*@observer@*/ uentry end)
7919 llassert (uentry_isValid (name));
7921 uentry_setUsed (name, exprNode_loc (body));
7923 ret = exprNode_createPartialCopy (body);
7924 iname = uentry_getName (name);
7926 if (uentry_isInvalid (end))
7929 message ("Iter %s not balanced with end_%s", iname, iname));
7933 cstring ename = uentry_getName (end);
7935 if (!cstring_equalPrefix (ename, "end_"))
7937 llerror (FLG_ITER, message ("Iter %s not balanced with end_%s: %s",
7938 iname, iname, ename));
7942 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
7945 message ("Iter %s not balanced with end_%s: %s",
7946 iname, iname, ename));
7950 cstring_free (ename);
7953 context_exitIterClause (body);
7955 ret->kind = XPR_ITER;
7956 ret->edata = exprData_makeIter (name, alist, body, end);
7958 if (uentry_isIter (name))
7960 (void) checkArgsReal (name, body,
7961 uentry_getParams (name), alist, TRUE, ret);
7964 cstring_free (iname);
7970 exprNode_iterNewId (/*@only@*/ cstring s)
7972 exprNode e = exprNode_new ();
7973 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
7975 llassert (processingIterVars ());
7977 e->loc = context_getSaveLocation ();
7979 if (fileloc_isUndefined (e->loc))
7981 fileloc_free (e->loc);
7982 e->loc = fileloc_copy (g_currentloc);
7985 e->uses = sRefSet_new ();
7986 e->sets = sRefSet_new ();
7987 e->msets = sRefSet_new ();
7989 e->val = multiVal_unknown ();
7990 e->guards = guardSet_new ();
7992 e->isJumpPoint = FALSE;
7993 e->exitCode = XK_NEVERESCAPE;
7995 /*> missing fields, detected by lclint <*/
7996 e->canBreak = FALSE;
7997 e->mustBreak = FALSE;
7998 e->etext = cstring_undefined;
8000 if (uentry_isYield (ue))
8002 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8003 fileloc_copy (e->loc),
8007 uue = usymtab_supEntrySrefReturn (uue);
8009 sr = uentry_getSref (uue);
8010 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8011 sr = uentry_getSref (uue);
8012 sRef_setDefined (sr, e->loc);
8014 e->typ = uentry_getType (uue);
8016 e->edata = exprData_makeId (uue);
8017 uentry_setUsed (uue, g_currentloc);
8023 sRef_setGlobalScope ();
8024 uue = uentry_makeVariableLoc (s, ctype_unknown);
8026 e->typ = ctype_unknown;
8027 e->edata = exprData_makeId (uue);
8029 uentry_setUsed (uue, e->loc);
8030 uentry_setHasNameError (uue);
8032 if (context_getFlag (FLG_REPEATUNRECOG))
8034 uentry_markOwned (uue);
8038 usymtab_supGlobalEntry (uue);
8041 sRef_clearGlobalScope ();
8043 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8050 exprNode_defineConstraints(e);
8055 exprNode_iterExpr (/*@returned@*/ exprNode e)
8057 if (!processingIterVars ())
8059 llcontbuglit ("checkIterParam: not in iter");
8063 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8066 if (exprNode_isDefined (e))
8068 if (fileloc_isDefined (e->loc))
8072 message ("Yield parameter is not simple identifier: %s",
8073 exprNode_unparse (e)),
8080 message ("Yield parameter is not simple identifier: %s",
8081 exprNode_unparse (e)),
8091 exprNode_iterId (/*@observer@*/ uentry c)
8095 llassert (processingIterVars ());
8097 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8100 if (uentry_isYield (ue))
8102 ctype ct = uentry_getType (ue);
8103 exprNode e = exprNode_createPlain (ct);
8104 cstring name = uentry_getName (c);
8105 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8107 uentry_setUsed (ue, g_currentloc);
8108 uentry_setHasNameError (ue);
8110 cstring_free (name);
8113 e->edata = exprData_makeId (le);
8114 e->loc = context_getSaveLocation ();
8115 e->sref = uentry_getSref (le);
8117 usymtab_supEntrySref (le);
8119 if (!context_inHeader ())
8123 message ("Yield parameter shadows local declaration: %q",
8124 uentry_getName (c)),
8125 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8127 uentry_showWhereDeclared (c);
8134 return (exprNode_fromIdentifierAux (c));
8137 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8139 exprNode ret = exprNode_create (ctype_unknown);
8141 ret->kind = XPR_ITERCALL;
8142 ret->edata = exprData_makeIterCall (name, alist);
8144 if (uentry_isIter (name))
8146 uentryList params = uentry_getParams (name);
8148 if (context_inIterDef ()
8149 && uentryList_size (params) == exprNodeList_size (alist))
8153 exprNodeList_elements (alist, arg)
8155 uentry parg = uentryList_getN (params, i);
8157 if (uentry_isYield (parg))
8159 uentry ue = exprNode_getUentry (arg);
8161 if (uentry_isValid (ue))
8168 } end_exprNodeList_elements;
8171 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8172 checkUnspecCall (ret, params, alist);
8178 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8180 if (exprNode_isDefined (e))
8183 if (e->sref == defref) /*@noaccess sRef@*/
8186 e->sref = sRef_makeUnknown ();
8187 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8198 return sRef_undefined;
8202 /*@observer@*/ cstring
8203 exprNode_unparseFirst (exprNode e)
8205 if (exprNode_isDefined (e))
8209 if (e->kind == XPR_STMTLIST
8210 || e->kind == XPR_COMMA || e->kind == XPR_COND)
8212 exprNode first = exprData_getPairA (e->edata);
8214 if (exprNode_isDefined (first))
8216 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8220 return (cstring_makeLiteralTemp ("..."));
8224 ret = cstring_elide (exprNode_unparse (e), 20);
8225 cstring_markOwned (ret);
8231 return cstring_makeLiteralTemp ("<error>");
8235 /*@observer@*/ cstring
8236 exprNode_unparse (/*@temp@*/ exprNode e)
8238 if (exprNode_isError (e))
8240 return cstring_makeLiteralTemp ("<error>");
8243 if (cstring_isDefined (e->etext))
8249 cstring ret = exprNode_doUnparse (e);
8251 /*@-modifies@*/ /* benevolent */
8258 /*@observer@*/ fileloc
8259 exprNode_loc (exprNode e)
8261 if (exprNode_isError (e))
8263 return (g_currentloc);
8272 ** executes exprNode e
8273 ** recursively rexecutes as though in original parse using
8274 ** information in e->edata
8277 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
8279 exprNodeList ret = exprNodeList_new ();
8281 exprNodeList_elements (e, current)
8283 exprNodeList_addh (ret, exprNode_effect (current));
8284 } end_exprNodeList_elements;
8289 static /*@only@*/ exprNode exprNode_effect (exprNode e)
8290 /*@globals internalState@*/
8292 bool innerEffect = inEffect;
8298 context_clearJustPopped ();
8300 if (exprNode_isError (e))
8302 ret = exprNode_undefined;
8307 ** Turn off expose and dependent transfer checking.
8308 ** Need to pass exposed internal nodes,
8309 ** [ copying would be a waste! ]
8310 ** [ Actually, I think I wasted a lot more time than its worth ]
8311 ** [ trying to do this. ]
8315 /*@-observertrans@*/
8316 /*@-dependenttrans@*/
8323 ret = exprNode_addParens (exprData_getUopTok (data),
8324 exprNode_effect (exprData_getUopNode (data)));
8327 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
8328 exprNode_effect (exprData_getOpB (data)),
8329 exprData_getOpTok (data));
8332 ret = exprNode_undefined;
8335 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
8336 exprNodeList_effect (exprData_getArgs (data)));
8349 cstring id = exprData_getId (data);
8350 uentry ue = usymtab_lookupSafe (id);
8352 ret = exprNode_fromIdentifierAux (ue);
8353 ret->loc = fileloc_update (ret->loc, e->loc);
8360 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
8361 exprNode_effect (exprData_getPairB (data)));
8364 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
8365 exprNode_effect (exprData_getOpB (data)),
8366 exprData_getOpTok (data));
8370 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
8371 exprData_getUopTok (data));
8374 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
8375 exprData_getUopTok (data));
8387 ret = exprNode_vaArg (exprData_getCastTok (data),
8388 exprNode_effect (exprData_getCastNode (data)),
8389 exprData_getCastType (data));
8393 ret = exprNode_cast (exprData_getCastTok (data),
8394 exprNode_effect (exprData_getCastNode (data)),
8395 exprData_getCastType (data));
8398 ret = exprNode_iterStart (exprData_getIterCallIter (data),
8400 (exprData_getIterCallArgs (data)));
8404 ret = exprNode_iter (exprData_getIterSname (data),
8405 exprNodeList_effect (exprData_getIterAlist (data)),
8406 exprNode_effect (exprData_getIterBody (data)),
8407 exprData_getIterEname (data));
8411 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
8412 exprNode_effect (exprData_getPairB (data)));
8416 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
8417 exprNode_effect (exprData_getTripleTest (data)),
8418 exprNode_effect (exprData_getTripleInc (data)));
8422 ret = exprNode_createTok (exprData_getTok (data));
8426 ret = exprNode_goto (exprData_getLiteral (data));
8427 ret->loc = fileloc_update (ret->loc, e->loc);
8431 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
8435 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
8439 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
8442 case XPR_NULLRETURN:
8443 ret = exprNode_nullReturn (exprData_getTok (data));
8447 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
8448 exprNode_effect (exprData_getPairB (data)));
8452 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
8453 exprNode_effect (exprData_getTripleTrue (data)),
8454 exprNode_effect (exprData_getTripleFalse (data)));
8457 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
8458 exprNode_effect (exprData_getPairB (data)));
8462 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
8463 exprNode_effect (exprData_getTripleTrue (data)),
8464 exprNode_effect (exprData_getTripleFalse (data)));
8467 ret = exprNode_whilePred (exprData_getSingle (data));
8471 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
8472 exprNode_effect (exprData_getPairB (data)));
8476 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
8477 exprNode_effect (exprData_getPairB (data)));
8481 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
8485 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
8486 exprData_getUopTok (data));
8490 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
8491 exprNode_effect (exprData_getPairB (data)));
8496 ret = exprNode_caseMarker
8497 (exprNode_effect (exprData_getSingle (data)),
8503 ret = exprNode_createTok (exprData_getTok (data));
8507 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
8508 exprNode_effect (exprData_getPairB (data)));
8512 ret = exprNode_makeInitialization
8513 (exprData_getInitId (data),
8514 exprNode_effect (exprData_getInitNode (data)));
8518 ret = exprNode_fieldAccessAux
8519 (exprNode_effect (exprData_getFieldNode (data)),
8520 exprNode_loc (exprData_getFieldNode (data)),
8521 cstring_copy (exprData_getFieldName (data)));
8525 ret = exprNode_arrowAccessAux
8526 (exprNode_effect (exprData_getFieldNode (data)),
8527 exprNode_loc (exprData_getFieldNode (data)),
8528 cstring_copy (exprData_getFieldName (data)));
8531 case XPR_STRINGLITERAL:
8545 /*@=observertrans@*/
8547 /*@=dependenttrans@*/
8558 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
8563 if (exprNode_isError (e))
8565 return cstring_undefined;
8573 ret = exprNode_rootVarName (exprData_getUopNode (data));
8576 ret = exprNode_rootVarName (exprData_getOpA (data));
8580 ret = exprData_getId (data);
8605 case XPR_NULLRETURN:
8628 case XPR_STRINGLITERAL:
8629 ret = cstring_undefined;
8636 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
8641 if (exprNode_isError (e))
8643 static /*@only@*/ cstring error = cstring_undefined;
8645 if (!cstring_isDefined (error))
8647 error = cstring_makeLiteral ("<error>");
8658 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
8661 ret = message ("%s %s %s",
8662 exprNode_unparse (exprData_getOpA (data)),
8663 lltok_unparse (exprData_getOpTok (data)),
8664 exprNode_unparse (exprData_getOpB (data)));
8667 ret = message ("%s(%q)",
8668 exprNode_unparse (exprData_getFcn (data)),
8669 exprNodeList_unparse (exprData_getArgs (data)));
8672 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
8675 ret = cstring_undefined;
8678 ret = message ("%s:", exprData_getId (data));
8682 ret = cstring_copy (exprData_getId (data));
8685 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
8686 exprNode_unparse (exprData_getPairB (data)));
8689 ret = message ("<body>");
8692 ret = message ("%s %s %s",
8693 exprNode_unparse (exprData_getOpA (data)),
8694 lltok_unparse (exprData_getOpTok (data)),
8695 exprNode_unparse (exprData_getOpB (data)));
8699 ret = message ("%s%s",
8700 lltok_unparse (exprData_getUopTok (data)),
8701 exprNode_unparse (exprData_getUopNode (data)));
8705 ret = message ("%s%s",
8706 exprNode_unparse (exprData_getUopNode (data)),
8707 lltok_unparse (exprData_getUopTok (data)));
8711 ret = message ("offsetof(%s,%q)",
8712 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
8713 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
8717 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8721 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
8725 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8729 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
8733 ret = message ("va_arg(%s, %q)",
8734 exprNode_unparse (exprData_getCastNode (data)),
8735 qtype_unparse (exprData_getCastType (data)));
8739 ret = message ("%q(%q)",
8740 uentry_getName (exprData_getIterCallIter (data)),
8741 exprNodeList_unparse (exprData_getIterCallArgs (data)));
8744 ret = message ("%q(%q) %s %q",
8745 uentry_getName (exprData_getIterSname (data)),
8746 exprNodeList_unparse (exprData_getIterAlist (data)),
8747 exprNode_unparse (exprData_getIterBody (data)),
8748 uentry_getName (exprData_getIterEname (data)));
8751 ret = message ("(%q)%s",
8752 qtype_unparse (exprData_getCastType (data)),
8753 exprNode_unparse (exprData_getCastNode (data)));
8757 ret = message ("%s %s",
8758 exprNode_unparse (exprData_getPairA (data)),
8759 exprNode_unparse (exprData_getPairB (data)));
8763 ret = message ("for (%s; %s; %s)",
8764 exprNode_unparse (exprData_getTripleInit (data)),
8765 exprNode_unparse (exprData_getTripleTest (data)),
8766 exprNode_unparse (exprData_getTripleInc (data)));
8770 ret = message ("goto %s", exprData_getLiteral (data));
8774 ret = cstring_makeLiteral ("continue");
8778 ret = cstring_makeLiteral ("break");
8782 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
8785 case XPR_NULLRETURN:
8786 ret = cstring_makeLiteral ("return");
8790 ret = message ("%s, %s",
8791 exprNode_unparse (exprData_getPairA (data)),
8792 exprNode_unparse (exprData_getPairB (data)));
8796 ret = message ("%s ? %s : %s",
8797 exprNode_unparse (exprData_getTriplePred (data)),
8798 exprNode_unparse (exprData_getTripleTrue (data)),
8799 exprNode_unparse (exprData_getTripleFalse (data)));
8802 ret = message ("if (%s) %s",
8803 exprNode_unparse (exprData_getPairA (data)),
8804 exprNode_unparse (exprData_getPairB (data)));
8808 ret = message ("if (%s) %s else %s",
8809 exprNode_unparse (exprData_getTriplePred (data)),
8810 exprNode_unparse (exprData_getTripleTrue (data)),
8811 exprNode_unparse (exprData_getTripleFalse (data)));
8814 ret = message ("while (%s) %s",
8815 exprNode_unparse (exprData_getPairA (data)),
8816 exprNode_unparse (exprData_getPairB (data)));
8820 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
8824 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
8828 ret = message ("do { %s } while (%s)",
8829 exprNode_unparse (exprData_getPairB (data)),
8830 exprNode_unparse (exprData_getPairA (data)));
8834 ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
8838 ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
8842 ret = message ("%s; %s",
8843 exprNode_unparse (exprData_getPairA (data)),
8844 exprNode_unparse (exprData_getPairB (data)));
8849 ret = cstring_makeLiteral ("default:");
8853 ret = message ("switch (%s) %s",
8854 exprNode_unparse (exprData_getPairA (data)),
8855 exprNode_unparse (exprData_getPairB (data)));
8860 ret = message ("case %s:",
8861 exprNode_unparse (exprData_getSingle (data)));
8865 if (exprNode_isError (exprData_getInitNode (data)))
8867 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
8871 ret = message ("%q = %s",
8872 idDecl_unparseC (exprData_getInitId (data)),
8873 exprNode_unparse (exprData_getInitNode (data)));
8878 ret = message ("%s.%s",
8879 exprNode_unparse (exprData_getFieldNode (data)),
8880 exprData_getFieldName (data));
8884 ret = message ("%s->%s",
8885 exprNode_unparse (exprData_getFieldNode (data)),
8886 exprData_getFieldName (data));
8889 case XPR_STRINGLITERAL:
8890 ret = message ("\"%s\"", exprData_getLiteral (data));
8894 ret = cstring_copy (exprData_getLiteral (data));
8898 ret = cstring_makeLiteral ("<node>");
8906 exprNode_isInitializer (exprNode e)
8908 return (exprNode_isDefined (e)
8909 && e->kind == XPR_INIT);
8913 exprNode_isCharLit (exprNode e)
8915 if (exprNode_isDefined (e))
8917 return (multiVal_isChar (exprNode_getValue (e)));
8926 exprNode_isNumLit (exprNode e)
8928 if (exprNode_isDefined (e))
8930 return (multiVal_isInt (exprNode_getValue (e)));
8939 exprNode_isFalseConstant (exprNode e)
8941 if (exprNode_isDefined (e))
8943 cstring s = exprNode_rootVarName (e);
8945 if (cstring_equal (s, context_getFalseName ()))
8955 exprNode_matchLiteral (ctype expected, exprNode e)
8957 if (exprNode_isDefined (e))
8959 multiVal m = exprNode_getValue (e);
8961 if (multiVal_isDefined (m))
8963 if (multiVal_isInt (m))
8965 long int val = multiVal_forceInt (m);
8967 if (ctype_isDirectBool (ctype_realishType (expected)))
8971 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
8979 if (ctype_isRealInt (expected))
8982 ** unsigned <- [ constant >= 0 is okay ]
8985 if (ctype_isUnsigned (expected))
8994 ** No checks on sizes of integers...maybe add
8998 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
8999 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9000 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9002 if (context_getFlag (FLG_NUMLITERAL)
9003 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9009 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9013 else if (ctype_isChar (expected))
9017 else if (ctype_isArrayPtr (expected))
9021 else if (ctype_isAnyFloat (expected))
9023 return (context_getFlag (FLG_NUMLITERAL));
9030 else if (multiVal_isDouble (m))
9032 if (ctype_isAnyFloat (expected))
9037 else if (multiVal_isChar (m))
9039 char val = multiVal_forceChar (m);
9041 if (ctype_isChar (expected))
9043 if (ctype_isUnsigned (expected) && ((int)val) < 0)
9064 exprNode_matchType (ctype expected, exprNode e)
9068 if (!exprNode_isDefined (e)) return TRUE;
9070 actual = ctype_realishType (exprNode_getType (e));
9072 if (ctype_match (ctype_realishType (expected), actual))
9077 llassert (!exprNode_isError (e));
9078 return (exprNode_matchLiteral (expected, e));
9082 exprNode_matchTypes (exprNode e1, exprNode e2)
9087 if (!exprNode_isDefined (e1)) return TRUE;
9088 if (!exprNode_isDefined (e2)) return TRUE;
9091 ** realish type --- keep bools, bools
9094 t1 = ctype_realishType (exprNode_getType (e1));
9095 t2 = ctype_realishType (exprNode_getType (e2));
9097 if (ctype_match (t1, t2))
9102 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9110 exprNode_matchArgType (ctype ct, exprNode e)
9114 if (!exprNode_isDefined (e))
9119 et = ctype_realType (exprNode_getType (e));
9121 if (ctype_matchArg (ct, et)) return TRUE;
9123 llassert (!exprNode_isError (e));
9124 return (exprNode_matchLiteral (ct, e));
9127 static /*@only@*/ exprNodeSList
9128 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9130 if (exprNode_isDefined (e))
9132 if (e->kind == XPR_STMTLIST)
9134 return (exprNodeSList_append
9135 (exprNode_flatten (exprData_getPairA (e->edata)),
9136 exprNode_flatten (exprData_getPairB (e->edata))));
9138 else if (e->kind == XPR_BLOCK)
9140 return (exprNode_flatten (exprData_getSingle (e->edata)));
9144 return (exprNodeSList_singleton (e));
9148 return exprNodeSList_new ();
9151 static /*@exposed@*/ exprNode
9152 exprNode_lastStatement (/*@returned@*/ exprNode e)
9154 if (exprNode_isDefined (e))
9156 if (e->kind == XPR_STMTLIST)
9158 exprNode b = exprData_getPairB (e->edata);
9160 if (exprNode_isDefined (b))
9162 return exprNode_lastStatement (b);
9166 return exprNode_lastStatement (exprData_getPairA (e->edata));
9169 else if (e->kind == XPR_BLOCK)
9171 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
9179 return exprNode_undefined;
9182 static /*@exposed@*/ exprNode
9183 exprNode_firstStatement (/*@returned@*/ exprNode e)
9185 if (exprNode_isDefined (e))
9187 if (e->kind == XPR_STMTLIST)
9189 exprNode b = exprData_getPairA (e->edata);
9191 if (exprNode_isDefined (b))
9193 return exprNode_firstStatement (b);
9197 return exprNode_firstStatement (exprData_getPairB (e->edata));
9200 else if (e->kind == XPR_BLOCK)
9202 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
9210 return exprNode_undefined;
9214 exprNode_mergeUSs (exprNode res, exprNode other)
9216 if (exprNode_isDefined (res) && exprNode_isDefined (other))
9218 res->msets = sRefSet_union (res->msets, other->msets);
9219 res->sets = sRefSet_union (res->sets, other->sets);
9220 res->uses = sRefSet_union (res->uses, other->uses);
9225 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
9227 if (exprNode_isDefined (res))
9229 if (exprNode_isDefined (other1))
9231 res->sets = sRefSet_union (res->sets, other1->sets);
9232 res->msets = sRefSet_union (res->msets, other1->msets);
9233 res->uses = sRefSet_union (res->uses, other1->uses);
9235 if (exprNode_isDefined (other2))
9237 res->sets = sRefSet_union (res->sets, other2->sets);
9238 res->msets = sRefSet_union (res->msets, other2->msets);
9239 res->uses = sRefSet_union (res->uses, other2->uses);
9247 ** Reports errors is s is not defined.
9251 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
9253 if (exprNode_isDefined (e))
9255 e->uses = sRefSet_insert (e->uses, s);
9260 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
9262 if (sRef_isKnown (s) && !sRef_isConst (s))
9265 ** need to check all outer types are useable
9268 DPRINTF (("Check use: %s / %s",
9269 exprNode_unparse (e), sRef_unparse (s)));
9271 exprNode_addUse (e, s);
9273 if (!context_inProtectVars ())
9276 ** only report the deepest error
9279 sRef errorRef = sRef_undefined;
9280 sRef lastRef = sRef_undefined;
9281 bool deadRef = FALSE;
9282 bool unuseable = FALSE;
9283 bool errorMaybe = FALSE;
9285 while (sRef_isValid (s) && sRef_isKnown (s))
9287 ynm readable = sRef_isReadable (s);
9289 DPRINTF (("Readable: %s / %s",
9290 sRef_unparseFull (s), ynm_unparse (readable)));
9292 if (!(ynm_toBoolStrict (readable)))
9294 if (ynm_isMaybe (readable))
9298 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
9299 deadRef = sRef_isPossiblyDead (errorRef);
9300 unuseable = sRef_isUnuseable (errorRef);
9307 deadRef = sRef_isDead (errorRef);
9308 unuseable = sRef_isUnuseable (errorRef);
9312 if (!sRef_isPartial (s))
9314 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
9315 sRef_setDefined (s, fileloc_undefined);
9319 s = sRef_getBaseSafe (s);
9322 if (sRef_isValid (errorRef))
9324 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
9325 && sRef_isPointer (errorRef))
9332 if (sRef_isThroughArrayFetch (errorRef))
9335 (FLG_STRICTUSERELEASED,
9336 message ("%q %q may be used after being released",
9337 sRef_unparseKindNamePlain (errorRef),
9338 sRef_unparse (errorRef)),
9341 sRef_showRefKilled (errorRef);
9343 if (sRef_isKept (errorRef))
9345 sRef_clearAliasState (errorRef, loc);
9351 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
9355 message ("%q %q %qused after being released",
9356 sRef_unparseKindNamePlain (errorRef),
9357 sRef_unparse (errorRef),
9358 cstring_makeLiteral (errorMaybe
9362 sRef_showRefKilled (errorRef);
9364 if (sRef_isKept (errorRef))
9366 sRef_clearAliasState (errorRef, loc);
9375 message ("%q %q%qused in inconsistent state",
9376 sRef_unparseKindName (errorRef),
9377 sRef_unparseOpt (errorRef),
9378 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9381 sRef_showStateInconsistent (errorRef);
9386 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
9390 message ("%q %q%qused before definition",
9391 sRef_unparseKindName (errorRef),
9392 sRef_unparseOpt (errorRef),
9393 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9396 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
9399 sRef_setDefined (errorRef, loc);
9401 if (sRef_isAddress (errorRef))
9403 sRef_setDefined (sRef_getRootBase (errorRef), loc);
9405 } /* end is error */
9413 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
9415 if (exprNode_isDefined (e) && sRef_isKnown (s))
9417 e->uses = sRefSet_insert (e->uses, s);
9422 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
9424 if (exprNode_isDefined (e))
9426 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
9431 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
9433 sRef defines = sRef_undefined;
9435 if (sRef_isValid (s) && !sRef_isNothing (s))
9437 uentry ue = sRef_getBaseUentry (s);
9439 if (uentry_isValid (ue))
9441 uentry_setLset (ue);
9444 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9446 voptgenerror (FLG_USEDEF,
9447 message ("Attempt to set unuseable storage: %q",
9452 if (sRef_isMeaningful (s))
9455 if (sRef_isDead (s))
9457 sRef base = sRef_getBaseSafe (s);
9459 if (sRef_isValid (base)
9460 && sRef_isDead (base))
9462 sRef_setPartial (s, exprNode_loc (e));
9465 defines = s; /* okay - modifies for only param */
9467 else if (sRef_isPartial (s))
9469 sRef eref = exprNode_getSref (e);
9471 if (!sRef_isPartial (eref))
9474 ** should do something different here???
9477 sRef_setDefinedComplete (eref, exprNode_loc (e));
9481 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
9484 if (sRef_isMeaningful (eref))
9493 else if (sRef_isAllocated (s))
9495 sRef eref = exprNode_getSref (e);
9498 if (!sRef_isAllocated (eref))
9500 sRef_setDefinedComplete (eref, exprNode_loc (e));
9504 sRef base = sRef_getBaseSafe (eref);
9506 if (sRef_isValid (base))
9508 sRef_setPdefined (base, exprNode_loc (e));
9516 sRef_setDefinedNCComplete (s, exprNode_loc (e));
9521 else /* not meaningful...but still need to insert it */
9527 if (exprNode_isDefined (e) && sRef_isValid (defines))
9529 e->sets = sRefSet_insert (e->sets, defines);
9534 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
9536 if (sRef_isValid (s) && !sRef_isNothing (s))
9538 uentry ue = sRef_getBaseUentry (s);
9540 if (uentry_isValid (ue))
9542 uentry_setLset (ue);
9545 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9547 voptgenerror (FLG_USEDEF,
9548 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
9552 if (sRef_isMeaningful (s))
9554 sRef_setDefinedComplete (s, exprNode_loc (e));
9557 if (exprNode_isDefined (e))
9559 e->msets = sRefSet_insert (e->msets, s);
9565 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
9567 checkAnyCall (fcn, cstring_undefined, params, args,
9568 FALSE, sRefSet_undefined, FALSE, 0);
9572 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
9573 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
9577 if (uentry_isYield (ucurrent))
9579 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
9580 exprNode_checkSet (current, current->sref);
9584 if (uentry_isSefParam (ucurrent))
9586 sRefSet sets = current->sets;
9587 sRef ref = exprNode_getSref (current);
9589 if (sRef_isMacroParamRef (ref))
9591 uentry ue = sRef_getUentry (ref);
9593 if (!uentry_isSefParam (ue))
9598 ("Parameter %d to %s is declared sef, but "
9599 "the argument is a macro parameter declared "
9601 argno, exprNode_unparse (fcn),
9602 exprNode_unparse (current)),
9603 exprNode_loc (current));
9607 if (!sRefSet_isEmpty (sets))
9609 sRefSet reported = sRefSet_undefined;
9611 sRefSet_realElements (current->sets, el)
9613 if (sRefSet_isSameNameMember (reported, el))
9615 ; /* don't report again */
9619 if (sRef_isUnconstrained (el))
9624 ("Parameter %d to %s is declared sef, but "
9625 "the argument calls unconstrained function %s "
9626 "(no guarantee it will not modify something): %s",
9627 argno, exprNode_unparse (fcn),
9628 sRef_unconstrainedName (el),
9629 exprNode_unparse (current)),
9630 exprNode_loc (current));
9637 ("Parameter %d to %s is declared sef, but "
9638 "the argument may modify %q: %s",
9639 argno, exprNode_unparse (fcn),
9641 exprNode_unparse (current)),
9642 exprNode_loc (current));
9645 } end_sRefSet_realElements;
9649 checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs);
9650 exprNode_mergeUSs (fcn, current);
9655 checkAnyCall (/*@dependent@*/ exprNode fcn,
9656 /*@dependent@*/ cstring fname,
9659 bool hasMods, sRefSet mods,
9664 int nargs = exprNodeList_size (args);
9669 ** concat all args ud's to f, add each arg sref as a use unless
9670 ** it was specified as "out", in which case it is a def.
9673 uentryList_reset (pn);
9678 ** if paramn is only or unique, no other arg may alias argn
9681 exprNodeList_elements (args, current)
9685 if (exprNode_isDefined (current))
9687 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
9689 uentry ucurrent = uentryList_current (pn);
9691 if (specialArgs == 0
9692 || (paramno < specialArgs))
9694 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
9696 if (context_maybeSet (FLG_ALIASUNIQUE))
9698 if (uentry_isOnly (ucurrent)
9699 || uentry_isUnique (ucurrent))
9701 checkUniqueParams (fcn, current, args,
9707 else /* uentry is undefined */
9709 if (specialArgs == 0)
9711 exprNode_checkUseParam (current);
9714 exprNode_mergeUSs (fcn, current);
9717 uentryList_advanceSafe (pn);
9718 } end_exprNodeList_elements;
9724 sRefSet_allElements (mods, s)
9727 sRef rb = sRef_getRootBase (s);
9729 if (sRef_isFileOrGlobalScope (rb))
9731 context_usedGlobal (rb);
9734 fb = sRef_fixBaseParam (s, args);
9736 if (!sRef_isMacroParamRef (fb))
9738 if (sRef_isNothing (fb))
9744 if (sRef_isValid (fb))
9746 uentry ue = sRef_getBaseUentry (s);
9748 if (uentry_isValid (ue))
9750 uentry_setLset (ue);
9754 fcn->sets = sRefSet_insert (fcn->sets, fb);
9757 sRef_clearDerivedComplete (s);
9758 } end_sRefSet_allElements;
9764 if (context_hasMods ())
9766 if (context_maybeSet (FLG_MODUNCON))
9770 message ("Undetected modification possible "
9771 "from call to unconstrained function %s: %s",
9773 exprNode_unparse (fcn)),
9774 exprNode_loc (fcn));
9779 if (context_maybeSet (FLG_MODUNCONNOMODS)
9780 && !(context_inIterDef () || context_inIterEnd ()))
9783 (FLG_MODUNCONNOMODS,
9784 message ("Undetected modification possible "
9785 "from call to unconstrained function %s: %s",
9787 exprNode_unparse (fcn)),
9788 exprNode_loc (fcn));
9792 exprNode_checkSetAny (fcn, fname);
9796 void exprNode_checkUseParam (exprNode current)
9798 if (exprNode_isDefined (current))
9800 exprNode_checkUse (current, current->sref, current->loc);
9805 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
9806 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
9811 if (!ctype_match (tr1, tr2))
9813 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
9814 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
9822 message ("Incompatible types for %s (%s, %s): %s %s %s",
9824 ctype_unparse (te1),
9825 ctype_unparse (te2),
9826 exprNode_unparse (e1), lltok_unparse (op),
9827 exprNode_unparse (e2)),
9830 ret = ctype_unknown;
9834 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
9836 ret = ctype_resolveNumerics (tr1, tr2);
9838 else if (!context_msgStrictOps ())
9840 if (ctype_isPointer (tr1))
9842 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
9846 else if (ctype_isInt (tr2))
9852 ret = ctype_unknown;
9855 else if (ctype_isPointer (tr2))
9857 if (ctype_isPointer (tr1))
9861 else if (ctype_isInt (tr1))
9867 ret = ctype_unknown;
9872 ret = ctype_resolveNumerics (tr1, tr2);
9877 int opid = lltok_getTok (op);
9878 bool comparop = (opid == EQ_OP || opid == NE_OP
9879 || opid == TLT || opid == TGT
9880 || opid == LE_OP || opid == GE_OP);
9882 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
9885 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
9886 || (ctype_isBool (tr1) && ctype_isBool (tr2))
9887 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
9893 if (ctype_sameName (te1, te2))
9897 message ("Operands of %s are non-numeric (%t): %s %s %s",
9898 lltok_unparse (op), te1,
9899 exprNode_unparse (e1), lltok_unparse (op),
9900 exprNode_unparse (e2)),
9907 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
9908 lltok_unparse (op), te1, te2,
9909 exprNode_unparse (e1), lltok_unparse (op),
9910 exprNode_unparse (e2)),
9915 else if (!ctype_isNumeric (tr1))
9919 message ("Right operand of %s is non-numeric (%t): %s %s %s",
9920 lltok_unparse (op), te1,
9921 exprNode_unparse (e1), lltok_unparse (op),
9922 exprNode_unparse (e2)),
9927 if (!ctype_isNumeric (tr2))
9931 message ("Left operand of %s is non-numeric (%t): %s %s %s",
9932 lltok_unparse (op), te2,
9933 exprNode_unparse (e1), lltok_unparse (op),
9934 exprNode_unparse (e2)),
9939 ret = ctype_unknown;
9947 abstractOpError (ctype tr1, ctype tr2, lltok op,
9948 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
9949 fileloc loc1, fileloc loc2)
9951 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
9953 if (ctype_match (tr1, tr2))
9957 message ("Operands of %s are abstract type (%t): %s %s %s",
9958 lltok_unparse (op), tr1,
9959 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9966 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
9967 lltok_unparse (op), tr1, tr2,
9968 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9972 else if (ctype_isRealAbstract (tr1))
9976 message ("Left operand of %s is abstract type (%t): %s %s %s",
9977 lltok_unparse (op), tr1,
9978 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9983 if (ctype_isRealAbstract (tr2))
9987 message ("Right operand of %s is abstract type (%t): %s %s %s",
9988 lltok_unparse (op), tr2,
9989 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
9998 ** requies e1 and e2 and not error exprNode's.
10002 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10003 ** the rep of the abstract type is exposed.
10005 ** The order is very important:
10007 ** check rep expose (move into check transfer)
10013 ** This isn't really a sensible procedure, but the indententation
10014 ** was getting too deep.
10018 checkOneRepExpose (sRef ysr, sRef base,
10019 /*@notnull@*/ exprNode e1,
10020 /*@notnull@*/ exprNode e2, ctype ct,
10023 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
10024 || sRef_isOwned (ysr)
10025 || sRef_isExposed (ysr)))
10027 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10028 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10031 if (sRef_isIReference (ysr))
10033 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10038 ("Assignment of mutable component of parameter %q "
10039 "to component of abstract "
10040 "type %s exposes rep: %s = %s",
10041 sRef_unparse (base),
10042 ctype_unparse (ct),
10043 exprNode_unparse (e1), exprNode_unparse (e2)),
10051 ("Assignment of mutable component of parameter %q "
10052 "(through alias %q) to component of abstract "
10053 "type %s exposes rep: %s = %s",
10054 sRef_unparse (base),
10055 sRef_unparse (e2->sref),
10056 ctype_unparse (ct),
10057 exprNode_unparse (e1), exprNode_unparse (e2)),
10063 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10067 message ("Assignment of mutable parameter %q "
10068 "to component of abstract type %s "
10069 "exposes rep: %s = %s",
10070 sRef_unparse (base),
10071 ctype_unparse (ct),
10072 exprNode_unparse (e1),
10073 exprNode_unparse (e2)),
10080 message ("Assignment of mutable parameter %q "
10081 "(through alias %q) to "
10082 "component of abstract type %s exposes "
10084 sRef_unparse (base),
10085 sRef_unparse (e2->sref),
10086 ctype_unparse (ct),
10087 exprNode_unparse (e1),
10088 exprNode_unparse (e2)),
10094 if (sRef_isFileOrGlobalScope (s2b))
10096 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10100 message ("Assignment of global %q "
10102 "abstract type %s exposes rep: %s = %s",
10103 sRef_unparse (base),
10104 ctype_unparse (ct),
10105 exprNode_unparse (e1), exprNode_unparse (e2)),
10112 message ("Assignment of global %q (through alias %q) "
10114 "abstract type %s exposes rep: %s = %s",
10115 sRef_unparse (base),
10116 sRef_unparse (e2->sref),
10117 ctype_unparse (ct),
10118 exprNode_unparse (e1), exprNode_unparse (e2)),
10126 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
10128 if (ctype_isRealFunction (exprNode_getType (e1))
10129 && !ctype_isRealPointer (exprNode_getType (e1)))
10133 message ("Invalid left-hand side of assignment (function type %s): %s",
10134 ctype_unparse (exprNode_getType (e1)),
10135 exprNode_unparse (e1)),
10139 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
10141 ctype t2 = exprNode_getType (e2);
10142 sRef sr = sRef_getRootBase (e1->sref);
10143 ctype ct = sRef_getType (sr);
10145 if (ctype_isAbstract (t2)
10146 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
10148 /* it is immutable, okay to reference */
10149 goto donerepexpose;
10152 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
10154 sRef s2b = sRef_getRootBase (e2->sref);
10155 sRef s1 = e1->sref;
10156 sRef s1b = sRef_getRootBase (s1);
10159 aliases = usymtab_canAlias (e2->sref);
10161 if (!sRef_similar (s2b, s1b)
10162 && !sRef_isExposed (s1)
10163 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
10165 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
10166 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
10167 && !sRef_isExposed (s2b))
10169 if (sRef_isIReference (e2->sref))
10174 ("Assignment of mutable component of parameter %q "
10175 "to component of abstract type %s exposes rep: %s = %s",
10176 sRef_unparse (s2b),
10177 ctype_unparse (ct),
10178 exprNode_unparse (e1), exprNode_unparse (e2)),
10185 message ("Assignment of mutable parameter %q to "
10186 "component of abstract type %s exposes rep: %s = %s",
10187 sRef_unparse (s2b),
10188 ctype_unparse (ct),
10189 exprNode_unparse (e1), exprNode_unparse (e2)),
10194 if (sRef_isFileOrGlobalScope (s2b))
10198 message ("Assignment of global %q to component of "
10199 "abstract type %s exposes rep: %s = %s",
10200 sRef_unparse (s2b),
10201 ctype_unparse (ct),
10202 exprNode_unparse (e1), exprNode_unparse (e2)),
10206 sRefSet_realElements (aliases, ysr)
10208 sRef base = sRef_getRootBase (ysr);
10210 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
10211 || sRef_sameName (base, s1b))
10213 ; /* error already reported or same sref */
10217 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
10219 } end_sRefSet_realElements;
10221 sRefSet_free (aliases);
10228 ** function variables don't really work...
10231 if (!ctype_isFunction (ctype_realType (e2->typ)))
10235 DPRINTF (("Check init: %s / %s",
10236 exprNode_unparse (e1), exprNode_unparse (e2)));
10237 checkInitTransfer (e1, e2);
10241 checkAssignTransfer (e1, e2);
10246 sRef fref = e2->sref;
10248 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
10249 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
10251 /* Need to typecheck the annotation on the parameters */
10253 if (ctype_isRealFunction (e1->typ)) {
10254 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
10255 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
10257 if (!uentryList_isMissingParams (e1p)
10258 && !uentryList_isMissingParams (e2p)
10259 && uentryList_size (e1p) > 0) {
10260 if (uentryList_size (e1p) == uentryList_size (e2p)) {
10263 uentryList_elements (e1p, el1) {
10266 el2 = uentryList_getN (e2p, n);
10268 uentry_checkMatchParam (el1, el2, n, e2);
10269 } end_uentryList_elements;
10275 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
10281 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
10282 updateAliases (e1, e2);
10287 checkMacroParen (exprNode e)
10289 if (exprNode_isError (e) || e->kind == XPR_CAST)
10295 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
10299 message ("Macro parameter used without parentheses: %s",
10300 exprNode_unparse (e)),
10307 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
10311 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
10315 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
10322 ** if e2 is a parameter or global derived location which
10323 ** can be modified (that is, e2 is a mutable abstract type,
10324 ** or a derived pointer), then e1 can alias e2.
10326 ** e1 can alias everything which e2 can alias.
10328 ** Also, if e1 is guarded, remove from guard sets!
10331 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
10333 if (!context_inProtectVars ())
10336 ** depends on types of e1 and e2
10339 sRef s1 = e1->sref;
10340 sRef s2 = e2->sref;
10341 ctype t1 = exprNode_getType (e1);
10343 /* handle pointer sRefs, record fields, arrays, etc... */
10345 if (!ctype_isRealSU (t1))
10347 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
10348 sRef_copyRealDerivedComplete (s1, s2);
10353 ** Fields should alias
10356 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
10359 if (ctype_isMutable (t1) && sRef_isKnown (s1))
10361 usymtab_clearAlias (s1);
10362 usymtab_addMustAlias (s1, s2);
10363 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
10367 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
10370 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
10372 usymtab_unguard (s1);
10377 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
10379 if (exprNode_isDefined (e))
10381 e->loc = fileloc_update (e->loc, loc);
10385 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
10391 static void checkUniqueParams (exprNode fcn,
10392 /*@notnull@*/ exprNode current,
10394 int paramno, uentry ucurrent)
10397 sRef thisref = exprNode_getSref (current);
10400 ** Check if any argument could match this argument.
10403 exprNodeList_elements (args, icurrent)
10407 if (iparamno != paramno)
10409 sRef sr = exprNode_getSref (icurrent);
10411 if (sRef_similarRelaxed (thisref, sr))
10413 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
10418 ("Parameter %d (%s) to function %s is declared %s but "
10419 "is aliased by parameter %d (%s)",
10421 exprNode_unparse (current),
10422 exprNode_unparse (fcn),
10423 alkind_unparse (uentry_getAliasKind (ucurrent)),
10424 iparamno, exprNode_unparse (icurrent)),
10430 sRefSet aliases = usymtab_canAlias (sr);
10432 sRefSet_allElements (aliases, asr)
10434 if (ctype_isUnknown (sRef_getType (thisref)))
10436 sRef_setType (thisref, uentry_getType (ucurrent));
10439 if (sRef_similarRelaxed (thisref, asr))
10441 if (sRef_isExternal (asr))
10443 if (sRef_isLocalState (thisref))
10449 sRef base = sRef_getRootBase (asr);
10451 if (!sRef_similar (sRef_getBase (asr), thisref))
10453 if (sRef_isUnique (base) || sRef_isOnly (base)
10454 || sRef_isKept (base)
10455 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
10456 || (sRef_isAddress (thisref)
10457 && sRef_isLocalVar (sRef_getRootBase (thisref))))
10459 ; /* okay, no error */
10464 (FLG_MAYALIASUNIQUE,
10466 ("Parameter %d (%s) to function %s is declared %s but "
10467 "may be aliased externally by parameter %d (%s)",
10469 exprNode_unparse (current),
10470 exprNode_unparse (fcn),
10471 alkind_unparse (uentry_getAliasKind (ucurrent)),
10472 iparamno, exprNode_unparse (icurrent)),
10483 ("Parameter %d (%s) to function %s is declared %s but "
10484 "is aliased externally by parameter %d (%s) through "
10487 exprNode_unparse (current),
10488 exprNode_unparse (fcn),
10489 alkind_unparse (uentry_getAliasKind (ucurrent)),
10490 iparamno, exprNode_unparse (icurrent),
10491 sRef_unparse (asr)),
10495 } end_sRefSet_allElements;
10496 sRefSet_free (aliases);
10499 } end_exprNodeList_elements;
10502 long exprNode_getLongValue (exprNode e) {
10505 if (exprNode_hasValue (e)
10506 && multiVal_isInt (exprNode_getValue (e)))
10508 value = multiVal_forceInt (exprNode_getValue (e));
10518 /*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
10520 if (exprNode_isDefined (p_e) )
10521 return ( p_e->loc );
10523 return fileloc_undefined;
10526 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
10529 ** Returns the location of the sequence point following e.
10531 ** Only works for statements (for now).
10534 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
10535 lltok t = exprData_getUopTok (e->edata);
10536 return fileloc_copy(lltok_getLoc (t));
10538 //drl possible problem : warning fix
10539 // llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
10540 return fileloc_undefined;
10544 exprNode exprNode_createNew(ctype c)
10548 ret = exprNode_createPlain (c);