2 ** Splint - 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://www.splint.org
28 # include <ctype.h> /* for isdigit */
29 # include "lclintMacros.nf"
31 # include "cgrammar.h"
32 # include "cgrammar_tokens.h"
34 # include "exprChecks.h"
35 # include "transferChecks.h"
36 # include "exprNodeSList.h"
38 static bool exprNode_isEmptyStatement (exprNode p_e);
39 static /*@exposed@*/ exprNode exprNode_firstStatement (/*@returned@*/ exprNode p_e);
40 static bool exprNode_isFalseConstant (exprNode p_e) /*@*/ ;
41 static bool exprNode_isBlock (exprNode p_e);
42 static void checkGlobUse (uentry p_glob, bool p_isCall, /*@notnull@*/ exprNode p_e);
43 static void exprNode_addUse (exprNode p_e, /*@exposed@*/ sRef p_s);
44 static bool exprNode_matchArgType (ctype p_ct, exprNode p_e);
45 static exprNode exprNode_fakeCopy (exprNode p_e) /*@*/ ;
46 static exprNode exprNode_statementError (/*@only@*/ exprNode p_e, /*@only@*/ lltok p_t);
47 static bool exprNode_matchTypes (exprNode p_e1, exprNode p_e2);
48 static void checkUniqueParams (exprNode p_fcn,
49 /*@notnull@*/ exprNode p_current, exprNodeList p_args,
50 int p_paramno, uentry p_ucurrent);
51 static void updateAliases (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2);
52 static void abstractOpError (ctype p_tr1, ctype p_tr2, lltok p_op,
53 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2,
54 fileloc p_loc1, fileloc p_loc2);
55 static ctype checkNumerics (ctype p_tr1, ctype p_tr2, ctype p_te1, ctype p_te2,
56 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, lltok p_op);
57 static void doAssign (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, bool p_isInit);
58 static void checkSafeUse (exprNode p_e, /*@exposed@*/ sRef p_s);
59 static void reflectNullTest (/*@notnull@*/ exprNode p_e, bool p_isnull);
60 static void checkMacroParen (exprNode p_e);
61 static exprNodeSList exprNode_flatten (/*@dependent@*/ exprNode p_e);
62 static void exprNode_checkSetAny (exprNode p_e, /*@dependent@*/ cstring p_name);
63 static void exprNode_checkUse (exprNode p_e, /*@exposed@*/ sRef p_s, fileloc p_loc);
64 static void exprNode_mergeUSs (exprNode p_res, exprNode p_other);
65 static void exprNode_mergeCondUSs (exprNode p_res, exprNode p_other1, exprNode p_other2);
66 static /*@only@*/ /*@notnull@*/ exprNode exprNode_fromIdentifierAux (/*@observer@*/ uentry p_c);
67 static void checkAnyCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn,
68 /*@dependent@*/ cstring p_fname,
69 uentryList p_pn, exprNodeList p_args,
70 bool p_hasMods, sRefSet p_mods, bool p_isSpec,
72 static void checkOneArg (uentry p_ucurrent, /*@notnull@*/ exprNode p_current,
73 /*@dependent@*/ exprNode p_fcn, bool p_isSpec, int p_argno, int p_totargs);
75 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn, uentryList p_params, exprNodeList p_args);
77 static /*@only@*/ exprNode exprNode_effect (exprNode p_e)
78 /*@globals internalState@*/ ;
79 static /*@only@*/ cstring exprNode_doUnparse (exprNode p_e);
80 static /*@observer@*/ cstring exprNode_rootVarName (exprNode p_e);
81 static /*@exposed@*/ exprNode
82 exprNode_lastStatement (/*@returned@*/ exprNode p_e);
84 static /*@null@*/ sRef defref = sRef_undefined;
85 static /*@only@*/ exprNode mustExitNode = exprNode_undefined;
87 static int checkArgsReal (uentry p_fcn, /*@dependent@*/ exprNode p_f,
89 exprNodeList p_args, bool p_isIter, exprNode p_ret);
91 static bool inEffect = FALSE;
92 static int nowalloc = 0;
93 static int totalloc = 0;
94 static int maxalloc = 0;
96 static /*@only@*/ uentry regArg;
97 static /*@only@*/ uentry outArg;
98 static /*@only@*/ uentry outStringArg;
99 static /*@exposed@*/ sRef stdinRef;
100 static /*@exposed@*/ sRef stdoutRef;
101 static /*@only@*/ uentry csArg;
102 static /*@only@*/ uentry csOnlyArg;
103 static ctype cstringType;
104 static ctype ctypeType;
105 static ctype filelocType;
106 static bool initMod = FALSE;
108 /*@function void exprNode_swap (sef exprNode, sef exprNode)@*/
110 # define exprNode_swap(e1,e2) do { exprNode m_tmp = (e1); (e1) = (e2); (e2) = m_tmp; } while (FALSE)
113 static void exprNode_defineConstraints(/*@sef@*/ /*@special@*/ /*@notnull@*/ exprNode e)
114 /*@defines e->requiresConstraints, e->ensuresConstraints,
115 e->trueEnsuresConstraints, e->falseEnsuresConstraints @*/
117 e->requiresConstraints = constraintList_makeNew ();
118 e->ensuresConstraints = constraintList_makeNew ();
119 e->trueEnsuresConstraints = constraintList_makeNew ();
120 e->falseEnsuresConstraints = constraintList_makeNew ();
124 ** must occur after library has been read
127 void exprNode_initMod (void)
128 /*@globals undef regArg, undef outArg, undef outStringArg,
129 undef csOnlyArg, undef csArg;
136 cstringType = ctype_unknown;
137 ctypeType = ctype_unknown;
138 filelocType = ctype_unknown;
140 defref = sRef_undefined;
142 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
144 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
147 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
149 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
152 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
154 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
157 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdin")))
159 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdin"));
161 else /* define stdin */
163 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdin"),
165 fileloc_getBuiltin (),
167 uentry_setHasNameError (ue);
168 ue = usymtab_supGlobalEntryReturn (ue);
171 stdinRef = sRef_makePointer (uentry_getSref (ue));
173 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdout")))
175 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdout"));
179 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdout"),
181 fileloc_getBuiltin (),
183 uentry_setHasNameError (ue);
184 ue = usymtab_supGlobalEntryReturn (ue);
187 stdoutRef = sRef_makePointer (uentry_getSref (ue));
189 tmp = idDecl_create (cstring_undefined, qtype_create (ctype_unknown));
191 regArg = uentry_makeParam (tmp, PARAMUNKNOWN);
194 qtype_addQual (qtype_create (ctype_makePointer (ctype_unknown)),
197 outArg = uentry_makeParam (tmp, PARAMUNKNOWN);
199 idDecl_setTyp (tmp, qtype_addQual (qtype_create (ctype_string),
202 outStringArg = uentry_makeParam (tmp, PARAMUNKNOWN);
204 idDecl_setTyp (tmp, qtype_addQual (qtype_addQual (qtype_create (cstringType),
206 qual_createNull ()));
208 csOnlyArg = uentry_makeParam (tmp, PARAMUNKNOWN);
210 idDecl_setTyp (tmp, qtype_addQual (qtype_create (cstringType), qual_createNull ()));
211 csArg = uentry_makeParam (tmp, PARAMUNKNOWN);
217 exprNode_destroyMod (void)
218 /*@globals killed regArg, killed outArg, killed outStringArg,
219 killed mustExitNode, initMod @*/
223 uentry_free (regArg);
224 uentry_free (outArg);
225 uentry_free (outStringArg);
227 exprNode_free (mustExitNode);
234 static void exprNode_resetSref (/*@notnull@*/ exprNode e)
239 exprNode exprNode_fakeCopy (exprNode e)
241 /*@-temptrans@*/ /*@-retalias@*/
243 /*@=temptrans@*/ /*@=retalias@*/
246 static bool isFlagKey (char key)
248 return (key == '-' || key == '+' || key == ' ' || key == '#');
251 static void exprNode_combineControl (/*@notnull@*/ exprNode ret,
252 /*@notnull@*/ exprNode ifclause,
253 /*@notnull@*/ exprNode elseclause)
255 ret->canBreak = ifclause->canBreak || elseclause->canBreak;
258 (ifclause->mustBreak || exprNode_mustEscape (ifclause))
259 && (elseclause->mustBreak || exprNode_mustEscape (elseclause));
261 ret->exitCode = exitkind_combine (ifclause->exitCode,
262 elseclause->exitCode);
267 ** For exprNode's returned by exprNode_effect.
270 static bool shallowKind (exprKind kind)
272 return (kind == XPR_STRINGLITERAL
273 || kind == XPR_NUMLIT
276 || kind == XPR_NODE);
280 exprNode_freeIniter (/*@only@*/ exprNode e)
282 if (!exprNode_isError (e))
288 ** Its a fake copy, don't free the field->rec and field->field
293 sfree (e->edata->field);
299 exprNode_free (e->edata->op->b);
300 /*@-compdestroy@*/ sfree (e->edata->op); /*@=compdestroy@*/
304 llbug (message ("other: %s", exprNode_unparse (e)));
307 multiVal_free (e->val);
308 cstring_free (e->etext);
309 fileloc_free (e->loc);
310 sRefSet_free (e->uses);
311 sRefSet_free (e->sets);
312 sRefSet_free (e->msets);
313 guardSet_free (e->guards);
315 constraintList_free(e->requiresConstraints);
316 constraintList_free(e->ensuresConstraints);
317 constraintList_free(e->trueEnsuresConstraints);
318 constraintList_free(e->falseEnsuresConstraints);
320 e->requiresConstraints = NULL;
321 e->ensuresConstraints = NULL;
322 e->trueEnsuresConstraints = NULL;
323 e->falseEnsuresConstraints = NULL;
330 exprNode_freeShallow (/*@only@*/ exprNode e)
332 if (!exprNode_isError (e))
334 if (shallowKind (e->kind))
341 if (e->kind == XPR_EMPTY
342 || e->kind == XPR_BODY
343 || e->kind == XPR_STRINGLITERAL
344 || e->kind == XPR_NUMLIT
345 || e->kind == XPR_NODE
346 || e->kind == XPR_OFFSETOF
347 || e->kind == XPR_ALIGNOFT
348 || e->kind == XPR_ALIGNOF
349 || e->kind == XPR_SIZEOFT
350 || e->kind == XPR_SIZEOF)
352 /* don't free anything */
356 /* multiVal_free (e->val); */
357 cstring_free (e->etext);
358 fileloc_free (e->loc);
359 sRefSet_free (e->uses);
360 sRefSet_free (e->sets);
361 sRefSet_free (e->msets);
362 guardSet_free (e->guards);
363 exprData_freeShallow (e->edata, e->kind);
365 /*@-compdestroy@*/ sfree (e); /*@=compdestroy@*/
374 exprNode_free (exprNode e)
376 if (!exprNode_isError (e))
380 multiVal_free (e->val);
381 cstring_free (e->etext);
382 fileloc_free (e->loc);
383 sRefSet_free (e->uses);
384 sRefSet_free (e->sets);
385 sRefSet_free (e->msets);
386 guardSet_free (e->guards);
387 exprData_free (e->edata, e->kind);
389 constraintList_free(e->requiresConstraints);
390 constraintList_free(e->ensuresConstraints);
391 constraintList_free(e->trueEnsuresConstraints);
392 constraintList_free(e->falseEnsuresConstraints);
394 e->requiresConstraints = NULL;
395 e->ensuresConstraints = NULL;
396 e->trueEnsuresConstraints = NULL;
397 e->falseEnsuresConstraints = NULL;
407 exprNode_makeError ()
409 return exprNode_undefined;
412 static /*@out@*/ /*@only@*/ /*@notnull@*/ exprNode
415 exprNode ret = (exprNode) dmalloc (sizeof (*ret));
416 /* static int lastexpnodes = 0; */
421 if (nowalloc > maxalloc)
429 static /*@notnull@*/ /*@special@*/ exprNode
430 exprNode_createPlain (ctype c)
432 /*@ensures isnull result->edata, result->loc, result->val, result->guards,
433 result->uses, result->sets, result->msets, result->etext @*/
436 exprNode e = exprNode_new ();
440 e->val = multiVal_undefined;
442 e->etext = cstring_undefined;
443 e->loc = fileloc_undefined;
444 e->guards = guardSet_undefined;
445 e->uses = sRefSet_undefined;
446 e->sets = sRefSet_undefined;
447 e->msets = sRefSet_undefined;
448 e->edata = exprData_undefined;
449 e->exitCode = XK_NEVERESCAPE;
451 e->mustBreak = FALSE;
452 e->isJumpPoint = FALSE;
454 exprNode_defineConstraints(e);
459 /*@observer@*/ exprNode exprNode_makeMustExit (void)
461 if (exprNode_isUndefined (mustExitNode))
463 mustExitNode = exprNode_createPlain (ctype_unknown);
464 mustExitNode->exitCode = XK_MUSTEXIT;
471 static /*@notnull@*/ /*@special@*/ exprNode exprNode_create (ctype c)
473 /*@post:isnull result->edata, result->guards, result->val,
474 result->uses, result->sets, result->msets@*/
477 exprNode e = exprNode_createPlain (c);
478 e->loc = fileloc_copy (g_currentloc);
482 static /*@notnull@*/ /*@special@*/ exprNode exprNode_createUnknown (void)
484 /*@post:isnull result->edata, result->guards,
485 result->uses, result->sets, result->msets@*/
488 return (exprNode_create (ctype_unknown));
491 static /*@notnull@*/ /*@special@*/ exprNode
492 exprNode_createLoc (ctype c, /*@keep@*/ fileloc loc)
494 /*@post:isnull result->edata, result->guards, result->val,
495 result->uses, result->sets, result->msets@*/
498 exprNode e = exprNode_createPlain (c);
504 exprNode_copySets (/*@special@*/ /*@notnull@*/ exprNode ret, exprNode e)
505 /*@defines ret->guards, ret->uses, ret->sets, ret->msets@*/
507 if (exprNode_isDefined (e))
509 ret->guards = guardSet_copy (e->guards);
510 ret->uses = sRefSet_newCopy (e->uses);
511 ret->sets = sRefSet_newCopy (e->sets);
512 ret->msets = sRefSet_newCopy (e->msets);
516 ret->guards = guardSet_undefined;
517 ret->uses = sRefSet_undefined;
518 ret->sets = sRefSet_undefined;
519 ret->msets = sRefSet_undefined;
523 static /*@notnull@*/ /*@special@*/ exprNode
524 exprNode_createPartialLocCopy (exprNode e, /*@only@*/ fileloc loc)
526 /*@post:isnull result->edata, result->etext@*/
529 exprNode ret = exprNode_new ();
531 if (exprNode_isError (e))
533 ret->typ = ctype_unknown;
534 ret->val = multiVal_undefined;
536 ret->guards = guardSet_undefined;
537 ret->uses = sRefSet_undefined;
538 ret->sets = sRefSet_undefined;
539 ret->msets = sRefSet_undefined;
544 ret->val = multiVal_copy (e->val);
546 ret->guards = guardSet_copy (e->guards);
547 ret->uses = sRefSet_newCopy (e->uses);
548 ret->sets = sRefSet_newCopy (e->sets);
549 ret->msets = sRefSet_newCopy (e->msets);
552 ret->kind = XPR_EMPTY;
554 ret->etext = cstring_undefined;
555 ret->exitCode = XK_NEVERESCAPE;
556 ret->canBreak = FALSE;
557 ret->mustBreak = FALSE;
558 ret->isJumpPoint = FALSE;
559 ret->edata = exprData_undefined;
561 exprNode_defineConstraints(ret);
567 static /*@notnull@*/ /*@special@*/ exprNode
568 exprNode_createPartialCopy (exprNode e)
570 /*@post:isnull result->edata, result->etext@*/
573 return (exprNode_createPartialLocCopy (e, fileloc_copy (exprNode_loc (e))));
576 static /*@notnull@*/ /*@special@*/ exprNode
577 exprNode_createPartialNVCopy (exprNode e)
579 /*@post:isnull result->edata, result->etext, result->val @*/
582 exprNode ret = exprNode_new ();
584 if (exprNode_isError (e))
586 ret->typ = ctype_unknown;
587 ret->loc = fileloc_undefined;
588 ret->guards = guardSet_undefined;
589 ret->uses = sRefSet_undefined;
590 ret->sets = sRefSet_undefined;
591 ret->msets = sRefSet_undefined;
596 ret->loc = fileloc_copy (e->loc);
597 ret->guards = guardSet_copy (e->guards);
598 ret->uses = sRefSet_newCopy (e->uses);
599 ret->sets = sRefSet_newCopy (e->sets);
600 ret->msets = sRefSet_newCopy (e->msets);
603 ret->val = multiVal_undefined;
604 ret->kind = XPR_EMPTY;
606 ret->etext = cstring_undefined;
607 ret->exitCode = XK_NEVERESCAPE;
608 ret->canBreak = FALSE;
609 ret->mustBreak = FALSE;
610 ret->isJumpPoint = FALSE;
611 ret->edata = exprData_undefined;
613 exprNode_defineConstraints(ret);
618 static /*@notnull@*/ /*@special@*/ exprNode
619 exprNode_createSemiCopy (exprNode e)
621 /*@post:isnull result->edata, result->etext, result->sets,
622 result->msets, result->uses, result->guards@*/
625 if (exprNode_isError (e))
627 return exprNode_createPlain (ctype_unknown);
631 exprNode ret = exprNode_new ();
634 ret->val = multiVal_copy (e->val);
635 ret->loc = fileloc_copy (e->loc);
636 ret->guards = guardSet_undefined;
637 ret->uses = sRefSet_undefined;
638 ret->sets = sRefSet_undefined;
639 ret->msets = sRefSet_undefined;
641 ret->kind = XPR_EMPTY;
643 ret->etext = cstring_undefined;
644 ret->exitCode = XK_NEVERESCAPE;
645 ret->canBreak = FALSE;
646 ret->mustBreak = FALSE;
647 ret->isJumpPoint = FALSE;
648 ret->edata = exprData_undefined;
650 exprNode_defineConstraints(ret);
657 exprNode_isNullValue (exprNode e)
659 if (exprNode_isDefined (e))
661 multiVal m = exprNode_getValue (e);
663 if (multiVal_isInt (m))
665 return (multiVal_forceInt (m) == 0);
673 exprNode_isUnknownConstant (/*@notnull@*/ exprNode e)
675 while (e->kind == XPR_PARENS)
677 e = exprData_getUopNode (e->edata);
678 llassert (exprNode_isDefined (e));
681 if (e->kind == XPR_CONST)
683 multiVal m = exprNode_getValue (e);
685 if (multiVal_isUnknown (m))
695 exprNode_numLiteral (ctype c, /*@temp@*/ cstring t,
696 /*@only@*/ fileloc loc, long val)
698 exprNode e = exprNode_createLoc (c, loc);
700 e->kind = XPR_NUMLIT;
702 llassert (multiVal_isUndefined (e->val));
703 e->val = multiVal_makeInt (val);
704 e->edata = exprData_makeLiteral (cstring_copy (t));
708 e->sref = sRef_makeUnknown ();
709 sRef_setDefNull (e->sref, e->loc);
712 DPRINTF (("Num lit: %s / %s", exprNode_unparse (e), ctype_unparse (exprNode_getType (e))));
717 exprNode_charLiteral (char c, cstring text, /*@only@*/ fileloc loc)
719 exprNode e = exprNode_createLoc (ctype_char, loc);
721 if (context_getFlag (FLG_CHARINTLITERAL))
723 e->typ = ctype_makeConj (ctype_char, ctype_int);
726 e->kind = XPR_NUMLIT;
727 e->val = multiVal_makeChar (c);
729 e->edata = exprData_makeLiteral (cstring_copy (text));
734 exprNode_floatLiteral (double d, ctype ct, cstring text, /*@only@*/ fileloc loc)
736 exprNode e = exprNode_createLoc (ct, loc);
738 e->kind = XPR_NUMLIT;
739 e->val = multiVal_makeDouble (d);
740 e->edata = exprData_makeLiteral (cstring_copy (text));
744 multiVal exprNode_getValue (exprNode e)
746 while (exprNode_isInParens (e)) {
747 if (e->edata != NULL) {
748 e = exprData_getUopNode (e->edata);
754 if (exprNode_isDefined (e)) {
757 return multiVal_undefined;
762 exprNode_combineLiterals (exprNode e, exprNode rest)
766 /* Both must be string literals. */
768 if (exprNode_isUndefined (rest) || exprNode_isUndefined (e))
770 exprNode_free (rest);
774 if (!exprNode_isStringLiteral (e))
778 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e),
779 exprNode_unparse (rest)),
781 exprNode_free (rest);
785 if (!exprNode_isStringLiteral (rest))
789 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e), exprNode_unparse (rest)),
792 exprNode_free (rest);
796 ns = cstring_concat (multiVal_forceString (exprNode_getValue (e)),
797 multiVal_forceString (exprNode_getValue (rest)));
799 multiVal_free (e->val);
800 exprData_free (e->edata, e->kind);
801 e->edata = exprData_makeLiteral (cstring_copy (ns));
802 e->val = multiVal_makeString (ns);
803 exprNode_free (rest);
808 exprNode_rawStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
810 exprNode e = exprNode_createLoc (ctype_string, loc);
811 int len = cstring_length (t);
813 if (context_getFlag (FLG_STRINGLITERALLEN))
815 if (len > context_getValue (FLG_STRINGLITERALLEN))
817 voptgenerror (FLG_STRINGLITERALLEN,
819 ("String literal length (%d) exceeds maximum "
820 "length (%d): \"%s\"",
822 context_getValue (FLG_STRINGLITERALLEN),
828 e->kind = XPR_STRINGLITERAL;
829 e->val = multiVal_makeString (cstring_copy (t));
830 e->edata = exprData_makeLiteral (t);
831 e->sref = sRef_makeConst (ctype_string);
833 if (context_getFlag (FLG_READONLYSTRINGS))
835 sRef_setAliasKind (e->sref, AK_STATIC, fileloc_undefined);
836 sRef_setExKind (e->sref, XO_OBSERVER, loc);
840 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
843 return (e); /* s released */
847 exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
849 int len = cstring_length (t) - 2;
850 char *ts = cstring_toCharsSafe (t);
851 char *s = cstring_toCharsSafe (cstring_create (len + 1));
853 llassert (*ts == '\"' && *(ts + len + 1) == '\"');
854 strncpy (s, ts+1, size_fromInt (len));
857 return exprNode_rawStringLiteral (cstring_fromCharsO (s), loc);
860 exprNode exprNode_fromUIO (cstring c)
862 fileloc loc = context_getSaveLocation ();
863 exprNode e = exprNode_createPlain (ctype_unknown);
867 if (fileloc_isUndefined (loc))
869 loc = fileloc_copy (g_currentloc);
872 e->loc = loc; /* save loc was mangled */
875 if (usymtab_exists (c))
877 uentry ue = usymtab_lookupEither (c);
879 if (uentry_isDatatype (ue)
880 && uentry_isSpecified (ue))
883 (message ("%q: Specified datatype %s used in code, but not defined. "
884 "(Cannot continue reasonably from this error.)",
885 fileloc_unparse (e->loc), c));
893 llassertprint (!usymtab_exists (c), ("Entry exists: %s", c));
896 ** was supercedeGlobalEntry...is this better?
899 if (!context_inIterEnd ())
901 if (context_inMacro ())
903 if (context_getFlag (FLG_UNRECOG))
907 message ("Unrecognized identifier in macro definition: %s", c), e->loc);
911 flagcode_recordSuppressed (FLG_UNRECOG);
917 (FLG_UNRECOG, message ("Unrecognized identifier: %s", c), e->loc);
921 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
923 /* No alias errors for unrecognized identifiers */
924 sRef_setAliasKind (e->sref, AK_ERROR, loc);
929 exprNode exprNode_createId (/*@observer@*/ uentry c)
931 if (uentry_isValid (c))
933 exprNode e = exprNode_new ();
935 e->typ = uentry_getType (c);
937 if (uentry_isFunction (c)
938 && !sRef_isLocalVar (uentry_getSref (c)))
940 e->sref = sRef_undefined;
944 e->sref = uentry_getSref (c);
947 if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
949 sRef_setDefined (e->sref, fileloc_undefined);
953 ** yoikes! leaving this out was a heinous bug...that would have been
954 ** caught if i had lclint working first. gag!
957 e->etext = cstring_undefined;
959 if (uentry_isEitherConstant (c))
962 e->val = multiVal_copy (uentry_getConstantValue (c));
967 e->val = multiVal_unknown ();
970 e->edata = exprData_makeId (c);
971 e->loc = context_getSaveLocation ();
973 if (fileloc_isUndefined (e->loc))
975 fileloc_free (e->loc);
976 e->loc = fileloc_copy (g_currentloc);
979 e->guards = guardSet_new ();
980 e->sets = sRefSet_new ();
981 e->msets = sRefSet_new ();
982 e->uses = sRefSet_new ();
984 /*> missing fields, detected by lclint <*/
985 e->exitCode = XK_NEVERESCAPE;
986 e->isJumpPoint = FALSE;
988 e->mustBreak = FALSE;
990 exprNode_defineConstraints(e);
996 return exprNode_createUnknown ();
1000 /*@notnull@*/ exprNode
1001 exprNode_fromIdentifier (/*@observer@*/ uentry c)
1005 if (context_justPopped ()) /* watch out! c could be dead */
1007 uentry ce = usymtab_lookupSafe (LastIdentifier ());
1009 if (uentry_isValid (ce))
1015 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
1019 ret = exprNode_fromIdentifierAux (c);
1024 static void exprNode_checkStringLiteralLength (ctype t1, exprNode e2)
1026 multiVal mval = exprNode_getValue (e2);
1030 if (ctype_isFixedArray (t1))
1032 int nelements = long_toInt (ctype_getArraySize (t1));
1034 llassert (multiVal_isString (mval));
1035 slit = multiVal_forceString (mval);
1036 len = cstring_length (slit);
1038 if (len == nelements)
1041 (FLG_STRINGLITNOROOM,
1042 message ("String literal with %d character%& "
1043 "is assigned to %s (no room for null terminator): %s",
1044 cstring_length (slit),
1046 exprNode_unparse (e2)),
1049 else if (len > nelements)
1052 (FLG_STRINGLITTOOLONG,
1053 message ("Stirng literal with %d character%& (counting null terminator) "
1054 "is assigned to %s (insufficient storage available): %s",
1055 cstring_length (slit),
1057 exprNode_unparse (e2)),
1060 else if (len < nelements - 1)
1063 (FLG_STRINGLITSMALLER,
1064 message ("String literal with %d character%& is assigned to %s (possible waste of storage): %s",
1065 cstring_length (slit),
1067 exprNode_unparse (e2)),
1077 static /*@only@*/ /*@notnull@*/ exprNode
1078 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
1080 exprNode e = exprNode_createId (c);
1083 uentry_setUsed (c, e->loc);
1085 if (uentry_isVar (c) && sRef_isFileOrGlobalScope (sr))
1087 checkGlobUse (c, FALSE, e);
1094 exprNode_isZero (exprNode e)
1096 if (exprNode_isDefined (e))
1098 multiVal m = exprNode_getValue (e);
1100 if (multiVal_isInt (m))
1102 return (multiVal_forceInt (m) == 0);
1110 exprNode_isNonNegative (exprNode e)
1112 if (exprNode_isDefined (e))
1114 multiVal m = exprNode_getValue (e);
1116 if (multiVal_isInt (m))
1118 return (multiVal_forceInt (m) >= 0);
1126 ** a[x] - uses a but NOT a[]
1127 ** result sref = a[] (set/use in assignment)
1129 ** The syntax x[a] is also legal in C, and has the same
1130 ** semantics. If ind is an array, and arr is an int, flip
1135 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
1138 ** error in arr, error propagates (no new messages)
1139 ** error in ind, assume valid and continue
1142 DPRINTF (("Array fetch: %s / %s",
1143 exprNode_unparse (e1), exprNode_unparse (e2)));
1145 if (exprNode_isError (e1))
1148 return (exprNode_makeError ());
1154 ctype carr = exprNode_getType (e1);
1155 ctype crarr = ctype_realType (carr);
1158 ** this sets up funny aliasing, that leads to spurious
1159 ** lclint errors. Hence, the i2 comments.
1162 /* evans 2001-09-09 added ctype_isKnown so there is no swap when e1 type is unknown */
1163 if (ctype_isKnown (crarr)
1164 && !ctype_isRealArray (crarr)
1165 && ctype_isRealNumeric (crarr)
1166 && !exprNode_isError (e2)
1167 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1172 carr = exprNode_getType (arr);
1173 crarr = ctype_realType (carr);
1181 DPRINTF (("arr: %s", exprNode_unparse (arr)));
1183 if (sRef_possiblyNull (arr->sref))
1185 if (!usymtab_isGuarded (arr->sref))
1187 if (optgenerror (FLG_NULLDEREF,
1188 message ("Index of %s pointer %q: %s",
1189 sRef_nullMessage (arr->sref),
1190 sRef_unparse (arr->sref),
1191 exprNode_unparse (arr)),
1194 DPRINTF (("ref: %s", sRef_unparseFull (arr->sref)));
1195 sRef_showNullInfo (arr->sref);
1197 /* suppress future messages */
1198 sRef_setNullError (arr->sref);
1203 if (exprNode_isError (ind))
1205 if ((ctype_isArrayPtr (crarr)
1206 && !ctype_isFunction (crarr))
1207 || ctype_isUnknown (carr))
1209 exprNode ret = exprNode_createPartialCopy (arr);
1211 if (ctype_isKnown (carr))
1213 ret->typ = ctype_baseArrayPtr (crarr);
1217 ret->typ = ctype_unknown;
1220 ret->sref = sRef_makeArrayFetch (arr->sref);
1222 ret->kind = XPR_FETCH;
1225 ** Because of funny aliasing (when arr and ind are
1226 ** flipped) spurious errors would be reported here.
1229 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1230 checkSafeUse (ret, arr->sref);
1235 voptgenerror (FLG_TYPE,
1236 message ("Array fetch from non-array (%t): %s[%s]", carr,
1237 exprNode_unparse (e1), exprNode_unparse (e2)),
1239 exprNode_free (arr);
1240 return (exprNode_makeError ());
1245 if (!ctype_isForceRealInt (&(ind->typ)))
1247 ctype rt = ctype_realType (ind->typ);
1249 if (ctype_isChar (rt))
1253 message ("Array fetch using non-integer, %t: %s[%s]",
1255 exprNode_unparse (e1), exprNode_unparse (e2)),
1258 else if (ctype_isEnum (rt))
1262 message ("Array fetch using non-integer, %t: %s[%s]",
1264 exprNode_unparse (e1), exprNode_unparse (e2)),
1271 message ("Array fetch using non-integer, %t: %s[%s]",
1273 exprNode_unparse (e1), exprNode_unparse (e2)),
1277 multiVal_free (ind->val);
1278 ind->val = multiVal_unknown ();
1281 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1283 exprNode ret = exprNode_createSemiCopy (arr);
1284 multiVal m = exprNode_getValue (ind);
1286 ret->typ = ctype_baseArrayPtr (crarr);
1287 ret->kind = XPR_FETCH;
1289 if (multiVal_isInt (m))
1291 int i = (int) multiVal_forceInt (m);
1293 if (sRef_isValid (arr->sref)) {
1294 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1296 ret->sref = sRef_undefined;
1301 ret->sref = sRef_makeArrayFetch (arr->sref);
1304 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1305 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1306 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1308 /* (see comment on spurious errors above) */
1309 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1311 exprNode_checkUse (ret, ind->sref, ind->loc);
1312 exprNode_checkUse (ret, arr->sref, arr->loc);
1318 if (ctype_isUnknown (carr))
1320 exprNode ret = exprNode_createPartialCopy (arr);
1322 ret->kind = XPR_FETCH;
1323 ret->typ = ctype_unknown;
1324 ret->sets = sRefSet_union (ret->sets, ind->sets);
1325 ret->msets = sRefSet_union (ret->msets, ind->msets);
1326 ret->uses = sRefSet_union (ret->uses, ind->uses);
1328 /* (see comment on spurious errors above) */
1329 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1331 exprNode_checkUse (ret, ind->sref, ind->loc);
1332 exprNode_checkUse (ret, arr->sref, arr->loc);
1339 message ("Array fetch from non-array (%t): %s[%s]", carr,
1340 exprNode_unparse (e1), exprNode_unparse (e2)),
1343 exprNode_free (arr);
1344 exprNode_free (ind);
1346 return (exprNode_makeError ());
1356 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1357 exprNodeList args, exprNode ret)
1359 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1363 ** checkPrintfArgs --- checks arguments for printf-like functions
1364 ** Arguments before ... have already been checked.
1365 ** The argument before the ... is a char *.
1366 ** argno is the format string argument.
1370 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1371 exprNodeList args, exprNode ret, int argno)
1374 ** the last argument before the elips is the format string
1379 int nargs = exprNodeList_size (args);
1380 uentryList params = uentry_getParams (fcn);
1384 ** These should be ensured by checkSpecialFunction
1387 llassert (uentryList_size (params) == argno + 1);
1388 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1390 a = exprNodeList_getN (args, argno - 1);
1391 formatloc = fileloc_copy (exprNode_loc (a));
1393 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1394 && exprNode_knownStringValue (a))
1396 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1397 char *code = format;
1400 nargs = exprNodeList_size (args);
1402 while ((code = strchr (code, '%')) != NULL)
1404 char *origcode = code;
1405 cstring codetext = cstring_newEmpty ();
1406 char key = *(++code);
1407 ctype modtype = ctype_int;
1408 bool modified = FALSE;
1410 fileloc_addColumn (formatloc, code - ocode);
1412 codetext = cstring_appendChar (codetext, key);
1415 while (isFlagKey (key))
1418 codetext = cstring_appendChar (codetext, key);
1419 fileloc_incColumn (formatloc);
1422 if (key == 'm') /* skipped in syslog */
1427 /* ignore field width */
1428 while (isdigit ((int) key) != 0)
1431 codetext = cstring_appendChar (codetext, key);
1432 fileloc_incColumn (formatloc);
1435 /* ignore precision */
1439 codetext = cstring_appendChar (codetext, key);
1440 fileloc_incColumn (formatloc);
1443 ** In printf, '*' means: read the next arg as an int for the
1444 ** field width. This seems to be missing from my copy of the
1445 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1446 ** later) but never does.
1451 ; /* don't do anything --- handle later */
1455 while (isdigit ((int) key) != 0)
1458 codetext = cstring_appendChar (codetext, key);
1459 fileloc_incColumn (formatloc);
1466 modtype = ctype_sint; /* short */
1468 codetext = cstring_appendChar (codetext, key);
1469 fileloc_incColumn (formatloc);
1471 else if (key == 'l' || key == 'L')
1473 modtype = ctype_lint; /* long */
1475 codetext = cstring_appendChar (codetext, key);
1476 fileloc_incColumn (formatloc);
1478 if (key == 'l' || key == 'L') {
1479 modtype = ctype_llint; /* long long */
1481 codetext = cstring_appendChar (codetext, key);
1482 fileloc_incColumn (formatloc);
1490 /* now, key = type of conversion to apply */
1492 fileloc_incColumn (formatloc);
1500 message ("No argument corresponding to %q format "
1501 "code %d (%%%s): \"%s\"",
1502 uentry_getName (fcn),
1504 cstring_fromChars (format)),
1507 if (fileloc_isDefined (formatloc)
1508 && context_getFlag (FLG_SHOWCOL))
1510 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1518 a = exprNodeList_getN (args, i);
1521 if (!exprNode_isError (a))
1527 case '*': /* int argument for fieldwidth */
1528 expecttype = ctype_int;
1529 *(--code) = '%'; /* convert it for next code */
1530 fileloc_subColumn (formatloc, 1);
1531 /*@switchbreak@*/ break;
1534 expecttype = ctype_combine (ctype_uint, modtype);
1535 /*@switchbreak@*/ break;
1537 case 'i': /* int argument */
1539 expecttype = ctype_combine (ctype_int, modtype);
1540 /*@switchbreak@*/ break;
1542 case 'x': /* unsigned int */
1544 expecttype = ctype_combine (ctype_uint, modtype);
1546 /*@switchbreak@*/ break;
1552 case 'f': /* double */
1553 expecttype = ctype_combine (ctype_double, modtype);
1554 /*@switchbreak@*/ break;
1556 case 'c': /* int converted to char (check its a char?) */
1557 expecttype = ctype_makeConj (ctype_int,
1558 ctype_makeConj (ctype_char,
1561 /* evans 2001-10-05 - changed to reflect correct ISO spec:
1562 int converted to char */
1564 /* expecttype = ctype_makeConj (ctype_char, ctype_uchar); */
1565 /*@switchbreak@*/ break;
1567 case 's': /* string */
1568 expecttype = ctype_string;
1569 /*@switchbreak@*/ break;
1572 while (((key = *(++code)) != ']')
1575 codetext = cstring_appendChar (codetext, key);
1576 fileloc_incColumn (formatloc);
1582 (message ("Bad character set format: %s",
1583 cstring_fromChars (origcode)));
1586 expecttype = ctype_string;
1587 /*@switchbreak@*/ break;
1589 case 'p': /* pointer */
1590 expecttype = ctype_makePointer (ctype_void);
1591 uentry_setDefState (regArg, SS_RELDEF); /* need not be defined */
1592 sRef_setPosNull (uentry_getSref (regArg), fileloc_undefined); /* could be null */
1593 /*@switchbreak@*/ break;
1595 case 'n': /* pointer to int, modified by call! */
1596 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1598 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1599 /*@switchbreak@*/ break;
1601 case 'm': /* in a syslog, it doesn't consume an argument */
1602 /* should check we're really doing syslog */
1604 /*@switchbreak@*/ break;
1608 expecttype = ctype_unknown;
1612 message ("Unrecognized format code: %s",
1613 cstring_fromChars (origcode)),
1614 fileloc_isDefined (formatloc)
1615 ? formatloc : g_currentloc);
1617 /*@switchbreak@*/ break;
1620 if (!(exprNode_matchArgType (expecttype, a)))
1622 if (ctype_isVoidPointer (expecttype)
1623 && ctype_isRealAbstract (a->typ)
1624 && (context_getFlag (FLG_ABSTVOIDP)))
1630 if (llgenformattypeerror
1631 (expecttype, exprNode_undefined,
1633 message ("Format argument %d to %q (%%%s) expects "
1636 uentry_getName (fcn),
1639 a->typ, exprNode_unparse (a)),
1642 if (fileloc_isDefined (formatloc)
1643 && context_getFlag (FLG_SHOWCOL))
1646 (cstring_makeLiteral
1647 ("Corresponding format code"),
1654 uentry_setType (regArg, expecttype);
1655 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1657 if (ctype_equal (expecttype, ctype_string))
1659 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1662 uentry_setType (regArg, ctype_unknown);
1663 uentry_fixupSref (regArg);
1667 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1678 cstring_free (codetext);
1683 voptgenerror (FLG_TYPE,
1684 message ("Format string for %q has %d arg%&, given %d",
1685 uentry_getName (fcn), i - argno, nargs - argno),
1691 /* no checking possible for compile-time unknown format strings */
1692 if (exprNode_isDefined (a))
1696 message ("Format string parameter to %s is not a compile-time constant: %s",
1697 exprNode_unparse (f),
1698 exprNode_unparse (a)),
1703 fileloc_free (formatloc);
1707 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1708 exprNodeList args, exprNode ret, int argno)
1712 int nargs = exprNodeList_size (args);
1713 uentryList params = uentry_getParams (fcn);
1717 ** These should be ensured by checkSpecialFunction
1720 llassert (uentryList_size (params) == argno + 1);
1721 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1723 a = exprNodeList_getN (args, argno - 1);
1724 formatloc = fileloc_copy (exprNode_loc (a));
1726 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1727 && exprNode_knownStringValue (a))
1729 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1730 char *code = format;
1733 nargs = exprNodeList_size (args);
1735 while ((code = strchr (code, '%')) != NULL)
1737 char *origcode = code;
1738 char key = *(++code);
1739 cstring codetext = cstring_newEmpty ();
1740 ctype modtype = ctype_int;
1741 char modifier = '\0';
1742 bool modified = TRUE;
1743 bool ignore = FALSE;
1745 codetext = cstring_appendChar (codetext, key);
1746 fileloc_addColumn (formatloc, code - ocode);
1749 ** this is based on ANSI standard library description of fscanf
1750 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1753 /* '*' suppresses assignment (does not need match argument) */
1758 codetext = cstring_appendChar (codetext, key);
1761 fileloc_incColumn (formatloc);
1764 /* ignore field width */
1765 while (isdigit ((int) key) != 0)
1768 codetext = cstring_appendChar (codetext, key);
1769 fileloc_incColumn (formatloc);
1774 modtype = ctype_sint; /* short */
1776 codetext = cstring_appendChar (codetext, key);
1777 fileloc_incColumn (formatloc);
1779 else if (key == 'l' || key == 'L')
1781 modtype = ctype_lint; /* long */
1785 codetext = cstring_appendChar (codetext, key);
1787 fileloc_incColumn (formatloc);
1789 if (key == 'l' || key == 'L') {
1790 modtype = ctype_llint; /* long long */
1792 codetext = cstring_appendChar (codetext, key);
1793 fileloc_incColumn (formatloc);
1801 /* now, key = type of conversion to apply */
1803 fileloc_incColumn (formatloc);
1817 message ("No argument corresponding to %q format "
1818 "code %d (%%%s): \"%s\"",
1819 uentry_getName (fcn),
1821 cstring_fromChars (format)),
1824 if (fileloc_isDefined (formatloc)
1825 && context_getFlag (FLG_SHOWCOL))
1828 (cstring_makeLiteral ("Corresponding format code"),
1836 a = exprNodeList_getN (args, i);
1839 if (!exprNode_isError (a))
1845 case '*': /* int argument for fieldwidth */
1846 expecttype = ctype_makePointer (ctype_int);
1847 *(--code) = '%'; /* convert it for next code */
1848 fileloc_subColumn (formatloc, 1);
1849 /*@switchbreak@*/ break;
1852 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1853 /*@switchbreak@*/ break;
1858 case 'X': /* unsigned int */
1859 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1860 /*@switchbreak@*/ break;
1867 /* printf is double, scanf is float! */
1869 if (modifier == 'l')
1871 expecttype = ctype_makePointer (ctype_double);
1873 else if (modifier == 'L')
1875 expecttype = ctype_makePointer (ctype_ldouble);
1879 llassert (modifier == '\0');
1880 expecttype = ctype_makePointer (ctype_float);
1882 /*@switchbreak@*/ break;
1884 case 'c': /* int converted to char (check its a char?) */
1885 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1886 /*@switchbreak@*/ break;
1888 case 's': /* string */
1889 expecttype = ctype_string;
1890 /*@switchbreak@*/ break;
1894 while (((key = *(++code)) != ']')
1897 codetext = cstring_appendChar (codetext, key);
1898 fileloc_incColumn (formatloc);
1904 (message ("Bad character set format: %s",
1905 cstring_fromChars (origcode)));
1908 expecttype = ctype_string;
1909 /*@switchbreak@*/ break;
1912 case 'p': /* pointer */
1915 message ("Format code should not be used in scanf: %s",
1916 cstring_fromChars (origcode)),
1917 fileloc_isDefined (formatloc)
1918 ? formatloc : g_currentloc);
1920 expecttype = ctype_unknown;
1921 /*@switchbreak@*/ break;
1923 case 'n': /* pointer to int, modified by call! */
1924 expecttype = ctype_makePointer (ctype_int);
1925 /*@switchbreak@*/ break;
1928 expecttype = ctype_unknown;
1932 message ("Unrecognized format code: %s",
1933 cstring_fromChars (origcode)),
1934 fileloc_isDefined (formatloc)
1935 ? formatloc : g_currentloc);
1937 /*@switchbreak@*/ break;
1940 if (!(exprNode_matchArgType (expecttype, a)))
1942 if (ctype_isVoidPointer (expecttype)
1943 && ctype_isRealAbstract (a->typ)
1944 && (context_getFlag (FLG_ABSTVOIDP)))
1950 if (llgenformattypeerror
1951 (expecttype, exprNode_undefined,
1953 message ("Format argument %d to %q (%%%s) expects "
1956 uentry_getName (fcn),
1957 codetext, expecttype,
1958 a->typ, exprNode_unparse (a)),
1961 if (fileloc_isDefined (formatloc)
1962 && context_getFlag (FLG_SHOWCOL))
1965 (cstring_makeLiteral
1966 ("Corresponding format code"),
1973 uentry_setType (outArg, expecttype);
1974 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
1975 uentry_setType (outArg, ctype_unknown);
1976 uentry_fixupSref (outArg);
1980 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1985 /* a->sref = defref; */
1992 cstring_free (codetext);
1997 voptgenerror (FLG_TYPE,
1998 message ("Format string for %q has %d arg%&, given %d",
1999 uentry_getName (fcn), i - argno, nargs - argno),
2005 /* no checking possible for compile-time unknown format strings */
2008 fileloc_free (formatloc);
2012 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
2015 /*@unused@*/ int argno)
2018 ** the last argument before the elips is the format string
2021 int nargs = exprNodeList_size (args);
2026 a = exprNodeList_getN (args, argno - 1);
2027 formatloc = fileloc_copy (exprNode_loc (a));
2029 if (ctype_isUnknown (cstringType)) {
2030 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
2032 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
2036 if (ctype_isUnknown (ctypeType)) {
2037 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
2039 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
2043 if (ctype_isUnknown (filelocType)) {
2044 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
2046 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
2050 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
2051 && exprNode_knownStringValue (a))
2053 cstring format = multiVal_forceString (exprNode_getValue (a));
2054 char *code = cstring_toCharsSafe (format);
2057 nargs = exprNodeList_size (args);
2059 while ((code = strchr (code, '%')) != NULL)
2061 char *origcode = code;
2062 char key = *(++code);
2063 cstring codetext = cstring_newEmpty ();
2064 bool isOnly = FALSE;
2066 codetext = cstring_appendChar (codetext, key);
2068 fileloc_addColumn (formatloc, code - ocode);
2070 while (key >= '0' && key <= '9')
2073 codetext = cstring_appendChar (codetext, key);
2074 fileloc_incColumn (formatloc);
2078 fileloc_incColumn (formatloc);
2082 if (key == '&') /* plural marker */
2091 message ("Message missing format arg %d (%%%s): \"%s\"",
2092 i + 1, codetext, format),
2098 a = exprNodeList_getN (args, i);
2102 if (!exprNode_isError (a))
2106 /*@-loopswitchbreak@*/
2112 expecttype = ctype_char; break;
2114 expecttype = cstringType; break;
2116 expecttype = cstringType; isOnly = TRUE; break;
2118 expecttype = cstringType; isOnly = TRUE; break;
2119 case 'd': expecttype = ctype_int; break;
2120 case 'u': expecttype = ctype_uint; break;
2121 case 'w': expecttype = ctype_ulint; break;
2122 case 'f': expecttype = ctype_float; break;
2123 case 'b': expecttype = ctype_bool; break;
2124 case 't': expecttype = ctypeType; break;
2125 case 'l': expecttype = filelocType; break;
2126 case '&': /* a wee bit of a hack methinks */
2127 expecttype = ctype_int;
2129 case 'r': expecttype = ctype_bool; break;
2131 expecttype = ctype_unknown;
2134 message ("Unrecognized format code: %s",
2135 cstring_fromChars (origcode)),
2136 fileloc_isDefined (formatloc)
2137 ? formatloc : g_currentloc);
2140 /*@=loopswitchbreak@*/
2142 if (!(exprNode_matchArgType (expecttype, a)))
2144 if (ctype_isVoidPointer (expecttype)
2145 && ctype_isRealAbstract (a->typ)
2146 && (context_getFlag (FLG_ABSTVOIDP)))
2152 if (llgenformattypeerror
2153 (expecttype, exprNode_undefined,
2155 message ("Format argument %d to %q (%%%s) expects "
2158 uentry_getName (fcn),
2159 codetext, expecttype,
2160 a->typ, exprNode_unparse (a)),
2163 if (fileloc_isDefined (formatloc)
2164 && context_getFlag (FLG_SHOWCOL))
2167 (cstring_makeLiteral
2168 ("Corresponding format code"),
2175 if (ctype_equal (expecttype, cstringType))
2179 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2180 uentry_fixupSref (csOnlyArg);
2184 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2185 uentry_fixupSref (csArg);
2190 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2191 uentry_fixupSref (regArg);
2197 cstring_free (codetext);
2202 voptgenerror (FLG_TYPE,
2203 message ("Format string for %q has %d arg%&, given %d",
2204 uentry_getName (fcn), i - argno, nargs -argno),
2210 /* no checking possible for compile-time unknown format strings */
2213 fileloc_free (formatloc);
2217 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2218 /*@notnull@*/ exprNode e2,
2224 bool hadUncon = FALSE;
2226 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
2227 sRefSet_hasUnconstrained (sets2))
2230 (FLG_EVALORDERUNCON,
2232 ("Expression may have undefined behavior (%q used in right operand "
2233 "may set global variable %q used in left operand): %s %s %s",
2234 sRefSet_unparseUnconstrained (sets2),
2235 sRef_unparse (sRef_getRootBase (e1->sref)),
2236 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2240 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
2241 sRefSet_hasUnconstrained (sets1))
2244 (FLG_EVALORDERUNCON,
2246 ("Expression has undefined behavior (%q used in left operand "
2247 "may set global variable %q used in right operand): %s %s %s",
2248 sRefSet_unparseUnconstrained (sets1),
2249 sRef_unparse (e2->sref),
2250 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2254 sRefSet_realElements (e1->uses, sr)
2256 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2261 ("Expression has undefined behavior (left operand uses %q, "
2262 "modified by right operand): %s %s %s",
2264 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2267 } end_sRefSet_realElements;
2269 sRefSet_realElements (sets1, sr)
2271 if (sRef_isMeaningful (sr))
2273 if (sRef_same (sr, e2->sref))
2278 ("Expression has undefined behavior (value of right operand "
2279 "modified by left operand): %s %s %s",
2280 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2283 else if (sRefSet_member (e2->uses, sr))
2288 ("Expression has undefined behavior (left operand modifies %q, "
2289 "used by right operand): %s %s %s",
2291 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2296 if (sRefSet_member (sets2, sr))
2298 if (sRef_isUnconstrained (sr))
2306 hadUncon = optgenerror
2307 (FLG_EVALORDERUNCON,
2309 ("Expression may have undefined behavior. Left operand "
2310 "calls %q; right operand calls %q. The unconstrained "
2311 "functions may modify global state used by "
2312 "the other operand): %s %s %s",
2313 sRefSet_unparseUnconstrained (sets1),
2314 sRefSet_unparseUnconstrained (sets2),
2315 exprNode_unparse (e1), lltok_unparse (op),
2316 exprNode_unparse (e2)),
2325 ("Expression has undefined behavior (both "
2326 "operands modify %q): %s %s %s",
2328 exprNode_unparse (e1),
2329 lltok_unparse (op), exprNode_unparse (e2)),
2335 } end_sRefSet_realElements;
2338 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2340 bool hasError = FALSE;
2342 if (exprNode_isError (e1) || exprNode_isError (e2))
2347 if (sRefSet_member (e2->sets, e1->sref))
2349 if (e2->kind == XPR_CALL)
2355 hasError = optgenerror
2357 message ("Expression has undefined behavior "
2358 "(value of left operand %s is modified "
2359 "by right operand %s): %s %s %s",
2360 exprNode_unparse (e1),
2361 exprNode_unparse (e2),
2362 exprNode_unparse (e1), lltok_unparse (op),
2363 exprNode_unparse (e2)),
2368 if (context_getFlag (FLG_EVALORDERUNCON))
2370 if (sRefSet_member (e2->msets, e1->sref))
2372 if (e2->kind == XPR_CALL)
2378 hasError = optgenerror
2381 ("Expression has undefined behavior (value of left "
2382 "operand may be modified by right operand): %s %s %s",
2383 exprNode_unparse (e1), lltok_unparse (op),
2384 exprNode_unparse (e2)),
2392 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2394 if (context_maybeSet (FLG_EVALORDERUNCON))
2396 checkExpressionDefinedAux (e1, e2, e1->msets,
2397 e2->msets, op, FLG_EVALORDERUNCON);
2402 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2405 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2406 exprNodeList args, bool isIter, exprNode ret)
2410 if (!exprNode_isError (f))
2412 if (!uentryList_isMissingParams (cl))
2414 int nargs = exprNodeList_size (args);
2415 int expectargs = uentryList_size (cl);
2419 if (expectargs == 0)
2427 message ("Iter %q invoked with %d args, "
2429 uentry_getName (fcn),
2437 message ("Function %s called with %d args, "
2439 exprNode_unparse (f), nargs),
2446 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2448 exprNodeList_reset (args);
2450 uentryList_elements (cl, current)
2452 ctype ct = uentry_getType (current);
2455 if (ctype_isElips (ct))
2458 ** do special checking for printf/scanf library functions
2460 ** this is kludgey code, just for handling the special case
2464 if (uentry_isPrintfLike (fcn))
2466 checkPrintfArgs (f, fcn, args, ret, i);
2469 else if (uentry_isScanfLike (fcn))
2471 checkScanfArgs (f, fcn, args, ret, i);
2474 else if (uentry_isMessageLike (fcn))
2476 checkMessageArgs (f, fcn, args, i);
2481 llassert (!uentry_isSpecialFunction (fcn));
2484 nargs = expectargs; /* avoid errors */
2489 if (i >= nargs) break;
2491 a = exprNodeList_current (args);
2492 exprNodeList_advance (args);
2496 if (exprNode_isError (a))
2503 probably necessary? I'm not sure about this one
2504 checkMacroParen (a);
2507 f->guards = guardSet_union (f->guards, a->guards);
2509 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2511 if (!(exprNode_matchArgType (ct, a)))
2513 DPRINTF (("Args mismatch!"));
2515 if (ctype_isVoidPointer (ct)
2516 && (ctype_isPointer (a->typ)
2517 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2522 ("Pointer to abstract type (%t) used "
2524 "(arg %d to %q): %s",
2526 uentry_getName (fcn),
2527 exprNode_unparse (a)),
2535 (ct, exprNode_undefined,
2538 ("Iter %q expects arg %d to "
2539 "be %t gets %t: %s",
2540 uentry_getName (fcn),
2541 i, ct, a->typ, exprNode_unparse (a)),
2552 ("Function %q expects arg %d to be %t gets %t: %s",
2553 uentry_getName (fcn),
2554 i, ct, a->typ, exprNode_unparse (a)),
2557 DPRINTF (("Types: %s / %s",
2559 ctype_unparse (a->typ)));
2563 ** Clear null marker for abstract types.
2564 ** (It is not revealed, so suppress future messages.)
2567 if (ctype_isAbstract (a->typ))
2569 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2576 } end_uentryList_elements ;
2579 if (expectargs != nargs) /* note: not != since we may have ... */
2581 if (ctype_isElips (last))
2585 message ("Function %s called with %d args, expects at least %d",
2586 exprNode_unparse (f),
2587 nargs, expectargs - 1),
2596 message ("Iter %q invoked with %d args, expects %d",
2597 uentry_getName (fcn), nargs, expectargs),
2604 message ("Function %s called with %d args, expects %d",
2605 exprNode_unparse (f),
2618 ** Check for undefined code sequences in function arguments:
2620 ** one parameter sets something used by another parameter
2621 ** one parameter sets something set by another parameter
2625 checkSequencingOne (exprNode f, exprNodeList args,
2626 /*@notnull@*/ exprNode el, int argno)
2629 ** Do second loop, iff +undefunspec
2633 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2635 for (checkloop = 0; checkloop < numloops; checkloop++)
2641 thissets = el->sets;
2645 llassert (checkloop == 1);
2646 thissets = el->msets;
2649 sRefSet_realElements (thissets, thisset)
2653 /*@access exprNodeList@*/
2654 for (j = 0; j < args->nelements; j++)
2656 exprNode jl = args->elements[j];
2657 int thisargno = j + 1;
2659 if (thisargno != argno && exprNode_isDefined (jl))
2661 sRefSet otheruses = jl->uses;
2663 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
2664 sRefSet_hasUnconstrained (thissets))
2667 (FLG_EVALORDERUNCON,
2670 ("%q used in argument %d may set "
2671 "global variable %q used by argument %d: %s(%q)",
2672 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2675 sRef_unparse (sRef_getRootBase (jl->sref)),
2677 exprNode_unparse (f), exprNodeList_unparse (args)),
2681 if (sRefSet_member (otheruses, thisset))
2683 if (sRef_isUnconstrained (thisset))
2686 (FLG_EVALORDERUNCON,
2688 ("Unconstrained functions used in arguments %d (%q) "
2689 "and %d (%s) may modify "
2690 "or use global state in undefined way: %s(%q)",
2692 sRefSet_unparseUnconstrainedPlain (otheruses),
2694 sRef_unconstrainedName (thisset),
2695 exprNode_unparse (f),
2696 exprNodeList_unparse (args)),
2704 ("Argument %d modifies %q, used by argument %d "
2705 "(order of evaluation of actual parameters is "
2706 "undefined): %s(%q)",
2707 argno, sRef_unparse (thisset), thisargno,
2708 exprNode_unparse (f), exprNodeList_unparse (args)),
2714 sRefSet othersets = jl->sets;
2716 if (sRefSet_member (othersets, thisset))
2718 if (sRef_isUnconstrained (thisset))
2721 (FLG_EVALORDERUNCON,
2723 ("Unconstrained functions used in "
2724 "arguments %d (%q) and %d (%s) may modify "
2725 "or use global state in undefined way: %s(%q)",
2727 sRefSet_unparseUnconstrainedPlain (othersets),
2729 sRef_unconstrainedName (thisset),
2730 exprNode_unparse (f), exprNodeList_unparse (args)),
2738 ("Argument %d modifies %q, set by argument %d (order of"
2739 " evaluation of actual parameters is undefined): %s(%q)",
2740 argno, sRef_unparse (thisset), thisargno,
2741 exprNode_unparse (f), exprNodeList_unparse (args)),
2748 /*@noaccess exprNodeList@*/
2749 } end_sRefSet_realElements;
2754 checkSequencing (exprNode f, exprNodeList args)
2756 if (exprNodeList_size (args) > 1)
2761 /*@access exprNodeList*/
2763 for (i = 0; i < args->nelements; i++)
2765 el = args->elements[i];
2767 if (!exprNode_isError (el))
2769 checkSequencingOne (f, args, el, i + 1);
2772 /*@noaccess exprNodeList*/
2777 ** requires le = exprNode_getUentry (f)
2781 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2782 uentry le, exprNodeList args,
2783 /*@notnull@*/ exprNode ret, int specialArgs)
2785 bool isSpec = FALSE;
2786 bool hasMods = FALSE;
2788 globSet usesGlobs = globSet_undefined;
2789 sRefSet mods = sRefSet_undefined;
2790 bool freshMods = FALSE;
2791 uentryList params = uentryList_undefined;
2793 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2796 ** check globals and modifies
2801 if (!uentry_isValid (le))
2803 ctype fr = ctype_realType (f->typ);
2805 if (ctype_isFunction (fr))
2807 params = ctype_argsFunction (fr);
2811 params = uentryList_missingParams;
2814 if (!context_getFlag (FLG_MODNOMODS)
2815 && !context_getFlag (FLG_GLOBUNSPEC))
2817 checkUnspecCall (f, params, args);
2823 fname = uentry_rawName (le);
2827 if (uentry_isFunction (le))
2829 params = uentry_getParams (le);
2830 mods = uentry_getMods (le);
2831 hasMods = uentry_hasMods (le);
2832 usesGlobs = uentry_getGlobs (le);
2833 isSpec = uentry_isSpecified (le);
2835 else /* not a function */
2837 ctype ct = ctype_realType (uentry_getType (le));
2839 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2840 ("checkModGlobs: uentry not a function: %s",
2841 uentry_unparse (le)));
2843 params = ctype_argsFunction (ct);
2844 return; /*@32 ! remove this? */
2853 globSet_allElements (usesGlobs, el)
2855 if (sRef_isValid (el))
2857 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2859 context_usedGlobal (el);
2860 exprNode_checkUse (f, el, f->loc);
2862 if (context_checkInternalUse ())
2864 if (!context_globAccess (el))
2866 if (sRef_isSystemState (el)
2867 && !context_getFlag (FLG_MODFILESYSTEM))
2876 ("Called procedure %s may access %q, but "
2877 "globals list does not include globals %s",
2878 exprNode_unparse (f),
2880 cstring_makeLiteralTemp (sRef_isInternalState (el)
2888 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2894 uentry gle = sRef_getUentry (el);
2895 sRef sr = sRef_updateSref (el);
2897 if (sRef_isUndefGlob (el))
2899 sRef_setDefined (sr, f->loc);
2900 exprNode_checkSet (f, sr);
2908 if (sRef_isAllocated (el))
2910 exprNode_checkSet (f, sr);
2914 if (sRef_isStateUndefined (sr))
2919 ("%s %q used by function undefined before call: %s",
2920 sRef_getScopeName (sr),
2922 exprNode_unparse (f)),
2924 sRef_setDefined (sr, f->loc);
2926 exprNode_checkUse (f, sr, f->loc);
2929 checkGlobUse (gle, TRUE, f);
2932 if (sRef_isKilledGlob (el))
2934 sRef_kill (sr, f->loc);
2935 context_usedGlobal (sr);
2939 } end_globSet_allElements;
2945 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
2947 sRefSet smods = sRefSet_undefined;
2950 ** NEED to check for modifies anything
2954 ** check each sRef that called function modifies (ml), is
2960 sRefSet_allElements (mods, s) /* s is something which may be modified */
2962 DPRINTF (("Check modify: %s", sRef_unparse (s)));
2964 if (sRef_isKindSpecial (s))
2966 if (sRef_isSpecInternalState (s))
2968 if (context_getFlag (FLG_MODINTERNALSTRICT))
2970 exprNode_checkCallModifyVal (s, args, f, ret);
2974 sRefSet mmods = context_modList ();
2976 sRefSet_allElements (mmods, el)
2978 if (sRef_isInternalState (el))
2980 sRef_setModified (el);
2982 } end_sRefSet_allElements ;
2987 exprNode_checkCallModifyVal (s, args, f, ret);
2992 sRef rb = sRef_getRootBase (s);
2994 if (sRef_isFileOrGlobalScope (rb))
2996 context_usedGlobal (rb);
2999 if (sRef_isFileStatic (s)
3000 && !fileId_equal (fileloc_fileId (f->loc),
3001 fileloc_fileId (uentry_whereDefined (le))))
3003 smods = sRefSet_insert (smods, s);
3007 exprNode_checkCallModifyVal (s, args, f, ret);
3010 } end_sRefSet_allElements;
3015 ** Static elements in modifies set can have nasty consequences.
3016 ** (I think...have not been able to reproduce a possible bug.)
3019 if (!sRefSet_isDefined (smods))
3021 mods = sRefSet_newCopy (mods);
3024 sRefSet_allElements (smods, el)
3026 bool res = sRefSet_delete (mods, el);
3029 } end_sRefSet_allElements;
3031 sRefSet_free (smods);
3036 else if (sRefSet_isDefined (mods))
3037 { /* just check observers */
3040 sRefSet_allElements (mods, s) /* s is something which may be modified */
3042 sRef rb = sRef_getRootBase (s);
3046 if (sRef_isParam (rb))
3048 sRef b = sRef_fixBaseParam (s, args);
3050 if (sRef_isObserver (b))
3052 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
3056 message ("Function call may modify observer%q: %s",
3057 sRef_unparsePreOpt (b), exprNode_unparse (e)),
3060 sRef_showExpInfo (b);
3064 } end_sRefSet_allElements;
3068 if (!hasMods) /* no specified modifications */
3070 if (context_getFlag (FLG_MODOBSERVERUNCON))
3072 exprNodeList_elements (args, e)
3074 if (exprNode_isDefined (e))
3076 sRef s = exprNode_getSref (e);
3078 if (sRef_isObserver (s)
3079 && ctype_isMutable (sRef_getType (s)))
3082 (FLG_MODOBSERVERUNCON,
3084 ("Call to unconstrained function %s may modify observer%q: %s",
3085 exprNode_unparse (f),
3086 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3089 sRef_showExpInfo (s);
3093 } end_exprNodeList_elements;
3098 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3100 ret->uses = sRefSet_union (ret->uses, f->uses);
3101 ret->sets = sRefSet_union (ret->sets, f->sets);
3102 ret->msets = sRefSet_union (ret->msets, f->msets);
3107 ** Spurious errors reported, because lclint can't tell
3108 ** mods must be fresh if freshMods is true.
3111 /*@i@*/ sRefSet_free (mods);
3117 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3119 if (uentry_isVar (glob))
3121 if (context_inFunctionLike ())
3123 sRef sr = uentry_getSref (glob);
3125 context_usedGlobal (sr);
3127 if (context_checkGlobUse (glob))
3129 if (!context_globAccess (sr))
3135 message ("Called procedure %s may access %s %q",
3136 exprNode_unparse (e),
3137 sRef_unparseScope (sr),
3138 uentry_getName (glob)),
3145 message ("Undocumented use of %s %s",
3146 sRef_unparseScope (sr),
3147 exprNode_unparse (e)),
3156 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3161 reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
3163 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3164 exprNode_unparse (f), exprNodeList_unparse (args),
3165 uentry_unparseFull (le),
3166 stateClauseList_unparse (uentry_getStateClauseList (le))));
3168 if (uentry_isValid (le) && uentry_isFunction (le))
3170 stateClauseList sclauses = uentry_getStateClauseList (le);
3172 if (stateClauseList_isDefined (sclauses))
3174 DPRINTF (("Reflect ensures: %s / %s / %s",
3175 uentry_unparse (le),
3176 exprNode_unparse (f), exprNodeList_unparse (args)));
3178 stateClauseList_elements (sclauses, cl)
3180 if (stateClause_hasEnsures (cl))
3182 /* Same in usymtab.c:1904 */
3183 if (stateClause_setsMetaState (cl))
3185 qual q = stateClause_getMetaQual (cl);
3186 annotationInfo ainfo = qual_getAnnotationInfo (q);
3187 metaStateInfo minfo = annotationInfo_getState (ainfo);
3188 cstring key = metaStateInfo_getName (minfo);
3189 int mvalue = annotationInfo_getValue (ainfo);
3191 sRefSet osrs = sRefSet_undefined;
3194 if (stateClause_isGlobal (cl))
3196 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3201 srs = stateClause_getRefs (cl);
3204 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3207 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3209 sRefSet_elements (srs, sel)
3213 if (sRef_isResult (sRef_getRootBase (sel)))
3215 s = exprNode_getSref (ret);
3219 s = sRef_fixBaseParam (sel, args);
3222 DPRINTF (("Reflecting state clause on: %s / %s",
3223 sRef_unparse (sel), sRef_unparse (s)));
3225 sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3226 } end_sRefSet_elements;
3228 sRefSet_free (osrs);
3232 sRefSet srs = stateClause_getRefs (cl);
3233 sRefModVal modf = stateClause_getEnsuresFunction (cl);
3234 int eparam = stateClause_getStateParameter (cl);
3236 DPRINTF (("Reflect after clause: %s / %s",
3237 stateClause_unparse (cl),
3238 sRefSet_unparse (srs)));
3240 sRefSet_elements (srs, sel)
3244 DPRINTF (("elements: %s", sRef_unparse (sel)));
3245 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3247 if (sRef_isResult (sRef_getRootBase (sel)))
3249 DPRINTF (("Fix base: %s / %s",
3250 sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
3251 s = sRef_fixBase (sel, exprNode_getSref (ret));
3252 DPRINTF (("==> %s", sRef_unparseFull (s)));
3256 s = sRef_fixBaseParam (sel, args);
3259 DPRINTF (("elements: %s", sRef_unparse (s)));
3260 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3262 DPRINTF (("Reflecting state clause on: %s / %s",
3263 sRef_unparseFull (sel), sRef_unparseFull (s)));
3265 /* evans 2001-08-24 - added aliasSetCompleteParam */
3266 sRef_aliasSetCompleteParam (modf, s, eparam, exprNode_loc (f));
3268 DPRINTF (("After reflecting state clause on: %s / %s",
3269 sRef_unparseFull (sel), sRef_unparseFull (s)));
3270 } end_sRefSet_elements;
3273 } end_stateClauseList_elements ;
3276 DPRINTF (("Here: %s / %s",
3277 uentry_unparseFull (le),
3278 bool_unparse (uentry_hasMetaStateEnsures (le))));
3280 if (uentry_hasMetaStateEnsures (le))
3282 fileloc loc = exprNode_loc (f);
3284 metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3286 metaStateConstraintList_elements (mscl, msc)
3288 metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3289 metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3290 metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
3291 cstring key = metaStateInfo_getName (msinfo);
3292 sRef mlsr = metaStateSpecifier_getSref (msspec);
3294 sRef lastref = sRef_undefined;
3295 stateValue sval = stateValue_undefined;
3297 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3298 metaStateConstraint_unparse (msc)));
3299 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3301 if (sRef_isResult (sRef_getRootBase (mlsr)))
3303 s = exprNode_getSref (ret);
3307 s = sRef_fixBaseParam (mlsr, args);
3310 DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3312 while (metaStateExpression_isDefined (msexpr))
3314 metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
3315 metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
3318 DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3320 if (metaStateExpression_isMerge (msexpr))
3322 msexpr = metaStateExpression_getRest (msexpr);
3326 msexpr = metaStateExpression_undefined;
3329 if (metaStateInfo_isDefined (msi))
3331 /* Must match lhs state */
3332 llassert (metaStateInfo_equal (msinfo, msi));
3335 if (metaStateSpecifier_isElipsis (ms))
3338 ** For elipsis, we need to merge all the relevant elipsis parameters
3342 uentryList params = uentry_getParams (le);
3343 int paramno = uentryList_size (params) - 1;
3345 if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
3349 message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3350 uentry_getName (le)),
3351 uentry_whereLast (le));
3352 /*@innerbreak@*/ break;
3355 while (paramno < exprNodeList_size (args))
3357 exprNode arg = exprNodeList_getN (args, paramno);
3358 fs = exprNode_getSref (arg);
3359 DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3361 /* cut and pasted... gack*/
3362 if (stateValue_isDefined (sval))
3364 /* Use combination table to merge old state value with new one: */
3365 stateValue tval = sRef_getMetaStateValue (fs, key);
3367 if (stateValue_isDefined (tval))
3369 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3370 cstring msg = cstring_undefined;
3371 int nval = stateCombinationTable_lookup (sctable,
3372 stateValue_getValue (sval),
3373 stateValue_getValue (tval),
3375 DPRINTF (("Combining: %s + %s -> %d",
3376 stateValue_unparseValue (sval, msinfo),
3377 stateValue_unparseValue (tval, msinfo),
3380 if (nval == stateValue_error)
3385 ("Attributes merged in ensures clause in states that "
3386 "cannot be combined (%q is %q, %q is %q)%q",
3387 sRef_unparse (lastref),
3388 stateValue_unparseValue (sval, msinfo),
3390 stateValue_unparseValue (tval, msinfo),
3391 cstring_isDefined (msg) ?
3392 message (": %s", msg) : cstring_undefined),
3395 sRef_showMetaStateInfo (fs, key);
3399 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3400 loc = exprNode_loc (arg);
3404 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3409 sval = sRef_getMetaStateValue (fs, key);
3414 if (stateValue_isError (sval))
3416 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3425 msr = metaStateSpecifier_getSref (ms);
3428 llassert (sRef_isParam (sRef_getRootBase (msr)));
3429 fs = sRef_fixBaseParam (msr, args);
3431 if (stateValue_isDefined (sval))
3433 /* Use combination table to merge old state value with new one: */
3434 stateValue tval = sRef_getMetaStateValue (fs, key);
3436 if (stateValue_isDefined (tval))
3438 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3439 cstring msg = cstring_undefined;
3440 int nval = stateCombinationTable_lookup (sctable,
3441 stateValue_getValue (sval),
3442 stateValue_getValue (tval),
3444 DPRINTF (("Combining: %s + %s -> %d",
3445 stateValue_unparseValue (sval, msinfo),
3446 stateValue_unparseValue (tval, msinfo),
3449 if (nval == stateValue_error)
3454 ("Attributes merged in ensures clause in states that "
3455 "cannot be combined (%q is %q, %q is %q)%q",
3456 sRef_unparse (lastref),
3457 stateValue_unparseValue (sval, msinfo),
3459 stateValue_unparseValue (tval, msinfo),
3460 cstring_isDefined (msg)
3461 ? message (": %s", msg) : cstring_undefined),
3464 sRef_showMetaStateInfo (fs, key);
3468 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3472 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3477 sval = sRef_getMetaStateValue (fs, key);
3482 if (stateValue_isError (sval))
3484 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3489 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3491 if (stateValue_isDefined (sval))
3493 sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
3497 DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
3499 } end_metaStateConstraintList_elements ;
3501 metaStateConstraintList_free (mscl);
3507 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3509 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3510 exprNode_unparse (f), exprNodeList_unparse (args),
3511 uentry_unparseFull (le),
3512 stateClauseList_unparse (uentry_getStateClauseList (le))));
3514 if (uentry_isValid (le) && uentry_isFunction (le))
3516 stateClauseList sclauses = uentry_getStateClauseList (le);
3518 if (stateClauseList_isDefined (sclauses))
3520 DPRINTF (("Check requires: %s / %s / %s",
3521 uentry_unparse (le),
3522 exprNode_unparse (f), exprNodeList_unparse (args)));
3524 stateClauseList_elements (sclauses, cl)
3526 DPRINTF (("Check clause: %s / %s",
3527 stateClause_unparse (cl),
3528 bool_unparse (stateClause_hasRequires (cl))));
3530 if (stateClause_hasRequires (cl))
3532 sRefSet osrs = sRefSet_undefined;
3535 if (stateClause_isGlobal (cl))
3537 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3542 srs = stateClause_getRefs (cl);
3545 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3547 if (stateClause_setsMetaState (cl))
3549 qual q = stateClause_getMetaQual (cl);
3550 annotationInfo ainfo = qual_getAnnotationInfo (q);
3551 metaStateInfo minfo = annotationInfo_getState (ainfo);
3552 cstring key = metaStateInfo_getName (minfo);
3553 int mvalue = annotationInfo_getValue (ainfo);
3555 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3557 sRefSet_elements (srs, sel)
3559 sRef s = sRef_fixBaseParam (sel, args);
3561 if (sRef_isResult (sRef_getRootBase (sel)))
3567 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3568 sRef_unparseFull (sel), sRef_unparseFull (s),
3571 if (!sRef_checkMetaStateValue (s, key, mvalue))
3573 DPRINTF (("HERE: %s", sRef_unparse (s)));
3577 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3578 uentry_getName (le),
3579 sRef_isGlobalMarker (s)
3581 : message (" by %q", sRef_unparse (s)),
3582 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3584 stateClause_unparse (cl)),
3587 sRef_showAliasInfo (s);
3591 DPRINTF (("Error supressed!"));
3592 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3593 DPRINTF (("Context supress: %s",
3594 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3598 } end_sRefSet_elements;
3602 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3603 int eparam = stateClause_getStateParameter (cl);
3605 DPRINTF (("Reflect after clause: %s / %s",
3606 stateClause_unparse (cl),
3607 sRefSet_unparse (srs)));
3609 sRefSet_elements (srs, sel)
3613 DPRINTF (("elements: %s", sRef_unparse (sel)));
3614 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3616 s = sRef_fixBaseParam (sel, args);
3618 DPRINTF (("elements: %s", sRef_unparse (s)));
3619 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3621 if (sRef_isResult (sRef_getRootBase (sel)))
3623 ; /*@i423 what do we do about results */
3627 DPRINTF (("Reflecting state clause on: %s / %s",
3628 sRef_unparse (sel), sRef_unparse (s)));
3630 modf (s, eparam, exprNode_loc (f));
3632 } end_sRefSet_elements;
3635 sRefSet_free (osrs);
3637 } end_stateClauseList_elements ;
3642 static /*@only@*/ exprNode
3643 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3644 ctype t, /*@keep@*/ exprNodeList args)
3646 /* requires f is a non-error exprNode, with type function */
3647 cstring fname = exprNode_unparse (f);
3648 uentry le = exprNode_getUentry (f);
3649 exprNode ret = exprNode_createPartialCopy (f);
3654 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3656 ret->typ = ctype_getReturnType (t);
3657 ret->kind = XPR_CALL;
3659 ret->edata = exprData_makeCall (f, args);
3662 ** Order of these steps is very important!
3664 ** Must check for argument dependencies before messing up uses and sets.
3667 if (context_getFlag (FLG_EVALORDER))
3669 exprNodeList_elements (args, current)
3671 if (exprNode_isDefined (current))
3673 exprNode_addUse (current, current->sref);
3675 } end_exprNodeList_elements;
3677 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3679 checkSequencing (f, args);
3682 exprNodeList_elements (args, current)
3684 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3686 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3688 } end_exprNodeList_elements ;
3691 special = checkArgs (le, f, t, args, ret);
3692 checkGlobMods (f, le, args, ret, special);
3693 checkRequiresClause (le, f, args);
3696 if (uentry_isValid (le)
3697 && (uentry_isFunction (le)
3698 || (uentry_isVariable (le)
3699 && ctype_isFunction (uentry_getType (le)))))
3701 exitkind exk = uentry_getExitCode (le);
3703 /* f->typ is already set to the return type */
3705 DPRINTF (("Function: %s", uentry_unparseFull (le)));
3706 ret->sref = uentry_returnedRef (le, args);
3707 DPRINTF (("Returned: %s / %s",
3708 uentry_unparseFull (le),
3709 sRef_unparseFull (ret->sref)));
3711 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3713 qual nullPred = uentry_nullPred (le);
3715 if (qual_isTrueNull (nullPred))
3717 exprNode arg = exprNodeList_head (args);
3719 if (exprNode_isDefined (arg))
3721 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3724 else if (qual_isFalseNull (nullPred))
3726 exprNode arg = exprNodeList_head (args);
3728 if (exprNode_isDefined (arg))
3730 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3735 llassert (qual_isUnknown (nullPred));
3739 if (exitkind_isConditionalExit (exk))
3743 ** if (arg0) then { exit! } else { ; }
3745 ** if (arg0) then { ; } else { exit! }
3750 llassert (!exprNodeList_isEmpty (args));
3751 firstArg = exprNodeList_head (args);
3753 if (exprNode_isDefined (firstArg)
3754 && !guardSet_isEmpty (firstArg->guards))
3756 usymtab_trueBranch (guardSet_undefined);
3757 usymtab_altBranch (guardSet_undefined);
3759 if (exitkind_isTrueExit (exk))
3761 usymtab_popBranches (firstArg,
3762 exprNode_makeMustExit (),
3764 TRUE, TRUEEXITCLAUSE);
3768 usymtab_popBranches (firstArg,
3770 exprNode_makeMustExit (),
3771 TRUE, FALSEEXITCLAUSE);
3775 ret->exitCode = XK_MAYEXIT;
3777 else if (exitkind_mustExit (exk))
3779 ret->exitCode = XK_MUSTEXIT;
3781 else if (exitkind_couldExit (exk))
3783 ret->exitCode = XK_MAYEXIT;
3790 if (cstring_equalLit (fname, "exit"))
3792 if (exprNodeList_size (args) == 1)
3794 exprNode arg = exprNodeList_head (args);
3796 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3798 long int val = multiVal_forceInt (exprNode_getValue (arg));
3805 ("Argument to exit has implementation defined behavior: %s",
3806 exprNode_unparse (arg)),
3807 exprNode_loc (arg));
3816 exprNode_checkSetAny (ret, uentry_rawName (le));
3819 DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3820 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3821 reflectEnsuresClause (ret, le, f, args);
3828 ** this is yucky! should keep the uentry as part of exprNode!
3831 uentry exprNode_getUentry (exprNode e)
3833 if (exprNode_isError (e))
3835 return uentry_undefined;
3839 cstring s = exprNode_rootVarName (e);
3840 uentry ue = usymtab_lookupSafe (s);
3847 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3849 exprNode ret = exprNode_createPlain (ctype_unknown);
3851 ret->kind = XPR_INITBLOCK;
3852 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3853 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3859 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3865 if (exprNode_isUndefined (f))
3868 exprNodeList_free (args);
3869 return exprNode_undefined;
3872 t = exprNode_getType (f);
3874 if (sRef_isLocalVar (f->sref))
3876 exprNode_checkUse (f, f->sref, f->loc);
3878 if (sRef_possiblyNull (f->sref))
3880 if (!usymtab_isGuarded (f->sref))
3882 if (optgenerror (FLG_NULLDEREF,
3883 message ("Function call using %s pointer %q",
3884 sRef_nullMessage (f->sref),
3885 sRef_unparse (f->sref)),
3888 sRef_showNullInfo (f->sref);
3889 sRef_setNullError (f->sref);
3897 if (ctype_isRealFunction (t))
3899 exprNode ret = functionCallSafe (f, t, args);
3903 else if (ctype_isUnknown (t))
3905 exprNode ret = exprNode_createPartialCopy (f);
3911 exprNodeList_elements (args, current)
3913 if (exprNode_isDefined (current))
3915 exprNode_checkUse (ret, current->sref, ret->loc);
3918 ** also, anything derivable from current->sref may be used
3921 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3922 exprNode_mergeUSs (ret, current);
3924 } end_exprNodeList_elements;
3926 ret->edata = exprData_makeCall (f, args);
3927 ret->kind = XPR_CALL;
3929 tstring = cstring_copy (exprNode_unparse (f));
3931 cstring_markOwned (tstring);
3932 exprNode_checkSetAny (ret, tstring);
3938 voptgenerror (FLG_TYPE,
3939 message ("Call to non-function (type %t): %s", t,
3940 exprNode_unparse (f)),
3943 exprNodeList_free (args);
3945 return (exprNode_makeError ());
3950 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
3951 /*@only@*/ cstring f)
3953 exprNode ret = exprNode_createPartialCopy (s);
3955 ret->kind = XPR_FACCESS;
3957 if (exprNode_isError (s))
3959 ret->edata = exprData_makeField (s, f);
3964 ctype t = exprNode_getType (s);
3965 ctype tr = ctype_realType (t);
3967 checkMacroParen (s);
3969 ret->edata = exprData_makeField (s, f);
3971 if (ctype_isStructorUnion (tr))
3973 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
3975 if (uentry_isUndefined (tf))
3977 voptgenerror (FLG_TYPE,
3978 message ("Access non-existent field %s of %t: %s", f, t,
3979 exprNode_unparse (ret)),
3981 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
3986 uentry_setUsed (tf, exprNode_loc (ret));
3988 ret->typ = uentry_getType (tf);
3989 checkSafeUse (ret, s->sref);
3991 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
3992 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
3996 else /* isStructorUnion */
3998 if (ctype_isRealAbstract (tr))
4002 message ("Access field of abstract type (%t): %s.%s",
4003 t, exprNode_unparse (s), f),
4005 ret->typ = ctype_unknown;
4009 if (ctype_isKnown (tr))
4014 ("Access field of non-struct or union (%t): %s.%s",
4015 t, exprNode_unparse (s), f),
4018 ret->typ = ctype_unknown;
4022 cstring sn = cstring_copy (f);
4024 checkSafeUse (ret, s->sref);
4025 cstring_markOwned (sn);
4026 ret->sref = sRef_makeField (s->sref, sn);
4038 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
4039 /*@only@*/ cstring f)
4041 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
4042 lltok_release (dot);
4047 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
4049 exprNode ret = exprNode_createPartialCopy (e);
4051 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
4052 ret->kind = XPR_PARENS;
4053 ret->edata = exprData_makeUop (e, lpar);
4055 if (!exprNode_isError (e))
4057 ret->exitCode = e->exitCode;
4058 ret->canBreak = e->canBreak;
4059 ret->mustBreak = e->mustBreak;
4060 ret->isJumpPoint = e->isJumpPoint;
4061 ret->sref = e->sref;
4068 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4069 /*@only@*/ cstring f)
4071 exprNode ret = exprNode_createPartialCopy (s);
4073 ret->edata = exprData_makeField (s, f);
4074 ret->kind = XPR_ARROW;
4076 if (exprNode_isError (s))
4082 ctype t = exprNode_getType (s);
4083 ctype tr = ctype_realType (t);
4085 checkMacroParen (s);
4087 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4089 if (ctype_isRealPointer (tr))
4091 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4093 if (ctype_isStructorUnion (b))
4095 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4097 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4099 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4103 message ("Arrow access from %s pointer%q: %s",
4104 sRef_nullMessage (s->sref),
4105 sRef_unparsePreOpt (s->sref),
4106 exprNode_unparse (ret)),
4109 sRef_showNullInfo (s->sref);
4110 sRef_setNullError (s->sref);
4115 if (uentry_isUndefined (fentry))
4119 message ("Access non-existent field %s of %t: %s",
4120 f, t, exprNode_unparse (ret)),
4122 ret->typ = ctype_unknown;
4128 ** was safeUse: shouldn't be safe!
4131 ** rec must be defined,
4132 ** *rec must be allocated
4133 ** rec->field need only be defined it if is an rvalue
4136 uentry_setUsed (fentry, exprNode_loc (ret));
4137 ret->typ = uentry_getType (fentry);
4139 exprNode_checkUse (ret, s->sref, s->loc);
4141 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4142 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4146 else /* Pointer to something that is not a struct or union*/
4148 if (ctype_isRealAbstract (tr))
4150 ctype xrt = ctype_forceRealType (tr);
4154 message ("Arrow access field of abstract type (%t): %s->%s",
4155 t, exprNode_unparse (s), f),
4159 ** Set the state correctly, as if the abstraction is broken.
4162 if (ctype_isRealPointer (xrt) &&
4163 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4164 ctype_isStructorUnion (b)))
4166 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4167 ret->typ = uentry_getType (fentry);
4168 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4172 ret->typ = ctype_unknown;
4173 ret->sref = sRef_undefined;
4176 else /* not a struct, union or abstract */
4178 if (ctype_isUnknown (tr)) {
4179 cstring sn = cstring_copy (f);
4181 DPRINTF (("Here: %s", exprNode_unparse (s)));
4183 exprNode_checkUse (ret, s->sref, s->loc);
4184 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4186 cstring_markOwned (sn);
4187 ret->sref = sRef_makeArrow (s->sref, sn);
4189 ret->kind = XPR_ARROW;
4194 message ("Arrow access field of non-struct or union "
4195 "pointer (%t): %s->%s",
4196 t, exprNode_unparse (s), f),
4199 ret->typ = ctype_unknown;
4200 ret->sref = sRef_undefined;
4205 else /* its not a pointer */
4207 if (!ctype_isUnknown (tr))
4211 message ("Arrow access of non-pointer (%t): %s->%s",
4212 t, exprNode_unparse (s), f),
4215 ret->typ = ctype_unknown;
4216 ret->sref = sRef_undefined;
4220 cstring sn = cstring_copy (f);
4222 DPRINTF (("Here: %s", exprNode_unparse (s)));
4224 exprNode_checkUse (ret, s->sref, s->loc);
4225 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4227 cstring_markOwned (sn);
4228 ret->sref = sRef_makeArrow (s->sref, sn);
4230 ret->kind = XPR_ARROW;
4241 exprNode_arrowAccess (/*@only@*/ exprNode s,
4242 /*@only@*/ lltok arrow,
4243 /*@only@*/ cstring f)
4245 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4246 lltok_release (arrow);
4251 ** only postOp's in C: i++ and i--
4255 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4257 /* check modification also */
4258 /* cstring opname = lltok_unparse (op);*/
4260 exprNode ret = exprNode_createPartialCopy (e);
4262 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4263 ret->kind = XPR_POSTOP;
4264 ret->edata = exprData_makeUop (e, op);
4266 if (!exprNode_isDefined (e))
4271 checkMacroParen (e);
4273 exprNode_checkUse (ret, e->sref, e->loc);
4274 exprNode_checkSet (ret, e->sref);
4276 t = exprNode_getType (e);
4278 if (sRef_isUnsafe (e->sref))
4280 voptgenerror (FLG_MACROPARAMS,
4281 message ("Operand of %s is macro parameter (non-functional): %s%s",
4282 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4284 sRef_makeSafe (e->sref);
4285 sRef_makeSafe (ret->sref);
4288 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4294 if (ctype_isRealAbstract (t))
4298 message ("Operand of %s is abstract type (%t): %s",
4299 lltok_unparse (op), t, exprNode_unparse (e)),
4306 message ("Operand of %s is non-numeric (%t): %s",
4307 lltok_unparse (op), t, exprNode_unparse (e)),
4310 ret->typ = ctype_unknown;
4313 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4315 exprNode_checkModify (e, ret);
4317 /* added 7/11/2000 D.L */
4319 /*DRL 6/8/01 I decided to disable all Splint warnings here since the code
4320 probably needs a rewrite any way */
4325 /* updateEnvironmentForPostOp (e); */
4327 /* start modifications */
4328 /* added by Seejo on 4/16/2000 */
4330 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4332 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4334 ret->sref = sRef_copy (e->sref);
4337 if (lltok_getTok (op) == INC_OP) {
4338 if (sRef_getSize(e->sref) > 0) {
4340 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4342 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4343 /* Assumption: there is only 1 \0 in the buffer */
4344 /* This will not be correct if there are 2 \0's in the buffer */
4345 sRef_setNotNullTerminatedState(ret->sref);
4346 sRef_resetLen(ret->sref);
4348 sRef_setNullTerminatedState(ret->sref);
4349 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4351 if (sRef_isNullTerminated (ret->sref))
4352 printf ("ret->sref is Null Terminated\n");
4353 else if (sRef_isPossiblyNullTerminated (ret->sref))
4354 printf ("ret->sref is Possibly Null Terminated\n");
4355 else if (sRef_isNotNullTerminated (ret->sref))
4356 printf ("ret->sref is Not Null Terminated\n");
4361 if (lltok_getTok (op) == DEC_OP) {
4362 if (sRef_getSize(e->sref) >= 0) {
4363 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4364 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4369 /* end modifications */
4375 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4377 bool checkMod = FALSE;
4379 int opid = lltok_getTok (op);
4380 exprNode ret = exprNode_createSemiCopy (e);
4382 exprNode_copySets (ret, e);
4384 multiVal_free (ret->val);
4385 ret->val = multiVal_undefined;
4386 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4387 ret->kind = XPR_PREOP;
4388 ret->edata = exprData_makeUop (e, op);
4390 if (exprNode_isError (e))
4395 checkMacroParen (e);
4397 te = exprNode_getType (e);
4398 tr = ctype_realType (te);
4400 if (opid != TAMPERSAND)
4402 exprNode_checkUse (ret, e->sref, e->loc);
4404 if (ctype_isRealAbstract (tr)
4405 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4407 if (optgenerror (FLG_ABSTRACT,
4408 message ("Operand of %s is abstract type (%t): %s",
4409 lltok_unparse (op), tr,
4410 exprNode_unparse (ret)),
4413 tr = te = ctype_unknown;
4414 ret->typ = ctype_unknown;
4415 sRef_setNullError (e->sref);
4423 case DEC_OP: /* should also check modification! */
4424 if (sRef_isMacroParamRef (e->sref))
4428 message ("Operand of %s is macro parameter (non-functional): %s",
4429 lltok_unparse (op), exprNode_unparse (ret)),
4434 exprNode_checkSet (ret, e->sref);
4437 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4442 if (context_msgStrictOps ())
4446 message ("Operand of %s is non-numeric (%t): %s",
4447 lltok_unparse (op), te, exprNode_unparse (ret)),
4450 ret->typ = ctype_int;
4453 /* start modifications */
4454 /* added by Seejo on 4/16/2000 */
4456 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4458 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4460 ret->sref = sRef_copy (e->sref);
4463 if (lltok_getTok (op) == INC_OP) {
4464 if (sRef_getSize(e->sref) > 0) {
4466 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4468 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4469 /* Assumption: there is only 1 \0 in the buffer */
4470 /* This will not be correct if there are 2 \0's in the buffer */
4471 sRef_setNotNullTerminatedState(ret->sref);
4472 sRef_resetLen (ret->sref);
4474 sRef_setNullTerminatedState(ret->sref);
4475 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4481 if (lltok_getTok (op) == DEC_OP) {
4482 if (sRef_getSize(e->sref) >= 0) {
4483 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4484 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4489 /* end modifications */
4496 if (ctype_isForceRealNumeric (&tr))
4500 ret->val = multiVal_invert (exprNode_getValue (e));
4504 ret->val = multiVal_copy (exprNode_getValue (e));
4509 if (context_msgStrictOps ())
4513 message ("Operand of %s is non-numeric (%t): %s",
4514 lltok_unparse (op), te, exprNode_unparse (ret)),
4518 ret->typ = ctype_int;
4522 case TEXCL: /* maybe this should be restricted */
4523 guardSet_flip (ret->guards);
4525 if (ctype_isRealBool (te) || ctype_isUnknown (te))
4531 if (ctype_isRealPointer (tr))
4533 if (sRef_isKnown (e->sref))
4535 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4539 (FLG_BOOLOPS, FLG_PTRNEGATE,
4540 message ("Operand of %s is non-boolean (%t): %s",
4541 lltok_unparse (op), te, exprNode_unparse (ret)),
4548 message ("Operand of %s is non-boolean (%t): %s",
4549 lltok_unparse (op), te, exprNode_unparse (ret)),
4553 ret->typ = ctype_bool;
4558 if (ctype_isForceRealInt (&tr))
4563 if (context_msgStrictOps ())
4567 message ("Operand of %s is non-integer (%t): %s",
4568 lltok_unparse (op), te, exprNode_unparse (ret)),
4572 if (ctype_isInt (e->typ))
4578 ret->typ = ctype_int;
4584 ret->typ = ctype_makePointer (e->typ);
4586 if (sRef_isKnown (e->sref))
4588 ret->sref = sRef_makeAddress (e->sref);
4595 if (ctype_isAP (tr))
4597 ret->typ = ctype_baseArrayPtr (e->typ);
4601 if (ctype_isKnown (te))
4603 if (ctype_isFunction (te))
4609 message ("Dereference of function type (%t): %s",
4610 te, exprNode_unparse (ret)),
4615 voptgenerror (FLG_TYPE,
4616 message ("Dereference of non-pointer (%t): %s",
4617 te, exprNode_unparse (ret)),
4619 ret->typ = ctype_unknown;
4624 ret->typ = ctype_unknown;
4629 if (sRef_isKnown (e->sref))
4631 DPRINTF (("Checking possibly null: %s", sRef_unparseFull (e->sref)));
4633 if (sRef_possiblyNull (e->sref))
4635 DPRINTF (("Checking possibly null: %s", sRef_unparse (e->sref)));
4636 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4640 message ("Dereference of %s pointer %q: %s",
4641 sRef_nullMessage (e->sref),
4642 sRef_unparse (e->sref),
4643 exprNode_unparse (ret)),
4646 sRef_showNullInfo (e->sref);
4647 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4652 ret->sref = sRef_makePointer (e->sref);
4657 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4662 exprNode_checkModify (e, ret);
4669 ** any reason to disallow sizeof (abstract type) ?
4673 ** used by both sizeof
4677 ctype sizeof_resultType (void)
4679 static ctype sizet = ctype_unknown;
4681 if (ctype_isUnknown (sizet))
4683 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4685 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4689 sizet = ctype_ulint;
4696 exprNode_sizeofType (/*@only@*/ qtype qt)
4698 exprNode ret = exprNode_create (sizeof_resultType ());
4699 ctype ct = qtype_getType (qt);
4701 ret->kind = XPR_SIZEOFT;
4702 ret->edata = exprData_makeSizeofType (qt);
4704 voptgenerror (FLG_SIZEOFTYPE,
4705 message ("Parameter to sizeof is type %s: %s",
4707 exprNode_unparse (ret)),
4714 exprNode_alignofType (/*@only@*/ qtype qt)
4716 exprNode ret = exprNode_create (sizeof_resultType ());
4717 ctype ct = qtype_getType (qt);
4719 ret->kind = XPR_ALIGNOFT;
4720 ret->edata = exprData_makeSizeofType (qt);
4722 voptgenerror (FLG_SIZEOFTYPE,
4723 message ("Parameter to alignof is type %s: %s",
4725 exprNode_unparse (ret)),
4731 exprNode exprNode_offsetof (qtype qt, cstringList s)
4733 exprNode ret = exprNode_create (sizeof_resultType ());
4734 ctype ct = qtype_getType (qt);
4736 ret->kind = XPR_OFFSETOF;
4737 ret->edata = exprData_makeOffsetof (qt, s);
4739 if (!ctype_isRealSU (ct))
4741 voptgenerror (FLG_TYPE,
4742 message ("First parameter to offsetof is not a "
4743 "struct or union type (type %s): %s",
4745 exprNode_unparse (ret)),
4752 cstringList_elements (s, el) {
4756 if (ctype_isUndefined (lt))
4760 else if (!ctype_isRealSU (lt))
4762 voptgenerror (FLG_TYPE,
4763 message ("Inner offsetof type is not a "
4764 "struct or union type (type %s before field %s): %s",
4765 ctype_unparse (lt), el,
4766 exprNode_unparse (ret)),
4772 fields = ctype_getFields (ctype_realType (lt));
4773 fld = uentryList_lookupField (fields, el);
4774 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4776 if (uentry_isUndefined (fld))
4778 if (ctype_equal (lt, ct)) {
4779 voptgenerror (FLG_TYPE,
4780 message ("Field %s in offsetof is not the "
4781 "name of a field of %s: %s",
4784 exprNode_unparse (ret)),
4787 voptgenerror (FLG_TYPE,
4788 message ("Deep field %s in offsetof is not the "
4789 "name of a field of %s: %s",
4792 exprNode_unparse (ret)),
4798 lt = uentry_getType (fld);
4801 } end_cstringList_elements;
4803 /* Should report error if its a bit field - behavior is undefined! */
4810 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4814 if (exprNode_isUndefined (e))
4816 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4817 ret->edata = exprData_makeSingle (e);
4818 ret->typ = sizeof_resultType ();
4819 ret->kind = XPR_SIZEOF;
4823 uentry u = exprNode_getUentry (e);
4825 ret = exprNode_createPartialCopy (e);
4826 ret->edata = exprData_makeSingle (e);
4828 ret->typ = sizeof_resultType ();
4829 ret->kind = XPR_SIZEOF;
4831 if (uentry_isValid (u)
4832 && uentry_isRefParam (u)
4833 && ctype_isRealArray (uentry_getType (u)))
4836 (FLG_SIZEOFFORMALARRAY,
4837 message ("Parameter to sizeof is an array-type function parameter: %s",
4838 exprNode_unparse (ret)),
4844 ** sizeof (x) doesn't "really" use x
4851 exprNode_alignofExpr (/*@only@*/ exprNode e)
4855 if (exprNode_isUndefined (e))
4857 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4861 ret = exprNode_createPartialCopy (e);
4864 ret->edata = exprData_makeSingle (e);
4865 ret->typ = sizeof_resultType ();
4866 ret->kind = XPR_ALIGNOF;
4869 ** sizeof (x) doesn't "really" use x
4876 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4882 if (exprNode_isError (e))
4885 lltok_release (tok);
4886 return exprNode_undefined;
4889 checkMacroParen (e);
4891 c = qtype_getType (q);
4892 t = exprNode_getType (e);
4894 ret = exprNode_createPartialCopy (e);
4896 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4898 ret->kind = XPR_CAST;
4899 ret->edata = exprData_makeCast (tok, e, q);
4901 if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
4904 ** This is a bit of a hack to avoid a problem
4905 ** when the code does,
4906 ** (some other struct) x
4911 ret->sref = sRef_copy (e->sref);
4912 usymtab_addForceMustAlias (ret->sref, e->sref);
4913 sRef_setTypeFull (ret->sref, c);
4914 DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
4915 sRef_unparseFull (ret->sref)));
4919 ret->sref = e->sref;
4920 sRef_setTypeFull (ret->sref, c);
4921 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
4928 ** void * <-> abstract * (if FLG_ABSTVOIDP)
4929 ** abstract * <-> void * (if FLG_ABSTVOIDP)
4932 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
4936 else if (ctype_isRealAP (c)) /* casting to array or pointer */
4938 ctype bc = ctype_getBaseType (c);
4939 ctype bt = ctype_getBaseType (t);
4940 ctype rt = ctype_realType (t);
4942 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
4943 && (ctype_isArrayPtr (rt)
4944 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4948 message ("Cast from function pointer type (%t) to "
4949 "non-function pointer (%t): %s",
4950 c, t, exprNode_unparse (ret)),
4954 if (!ctype_isFunction (ctype_baseArrayPtr (c))
4955 && (ctype_isArrayPtr (rt)
4956 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4960 message ("Cast from non-function pointer type (%t) to "
4961 "function pointer (%t): %s",
4962 c, t, exprNode_unparse (ret)),
4966 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
4967 !(ctype_isRealAbstract (bc)
4968 && context_hasAccess (ctype_typeId (bc))))
4970 ; /* okay to cast zero */
4974 if (ctype_isRealAbstract (bc)
4975 && !context_hasAccess (ctype_typeId (bc)))
4977 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
4981 message ("Cast to underlying abstract type %t: %s",
4982 c, exprNode_unparse (ret)),
4989 message ("Cast to underlying abstract type %t: %s",
4990 c, exprNode_unparse (ret)),
4995 if (ctype_isRealAbstract (bt)
4996 && !context_hasAccess (ctype_typeId (bt)))
4998 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
5002 message ("Cast from underlying abstract type %t: %s",
5003 t, exprNode_unparse (ret)),
5010 message ("Cast from underlying abstract type %t: %s",
5011 t, exprNode_unparse (ret)),
5019 ctype bt = ctype_realType (ctype_getBaseType (t));
5020 ctype bc = ctype_realType (ctype_getBaseType (c));
5022 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
5024 if (ctype_match (c, t))
5026 if (ctype_equal (c, t))
5030 message ("Redundant cast involving abstract type %t: %s",
5031 bt, exprNode_unparse (ret)),
5039 message ("Cast from abstract type %t: %s",
5040 bt, exprNode_unparse (ret)),
5045 if (ctype_isAbstract (bc)
5046 && !context_hasAccess (ctype_typeId (bc)))
5048 if (ctype_match (c, t))
5054 DPRINTF (("No access to: %s / %d",
5055 ctype_unparse (bc), ctype_typeId (bc)));
5056 DPRINTF (("Context %s %s",
5057 bool_unparse (context_inFunctionLike ()),
5058 context_unparse ()));
5061 message ("Cast to abstract type %t: %s", bc,
5062 exprNode_unparse (ret)),
5068 if (ctype_isAbstract (c))
5070 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
5072 /* okay, cast exposed to abstract */
5073 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
5077 if (ctype_isVisiblySharable (t)
5078 && sRef_isExternallyVisible (e->sref)
5079 && !(ctype_isAbstract (t)
5080 && context_hasAccess (ctype_typeId (t))))
5084 message ("Cast to abstract type from externally visible "
5085 "mutable storage exposes rep of %s: %s",
5087 exprNode_unparse (e)),
5097 evaluationOrderUndefined (lltok op)
5099 int opid = lltok_getTok (op);
5101 return (opid != AND_OP && opid != OR_OP);
5104 static bool checkIntegral (/*@notnull@*/ exprNode e1,
5105 /*@notnull@*/ exprNode e2,
5106 /*@notnull@*/ exprNode ret,
5111 ctype te1 = exprNode_getType (e1);
5112 ctype te2 = exprNode_getType (e2);
5114 ctype tr1 = ctype_realishType (te1);
5115 ctype tr2 = ctype_realishType (te2);
5117 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5123 if (context_msgStrictOps ())
5125 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5127 if (ctype_sameName (te1, te2))
5131 message ("Operands of %s are non-integer (%t): %s",
5132 lltok_unparse (op), te1,
5133 exprNode_unparse (ret)),
5140 message ("Operands of %s are non-integers (%t, %t): %s",
5141 lltok_unparse (op), te1, te2,
5142 exprNode_unparse (ret)),
5146 else if (!ctype_isInt (tr1))
5150 message ("Left operand of %s is non-integer (%t): %s",
5151 lltok_unparse (op), te1, exprNode_unparse (ret)),
5155 /* !ctype_isInt (te2) */
5159 message ("Right operand of %s is non-integer (%t): %s",
5160 lltok_unparse (op), te2, exprNode_unparse (ret)),
5170 ** returns exprNode representing e1 op e2
5172 ** uses msg if there are errors
5173 ** can be used for both assignment ops and regular ops
5178 static /*@only@*/ /*@notnull@*/ exprNode
5179 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
5180 /*@keep@*/ lltok op)
5182 ctype te1, te2, tr1, tr2, tret;
5183 int opid = lltok_getTok (op);
5184 bool hasError = FALSE;
5187 if (exprNode_isError (e1))
5189 ret = exprNode_createPartialNVCopy (e2);
5193 ret = exprNode_createPartialNVCopy (e1);
5196 ret->val = multiVal_undefined;
5198 ret->edata = exprData_makeOp (e1, e2, op);
5200 if (exprNode_isError (e1) || exprNode_isError (e2))
5202 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5203 || opid == EQ_OP || opid == NE_OP
5204 || opid == AND_OP || opid == OR_OP)
5206 ret->typ = ctype_bool;
5209 if (exprNode_isDefined (e1))
5211 exprNode_checkUse (ret, e1->sref, e1->loc);
5214 if (exprNode_isDefined (e2))
5216 exprNode_mergeUSs (ret, e2);
5217 exprNode_checkUse (ret, e2->sref, e2->loc);
5223 tret = ctype_unknown;
5224 te1 = exprNode_getType (e1);
5226 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5228 te2 = exprNode_getType (e2);
5230 tr1 = ctype_realishType (te1);
5231 tr2 = ctype_realishType (te2);
5235 ret->guards = guardSet_or (ret->guards, e2->guards);
5237 else if (opid == AND_OP)
5239 ret->guards = guardSet_and (ret->guards, e2->guards);
5246 if (opid == EQ_OP || opid == NE_OP)
5248 exprNode temp1 = e1, temp2 = e2;
5250 /* could do NULL == x */
5252 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5254 temp1 = e2; temp2 = e1;
5257 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5259 reflectNullTest (temp1, (opid == NE_OP));
5260 guardSet_free (ret->guards);
5261 ret->guards = guardSet_copy (temp1->guards);
5265 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5266 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5271 if (anyAbstract (tr1, tr2) &&
5272 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
5273 (opid == AND_OP || opid == OR_OP
5274 || opid == EQ_OP || opid == NE_OP))))
5276 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
5278 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5280 /* unknown types, no comparisons possible */
5286 case TMULT: /* multiplication and division: */
5288 case MUL_ASSIGN: /* numeric, numeric -> numeric */
5289 case DIV_ASSIGN: /* */
5291 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5294 case TPLUS: /* addition and subtraction: */
5295 case TMINUS: /* pointer, int -> pointer */
5296 case SUB_ASSIGN: /* int, pointer -> pointer */
5297 case ADD_ASSIGN: /* numeric, numeric -> numeric */
5299 tr1 = ctype_fixArrayPtr (tr1);
5301 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5302 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5306 if (context_msgPointerArith ())
5310 message ("Pointer arithmetic (%t, %t): %s",
5311 te1, te2, exprNode_unparse (ret)),
5316 ** Swap terms so e1 is always the pointer
5319 if (ctype_isRealPointer (tr1))
5325 exprNode_swap (e1, e2);
5329 if (sRef_possiblyNull (e1->sref)
5330 && !usymtab_isGuarded (e1->sref))
5333 (FLG_NULLPOINTERARITH,
5334 message ("Pointer arithmetic involving possibly "
5335 "null pointer %s: %s",
5336 exprNode_unparse (e1),
5337 exprNode_unparse (ret)),
5341 ret->sref = sRef_copy (e1->sref);
5343 /* start modifications */
5344 /* added by Seejo on 4/16/2000 */
5346 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5348 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5351 added ugly fixed to stop
5352 program from crashing on point + int +int
5353 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5355 if (!multiVal_isInt (e2->val) )
5359 val = (int) multiVal_forceInt (e2->val);
5361 /* Operator : + or += */
5362 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5363 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5364 val should not result in a
5365 size < 0 (size = 0 is ok !) */
5367 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5369 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5370 sRef_setNotNullTerminatedState(ret->sref);
5371 sRef_resetLen (ret->sref);
5373 sRef_setNullTerminatedState(ret->sref);
5374 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5379 /* Operator : - or -= */
5380 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5381 if (sRef_getSize(e1->sref) >= 0) {
5382 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5383 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5388 /* end modifications */
5390 sRef_setNullError (ret->sref);
5393 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5394 ** since is points to storage that should not be deallocated
5395 ** through this pointer.
5398 if (sRef_isOnly (ret->sref)
5399 || sRef_isFresh (ret->sref))
5401 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5406 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5407 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5409 if (context_msgPointerArith ())
5413 message ("Pointer arithmetic (%t, %t): %s",
5414 te1, te2, exprNode_unparse (ret)),
5418 if (sRef_possiblyNull (e1->sref)
5419 && !usymtab_isGuarded (e1->sref))
5422 (FLG_NULLPOINTERARITH,
5423 message ("Pointer arithmetic involving possibly "
5424 "null pointer %s: %s",
5425 exprNode_unparse (e2),
5426 exprNode_unparse (ret)),
5430 ret->sref = sRef_copy (e2->sref);
5432 /* start modifications */
5433 /* added by Seejo on 4/16/2000 */
5435 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5438 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5439 int val = (int) multiVal_forceInt (e1->val);
5441 /* Operator : + or += */
5442 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5443 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5444 val should not result in a
5445 size < 0 (size = 0 is ok !) */
5447 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5449 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5450 sRef_setNotNullTerminatedState(ret->sref);
5451 sRef_resetLen (ret->sref);
5453 sRef_setNullTerminatedState(ret->sref);
5454 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5459 /* Operator : - or -= */
5460 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5461 if (sRef_getSize(e2->sref) >= 0) {
5462 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5463 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5467 /* end modifications */
5469 sRef_setNullError (ret->sref);
5472 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5473 ** since is points to storage that should not be deallocated
5474 ** through this pointer.
5477 if (sRef_isOnly (ret->sref)
5478 || sRef_isFresh (ret->sref)) {
5479 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5483 ret->sref = e2->sref;
5487 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5492 case LEFT_ASSIGN: /* Shifts: should be unsigned values */
5496 case TAMPERSAND: /* bitwise & */
5498 case TCIRC: /* ^ (XOR) */
5503 bool reported = FALSE;
5504 flagcode code = FLG_BITWISEOPS;
5506 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5507 || opid == RIGHT_OP || opid == RIGHT_ASSIGN) {
5508 code = FLG_SHIFTSIGNED;
5511 if (!ctype_isUnsigned (tr1))
5513 if (exprNode_isNonNegative (e1)) {
5516 reported = optgenerror
5518 message ("Left operand of %s is not unsigned value (%t): %s",
5519 lltok_unparse (op), te1,
5520 exprNode_unparse (ret)),
5530 /* right need not be signed for shifts */
5531 if (code != FLG_SHIFTSIGNED
5532 && !ctype_isUnsigned (tr2))
5534 if (!exprNode_isNonNegative (e2)) {
5535 reported = optgenerror
5537 message ("Right operand of %s is not unsigned value (%t): %s",
5538 lltok_unparse (op), te2,
5539 exprNode_unparse (ret)),
5547 if (!checkIntegral (e1, e2, ret, op)) {
5548 te1 = ctype_unknown;
5552 DPRINTF (("Set: %s", ctype_unparse (te1)));
5555 ** tret is the widest type of te1 and te2
5558 tret = ctype_widest (te1, te2);
5563 if (checkIntegral (e1, e2, ret, op)) {
5566 tret = ctype_unknown;
5571 case TLT: /* comparisons */
5572 case TGT: /* numeric, numeric -> bool */
5574 DPRINTF (("Here we go: %s / %s",
5575 ctype_unparse (tr1), ctype_unparse (tr2)));
5577 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5578 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5581 bool fepsilon = FALSE;
5583 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5588 if (opid == TLT || opid == TGT)
5590 uentry ue1 = exprNode_getUentry (e1);
5591 uentry ue2 = exprNode_getUentry (e2);
5594 ** FLT_EPSILON, etc. really is a variable, not
5598 if (uentry_isVariable (ue1))
5600 cstring uname = uentry_rawName (ue1);
5602 if (cstring_equalLit (uname, "FLT_EPSILON")
5603 || cstring_equalLit (uname, "DBL_EPSILON")
5604 || cstring_equalLit (uname, "LDBL_EPSILON"))
5610 if (uentry_isVariable (ue2))
5612 cstring uname = uentry_rawName (ue2);
5614 if (cstring_equalLit (uname, "FLT_EPSILON")
5615 || cstring_equalLit (uname, "DBL_EPSILON")
5616 || cstring_equalLit (uname, "LDBL_EPSILON"))
5625 ; /* Don't complain. */
5631 message ("Dangerous comparison involving %s types: %s",
5632 ctype_unparse (rtype),
5633 exprNode_unparse (ret)),
5642 ** Types should match.
5645 DPRINTF (("Match types: %s / %s", exprNode_unparse (e1),
5646 exprNode_unparse (e2)));
5648 if (!exprNode_matchTypes (e1, e2))
5650 hasError = gentypeerror
5652 message ("Operands of %s have incompatible types (%t, %t): %s",
5653 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5659 || (ctype_isForceRealNumeric (&tr1)
5660 && ctype_isForceRealNumeric (&tr2)) ||
5661 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5667 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5668 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5672 message ("Comparison of pointer and numeric (%t, %t): %s",
5673 te1, te2, exprNode_unparse (ret)),
5678 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5683 /* certain comparisons on unsigned's and zero look suspicious */
5685 if (opid == TLT || opid == LE_OP || opid == GE_OP)
5687 if ((ctype_isUnsigned (tr1) && exprNode_isZero (e2))
5688 || (ctype_isUnsigned (tr2) && exprNode_isZero (e1)))
5691 (FLG_UNSIGNEDCOMPARE,
5692 message ("Comparison of unsigned value involving zero: %s",
5693 exprNode_unparse (ret)),
5698 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5700 if ((opid == EQ_OP || opid == NE_OP) &&
5701 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5704 ** is one a variable?
5707 if (uentry_isVariable (exprNode_getUentry (e1))
5708 || uentry_isVariable (exprNode_getUentry (e2)))
5711 ** comparisons with FALSE are okay
5714 if (exprNode_isFalseConstant (e1)
5715 || exprNode_isFalseConstant (e2))
5724 ("Use of %q with %s variables (risks inconsistency because "
5725 "of multiple true values): %s",
5726 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5727 context_printBoolName (), exprNode_unparse (ret)),
5734 case AND_OP: /* bool, bool -> bool */
5737 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5743 if (context_maybeSet (FLG_BOOLOPS))
5745 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5747 if (ctype_sameName (te1, te2))
5751 message ("Operands of %s are non-boolean (%t): %s",
5752 lltok_unparse (op), te1,
5753 exprNode_unparse (ret)),
5761 ("Operands of %s are non-booleans (%t, %t): %s",
5762 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5766 else if (!ctype_isRealBool (te1))
5770 message ("Left operand of %s is non-boolean (%t): %s",
5771 lltok_unparse (op), te1, exprNode_unparse (ret)),
5774 else if (!ctype_isRealBool (te2))
5778 message ("Right operand of %s is non-boolean (%t): %s",
5779 lltok_unparse (op), te2, exprNode_unparse (ret)),
5792 (cstring_makeLiteral
5793 ("There has been a problem in the parser. This is believed to result "
5794 "from a problem with bison v. 1.25. Please try rebuidling Splint "
5795 "using the pre-compiled grammar files by commenting out the "
5796 "BISON= line in the top-level Makefile."));
5801 DPRINTF (("Return type: %s", ctype_unparse (tret)));
5804 exprNode_checkUse (ret, e1->sref, e1->loc);
5805 exprNode_mergeUSs (ret, e2);
5806 exprNode_checkUse (ret, e2->sref, e2->loc);
5812 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5813 /*@only@*/ lltok op)
5817 checkMacroParen (e1);
5818 checkMacroParen (e2);
5820 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5822 checkExpressionDefined (e1, e2, op);
5825 ret = exprNode_makeOp (e1, e2, op);
5830 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5833 ** This is somewhat bogus!
5835 ** Assigning to a nested observer in a non-observer datatype
5836 ** should not produce an error.
5839 sRef ref = exprNode_getSref (e1);
5841 DPRINTF (("Check assign mod: %s",
5842 sRef_unparseFull (ref)));
5844 if (sRef_isObserver (ref)
5845 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
5846 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5848 sRef base = sRef_getBase (ref);
5850 if (sRef_isValid (base) && sRef_isObserver (base))
5852 exprNode_checkModify (e1, ret);
5856 exprNode_checkModifyVal (e1, ret);
5861 exprNode_checkModify (e1, ret);
5866 exprNode_assign (/*@only@*/ exprNode e1,
5867 /*@only@*/ exprNode e2, /*@only@*/ lltok op)
5869 bool isalloc = FALSE;
5870 bool isjustalloc = FALSE;
5871 bool noalias = FALSE;
5874 DPRINTF (("%s [%s] <- %s [%s]",
5875 exprNode_unparse (e1),
5876 ctype_unparse (e1->typ),
5877 exprNode_unparse (e2),
5878 ctype_unparse (e2->typ)));
5880 if (lltok_getTok (op) != TASSIGN)
5882 ret = exprNode_makeOp (e1, e2, op);
5884 DPRINTF (("Here goes: %s %s",
5885 ctype_unparse (e1->typ),
5886 ctype_unparse (e2->typ)));
5888 if (ctype_isNumeric (e2->typ)
5889 || ctype_isNumeric (e1->typ))
5891 /* Its a pointer arithmetic expression like ptr += i */
5897 ret = exprNode_createPartialCopy (e1);
5898 ret->kind = XPR_ASSIGN;
5899 ret->edata = exprData_makeOp (e1, e2, op);
5901 if (!exprNode_isError (e2))
5903 ret->sets = sRefSet_union (ret->sets, e2->sets);
5904 ret->msets = sRefSet_union (ret->msets, e2->msets);
5905 ret->uses = sRefSet_union (ret->uses, e2->uses);
5909 checkExpressionDefined (e1, e2, op);
5911 if (exprNode_isError (e1))
5913 if (!exprNode_isError (e2))
5915 ret->loc = fileloc_update (ret->loc, e2->loc);
5919 ret->loc = fileloc_update (ret->loc, g_currentloc);
5923 if (!exprNode_isError (e2))
5925 checkMacroParen (e2);
5928 if (exprNode_isDefined (e1))
5930 if (sRef_isMacroParamRef (e1->sref))
5932 if (context_inIterDef ())
5934 uentry ue = sRef_getUentry (e1->sref);
5936 if (uentry_isYield (ue))
5942 if (fileloc_isDefined (e1->loc))
5946 message ("Assignment to non-yield iter parameter: %q",
5947 sRef_unparse (e1->sref)),
5954 message ("Assignment to non-yield iter parameter: %q",
5955 sRef_unparse (e1->sref)),
5962 if (fileloc_isDefined (e1->loc))
5966 message ("Assignment to macro parameter: %q",
5967 sRef_unparse (e1->sref)),
5974 message ("Assignment to macro parameter: %q",
5975 sRef_unparse (e1->sref)),
5979 exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
5984 exprNode_checkAssignMod (e1, ret);
5987 if (exprNode_isDefined (e2))
5989 if (lltok_getTok (op) == TASSIGN)
5991 ctype te1 = exprNode_getType (e1);
5992 ctype te2 = exprNode_getType (e2);
5994 if (!ctype_forceMatch (te1, te2))
5996 if (exprNode_matchLiteral (te1, e2))
6004 message ("Assignment of %t to %t: %s %s %s",
6005 te2, te1, exprNode_unparse (e1),
6007 exprNode_unparse (e2)),
6013 exprNode_mergeUSs (ret, e2);
6014 exprNode_checkUse (ret, e2->sref, e2->loc);
6016 DPRINTF (("Do assign! %s %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6023 doAssign (e1, e2, FALSE);
6026 ret->sref = e1->sref;
6030 if (exprNode_isDefined (e2))
6032 exprNode_mergeUSs (ret, e2);
6033 exprNode_checkUse (ret, e2->sref, e2->loc);
6037 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
6039 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
6042 isjustalloc = sRef_isJustAllocated (e1->sref);
6043 isalloc = sRef_isAllocated (e1->sref);
6045 if (sRef_isField (e1->sref))
6047 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
6049 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
6051 exprNode_checkUse (ret, root, e1->loc);
6057 ** be careful! this defines e1->sref.
6060 /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
6062 DPRINTF (("Setting: %s -> %s", exprNode_unparse (ret), sRef_unparse (e1->sref)));
6063 exprNode_checkSet (ret, e1->sref);
6067 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
6068 ? e2->loc : e1->loc);
6074 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
6083 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
6084 /*@keep@*/ exprNode elseclause)
6088 if (!exprNode_isError (pred))
6090 ret = exprNode_createPartialCopy (pred);
6091 checkMacroParen (pred);
6092 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
6094 if (!exprNode_isError (ifclause))
6096 checkMacroParen (ifclause); /* update macro counts! */
6098 if (!exprNode_isError (elseclause))
6100 checkMacroParen (elseclause);
6102 if (!exprNode_matchTypes (ifclause, elseclause))
6105 (exprNode_getType (ifclause),
6107 exprNode_getType (elseclause),
6109 message ("Conditional clauses are not of same type: "
6111 exprNode_unparse (ifclause),
6112 exprNode_getType (ifclause),
6113 exprNode_unparse (elseclause),
6114 exprNode_getType (elseclause)),
6117 ret->sref = sRef_undefined;
6118 ret->typ = ctype_unknown;
6123 /* for now...should merge the states */
6124 ret->sref = ifclause->sref;
6125 ret->typ = ifclause->typ;
6127 if (exprNode_isNullValue (ifclause))
6129 ret->typ = elseclause->typ;
6133 exprNode_checkUse (ret, pred->sref, pred->loc);
6134 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6135 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6137 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6142 ret->typ = ifclause->typ;
6144 exprNode_checkUse (pred, pred->sref, pred->loc);
6145 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6147 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6152 if (!exprNode_isError (elseclause))
6154 ret->typ = elseclause->typ;
6156 exprNode_checkUse (pred, pred->sref, pred->loc);
6157 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6159 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6163 else /* pred is error */
6165 if (!exprNode_isError (ifclause))
6167 ret = exprNode_createSemiCopy (ifclause);
6169 checkMacroParen (ifclause); /* update macro counts! */
6171 if (!exprNode_isError (elseclause))
6173 checkMacroParen (elseclause);
6175 ret->typ = ifclause->typ;
6177 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6180 (exprNode_getType (ifclause),
6182 exprNode_getType (elseclause),
6184 message ("Conditional clauses are not of same type: "
6186 exprNode_unparse (ifclause),
6187 exprNode_getType (ifclause),
6188 exprNode_unparse (elseclause),
6189 exprNode_getType (elseclause)),
6192 ret->typ = ctype_unknown;
6196 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6197 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6199 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6202 else if (!exprNode_isError (elseclause)) /* pred, if errors */
6204 ret = exprNode_createSemiCopy (ifclause);
6206 ret->typ = elseclause->typ;
6207 checkMacroParen (elseclause);
6209 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6210 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6212 else /* all errors! */
6214 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6218 ret->kind = XPR_COND;
6219 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
6221 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6223 exprNode_combineControl (ret, ifclause, elseclause);
6230 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6232 ctype totype = qtype_getType (qt);
6234 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6238 ** check use of va_arg : <valist>, type -> type
6241 if (exprNode_isError (arg))
6246 targ = exprNode_getType (arg);
6249 ** arg should have be a pointer
6252 if (!ctype_isUA (targ) ||
6253 (!usymId_equal (ctype_typeId (targ),
6254 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6258 message ("First argument to va_arg is not a va_list (type %t): %s",
6259 targ, exprNode_unparse (arg)),
6263 exprNode_checkSet (ret, arg->sref);
6267 ** return type is totype
6271 ret->kind = XPR_VAARG;
6272 ret->edata = exprData_makeCast (tok, arg, qt);
6277 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6279 exprNode ret = exprNode_createPlain (ctype_undefined);
6280 ret->kind = XPR_LABEL;
6281 ret->edata = exprData_makeLiteral (label);
6282 ret->isJumpPoint = TRUE;
6284 return (ret); /* for now, ignore label */
6287 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6289 if (exprNode_isDefined (stmt))
6291 stmt->isJumpPoint = TRUE;
6293 /* This prevent stray no return path errors, etc. */
6294 stmt->exitCode = XK_MUSTEXIT;
6300 bool exprNode_isDefaultMarker (exprNode e)
6302 if (exprNode_isDefined (e))
6304 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6310 bool exprNode_isCaseMarker (exprNode e)
6312 if (exprNode_isDefined (e))
6314 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6320 bool exprNode_isLabelMarker (exprNode e)
6322 if (exprNode_isDefined (e))
6324 return (e->kind == XPR_LABEL);
6330 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6332 exprNode ret = exprNode_createPartialCopy (test);
6334 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6336 if (exprNode_isError (test)) {
6340 exprNode_checkUse (ret, test->sref, test->loc);
6342 usymtab_setExitCode (ret->exitCode);
6346 usymtab_setMustBreak ();
6349 ret->edata = exprData_makeSingle (test);
6350 ret->isJumpPoint = TRUE;
6356 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6358 exprNode ret = exprNode_createPartialCopy (test);
6360 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6361 ret->edata = exprData_makePair (test, stmt);
6362 ret->isJumpPoint = TRUE;
6364 if (exprNode_isError (test))
6369 exprNode_checkUse (ret, test->sref, test->loc);
6371 if (exprNode_isError (stmt))
6376 exprNode_mergeUSs (ret, stmt);
6378 ret->exitCode = stmt->exitCode;
6379 ret->mustBreak = stmt->mustBreak;
6380 ret->canBreak = stmt->canBreak;
6382 usymtab_setExitCode (ret->exitCode);
6386 usymtab_setMustBreak ();
6393 /*@notnull@*/ /*@only@*/ exprNode
6394 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6396 exprNode ret = exprNode_createTok (def);
6398 ret->isJumpPoint = TRUE;
6399 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6404 exprNode_mayEscape (exprNode e)
6406 if (exprNode_isDefined (e))
6408 return exitkind_couldEscape (e->exitCode);
6414 exprNode_mustBreak (exprNode e)
6416 if (exprNode_isDefined (e))
6418 return e->mustBreak;
6425 exprNode_mustEscape (exprNode e)
6427 if (exprNode_isDefined (e))
6429 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6436 exprNode_errorEscape (exprNode e)
6438 if (exprNode_isDefined (e))
6440 return exitkind_isError (e->exitCode);
6446 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6448 exprNode ret = exprNode_createPartialCopy (e1);
6450 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6452 ret->edata = exprData_makePair (e1, e2);
6453 ret->kind = XPR_STMTLIST;
6455 if (exprNode_isDefined (e1))
6457 ret->isJumpPoint = e1->isJumpPoint;
6458 ret->canBreak = e1->canBreak;
6462 if (exprNode_isDefined (e2))
6464 ret->loc = fileloc_update (ret->loc, e2->loc);
6468 if (exprNode_isDefined (e2))
6470 ret->exitCode = e2->exitCode;
6471 ret->mustBreak = e2->mustBreak;
6472 if (e2->canBreak) ret->canBreak = TRUE;
6476 ** if e1 must return, then e2 is unreachable!
6479 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6481 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6482 && !(e2->isJumpPoint))
6484 if (context_getFlag (FLG_UNREACHABLE))
6488 if (e2->kind == XPR_STMT)
6490 nr = exprData_getUopNode (e2->edata);
6493 if ((nr->kind == XPR_TOK
6494 && lltok_isSemi (exprData_getTok (nr->edata))))
6496 /* okay to have unreachable ";" */
6497 ret->exitCode = XK_MUSTEXIT;
6498 ret->canBreak = TRUE;
6502 if (optgenerror (FLG_UNREACHABLE,
6503 message ("Unreachable code: %s",
6504 exprNode_unparseFirst (nr)),
6507 ret->isJumpPoint = TRUE;
6508 ret->mustBreak = FALSE;
6509 ret->exitCode = XK_ERROR;
6510 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6514 ret->exitCode = XK_MUSTEXIT;
6515 ret->canBreak = TRUE;
6523 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6526 ** We want a warning anytime we have:
6528 ** yyy; <<<- no break or return
6532 exprNode lastStmt = exprNode_lastStatement (e1);
6534 if (exprNode_isDefined (lastStmt)
6535 && !exprNode_mustEscape (lastStmt)
6536 && !exprNode_mustBreak (lastStmt)
6537 && !exprNode_isCaseMarker (lastStmt)
6538 && !exprNode_isDefaultMarker (lastStmt)
6539 && !exprNode_isLabelMarker (lastStmt))
6541 voptgenerror (FLG_CASEBREAK,
6543 ("Fall through case (no preceding break)"),
6550 exprNode_mergeUSs (ret, e2);
6552 usymtab_setExitCode (ret->exitCode);
6556 usymtab_setMustBreak ();
6562 exprNode exprNode_createTok (/*@only@*/ lltok t)
6564 exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6565 ret = exprNode_create (ctype_unknown);
6566 ret->kind = XPR_TOK;
6567 ret->edata = exprData_makeTok (t);
6571 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6573 if (!exprNode_isError (e))
6575 exprNode_checkStatement(e);
6578 return (exprNode_statementError (e, t));
6581 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6583 exprNode ret = exprNode_createPartialCopy (e);
6585 if (!exprNode_isError (e))
6587 if (e->kind != XPR_ASSIGN)
6589 exprNode_checkUse (ret, e->sref, e->loc);
6592 ret->exitCode = e->exitCode;
6593 ret->canBreak = e->canBreak;
6594 ret->mustBreak = e->mustBreak;
6597 ret->edata = exprData_makeUop (e, t);
6598 ret->kind = XPR_STMT;
6603 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6605 if (!exprNode_isError (e))
6607 if (e->kind != XPR_ASSIGN)
6609 exprNode_checkUse (e, e->sref, e->loc);
6616 void exprNode_produceGuards (exprNode pred)
6618 if (!exprNode_isError (pred))
6620 if (ctype_isRealPointer (pred->typ))
6622 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6625 exprNode_checkUse (pred, pred->sref, pred->loc);
6626 exprNode_resetSref (pred);
6630 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6632 exprNode ret = exprNode_createPartialCopy (e);
6634 if (!exprNode_isError (e))
6636 ret->exitCode = e->exitCode;
6637 ret->canBreak = e->canBreak;
6638 ret->mustBreak = e->mustBreak;
6641 ret->edata = exprData_makeSingle (e);
6642 ret->kind = XPR_BLOCK;
6646 bool exprNode_isBlock (exprNode e)
6648 return (exprNode_isDefined (e)
6649 && ((e)->kind == XPR_BLOCK));
6652 bool exprNode_isAssign (exprNode e)
6654 if (exprNode_isDefined (e))
6656 return (e->kind == XPR_ASSIGN);
6662 bool exprNode_isEmptyStatement (exprNode e)
6664 return (exprNode_isDefined (e)
6665 && (e->kind == XPR_TOK)
6666 && (lltok_isSemi (exprData_getTok (e->edata))));
6669 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6672 bool emptyErr = FALSE;
6674 if (context_maybeSet (FLG_IFEMPTY))
6676 if (exprNode_isEmptyStatement (tclause))
6678 emptyErr = optgenerror (FLG_IFEMPTY,
6680 ("Body of if statement is empty"),
6681 exprNode_loc (tclause));
6685 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6687 if (exprNode_isDefined (tclause)
6688 && !exprNode_isBlock (tclause))
6690 voptgenerror (FLG_IFBLOCK,
6692 ("Body of if statement is not a block: %s",
6693 exprNode_unparse (tclause)),
6694 exprNode_loc (tclause));
6698 if (exprNode_isError (pred))
6700 if (exprNode_isError (tclause))
6702 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6706 ret = exprNode_createPartialCopy (tclause);
6711 if (exprNode_mustEscape (pred))
6715 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6716 exprNode_loc (pred));
6719 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6720 exprNode_checkUse (pred, pred->sref, pred->loc);
6722 if (!exprNode_isError (tclause))
6724 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
6727 ret = exprNode_createPartialCopy (pred);
6731 ret->edata = exprData_makePair (pred, tclause);
6733 ret->exitCode = XK_UNKNOWN;
6735 if (exprNode_isDefined (tclause))
6737 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
6738 ret->canBreak = tclause->canBreak;
6739 ret->sets = sRefSet_union (ret->sets, tclause->sets);
6740 ret->msets = sRefSet_union (ret->msets, tclause->msets);
6741 ret->uses = sRefSet_union (ret->uses, tclause->uses);
6744 ret->mustBreak = FALSE;
6749 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
6750 /*@only@*/ exprNode tclause,
6751 /*@only@*/ exprNode eclause)
6754 bool tEmptyErr = FALSE;
6755 bool eEmptyErr = FALSE;
6757 if (context_maybeSet (FLG_IFEMPTY))
6759 if (exprNode_isEmptyStatement (tclause))
6761 tEmptyErr = optgenerror
6764 ("Body of if clause of if statement is empty"),
6765 exprNode_loc (tclause));
6768 if (exprNode_isEmptyStatement (eclause))
6770 eEmptyErr = optgenerror
6773 ("Body of else clause of if statement is empty"),
6774 exprNode_loc (eclause));
6778 if (context_maybeSet (FLG_IFBLOCK))
6781 && exprNode_isDefined (tclause)
6782 && !exprNode_isBlock (tclause))
6784 voptgenerror (FLG_IFBLOCK,
6786 ("Body of if clause of if statement is not a block: %s",
6787 exprNode_unparse (tclause)),
6788 exprNode_loc (tclause));
6792 && exprNode_isDefined (eclause)
6793 && !exprNode_isBlock (eclause)
6794 && !(eclause->kind == XPR_IF)
6795 && !(eclause->kind == XPR_IFELSE))
6800 ("Body of else clause of if statement is not a block: %s",
6801 exprNode_unparse (eclause)),
6802 exprNode_loc (eclause));
6806 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
6808 if (exprNode_isDefined (eclause)
6809 && (eclause->kind == XPR_IF))
6811 voptgenerror (FLG_ELSEIFCOMPLETE,
6812 message ("Incomplete else if logic (no final else): %s",
6813 exprNode_unparse (eclause)),
6814 exprNode_loc (eclause));
6818 if (exprNode_isError (pred))
6820 if (exprNode_isError (tclause))
6822 if (exprNode_isError (eclause))
6824 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6828 ret = exprNode_createPartialCopy (eclause);
6833 ret = exprNode_createPartialCopy (tclause);
6836 else /* pred is okay */
6838 ret = exprNode_createPartialCopy (pred);
6840 if (exprNode_mustEscape (pred))
6844 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6845 exprNode_loc (pred));
6848 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6849 exprNode_checkUse (ret, pred->sref, pred->loc);
6851 exprNode_mergeCondUSs (ret, tclause, eclause);
6854 ret->kind = XPR_IFELSE;
6855 ret->edata = exprData_makeCond (pred, tclause, eclause);
6857 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
6859 exprNode_combineControl (ret, tclause, eclause);
6860 ret->loc = fileloc_update (ret->loc, eclause->loc);
6867 ** *allpaths <- TRUE iff all executions paths must go through the switch
6871 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
6873 exprNodeSList el = exprNode_flatten (e);
6874 bool mustReturn = TRUE; /* find a branch that doesn't */
6875 bool thisReturn = FALSE;
6876 bool hasDefault = FALSE;
6877 bool hasAllMembers = FALSE;
6878 bool inSwitch = FALSE;
6879 bool isEnumSwitch = FALSE;
6880 bool canBreak = FALSE;
6881 bool fallThrough = FALSE;
6882 ctype ct = ctype_unknown;
6883 enumNameSList usedEnums;
6886 if (exprNode_isDefined (test))
6891 ttype = ctype_realType (ct);
6893 if (ctype_isEnum (ttype))
6895 isEnumSwitch = TRUE;
6896 enums = ctype_elist (ttype);
6897 usedEnums = enumNameSList_new ();
6901 exprNodeSList_elements (el, current)
6903 if (exprNode_isDefined (current))
6905 switch (current->kind)
6913 message ("Duplicate default cases in switch"),
6914 exprNode_loc (current));
6919 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
6927 exprNode st = exprData_getSingle (current->edata);
6928 uentry ue = exprNode_getUentry (st);
6930 if (uentry_isValid (ue))
6932 cstring cname = uentry_rawName (ue);
6934 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
6936 if (enumNameSList_member
6937 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
6941 message ("Duplicate case in switch: %s",
6947 enumNameSList_addh (usedEnums, cname);
6954 message ("Case in switch not %s member: %s",
6955 ctype_unparse (ct), cname),
6962 if (inSwitch && !fallThrough)
6964 if (!thisReturn || canBreak)
6974 /*@switchbreak@*/ break;
6976 thisReturn = thisReturn || exprNode_mustEscape (current);
6977 canBreak = canBreak || current->canBreak;
6978 if (canBreak) fallThrough = FALSE;
6981 } end_exprNodeSList_elements;
6983 if (inSwitch) /* check the last one! */
6985 if (!thisReturn || canBreak)
6994 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
6995 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
6997 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
6999 voptgenerror (FLG_MISSCASE,
7000 message ("Missing case%s in switch: %q",
7001 cstring_makeLiteralTemp
7002 ((enumNameSList_size (unused) > 1) ? "s" : ""),
7003 enumNameSList_unparse (unused)),
7006 enumNameSList_free (unused);
7010 hasAllMembers = TRUE;
7014 enumNameSList_free (usedEnums);
7018 *allpaths = hasDefault;
7021 exprNodeSList_free (el);
7022 return ((hasDefault || hasAllMembers) && mustReturn);
7025 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
7027 exprNode ret = exprNode_createPartialCopy (e);
7030 DPRINTF (("Switch: %s", exprNode_unparse (s)));
7032 ret->kind = XPR_SWITCH;
7033 ret->edata = exprData_makePair (e, s);
7035 if (!exprNode_isError (s))
7037 exprNode fs = exprNode_firstStatement (s);
7038 ret->loc = fileloc_update (ret->loc, s->loc);
7040 if (exprNode_isUndefined (fs)
7041 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
7042 || exprNode_isDefaultMarker (fs)) {
7045 voptgenerror (FLG_FIRSTCASE,
7047 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
7052 if (!exprNode_isError (e))
7054 if (checkSwitchExpr (e, s, &allpaths))
7056 ret->exitCode = XK_MUSTRETURN;
7060 ret->exitCode = e->exitCode;
7063 ret->canBreak = e->canBreak;
7064 ret->mustBreak = e->mustBreak;
7068 ** exprNode.c:3883,32: Variable allpaths used before definition
7075 DPRINTF (("Context exit switch!"));
7076 context_exitSwitch (ret, allpaths);
7077 DPRINTF (("Context exit switch done!"));
7082 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
7083 /*@notnull@*/ exprNode body)
7085 sRefSet tuses = test->uses;
7087 if (!sRefSet_isEmpty (test->uses))
7089 sRefSet sets = sRefSet_newCopy (body->sets);
7090 bool hasError = TRUE;
7091 bool innerState = FALSE;
7092 sRefSet tuncon = sRefSet_undefined;
7094 sets = sRefSet_union (sets, test->sets);
7095 sets = sRefSet_union (sets, body->msets);
7096 sets = sRefSet_union (sets, test->msets);
7098 sRefSet_allElements (tuses, el)
7100 if (sRef_isUnconstrained (el))
7102 tuncon = sRefSet_insert (tuncon, el);
7106 if (sRefSet_member (sets, el))
7113 if (sRef_isInternalState (el)
7114 || sRef_isFileStatic (sRef_getRootBase (el)))
7118 } end_sRefSet_allElements ;
7122 sRefSet suncon = sRefSet_undefined;
7123 bool sinner = FALSE;
7125 sRefSet_allElements (sets, el)
7127 if (sRef_isUnconstrained (el))
7129 suncon = sRefSet_insert (suncon, el);
7131 else if (sRef_isInternalState (el))
7139 } end_sRefSet_allElements ;
7141 if (sinner && innerState)
7145 else if (sRefSet_isEmpty (tuncon)
7146 && sRefSet_isEmpty (suncon))
7151 ("Suspected infinite loop. No value used in loop test (%q) "
7152 "is modified by test or loop body.",
7153 sRefSet_unparsePlain (tuses)),
7158 if (sRefSet_isEmpty (tuncon))
7162 message ("Suspected infinite loop. No condition values "
7163 "modified. Modification possible through "
7164 "unconstrained calls: %q",
7165 sRefSet_unparsePlain (suncon)),
7172 message ("Suspected infinite loop. No condition values "
7173 "modified. Possible undetected dependency through "
7174 "unconstrained calls in loop test: %q",
7175 sRefSet_unparsePlain (tuncon)),
7181 sRefSet_free (sets);
7185 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7188 bool emptyErr = FALSE;
7190 if (context_maybeSet (FLG_WHILEEMPTY))
7192 if (exprNode_isEmptyStatement (b))
7194 emptyErr = optgenerror
7197 ("Body of while statement is empty"),
7202 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7204 if (exprNode_isDefined (b)
7205 && !exprNode_isBlock (b))
7207 if (context_inIterDef ()
7208 && (b->kind == XPR_STMTLIST
7209 || b->kind == XPR_TOK))
7215 voptgenerror (FLG_WHILEBLOCK,
7217 ("Body of while statement is not a block: %s",
7218 exprNode_unparse (b)),
7224 if (exprNode_isError (t))
7226 if (exprNode_isError (b))
7228 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7232 ret = exprNode_createPartialCopy (b);
7239 ret = exprNode_createPartialCopy (t);
7241 llassert (t->kind == XPR_WHILEPRED);
7243 test = exprData_getSingle (t->edata);
7245 if (!exprNode_isError (b) && exprNode_isDefined (test))
7247 if (context_maybeSet (FLG_INFLOOPS)
7248 || context_maybeSet (FLG_INFLOOPSUNCON))
7251 ** check that some variable in the predicate is set by the body
7252 ** if the predicate uses any variables
7255 checkInfiniteLoop (test, b);
7258 exprNode_mergeUSs (ret, b);
7260 if (exprNode_isDefined (b))
7262 ret->exitCode = exitkind_makeConditional (b->exitCode);
7267 ret->edata = exprData_makePair (t, b);
7268 ret->kind = XPR_WHILE;
7270 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7274 message ("Predicate always exits: %s", exprNode_unparse (t)),
7278 ret->exitCode = XK_NEVERESCAPE;
7281 ** If loop is infinite, and there is no break inside,
7282 ** exit code is never reach.
7285 if (exprNode_knownIntValue (t))
7287 if (!exprNode_isZero (t))
7289 if (exprNode_isDefined (b))
7293 /* Really, it means never reached. */
7294 ret->exitCode = XK_MUSTEXIT;
7304 ret->canBreak = FALSE;
7305 ret->mustBreak = FALSE;
7311 ** do { b } while (t);
7313 ** note: body passed as first argument
7316 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7320 DPRINTF (("Do while: %s / %s",
7321 exprNode_unparse (b), exprNode_unparse (t)));
7323 if (exprNode_isError (t))
7325 if (exprNode_isError (b))
7327 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7331 ret = exprNode_createPartialCopy (b);
7333 ret->exitCode = exitkind_makeConditional (b->exitCode);
7334 exprNode_checkUse (ret, b->sref, b->loc);
7335 ret->exitCode = b->exitCode;
7336 ret->canBreak = b->canBreak;
7337 ret->mustBreak = FALSE;
7342 DPRINTF (("Do while: %s / %s",
7343 exitkind_unparse (t->exitCode),
7344 exitkind_unparse (b->exitCode)));
7346 ret = exprNode_createPartialCopy (t);
7347 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7349 if (!exprNode_isError (b))
7352 ** forgot the copy's --- why wasn't this detected??
7355 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7356 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7357 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
7359 /* left this out --- causes and aliasing bug (infinite loop)
7360 should be detected?? */
7362 exprNode_checkUse (ret, b->sref, b->loc);
7363 exprNode_mergeUSs (ret, t);
7364 exprNode_checkUse (ret, t->sref, t->loc);
7366 /* evans 2001-10-05: while loop can break */
7367 ret->exitCode = exitkind_makeConditional (b->exitCode);
7369 DPRINTF (("Do while: %s",
7370 exitkind_unparse (ret->exitCode)));
7372 ret->canBreak = b->canBreak;
7374 /* Always FALSE for doWhile loops - break's when test is false */
7375 ret->mustBreak = FALSE; /* b->mustBreak; */
7379 context_exitDoWhileClause (t);
7381 ret->kind = XPR_DOWHILE;
7382 ret->edata = exprData_makePair (t, b);
7386 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7389 bool emptyErr = FALSE;
7391 if (context_maybeSet (FLG_FOREMPTY))
7393 if (exprNode_isEmptyStatement (body))
7395 emptyErr = optgenerror
7398 ("Body of for statement is empty"),
7399 exprNode_loc (body));
7403 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7405 if (exprNode_isDefined (body)
7406 && !exprNode_isBlock (body))
7408 if (context_inIterDef ()
7409 && (body->kind == XPR_STMTLIST
7410 || body->kind == XPR_TOK))
7416 voptgenerror (FLG_FORBLOCK,
7418 ("Body of for statement is not a block: %s",
7419 exprNode_unparse (body)),
7420 exprNode_loc (body));
7426 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7429 if (exprNode_isError (body))
7431 ret = exprNode_createPartialCopy (inc);
7435 ret = exprNode_createPartialCopy (body);
7437 ret->exitCode = exitkind_makeConditional (body->exitCode);
7439 exprNode_mergeUSs (inc, body);
7441 if (exprNode_isDefined (inc))
7445 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7448 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7449 exprNode_freeShallow (tmp);
7451 context_clearMessageAnnote ();
7452 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7454 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7455 exprNode_freeShallow (tmp);
7457 context_clearMessageAnnote ();
7459 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7460 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7461 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7465 ret->kind = XPR_FOR;
7466 ret->edata = exprData_makePair (inc, body);
7468 if (exprNode_isDefined (inc)) {
7469 exprNode test = exprData_getTripleTest (inc->edata);
7471 if (exprNode_isUndefined (test)) {
7472 if (exprNode_isDefined (body)) {
7473 if (!body->canBreak) {
7474 /* Really, it means never reached. */
7475 ret->exitCode = XK_MUSTEXIT;
7485 ** for (init; test; inc)
7488 ** while (test) { body; inc; }
7490 ** Now: check use of init (may set vars for test)
7491 ** check use of test
7495 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7499 if (exprNode_isError (pred)) return guardSet_undefined;
7501 llassert (pred->kind == XPR_FORPRED);
7503 test = exprData_getTripleTest (pred->edata);
7505 if (!exprNode_isError (test))
7507 return (test->guards);
7510 return guardSet_undefined;
7513 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7515 exprNode ret = exprNode_createSemiCopy (test);
7517 if (exprNode_isDefined (test))
7519 exprNode_copySets (ret, test);
7520 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7521 exprNode_checkUse (ret, test->sref, test->loc);
7523 exprNode_produceGuards (test);
7525 ret->guards = guardSet_copy (test->guards);
7528 ret->edata = exprData_makeSingle (test);
7529 ret->kind = XPR_WHILEPRED;
7533 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7534 /*@only@*/ exprNode inc)
7539 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7542 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7544 if (!exprNode_isError (inc))
7546 ret = exprNode_createPartialCopy (inc);
7550 if (!exprNode_isError (init))
7552 ret = exprNode_createPartialCopy (init);
7554 else if (!exprNode_isError (test))
7556 ret = exprNode_createPartialCopy (test);
7560 ret = exprNode_createUnknown ();
7564 exprNode_mergeUSs (ret, init);
7566 if (exprNode_isDefined (init))
7568 exprNode_checkUse (ret, init->sref, init->loc);
7571 exprNode_mergeUSs (ret, test);
7573 if (exprNode_isDefined (test))
7575 exprNode_checkUse (ret, test->sref, test->loc);
7578 ret->kind = XPR_FORPRED;
7579 ret->edata = exprData_makeFor (init, test, inc);
7583 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7585 exprNode ret = exprNode_createUnknown ();
7587 if (context_inMacro ())
7589 voptgenerror (FLG_MACROSTMT,
7590 message ("Macro %s uses goto (not functional)",
7591 context_inFunctionName ()),
7595 ret->kind = XPR_GOTO;
7596 ret->edata = exprData_makeLiteral (label);
7597 ret->mustBreak = TRUE;
7598 ret->exitCode = XK_GOTO;
7599 ret->canBreak = TRUE;
7603 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7605 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7607 ret->kind = XPR_CONTINUE;
7608 ret->edata = exprData_makeTok (l);
7609 ret->canBreak = TRUE;
7610 ret->mustBreak = TRUE;
7612 if (qcontinue == QSAFEBREAK)
7616 else if (qcontinue == QINNERCONTINUE)
7618 if (!context_inDeepLoop ())
7621 (FLG_LOOPLOOPCONTINUE,
7622 cstring_makeLiteral ("Continue statement marked with innercontinue "
7623 "is not inside a nested loop"),
7624 exprNode_loc (ret));
7627 else if (qcontinue == BADTOK)
7629 if (context_inDeepLoop ())
7632 (FLG_LOOPLOOPCONTINUE,
7633 cstring_makeLiteral ("Continue statement in nested loop"),
7634 exprNode_loc (ret));
7639 llbuglit ("exprNode_continue: bad qcontinue");
7645 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
7647 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7648 clause breakClause = context_breakClause ();
7650 ret->kind = XPR_BREAK;
7651 ret->edata = exprData_makeTok (l);
7652 ret->canBreak = TRUE;
7653 ret->mustBreak = TRUE;
7655 if (breakClause == NOCLAUSE)
7659 cstring_makeLiteral ("Break not inside while, for or switch statement"),
7660 exprNode_loc (ret));
7664 if (bqual != BADTOK)
7671 if (breakClause == SWITCHCLAUSE)
7673 if (!context_inDeepSwitch ())
7675 voptgenerror (FLG_SYNTAX,
7677 ("Break preceded by innerbreak is not in a deep switch"),
7678 exprNode_loc (ret));
7683 if (!context_inDeepLoop ())
7685 voptgenerror (FLG_SYNTAX,
7687 ("Break preceded by innerbreak is not in a deep loop"),
7688 exprNode_loc (ret));
7693 if (breakClause == SWITCHCLAUSE)
7695 voptgenerror (FLG_SYNTAX,
7697 ("Break preceded by loopbreak is breaking a switch"),
7698 exprNode_loc (ret));
7702 if (breakClause != SWITCHCLAUSE)
7706 message ("Break preceded by switchbreak is breaking %s",
7707 cstring_makeLiteralTemp
7708 ((breakClause == WHILECLAUSE
7709 || breakClause == DOWHILECLAUSE) ? "a while loop"
7710 : (breakClause == FORCLAUSE) ? "a for loop"
7711 : (breakClause == ITERCLAUSE) ? "an iterator"
7713 exprNode_loc (ret));
7721 if (breakClause == SWITCHCLAUSE)
7723 clause nextBreakClause = context_nextBreakClause ();
7725 switch (nextBreakClause)
7727 case NOCLAUSE: break;
7733 (FLG_LOOPSWITCHBREAK,
7734 cstring_makeLiteral ("Break statement in switch inside loop"),
7735 exprNode_loc (ret));
7739 (FLG_SWITCHSWITCHBREAK,
7740 cstring_makeLiteral ("Break statement in switch inside switch"),
7741 exprNode_loc (ret));
7748 if (context_inDeepLoop ())
7752 cstring_makeLiteral ("Break statement in nested loop"),
7753 exprNode_loc (ret));
7757 if (context_inDeepLoopSwitch ())
7760 (FLG_SWITCHLOOPBREAK,
7761 cstring_makeLiteral ("Break statement in loop inside switch"),
7762 exprNode_loc (ret));
7772 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
7774 fileloc loc = lltok_getLoc (t);
7775 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
7777 context_returnFunction ();
7778 exprChecks_checkNullReturn (loc);
7780 ret->kind = XPR_NULLRETURN;
7781 ret->edata = exprData_makeTok (t);
7782 ret->exitCode = XK_MUSTRETURN;
7786 exprNode exprNode_return (/*@only@*/ exprNode e)
7790 if (exprNode_isError (e))
7792 ret = exprNode_createUnknown ();
7796 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
7798 exprNode_checkUse (ret, e->sref, e->loc);
7799 exprNode_checkReturn (e);
7802 context_returnFunction ();
7803 ret->kind = XPR_RETURN;
7804 ret->edata = exprData_makeSingle (e);
7805 ret->exitCode = XK_MUSTRETURN;
7810 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
7814 if (exprNode_isError (e1))
7816 if (exprNode_isError (e2))
7818 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7822 ret = exprNode_createPartialCopy (e2);
7823 exprNode_checkUse (ret, e2->sref, e2->loc);
7824 ret->sref = e2->sref;
7829 ret = exprNode_createPartialCopy (e1);
7831 exprNode_checkUse (ret, e1->sref, e1->loc);
7833 if (!exprNode_isError (e2))
7835 exprNode_mergeUSs (ret, e2);
7836 exprNode_checkUse (ret, e2->sref, e2->loc);
7837 ret->sref = e2->sref;
7841 ret->kind = XPR_COMMA;
7842 ret->edata = exprData_makePair (e1, e2);
7844 if (exprNode_isDefined (e1))
7846 if (exprNode_isDefined (e2))
7850 if (exprNode_mustEscape (e1) || e1->mustBreak)
7854 message ("Second clause of comma expression is unreachable: %s",
7855 exprNode_unparse (e2)),
7859 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
7860 ret->mustBreak = e1->mustBreak || e2->mustBreak;
7861 ret->canBreak = e1->canBreak || e2->canBreak;
7865 if (exprNode_mustEscape (e1) || e1->mustBreak)
7869 message ("Second clause of comma expression is unreachable: %s",
7870 exprNode_unparse (e2)),
7874 ret->exitCode = e1->exitCode;
7875 ret->canBreak = e1->canBreak;
7880 if (exprNode_isDefined (e2))
7882 ret->exitCode = e2->exitCode;
7883 ret->mustBreak = e2->mustBreak;
7884 ret->canBreak = e2->canBreak;
7891 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
7893 ctype t1 = exprNode_getType (el);
7894 ctype t2 = exprNode_getType (val);
7895 bool hasError = FALSE;
7897 if (ctype_isUnknown (t1))
7899 voptgenerror (FLG_IMPTYPE,
7900 message ("Variable has unknown (implicitly int) type: %s",
7901 exprNode_unparse (el)),
7905 el->typ = ctype_int;
7908 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
7910 exprNodeList vals = exprData_getArgs (val->edata);
7912 DPRINTF (("Check one init: %s", exprNodeList_unparse (vals)));
7913 DPRINTF (("Type: %s", ctype_unparse (t1)));
7915 if (ctype_isRealAP (t1))
7920 if (ctype_isFixedArray (t1))
7922 int nelements = long_toInt (ctype_getArraySize (t1));
7924 if (exprNode_isStringLiteral (val))
7926 exprNode_checkStringLiteralLength (t1, val);
7930 if (exprNodeList_size (vals) != nelements)
7932 hasError = optgenerror
7933 (exprNodeList_size (vals) > nelements ? FLG_INITSIZE : FLG_INITALLELEMENTS,
7934 message ("Initializer block for "
7935 "%s has %d element%&, but declared as %s: %q",
7936 exprNode_unparse (el),
7937 exprNodeList_size (vals),
7939 exprNodeList_unparse (vals)),
7945 exprNodeList_elements (vals, oneval)
7947 cstring istring = message ("%d", i);
7950 (exprNode_fakeCopy (el),
7951 exprNode_numLiteral (ctype_int, istring,
7952 fileloc_copy (el->loc), i));
7954 if (exprNode_isDefined (newel))
7956 if (exprNodeList_size (vals) == 1
7957 && ctype_isString (exprNode_getType (oneval))
7958 && ctype_isChar (exprNode_getType (newel)))
7960 exprNode_freeIniter (newel);
7964 if (exprNode_checkOneInit (newel, oneval))
7969 if (nerrors > 3 && exprNodeList_size (vals) > 6)
7972 (message ("Additional initialization errors "
7973 "for %s not reported",
7974 exprNode_unparse (el)),
7976 exprNode_freeIniter (newel);
7981 exprNode_freeIniter (newel);
7986 exprNode_freeIniter (newel);
7991 cstring_free (istring);
7994 } end_exprNodeList_elements;
7997 else if (ctype_isStruct (ctype_realType (t1)))
7999 uentryList fields = ctype_getFields (t1);
8002 if (uentryList_size (fields) != exprNodeList_size (vals))
8004 if (uentryList_size (fields) > exprNodeList_size (vals))
8006 hasError = optgenerror
8008 message ("Initializer block for "
8009 "%s has %d field%&, but %s has %d field%&: %q",
8010 exprNode_unparse (el),
8011 exprNodeList_size (vals),
8013 uentryList_size (fields),
8014 exprNodeList_unparse (vals)),
8019 hasError = optgenerror
8021 message ("Initializer block for "
8022 "%s has %d field%&, but %s has %d field%&: %q",
8023 exprNode_unparse (el),
8024 exprNodeList_size (vals),
8026 uentryList_size (fields),
8027 exprNodeList_unparse (vals)),
8033 exprNodeList_elements (vals, oneval)
8035 uentry thisfield = uentryList_getN (fields, i);
8037 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8039 uentry_getName (thisfield));
8041 if (exprNode_isDefined (newel))
8043 if (exprNode_checkOneInit (newel, oneval))
8048 exprNode_freeIniter (newel);
8052 } end_exprNodeList_elements;
8057 hasError = optgenerror
8059 message ("Initializer block used for "
8060 "%s where %t is expected: %s",
8061 exprNode_unparse (el), t1, exprNode_unparse (val)),
8067 if (exprNode_isDefined (val))
8069 doAssign (el, val, TRUE);
8071 if (!exprNode_matchType (t1, val))
8073 hasError = gentypeerror
8075 message ("Initial value of %s is type %t, "
8077 exprNode_unparse (el),
8078 t2, t1, exprNode_unparse (val)),
8088 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
8092 if (usymtab_exists (idDecl_observeId (t)))
8094 uentry ue = usymtab_lookup (idDecl_observeId (t));
8095 ret = exprNode_createId (ue);
8097 /*@i723 don't do this...but why? */
8099 ct = ctype_realishType (ret->typ);
8101 DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
8103 if (ctype_isUnknown (ct))
8105 if (uentry_isAnyTag (ue))
8109 message ("%s used but not previously declared: %s",
8110 uentry_ekindName (ue),
8111 idDecl_getName (t)),
8119 message ("Variable has unknown (implicitly int) type: %s",
8120 idDecl_getName (t)),
8132 DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
8134 ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
8135 /*!! fileloc_copy (g_currentloc)); */
8136 /*@i32!!! should get error without this */
8137 ret = exprNode_fromIdentifierAux (ue);
8140 ** No error - this happens in old style declarations:
8144 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8151 exprData_free (ret->edata, ret->kind);
8152 ret->edata = exprData_undefined;
8154 ret->exitCode = XK_NEVERESCAPE;
8155 ret->mustBreak = FALSE;
8156 ret->kind = XPR_INIT;
8160 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8162 exprNode ret = exprNode_makeInitializationAux (t);
8163 llassert (ret->edata == exprData_undefined);
8164 ret->edata = exprData_makeInit (t, exprNode_undefined);
8168 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8169 /*@only@*/ exprNode e)
8171 uentry ue = usymtab_lookup (idDecl_observeId (t));
8172 exprNode ret = exprNode_makeInitializationAux (t);
8173 fileloc loc = exprNode_loc (e);
8175 if (exprNode_isError (e))
8177 e = exprNode_createUnknown ();
8180 /* error: assume initializer is defined */
8181 sRef_setDefined (ret->sref, g_currentloc);
8185 ctype ct = ctype_realishType (ret->typ);
8190 ** was addSafeUse --- what's the problem?
8192 ** int x = 3, y = x ?
8195 exprData_free (ret->edata, ret->kind);
8196 ret->edata = exprData_makeInit (t, e);
8198 exprNode_checkUse (ret, e->sref, e->loc);
8200 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8202 exprNode lhs = exprNode_createId (ue);
8205 ** static storage should be undefined before initializing
8208 if (uentry_isStatic (ue))
8210 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8213 (void) exprNode_checkOneInit (lhs, e);
8215 if (uentry_isStatic (ue))
8217 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8220 exprNode_free (lhs);
8224 if (!exprNode_matchType (ct, e))
8226 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
8233 (exprNode_getType (e), e, exprNode_getType (ret), ret,
8235 ("Variable %q initialized to type %t, expects %t: %s",
8236 uentry_getName (ue), exprNode_getType (e),
8237 exprNode_getType (ret),
8238 exprNode_unparse (e)),
8244 if (uentry_isStatic (ue))
8246 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8249 doAssign (ret, e, TRUE);
8251 if (uentry_isStatic (ue))
8253 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8257 if (context_inIterDef ())
8259 /* should check if it is yield */
8260 uentry_setUsed (ue, loc);
8267 exprNode_mergeUSs (ret, e);
8271 exprNode exprNode_iter (/*@observer@*/ uentry name,
8272 /*@only@*/ exprNodeList alist,
8273 /*@only@*/ exprNode body,
8274 /*@observer@*/ uentry end)
8279 llassert (uentry_isValid (name));
8281 uentry_setUsed (name, exprNode_loc (body));
8283 ret = exprNode_createPartialCopy (body);
8284 iname = uentry_getName (name);
8286 if (uentry_isInvalid (end))
8289 message ("Iter %s not balanced with end_%s", iname, iname));
8293 cstring ename = uentry_getName (end);
8295 if (!cstring_equalPrefixLit (ename, "end_"))
8297 llerror (FLG_ITER, message ("Iter %s not balanced with end_%s: %s",
8298 iname, iname, ename));
8302 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8305 message ("Iter %s not balanced with end_%s: %s",
8306 iname, iname, ename));
8310 cstring_free (ename);
8313 context_exitIterClause (body);
8315 ret->kind = XPR_ITER;
8316 ret->edata = exprData_makeIter (name, alist, body, end);
8318 if (uentry_isIter (name))
8320 (void) checkArgsReal (name, body,
8321 uentry_getParams (name), alist, TRUE, ret);
8324 cstring_free (iname);
8330 exprNode_iterNewId (/*@only@*/ cstring s)
8332 exprNode e = exprNode_new ();
8333 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8335 llassert (processingIterVars ());
8337 e->loc = context_getSaveLocation ();
8339 if (fileloc_isUndefined (e->loc))
8341 fileloc_free (e->loc);
8342 e->loc = fileloc_copy (g_currentloc);
8345 e->uses = sRefSet_new ();
8346 e->sets = sRefSet_new ();
8347 e->msets = sRefSet_new ();
8349 e->val = multiVal_unknown ();
8350 e->guards = guardSet_new ();
8352 e->isJumpPoint = FALSE;
8353 e->exitCode = XK_NEVERESCAPE;
8355 /*> missing fields, detected by lclint <*/
8356 e->canBreak = FALSE;
8357 e->mustBreak = FALSE;
8358 e->etext = cstring_undefined;
8360 if (uentry_isYield (ue))
8362 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8363 fileloc_copy (e->loc),
8367 uue = usymtab_supEntrySrefReturn (uue);
8369 sr = uentry_getSref (uue);
8370 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8371 sr = uentry_getSref (uue);
8372 sRef_setDefined (sr, e->loc);
8374 e->typ = uentry_getType (uue);
8376 e->edata = exprData_makeId (uue);
8377 uentry_setUsed (uue, g_currentloc);
8383 sRef_setGlobalScope ();
8384 uue = uentry_makeVariableLoc (s, ctype_unknown);
8386 e->typ = ctype_unknown;
8387 e->edata = exprData_makeId (uue);
8389 uentry_setUsed (uue, e->loc);
8390 uentry_setHasNameError (uue);
8392 if (context_getFlag (FLG_REPEATUNRECOG))
8394 uentry_markOwned (uue);
8398 usymtab_supGlobalEntry (uue);
8401 sRef_clearGlobalScope ();
8403 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8410 exprNode_defineConstraints(e);
8415 exprNode_iterExpr (/*@returned@*/ exprNode e)
8417 if (!processingIterVars ())
8419 llcontbuglit ("checkIterParam: not in iter");
8423 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8426 if (exprNode_isDefined (e))
8428 if (fileloc_isDefined (e->loc))
8432 message ("Yield parameter is not simple identifier: %s",
8433 exprNode_unparse (e)),
8440 message ("Yield parameter is not simple identifier: %s",
8441 exprNode_unparse (e)),
8451 exprNode_iterId (/*@observer@*/ uentry c)
8455 llassert (processingIterVars ());
8457 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8460 if (uentry_isYield (ue))
8462 ctype ct = uentry_getType (ue);
8463 exprNode e = exprNode_createPlain (ct);
8464 cstring name = uentry_getName (c);
8465 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8467 uentry_setUsed (ue, g_currentloc);
8468 uentry_setHasNameError (ue);
8470 cstring_free (name);
8473 e->edata = exprData_makeId (le);
8474 e->loc = context_getSaveLocation ();
8475 e->sref = uentry_getSref (le);
8477 usymtab_supEntrySref (le);
8479 if (!context_inHeader ())
8483 message ("Yield parameter shadows local declaration: %q",
8484 uentry_getName (c)),
8485 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8487 uentry_showWhereDeclared (c);
8494 return (exprNode_fromIdentifierAux (c));
8497 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8499 exprNode ret = exprNode_create (ctype_unknown);
8501 ret->kind = XPR_ITERCALL;
8502 ret->edata = exprData_makeIterCall (name, alist);
8504 if (uentry_isIter (name))
8506 uentryList params = uentry_getParams (name);
8508 if (context_inIterDef ()
8509 && uentryList_size (params) == exprNodeList_size (alist))
8513 exprNodeList_elements (alist, arg)
8515 uentry parg = uentryList_getN (params, i);
8517 if (uentry_isYield (parg))
8519 uentry ue = exprNode_getUentry (arg);
8521 if (uentry_isValid (ue))
8528 } end_exprNodeList_elements;
8531 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8532 checkUnspecCall (ret, params, alist);
8538 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8540 if (exprNode_isDefined (e))
8543 if (e->sref == defref) /*@noaccess sRef@*/
8546 e->sref = sRef_makeUnknown ();
8547 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8558 return sRef_undefined;
8562 /*@observer@*/ cstring
8563 exprNode_unparseFirst (exprNode e)
8565 if (exprNode_isDefined (e))
8569 if (e->kind == XPR_STMTLIST
8570 || e->kind == XPR_COMMA || e->kind == XPR_COND)
8572 exprNode first = exprData_getPairA (e->edata);
8574 if (exprNode_isDefined (first))
8576 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8580 return (cstring_makeLiteralTemp ("..."));
8584 ret = cstring_elide (exprNode_unparse (e), 20);
8585 cstring_markOwned (ret);
8591 return cstring_makeLiteralTemp ("<error>");
8595 /*@observer@*/ cstring
8596 exprNode_unparse (/*@temp@*/ exprNode e)
8598 if (exprNode_isError (e))
8600 return cstring_makeLiteralTemp ("<error>");
8603 if (cstring_isDefined (e->etext))
8609 cstring ret = exprNode_doUnparse (e);
8611 /*@-modifies@*/ /* benevolent */
8618 /*@observer@*/ fileloc
8619 exprNode_loc (exprNode e)
8621 if (exprNode_isError (e))
8623 return (g_currentloc);
8632 ** executes exprNode e
8633 ** recursively rexecutes as though in original parse using
8634 ** information in e->edata
8637 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
8639 exprNodeList ret = exprNodeList_new ();
8641 exprNodeList_elements (e, current)
8643 exprNodeList_addh (ret, exprNode_effect (current));
8644 } end_exprNodeList_elements;
8649 static /*@only@*/ exprNode exprNode_effect (exprNode e)
8650 /*@globals internalState@*/
8652 bool innerEffect = inEffect;
8658 context_clearJustPopped ();
8660 if (exprNode_isError (e))
8662 ret = exprNode_undefined;
8667 ** Turn off expose and dependent transfer checking.
8668 ** Need to pass exposed internal nodes,
8669 ** [ copying would be a waste! ]
8670 ** [ Actually, I think I wasted a lot more time than its worth ]
8671 ** [ trying to do this. ]
8675 /*@-observertrans@*/
8676 /*@-dependenttrans@*/
8683 ret = exprNode_addParens (exprData_getUopTok (data),
8684 exprNode_effect (exprData_getUopNode (data)));
8687 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
8688 exprNode_effect (exprData_getOpB (data)),
8689 exprData_getOpTok (data));
8692 ret = exprNode_undefined;
8695 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
8696 exprNodeList_effect (exprData_getArgs (data)));
8709 cstring id = exprData_getId (data);
8710 uentry ue = usymtab_lookupSafe (id);
8712 ret = exprNode_fromIdentifierAux (ue);
8713 ret->loc = fileloc_update (ret->loc, e->loc);
8720 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
8721 exprNode_effect (exprData_getPairB (data)));
8724 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
8725 exprNode_effect (exprData_getOpB (data)),
8726 exprData_getOpTok (data));
8730 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
8731 exprData_getUopTok (data));
8734 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
8735 exprData_getUopTok (data));
8747 ret = exprNode_vaArg (exprData_getCastTok (data),
8748 exprNode_effect (exprData_getCastNode (data)),
8749 exprData_getCastType (data));
8753 ret = exprNode_cast (exprData_getCastTok (data),
8754 exprNode_effect (exprData_getCastNode (data)),
8755 exprData_getCastType (data));
8758 ret = exprNode_iterStart (exprData_getIterCallIter (data),
8760 (exprData_getIterCallArgs (data)));
8764 ret = exprNode_iter (exprData_getIterSname (data),
8765 exprNodeList_effect (exprData_getIterAlist (data)),
8766 exprNode_effect (exprData_getIterBody (data)),
8767 exprData_getIterEname (data));
8771 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
8772 exprNode_effect (exprData_getPairB (data)));
8776 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
8777 exprNode_effect (exprData_getTripleTest (data)),
8778 exprNode_effect (exprData_getTripleInc (data)));
8782 ret = exprNode_createTok (exprData_getTok (data));
8786 ret = exprNode_goto (exprData_getLiteral (data));
8787 ret->loc = fileloc_update (ret->loc, e->loc);
8791 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
8795 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
8799 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
8802 case XPR_NULLRETURN:
8803 ret = exprNode_nullReturn (exprData_getTok (data));
8807 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
8808 exprNode_effect (exprData_getPairB (data)));
8812 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
8813 exprNode_effect (exprData_getTripleTrue (data)),
8814 exprNode_effect (exprData_getTripleFalse (data)));
8817 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
8818 exprNode_effect (exprData_getPairB (data)));
8822 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
8823 exprNode_effect (exprData_getTripleTrue (data)),
8824 exprNode_effect (exprData_getTripleFalse (data)));
8827 ret = exprNode_whilePred (exprData_getSingle (data));
8831 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
8832 exprNode_effect (exprData_getPairB (data)));
8836 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
8837 exprNode_effect (exprData_getPairB (data)));
8841 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
8845 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
8846 exprData_getUopTok (data));
8850 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
8851 exprNode_effect (exprData_getPairB (data)));
8856 ret = exprNode_caseMarker
8857 (exprNode_effect (exprData_getSingle (data)),
8863 ret = exprNode_createTok (exprData_getTok (data));
8867 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
8868 exprNode_effect (exprData_getPairB (data)));
8872 ret = exprNode_makeInitialization
8873 (exprData_getInitId (data),
8874 exprNode_effect (exprData_getInitNode (data)));
8878 ret = exprNode_fieldAccessAux
8879 (exprNode_effect (exprData_getFieldNode (data)),
8880 exprNode_loc (exprData_getFieldNode (data)),
8881 cstring_copy (exprData_getFieldName (data)));
8885 ret = exprNode_arrowAccessAux
8886 (exprNode_effect (exprData_getFieldNode (data)),
8887 exprNode_loc (exprData_getFieldNode (data)),
8888 cstring_copy (exprData_getFieldName (data)));
8891 case XPR_STRINGLITERAL:
8905 /*@=observertrans@*/
8907 /*@=dependenttrans@*/
8918 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
8923 if (exprNode_isError (e))
8925 return cstring_undefined;
8933 ret = exprNode_rootVarName (exprData_getUopNode (data));
8936 ret = exprNode_rootVarName (exprData_getOpA (data));
8940 ret = exprData_getId (data);
8943 ret = idDecl_getName (exprData_getInitId (data));
8968 case XPR_NULLRETURN:
8990 case XPR_STRINGLITERAL:
8991 ret = cstring_undefined;
8998 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
9003 if (exprNode_isError (e))
9005 static /*@only@*/ cstring error = cstring_undefined;
9007 if (!cstring_isDefined (error))
9009 error = cstring_makeLiteral ("<error>");
9020 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
9023 ret = message ("%s %s %s",
9024 exprNode_unparse (exprData_getOpA (data)),
9025 lltok_unparse (exprData_getOpTok (data)),
9026 exprNode_unparse (exprData_getOpB (data)));
9029 ret = message ("%s(%q)",
9030 exprNode_unparse (exprData_getFcn (data)),
9031 exprNodeList_unparse (exprData_getArgs (data)));
9034 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
9037 ret = cstring_undefined;
9040 ret = message ("%s:", exprData_getId (data));
9044 ret = cstring_copy (exprData_getId (data));
9047 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
9048 exprNode_unparse (exprData_getPairB (data)));
9051 ret = message ("<body>");
9054 ret = message ("%s %s %s",
9055 exprNode_unparse (exprData_getOpA (data)),
9056 lltok_unparse (exprData_getOpTok (data)),
9057 exprNode_unparse (exprData_getOpB (data)));
9061 ret = message ("%s%s",
9062 lltok_unparse (exprData_getUopTok (data)),
9063 exprNode_unparse (exprData_getUopNode (data)));
9067 ret = message ("%s%s",
9068 exprNode_unparse (exprData_getUopNode (data)),
9069 lltok_unparse (exprData_getUopTok (data)));
9073 ret = message ("offsetof(%s,%q)",
9074 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
9075 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
9079 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9083 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
9087 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9091 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
9095 ret = message ("va_arg(%s, %q)",
9096 exprNode_unparse (exprData_getCastNode (data)),
9097 qtype_unparse (exprData_getCastType (data)));
9101 ret = message ("%q(%q)",
9102 uentry_getName (exprData_getIterCallIter (data)),
9103 exprNodeList_unparse (exprData_getIterCallArgs (data)));
9106 ret = message ("%q(%q) %s %q",
9107 uentry_getName (exprData_getIterSname (data)),
9108 exprNodeList_unparse (exprData_getIterAlist (data)),
9109 exprNode_unparse (exprData_getIterBody (data)),
9110 uentry_getName (exprData_getIterEname (data)));
9113 ret = message ("(%q)%s",
9114 qtype_unparse (exprData_getCastType (data)),
9115 exprNode_unparse (exprData_getCastNode (data)));
9119 ret = message ("%s %s",
9120 exprNode_unparse (exprData_getPairA (data)),
9121 exprNode_unparse (exprData_getPairB (data)));
9125 ret = message ("for (%s; %s; %s)",
9126 exprNode_unparse (exprData_getTripleInit (data)),
9127 exprNode_unparse (exprData_getTripleTest (data)),
9128 exprNode_unparse (exprData_getTripleInc (data)));
9132 ret = message ("goto %s", exprData_getLiteral (data));
9136 ret = cstring_makeLiteral ("continue");
9140 ret = cstring_makeLiteral ("break");
9144 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
9147 case XPR_NULLRETURN:
9148 ret = cstring_makeLiteral ("return");
9152 ret = message ("%s, %s",
9153 exprNode_unparse (exprData_getPairA (data)),
9154 exprNode_unparse (exprData_getPairB (data)));
9158 ret = message ("%s ? %s : %s",
9159 exprNode_unparse (exprData_getTriplePred (data)),
9160 exprNode_unparse (exprData_getTripleTrue (data)),
9161 exprNode_unparse (exprData_getTripleFalse (data)));
9164 ret = message ("if (%s) %s",
9165 exprNode_unparse (exprData_getPairA (data)),
9166 exprNode_unparse (exprData_getPairB (data)));
9170 ret = message ("if (%s) %s else %s",
9171 exprNode_unparse (exprData_getTriplePred (data)),
9172 exprNode_unparse (exprData_getTripleTrue (data)),
9173 exprNode_unparse (exprData_getTripleFalse (data)));
9176 ret = message ("while (%s) %s",
9177 exprNode_unparse (exprData_getPairA (data)),
9178 exprNode_unparse (exprData_getPairB (data)));
9182 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9186 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9190 ret = message ("do { %s } while (%s)",
9191 exprNode_unparse (exprData_getPairB (data)),
9192 exprNode_unparse (exprData_getPairA (data)));
9196 ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
9200 ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
9204 ret = message ("%s; %s",
9205 exprNode_unparse (exprData_getPairA (data)),
9206 exprNode_unparse (exprData_getPairB (data)));
9211 ret = cstring_makeLiteral ("default:");
9215 ret = message ("switch (%s) %s",
9216 exprNode_unparse (exprData_getPairA (data)),
9217 exprNode_unparse (exprData_getPairB (data)));
9222 ret = message ("case %s:",
9223 exprNode_unparse (exprData_getSingle (data)));
9227 if (exprNode_isError (exprData_getInitNode (data)))
9229 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9233 ret = message ("%q = %s",
9234 idDecl_unparseC (exprData_getInitId (data)),
9235 exprNode_unparse (exprData_getInitNode (data)));
9240 ret = message ("%s.%s",
9241 exprNode_unparse (exprData_getFieldNode (data)),
9242 exprData_getFieldName (data));
9246 ret = message ("%s->%s",
9247 exprNode_unparse (exprData_getFieldNode (data)),
9248 exprData_getFieldName (data));
9251 case XPR_STRINGLITERAL:
9252 ret = message ("\"%s\"", exprData_getLiteral (data));
9256 ret = cstring_copy (exprData_getLiteral (data));
9260 ret = cstring_makeLiteral ("<node>");
9268 exprNode_isInitializer (exprNode e)
9270 return (exprNode_isDefined (e)
9271 && e->kind == XPR_INIT);
9275 exprNode_isCharLit (exprNode e)
9277 if (exprNode_isDefined (e))
9279 return (multiVal_isChar (exprNode_getValue (e)));
9288 exprNode_isNumLit (exprNode e)
9290 if (exprNode_isDefined (e))
9292 return (multiVal_isInt (exprNode_getValue (e)));
9301 exprNode_isFalseConstant (exprNode e)
9303 if (exprNode_isDefined (e))
9305 cstring s = exprNode_rootVarName (e);
9307 if (cstring_equal (s, context_getFalseName ()))
9317 exprNode_matchLiteral (ctype expected, exprNode e)
9319 if (exprNode_isDefined (e))
9321 multiVal m = exprNode_getValue (e);
9323 if (multiVal_isDefined (m))
9325 if (multiVal_isInt (m))
9327 long int val = multiVal_forceInt (m);
9329 if (ctype_isDirectBool (ctype_realishType (expected)))
9333 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9341 if (ctype_isRealInt (expected))
9344 ** unsigned <- [ constant >= 0 is okay ]
9347 if (ctype_isUnsigned (expected))
9356 ** No checks on sizes of integers...maybe add
9360 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9361 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9362 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9364 if (context_getFlag (FLG_NUMLITERAL)
9365 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9371 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9375 else if (ctype_isChar (expected))
9379 else if (ctype_isArrayPtr (expected))
9382 ** evans 2001-10-14: We allow 0 to match any pointer, but only if the type matches or is void *.
9387 if (ctype_match (exprNode_getType (e), expected)
9388 || ctype_isVoidPointer (exprNode_getType (e)))
9398 else if (ctype_isAnyFloat (expected))
9400 return (context_getFlag (FLG_NUMLITERAL));
9407 else if (multiVal_isDouble (m))
9409 if (ctype_isAnyFloat (expected))
9414 else if (multiVal_isChar (m))
9416 char val = multiVal_forceChar (m);
9418 if (ctype_isChar (expected))
9420 if (ctype_isUnsigned (expected) && ((int)val) < 0)
9441 exprNode_matchType (ctype expected, exprNode e)
9445 if (!exprNode_isDefined (e)) return TRUE;
9447 actual = ctype_realishType (exprNode_getType (e));
9449 if (ctype_match (ctype_realishType (expected), actual))
9454 llassert (!exprNode_isError (e));
9455 return (exprNode_matchLiteral (expected, e));
9459 exprNode_matchTypes (exprNode e1, exprNode e2)
9464 if (!exprNode_isDefined (e1)) return TRUE;
9465 if (!exprNode_isDefined (e2)) return TRUE;
9468 ** realish type --- keep bools, bools
9471 t1 = ctype_realishType (exprNode_getType (e1));
9472 t2 = ctype_realishType (exprNode_getType (e2));
9474 if (ctype_match (t1, t2))
9479 DPRINTF (("Matching literal! %s %s %s %s",
9480 ctype_unparse (t1), exprNode_unparse (e2),
9481 ctype_unparse (t2), exprNode_unparse (e1)));
9483 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9491 exprNode_matchArgType (ctype ct, exprNode e)
9495 if (!exprNode_isDefined (e))
9500 et = ctype_realType (exprNode_getType (e));
9502 if (ctype_matchArg (ct, et)) return TRUE;
9504 llassert (!exprNode_isError (e));
9505 return (exprNode_matchLiteral (ct, e));
9508 static /*@only@*/ exprNodeSList
9509 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9511 if (exprNode_isDefined (e))
9513 if (e->kind == XPR_STMTLIST)
9515 return (exprNodeSList_append
9516 (exprNode_flatten (exprData_getPairA (e->edata)),
9517 exprNode_flatten (exprData_getPairB (e->edata))));
9519 else if (e->kind == XPR_BLOCK)
9521 return (exprNode_flatten (exprData_getSingle (e->edata)));
9525 return (exprNodeSList_singleton (e));
9529 return exprNodeSList_new ();
9532 static /*@exposed@*/ exprNode
9533 exprNode_lastStatement (/*@returned@*/ exprNode e)
9535 if (exprNode_isDefined (e))
9537 if (e->kind == XPR_STMTLIST)
9539 exprNode b = exprData_getPairB (e->edata);
9541 if (exprNode_isDefined (b))
9543 return exprNode_lastStatement (b);
9547 return exprNode_lastStatement (exprData_getPairA (e->edata));
9550 else if (e->kind == XPR_BLOCK)
9552 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
9560 return exprNode_undefined;
9563 static /*@exposed@*/ exprNode
9564 exprNode_firstStatement (/*@returned@*/ exprNode e)
9566 if (exprNode_isDefined (e))
9568 if (e->kind == XPR_STMTLIST)
9570 exprNode b = exprData_getPairA (e->edata);
9572 if (exprNode_isDefined (b))
9574 return exprNode_firstStatement (b);
9578 return exprNode_firstStatement (exprData_getPairB (e->edata));
9581 else if (e->kind == XPR_BLOCK)
9583 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
9591 return exprNode_undefined;
9595 exprNode_mergeUSs (exprNode res, exprNode other)
9597 if (exprNode_isDefined (res) && exprNode_isDefined (other))
9599 res->msets = sRefSet_union (res->msets, other->msets);
9600 res->sets = sRefSet_union (res->sets, other->sets);
9601 res->uses = sRefSet_union (res->uses, other->uses);
9606 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
9608 if (exprNode_isDefined (res))
9610 if (exprNode_isDefined (other1))
9612 res->sets = sRefSet_union (res->sets, other1->sets);
9613 res->msets = sRefSet_union (res->msets, other1->msets);
9614 res->uses = sRefSet_union (res->uses, other1->uses);
9616 if (exprNode_isDefined (other2))
9618 res->sets = sRefSet_union (res->sets, other2->sets);
9619 res->msets = sRefSet_union (res->msets, other2->msets);
9620 res->uses = sRefSet_union (res->uses, other2->uses);
9628 ** Reports errors is s is not defined.
9632 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
9634 if (exprNode_isDefined (e))
9636 e->uses = sRefSet_insert (e->uses, s);
9641 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
9643 if (sRef_isKnown (s) && !sRef_isConst (s))
9646 ** need to check all outer types are useable
9649 DPRINTF (("Check use: %s / %s",
9650 exprNode_unparse (e), sRef_unparse (s)));
9652 exprNode_addUse (e, s);
9654 if (!context_inProtectVars ())
9657 ** only report the deepest error
9660 sRef errorRef = sRef_undefined;
9661 sRef lastRef = sRef_undefined;
9662 bool deadRef = FALSE;
9663 bool unuseable = FALSE;
9664 bool errorMaybe = FALSE;
9666 while (sRef_isValid (s) && sRef_isKnown (s))
9668 ynm readable = sRef_isReadable (s);
9670 DPRINTF (("Readable: %s / %s",
9671 sRef_unparseFull (s), ynm_unparse (readable)));
9673 if (!(ynm_toBoolStrict (readable)))
9675 if (ynm_isMaybe (readable))
9679 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
9680 deadRef = sRef_isPossiblyDead (errorRef);
9681 unuseable = sRef_isUnuseable (errorRef);
9688 deadRef = sRef_isDead (errorRef);
9689 unuseable = sRef_isUnuseable (errorRef);
9693 if (!sRef_isPartial (s))
9695 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
9696 sRef_setDefined (s, fileloc_undefined);
9700 s = sRef_getBaseSafe (s);
9703 if (sRef_isValid (errorRef))
9705 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
9706 && sRef_isPointer (errorRef))
9713 if (sRef_isThroughArrayFetch (errorRef))
9716 (FLG_STRICTUSERELEASED,
9717 message ("%q %q may be used after being released",
9718 sRef_unparseKindNamePlain (errorRef),
9719 sRef_unparse (errorRef)),
9722 sRef_showRefKilled (errorRef);
9724 if (sRef_isKept (errorRef))
9726 sRef_clearAliasState (errorRef, loc);
9732 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
9736 message ("%q %q %qused after being released",
9737 sRef_unparseKindNamePlain (errorRef),
9738 sRef_unparse (errorRef),
9739 cstring_makeLiteral (errorMaybe
9743 sRef_showRefKilled (errorRef);
9745 if (sRef_isKept (errorRef))
9747 sRef_clearAliasState (errorRef, loc);
9756 message ("%q %q%qused in inconsistent state",
9757 sRef_unparseKindName (errorRef),
9758 sRef_unparseOpt (errorRef),
9759 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9762 sRef_showStateInconsistent (errorRef);
9767 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
9771 message ("%q %q%qused before definition",
9772 sRef_unparseKindName (errorRef),
9773 sRef_unparseOpt (errorRef),
9774 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9777 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
9780 sRef_setDefined (errorRef, loc);
9782 if (sRef_isAddress (errorRef))
9784 sRef_setDefined (sRef_getRootBase (errorRef), loc);
9786 } /* end is error */
9794 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
9796 if (exprNode_isDefined (e) && sRef_isKnown (s))
9798 e->uses = sRefSet_insert (e->uses, s);
9803 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
9805 if (exprNode_isDefined (e))
9807 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
9812 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
9814 sRef defines = sRef_undefined;
9816 if (sRef_isValid (s) && !sRef_isNothing (s))
9818 uentry ue = sRef_getBaseUentry (s);
9820 if (uentry_isValid (ue))
9822 uentry_setLset (ue);
9825 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9827 voptgenerror (FLG_USEDEF,
9828 message ("Attempt to set unuseable storage: %q",
9833 if (sRef_isMeaningful (s))
9835 if (sRef_isDead (s))
9837 sRef base = sRef_getBaseSafe (s);
9839 if (sRef_isValid (base)
9840 && sRef_isDead (base))
9842 sRef_setPartial (s, exprNode_loc (e));
9845 defines = s; /* okay - modifies for only param */
9847 else if (sRef_isPartial (s))
9849 sRef eref = exprNode_getSref (e);
9851 if (!sRef_isPartial (eref))
9854 ** should do something different here???
9857 sRef_setDefinedComplete (eref, exprNode_loc (e));
9861 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
9864 if (sRef_isMeaningful (eref))
9873 else if (sRef_isAllocated (s))
9875 sRef eref = exprNode_getSref (e);
9878 if (!sRef_isAllocated (eref))
9880 sRef_setDefinedComplete (eref, exprNode_loc (e));
9884 sRef base = sRef_getBaseSafe (eref);
9886 if (sRef_isValid (base))
9888 sRef_setPdefined (base, exprNode_loc (e));
9896 sRef_setDefinedNCComplete (s, exprNode_loc (e));
9901 else /* not meaningful...but still need to insert it */
9907 if (exprNode_isDefined (e) && sRef_isValid (defines))
9909 e->sets = sRefSet_insert (e->sets, defines);
9914 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
9916 if (sRef_isValid (s) && !sRef_isNothing (s))
9918 uentry ue = sRef_getBaseUentry (s);
9920 if (uentry_isValid (ue))
9922 uentry_setLset (ue);
9925 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9927 voptgenerror (FLG_USEDEF,
9928 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
9932 if (sRef_isMeaningful (s))
9934 sRef_setDefinedComplete (s, exprNode_loc (e));
9937 if (exprNode_isDefined (e))
9939 e->msets = sRefSet_insert (e->msets, s);
9945 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
9947 checkAnyCall (fcn, cstring_undefined, params, args,
9948 FALSE, sRefSet_undefined, FALSE, 0);
9952 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
9953 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
9957 if (uentry_isYield (ucurrent))
9959 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
9960 exprNode_checkSet (current, current->sref);
9964 if (uentry_isSefParam (ucurrent))
9966 sRefSet sets = current->sets;
9967 sRef ref = exprNode_getSref (current);
9969 if (sRef_isMacroParamRef (ref))
9971 uentry ue = sRef_getUentry (ref);
9973 if (!uentry_isSefParam (ue))
9978 ("Parameter %d to %s is declared sef, but "
9979 "the argument is a macro parameter declared "
9981 argno, exprNode_unparse (fcn),
9982 exprNode_unparse (current)),
9983 exprNode_loc (current));
9987 if (!sRefSet_isEmpty (sets))
9989 sRefSet reported = sRefSet_undefined;
9991 sRefSet_realElements (current->sets, el)
9993 if (sRefSet_isSameNameMember (reported, el))
9995 ; /* don't report again */
9999 if (sRef_isUnconstrained (el))
10004 ("Parameter %d to %s is declared sef, but "
10005 "the argument calls unconstrained function %s "
10006 "(no guarantee it will not modify something): %s",
10007 argno, exprNode_unparse (fcn),
10008 sRef_unconstrainedName (el),
10009 exprNode_unparse (current)),
10010 exprNode_loc (current));
10017 ("Parameter %d to %s is declared sef, but "
10018 "the argument may modify %q: %s",
10019 argno, exprNode_unparse (fcn),
10021 exprNode_unparse (current)),
10022 exprNode_loc (current));
10025 } end_sRefSet_realElements;
10029 checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs);
10030 exprNode_mergeUSs (fcn, current);
10035 checkAnyCall (/*@dependent@*/ exprNode fcn,
10036 /*@dependent@*/ cstring fname,
10039 bool hasMods, sRefSet mods,
10044 int nargs = exprNodeList_size (args);
10049 ** concat all args ud's to f, add each arg sref as a use unless
10050 ** it was specified as "out", in which case it is a def.
10053 uentryList_reset (pn);
10056 ** aliasing checks:
10058 ** if paramn is only or unique, no other arg may alias argn
10061 exprNodeList_elements (args, current)
10065 if (exprNode_isDefined (current))
10067 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
10069 uentry ucurrent = uentryList_current (pn);
10071 if (specialArgs == 0
10072 || (paramno < specialArgs))
10074 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
10076 if (context_maybeSet (FLG_ALIASUNIQUE))
10078 if (uentry_isOnly (ucurrent)
10079 || uentry_isUnique (ucurrent))
10081 checkUniqueParams (fcn, current, args,
10082 paramno, ucurrent);
10087 else /* uentry is undefined */
10089 if (specialArgs == 0)
10091 exprNode_checkUseParam (current);
10094 exprNode_mergeUSs (fcn, current);
10097 uentryList_advanceSafe (pn);
10098 } end_exprNodeList_elements;
10104 sRefSet_allElements (mods, s)
10107 sRef rb = sRef_getRootBase (s);
10109 if (sRef_isFileOrGlobalScope (rb))
10111 context_usedGlobal (rb);
10114 fb = sRef_fixBaseParam (s, args);
10116 if (!sRef_isMacroParamRef (fb))
10118 if (sRef_isNothing (fb))
10124 if (sRef_isValid (fb))
10126 uentry ue = sRef_getBaseUentry (s);
10128 if (uentry_isValid (ue))
10130 uentry_setLset (ue);
10134 fcn->sets = sRefSet_insert (fcn->sets, fb);
10137 sRef_clearDerivedComplete (s);
10138 } end_sRefSet_allElements;
10144 if (context_hasMods ())
10146 if (context_maybeSet (FLG_MODUNCON))
10150 message ("Undetected modification possible "
10151 "from call to unconstrained function %s: %s",
10153 exprNode_unparse (fcn)),
10154 exprNode_loc (fcn));
10159 if (context_maybeSet (FLG_MODUNCONNOMODS)
10160 && !(context_inIterDef () || context_inIterEnd ()))
10163 (FLG_MODUNCONNOMODS,
10164 message ("Undetected modification possible "
10165 "from call to unconstrained function %s: %s",
10167 exprNode_unparse (fcn)),
10168 exprNode_loc (fcn));
10172 exprNode_checkSetAny (fcn, fname);
10176 void exprNode_checkUseParam (exprNode current)
10178 if (exprNode_isDefined (current))
10180 exprNode_checkUse (current, current->sref, current->loc);
10185 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10186 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10191 if (!ctype_match (tr1, tr2))
10193 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10194 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10196 DPRINTF (("No error: [%s] %s / [%s] %s",
10197 exprNode_unparse (e1), ctype_unparse (tr1),
10198 exprNode_unparse (e2), ctype_unparse (tr2)));
10202 (void) gentypeerror
10204 message ("Incompatible types for %s (%s, %s): %s %s %s",
10205 lltok_unparse (op),
10206 ctype_unparse (te1),
10207 ctype_unparse (te2),
10208 exprNode_unparse (e1), lltok_unparse (op),
10209 exprNode_unparse (e2)),
10212 ret = ctype_unknown;
10216 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
10218 ret = ctype_resolveNumerics (tr1, tr2);
10220 else if (!context_msgStrictOps ())
10222 if (ctype_isPointer (tr1))
10224 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10228 else if (ctype_isInt (tr2))
10234 ret = ctype_unknown;
10237 else if (ctype_isPointer (tr2))
10239 if (ctype_isPointer (tr1))
10243 else if (ctype_isInt (tr1))
10249 ret = ctype_unknown;
10254 ret = ctype_resolveNumerics (tr1, tr2);
10259 int opid = lltok_getTok (op);
10260 bool comparop = (opid == EQ_OP || opid == NE_OP
10261 || opid == TLT || opid == TGT
10262 || opid == LE_OP || opid == GE_OP);
10264 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10267 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10268 || (ctype_isBool (tr1) && ctype_isBool (tr2))
10269 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10275 if (ctype_sameName (te1, te2))
10279 message ("Operands of %s are non-numeric (%t): %s %s %s",
10280 lltok_unparse (op), te1,
10281 exprNode_unparse (e1), lltok_unparse (op),
10282 exprNode_unparse (e2)),
10289 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10290 lltok_unparse (op), te1, te2,
10291 exprNode_unparse (e1), lltok_unparse (op),
10292 exprNode_unparse (e2)),
10297 else if (!ctype_isNumeric (tr1))
10301 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10302 lltok_unparse (op), te1,
10303 exprNode_unparse (e1), lltok_unparse (op),
10304 exprNode_unparse (e2)),
10309 if (!ctype_isNumeric (tr2))
10313 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10314 lltok_unparse (op), te2,
10315 exprNode_unparse (e1), lltok_unparse (op),
10316 exprNode_unparse (e2)),
10321 ret = ctype_unknown;
10329 abstractOpError (ctype tr1, ctype tr2, lltok op,
10330 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10331 fileloc loc1, fileloc loc2)
10333 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10335 if (ctype_match (tr1, tr2))
10339 message ("Operands of %s are abstract type (%t): %s %s %s",
10340 lltok_unparse (op), tr1,
10341 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10348 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10349 lltok_unparse (op), tr1, tr2,
10350 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10354 else if (ctype_isRealAbstract (tr1))
10358 message ("Left operand of %s is abstract type (%t): %s %s %s",
10359 lltok_unparse (op), tr1,
10360 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10365 if (ctype_isRealAbstract (tr2))
10369 message ("Right operand of %s is abstract type (%t): %s %s %s",
10370 lltok_unparse (op), tr2,
10371 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10380 ** requies e1 and e2 and not error exprNode's.
10384 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10385 ** the rep of the abstract type is exposed.
10387 ** The order is very important:
10389 ** check rep expose (move into check transfer)
10395 ** This isn't really a sensible procedure, but the indententation
10396 ** was getting too deep.
10400 checkOneRepExpose (sRef ysr, sRef base,
10401 /*@notnull@*/ exprNode e1,
10402 /*@notnull@*/ exprNode e2, ctype ct,
10405 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
10406 || sRef_isOwned (ysr)
10407 || sRef_isExposed (ysr)))
10409 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10410 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10413 if (sRef_isIReference (ysr))
10415 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10420 ("Assignment of mutable component of parameter %q "
10421 "to component of abstract "
10422 "type %s exposes rep: %s = %s",
10423 sRef_unparse (base),
10424 ctype_unparse (ct),
10425 exprNode_unparse (e1), exprNode_unparse (e2)),
10433 ("Assignment of mutable component of parameter %q "
10434 "(through alias %q) to component of abstract "
10435 "type %s exposes rep: %s = %s",
10436 sRef_unparse (base),
10437 sRef_unparse (e2->sref),
10438 ctype_unparse (ct),
10439 exprNode_unparse (e1), exprNode_unparse (e2)),
10445 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10449 message ("Assignment of mutable parameter %q "
10450 "to component of abstract type %s "
10451 "exposes rep: %s = %s",
10452 sRef_unparse (base),
10453 ctype_unparse (ct),
10454 exprNode_unparse (e1),
10455 exprNode_unparse (e2)),
10462 message ("Assignment of mutable parameter %q "
10463 "(through alias %q) to "
10464 "component of abstract type %s exposes "
10466 sRef_unparse (base),
10467 sRef_unparse (e2->sref),
10468 ctype_unparse (ct),
10469 exprNode_unparse (e1),
10470 exprNode_unparse (e2)),
10476 if (sRef_isFileOrGlobalScope (s2b))
10478 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10482 message ("Assignment of global %q "
10484 "abstract type %s exposes rep: %s = %s",
10485 sRef_unparse (base),
10486 ctype_unparse (ct),
10487 exprNode_unparse (e1), exprNode_unparse (e2)),
10494 message ("Assignment of global %q (through alias %q) "
10496 "abstract type %s exposes rep: %s = %s",
10497 sRef_unparse (base),
10498 sRef_unparse (e2->sref),
10499 ctype_unparse (ct),
10500 exprNode_unparse (e1), exprNode_unparse (e2)),
10508 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
10510 DPRINTF (("Do assign: %s <- %s",
10511 exprNode_unparse (e1), exprNode_unparse (e2)));
10512 DPRINTF (("Ctype: %s", ctype_unparse (exprNode_getType (e1))));
10514 if (ctype_isRealFunction (exprNode_getType (e1))
10515 && !ctype_isRealPointer (exprNode_getType (e1)))
10519 message ("Invalid left-hand side of assignment (function type %s): %s",
10520 ctype_unparse (exprNode_getType (e1)),
10521 exprNode_unparse (e1)),
10525 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
10527 ctype t2 = exprNode_getType (e2);
10528 sRef sr = sRef_getRootBase (e1->sref);
10529 ctype ct = sRef_getType (sr);
10531 if (ctype_isAbstract (t2)
10532 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
10534 /* it is immutable, okay to reference */
10535 goto donerepexpose;
10538 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
10540 sRef s2b = sRef_getRootBase (e2->sref);
10541 sRef s1 = e1->sref;
10542 sRef s1b = sRef_getRootBase (s1);
10545 aliases = usymtab_canAlias (e2->sref);
10547 if (!sRef_similar (s2b, s1b)
10548 && !sRef_isExposed (s1)
10549 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
10551 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
10552 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
10553 && !sRef_isExposed (s2b))
10555 if (sRef_isIReference (e2->sref))
10560 ("Assignment of mutable component of parameter %q "
10561 "to component of abstract type %s exposes rep: %s = %s",
10562 sRef_unparse (s2b),
10563 ctype_unparse (ct),
10564 exprNode_unparse (e1), exprNode_unparse (e2)),
10571 message ("Assignment of mutable parameter %q to "
10572 "component of abstract type %s exposes rep: %s = %s",
10573 sRef_unparse (s2b),
10574 ctype_unparse (ct),
10575 exprNode_unparse (e1), exprNode_unparse (e2)),
10580 if (sRef_isFileOrGlobalScope (s2b))
10584 message ("Assignment of global %q to component of "
10585 "abstract type %s exposes rep: %s = %s",
10586 sRef_unparse (s2b),
10587 ctype_unparse (ct),
10588 exprNode_unparse (e1), exprNode_unparse (e2)),
10592 sRefSet_realElements (aliases, ysr)
10594 sRef base = sRef_getRootBase (ysr);
10596 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
10597 || sRef_sameName (base, s1b))
10599 ; /* error already reported or same sref */
10603 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
10605 } end_sRefSet_realElements;
10607 sRefSet_free (aliases);
10614 ** function variables don't really work...
10617 if (!ctype_isFunction (ctype_realType (e2->typ)))
10621 DPRINTF (("Check init: %s / %s",
10622 exprNode_unparse (e1), exprNode_unparse (e2)));
10623 checkInitTransfer (e1, e2);
10627 checkAssignTransfer (e1, e2);
10632 sRef fref = e2->sref;
10634 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
10635 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
10637 /* Need to typecheck the annotation on the parameters */
10639 if (ctype_isRealFunction (e1->typ)) {
10640 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
10641 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
10643 if (!uentryList_isMissingParams (e1p)
10644 && !uentryList_isMissingParams (e2p)
10645 && uentryList_size (e1p) > 0) {
10646 if (uentryList_size (e1p) == uentryList_size (e2p)) {
10649 uentryList_elements (e1p, el1) {
10652 el2 = uentryList_getN (e2p, n);
10654 uentry_checkMatchParam (el1, el2, n, e2);
10655 } end_uentryList_elements;
10661 if (exprNode_isStringLiteral (e2))
10663 exprNode_checkStringLiteralLength (exprNode_getType (e1), e2);
10666 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
10672 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
10673 updateAliases (e1, e2);
10678 checkMacroParen (exprNode e)
10680 if (exprNode_isError (e) || e->kind == XPR_CAST)
10686 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
10690 message ("Macro parameter used without parentheses: %s",
10691 exprNode_unparse (e)),
10698 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
10702 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
10706 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
10713 ** if e2 is a parameter or global derived location which
10714 ** can be modified (that is, e2 is a mutable abstract type,
10715 ** or a derived pointer), then e1 can alias e2.
10717 ** e1 can alias everything which e2 can alias.
10719 ** Also, if e1 is guarded, remove from guard sets!
10722 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
10724 if (!context_inProtectVars ())
10727 ** depends on types of e1 and e2
10730 sRef s1 = e1->sref;
10731 sRef s2 = e2->sref;
10732 ctype t1 = exprNode_getType (e1);
10734 /* handle pointer sRefs, record fields, arrays, etc... */
10736 if (!ctype_isRealSU (t1))
10738 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
10739 sRef_copyRealDerivedComplete (s1, s2);
10744 ** Fields should alias
10747 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
10750 if (ctype_isMutable (t1) && sRef_isKnown (s1))
10752 usymtab_clearAlias (s1);
10753 usymtab_addMustAlias (s1, s2);
10754 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
10758 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
10761 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
10763 usymtab_unguard (s1);
10768 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
10770 if (exprNode_isDefined (e))
10772 e->loc = fileloc_update (e->loc, loc);
10776 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
10782 static void checkUniqueParams (exprNode fcn,
10783 /*@notnull@*/ exprNode current,
10785 int paramno, uentry ucurrent)
10788 sRef thisref = exprNode_getSref (current);
10791 ** Check if any argument could match this argument.
10794 exprNodeList_elements (args, icurrent)
10798 if (iparamno != paramno)
10800 sRef sr = exprNode_getSref (icurrent);
10802 if (sRef_similarRelaxed (thisref, sr))
10804 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
10809 ("Parameter %d (%s) to function %s is declared %s but "
10810 "is aliased by parameter %d (%s)",
10812 exprNode_unparse (current),
10813 exprNode_unparse (fcn),
10814 alkind_unparse (uentry_getAliasKind (ucurrent)),
10815 iparamno, exprNode_unparse (icurrent)),
10821 sRefSet aliases = usymtab_canAlias (sr);
10823 sRefSet_allElements (aliases, asr)
10825 if (ctype_isUnknown (sRef_getType (thisref)))
10827 sRef_setType (thisref, uentry_getType (ucurrent));
10830 if (sRef_similarRelaxed (thisref, asr))
10832 if (sRef_isExternal (asr))
10834 if (sRef_isLocalState (thisref))
10840 sRef base = sRef_getRootBase (asr);
10842 if (!sRef_similar (sRef_getBase (asr), thisref))
10844 if (sRef_isUnique (base) || sRef_isOnly (base)
10845 || sRef_isKept (base)
10846 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
10847 || (sRef_isAddress (thisref)
10848 && sRef_isLocalVar (sRef_getRootBase (thisref))))
10850 ; /* okay, no error */
10855 (FLG_MAYALIASUNIQUE,
10857 ("Parameter %d (%s) to function %s is declared %s but "
10858 "may be aliased externally by parameter %d (%s)",
10860 exprNode_unparse (current),
10861 exprNode_unparse (fcn),
10862 alkind_unparse (uentry_getAliasKind (ucurrent)),
10863 iparamno, exprNode_unparse (icurrent)),
10874 ("Parameter %d (%s) to function %s is declared %s but "
10875 "is aliased externally by parameter %d (%s) through "
10878 exprNode_unparse (current),
10879 exprNode_unparse (fcn),
10880 alkind_unparse (uentry_getAliasKind (ucurrent)),
10881 iparamno, exprNode_unparse (icurrent),
10882 sRef_unparse (asr)),
10886 } end_sRefSet_allElements;
10887 sRefSet_free (aliases);
10890 } end_exprNodeList_elements;
10893 long exprNode_getLongValue (exprNode e) {
10896 if (exprNode_hasValue (e)
10897 && multiVal_isInt (exprNode_getValue (e)))
10899 value = multiVal_forceInt (exprNode_getValue (e));
10910 /*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
10912 if (exprNode_isDefined (p_e) )
10913 return ( p_e->loc );
10915 return fileloc_undefined;
10918 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
10921 ** Returns the location of the sequence point following e.
10923 ** Only works for statements (for now).
10926 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
10927 lltok t = exprData_getUopTok (e->edata);
10928 return fileloc_copy(lltok_getLoc (t));
10930 /* drl possible problem : warning fix
10931 llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
10933 return fileloc_undefined;
10937 exprNode exprNode_createNew(ctype c)
10941 ret = exprNode_createPlain (c);
10946 bool exprNode_isInitBlock (exprNode e)
10948 return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);