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_makeConstantString (cstring c, /*@only@*/ fileloc loc)
931 exprNode e = exprNode_createPlain (ctype_unknown);
934 e->sref = sRef_makeConst (ctype_string);
935 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
936 e->typ = ctype_string;
938 /* No alias errors for unrecognized identifiers */
939 sRef_setAliasKind (e->sref, AK_STATIC, loc);
940 sRef_setExKind (e->sref, XO_OBSERVER, loc);
945 exprNode exprNode_createId (/*@observer@*/ uentry c)
947 if (uentry_isValid (c))
949 exprNode e = exprNode_new ();
951 e->typ = uentry_getType (c);
953 if (uentry_isFunction (c)
954 && !sRef_isLocalVar (uentry_getSref (c)))
956 e->sref = sRef_undefined;
960 e->sref = uentry_getSref (c);
963 if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
965 sRef_setDefined (e->sref, fileloc_undefined);
969 ** yoikes! leaving this out was a heinous bug...that would have been
970 ** caught if i had lclint working first. gag!
973 e->etext = cstring_undefined;
975 if (uentry_isEitherConstant (c))
978 e->val = multiVal_copy (uentry_getConstantValue (c));
983 e->val = multiVal_unknown ();
986 e->edata = exprData_makeId (c);
987 e->loc = context_getSaveLocation ();
989 if (fileloc_isUndefined (e->loc))
991 fileloc_free (e->loc);
992 e->loc = fileloc_copy (g_currentloc);
995 e->guards = guardSet_new ();
996 e->sets = sRefSet_new ();
997 e->msets = sRefSet_new ();
998 e->uses = sRefSet_new ();
1000 /*> missing fields, detected by lclint <*/
1001 e->exitCode = XK_NEVERESCAPE;
1002 e->isJumpPoint = FALSE;
1003 e->canBreak = FALSE;
1004 e->mustBreak = FALSE;
1006 exprNode_defineConstraints(e);
1012 return exprNode_createUnknown ();
1016 /*@notnull@*/ exprNode
1017 exprNode_fromIdentifier (/*@observer@*/ uentry c)
1021 if (context_justPopped ()) /* watch out! c could be dead */
1023 uentry ce = usymtab_lookupSafe (LastIdentifier ());
1025 if (uentry_isValid (ce))
1031 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
1035 ret = exprNode_fromIdentifierAux (c);
1040 static void exprNode_checkStringLiteralLength (ctype t1, exprNode e2)
1042 multiVal mval = exprNode_getValue (e2);
1046 if (ctype_isFixedArray (t1))
1048 int nelements = long_toInt (ctype_getArraySize (t1));
1050 llassert (multiVal_isString (mval));
1051 slit = multiVal_forceString (mval);
1052 len = cstring_length (slit);
1054 if (len == nelements)
1057 (FLG_STRINGLITNOROOM,
1058 message ("String literal with %d character%& "
1059 "is assigned to %s (no room for null terminator): %s",
1060 cstring_length (slit),
1062 exprNode_unparse (e2)),
1065 else if (len > nelements)
1068 (FLG_STRINGLITTOOLONG,
1069 message ("Stirng literal with %d character%& (counting null terminator) "
1070 "is assigned to %s (insufficient storage available): %s",
1071 cstring_length (slit),
1073 exprNode_unparse (e2)),
1076 else if (len < nelements - 1)
1079 (FLG_STRINGLITSMALLER,
1080 message ("String literal with %d character%& is assigned to %s (possible waste of storage): %s",
1081 cstring_length (slit),
1083 exprNode_unparse (e2)),
1093 static /*@only@*/ /*@notnull@*/ exprNode
1094 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
1096 exprNode e = exprNode_createId (c);
1099 uentry_setUsed (c, e->loc);
1101 if (uentry_isVar (c) && sRef_isFileOrGlobalScope (sr))
1103 checkGlobUse (c, FALSE, e);
1110 exprNode_isZero (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 exprNode_isNonNegative (exprNode e)
1128 if (exprNode_isDefined (e))
1130 multiVal m = exprNode_getValue (e);
1132 if (multiVal_isInt (m))
1134 return (multiVal_forceInt (m) >= 0);
1142 ** a[x] - uses a but NOT a[]
1143 ** result sref = a[] (set/use in assignment)
1145 ** The syntax x[a] is also legal in C, and has the same
1146 ** semantics. If ind is an array, and arr is an int, flip
1151 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
1154 ** error in arr, error propagates (no new messages)
1155 ** error in ind, assume valid and continue
1158 DPRINTF (("Array fetch: %s / %s",
1159 exprNode_unparse (e1), exprNode_unparse (e2)));
1161 if (exprNode_isError (e1))
1164 return (exprNode_makeError ());
1170 ctype carr = exprNode_getType (e1);
1171 ctype crarr = ctype_realType (carr);
1174 ** this sets up funny aliasing, that leads to spurious
1175 ** lclint errors. Hence, the i2 comments.
1178 /* evans 2001-09-09 added ctype_isKnown so there is no swap when e1 type is unknown */
1179 if (ctype_isKnown (crarr)
1180 && !ctype_isRealArray (crarr)
1181 && ctype_isRealNumeric (crarr)
1182 && !exprNode_isError (e2)
1183 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1188 carr = exprNode_getType (arr);
1189 crarr = ctype_realType (carr);
1197 DPRINTF (("arr: %s", exprNode_unparse (arr)));
1199 if (sRef_possiblyNull (arr->sref))
1201 if (!usymtab_isGuarded (arr->sref))
1203 if (optgenerror (FLG_NULLDEREF,
1204 message ("Index of %s pointer %q: %s",
1205 sRef_nullMessage (arr->sref),
1206 sRef_unparse (arr->sref),
1207 exprNode_unparse (arr)),
1210 DPRINTF (("ref: %s", sRef_unparseFull (arr->sref)));
1211 sRef_showNullInfo (arr->sref);
1213 /* suppress future messages */
1214 sRef_setNullError (arr->sref);
1219 if (exprNode_isError (ind))
1221 if ((ctype_isArrayPtr (crarr)
1222 && !ctype_isFunction (crarr))
1223 || ctype_isUnknown (carr))
1225 exprNode ret = exprNode_createPartialCopy (arr);
1227 if (ctype_isKnown (carr))
1229 ret->typ = ctype_baseArrayPtr (crarr);
1233 ret->typ = ctype_unknown;
1236 ret->sref = sRef_makeArrayFetch (arr->sref);
1238 ret->kind = XPR_FETCH;
1241 ** Because of funny aliasing (when arr and ind are
1242 ** flipped) spurious errors would be reported here.
1245 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1246 checkSafeUse (ret, arr->sref);
1251 voptgenerror (FLG_TYPE,
1252 message ("Array fetch from non-array (%t): %s[%s]", carr,
1253 exprNode_unparse (e1), exprNode_unparse (e2)),
1255 exprNode_free (arr);
1256 return (exprNode_makeError ());
1261 if (!ctype_isForceRealInt (&(ind->typ)))
1263 ctype rt = ctype_realType (ind->typ);
1265 if (ctype_isChar (rt))
1269 message ("Array fetch using non-integer, %t: %s[%s]",
1271 exprNode_unparse (e1), exprNode_unparse (e2)),
1274 else if (ctype_isEnum (rt))
1278 message ("Array fetch using non-integer, %t: %s[%s]",
1280 exprNode_unparse (e1), exprNode_unparse (e2)),
1287 message ("Array fetch using non-integer, %t: %s[%s]",
1289 exprNode_unparse (e1), exprNode_unparse (e2)),
1293 multiVal_free (ind->val);
1294 ind->val = multiVal_unknown ();
1297 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1299 exprNode ret = exprNode_createSemiCopy (arr);
1300 multiVal m = exprNode_getValue (ind);
1302 ret->typ = ctype_baseArrayPtr (crarr);
1303 ret->kind = XPR_FETCH;
1305 if (multiVal_isInt (m))
1307 int i = (int) multiVal_forceInt (m);
1309 if (sRef_isValid (arr->sref)) {
1310 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1312 ret->sref = sRef_undefined;
1317 ret->sref = sRef_makeArrayFetch (arr->sref);
1320 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1321 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1322 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1324 /* (see comment on spurious errors above) */
1325 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1327 exprNode_checkUse (ret, ind->sref, ind->loc);
1328 exprNode_checkUse (ret, arr->sref, arr->loc);
1334 if (ctype_isUnknown (carr))
1336 exprNode ret = exprNode_createPartialCopy (arr);
1338 ret->kind = XPR_FETCH;
1339 ret->typ = ctype_unknown;
1340 ret->sets = sRefSet_union (ret->sets, ind->sets);
1341 ret->msets = sRefSet_union (ret->msets, ind->msets);
1342 ret->uses = sRefSet_union (ret->uses, ind->uses);
1344 /* (see comment on spurious errors above) */
1345 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1347 exprNode_checkUse (ret, ind->sref, ind->loc);
1348 exprNode_checkUse (ret, arr->sref, arr->loc);
1355 message ("Array fetch from non-array (%t): %s[%s]", carr,
1356 exprNode_unparse (e1), exprNode_unparse (e2)),
1359 exprNode_free (arr);
1360 exprNode_free (ind);
1362 return (exprNode_makeError ());
1372 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1373 exprNodeList args, exprNode ret)
1375 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1379 ** checkPrintfArgs --- checks arguments for printf-like functions
1380 ** Arguments before ... have already been checked.
1381 ** The argument before the ... is a char *.
1382 ** argno is the format string argument.
1386 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1387 exprNodeList args, exprNode ret, int argno)
1390 ** the last argument before the elips is the format string
1395 int nargs = exprNodeList_size (args);
1396 uentryList params = uentry_getParams (fcn);
1400 ** These should be ensured by checkSpecialFunction
1403 llassert (uentryList_size (params) == argno + 1);
1404 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1406 a = exprNodeList_getN (args, argno - 1);
1407 formatloc = fileloc_copy (exprNode_loc (a));
1409 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1410 && exprNode_knownStringValue (a))
1412 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1413 char *code = format;
1416 nargs = exprNodeList_size (args);
1418 while ((code = strchr (code, '%')) != NULL)
1420 char *origcode = code;
1421 cstring codetext = cstring_newEmpty ();
1422 char key = *(++code);
1423 ctype modtype = ctype_int;
1424 bool modified = FALSE;
1426 fileloc_addColumn (formatloc, code - ocode);
1428 codetext = cstring_appendChar (codetext, key);
1431 while (isFlagKey (key))
1434 codetext = cstring_appendChar (codetext, key);
1435 fileloc_incColumn (formatloc);
1438 if (key == 'm') /* skipped in syslog */
1443 /* ignore field width */
1444 while (isdigit ((int) key) != 0)
1447 codetext = cstring_appendChar (codetext, key);
1448 fileloc_incColumn (formatloc);
1451 /* ignore precision */
1455 codetext = cstring_appendChar (codetext, key);
1456 fileloc_incColumn (formatloc);
1459 ** In printf, '*' means: read the next arg as an int for the
1460 ** field width. This seems to be missing from my copy of the
1461 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1462 ** later) but never does.
1467 ; /* don't do anything --- handle later */
1471 while (isdigit ((int) key) != 0)
1474 codetext = cstring_appendChar (codetext, key);
1475 fileloc_incColumn (formatloc);
1482 modtype = ctype_sint; /* short */
1484 codetext = cstring_appendChar (codetext, key);
1485 fileloc_incColumn (formatloc);
1487 else if (key == 'l' || key == 'L')
1489 modtype = ctype_lint; /* long */
1491 codetext = cstring_appendChar (codetext, key);
1492 fileloc_incColumn (formatloc);
1494 if (key == 'l' || key == 'L') {
1495 modtype = ctype_llint; /* long long */
1497 codetext = cstring_appendChar (codetext, key);
1498 fileloc_incColumn (formatloc);
1506 /* now, key = type of conversion to apply */
1508 fileloc_incColumn (formatloc);
1516 message ("No argument corresponding to %q format "
1517 "code %d (%%%s): \"%s\"",
1518 uentry_getName (fcn),
1520 cstring_fromChars (format)),
1523 if (fileloc_isDefined (formatloc)
1524 && context_getFlag (FLG_SHOWCOL))
1526 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1534 a = exprNodeList_getN (args, i);
1537 if (!exprNode_isError (a))
1543 case '*': /* int argument for fieldwidth */
1544 expecttype = ctype_int;
1545 *(--code) = '%'; /* convert it for next code */
1546 fileloc_subColumn (formatloc, 1);
1547 /*@switchbreak@*/ break;
1550 expecttype = ctype_combine (ctype_uint, modtype);
1551 /*@switchbreak@*/ break;
1553 case 'i': /* int argument */
1555 expecttype = ctype_combine (ctype_int, modtype);
1556 /*@switchbreak@*/ break;
1558 case 'x': /* unsigned int */
1560 expecttype = ctype_combine (ctype_uint, modtype);
1562 /*@switchbreak@*/ break;
1568 case 'f': /* double */
1569 expecttype = ctype_combine (ctype_double, modtype);
1570 /*@switchbreak@*/ break;
1572 case 'c': /* int converted to char (check its a char?) */
1573 expecttype = ctype_makeConj (ctype_int,
1574 ctype_makeConj (ctype_char,
1577 /* evans 2001-10-05 - changed to reflect correct ISO spec:
1578 int converted to char */
1580 /* expecttype = ctype_makeConj (ctype_char, ctype_uchar); */
1581 /*@switchbreak@*/ break;
1583 case 's': /* string */
1584 expecttype = ctype_string;
1585 /*@switchbreak@*/ break;
1588 while (((key = *(++code)) != ']')
1591 codetext = cstring_appendChar (codetext, key);
1592 fileloc_incColumn (formatloc);
1598 (message ("Bad character set format: %s",
1599 cstring_fromChars (origcode)));
1602 expecttype = ctype_string;
1603 /*@switchbreak@*/ break;
1605 case 'p': /* pointer */
1606 expecttype = ctype_makePointer (ctype_void);
1607 uentry_setDefState (regArg, SS_RELDEF); /* need not be defined */
1608 sRef_setPosNull (uentry_getSref (regArg), fileloc_undefined); /* could be null */
1609 /*@switchbreak@*/ break;
1611 case 'n': /* pointer to int, modified by call! */
1612 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1614 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1615 /*@switchbreak@*/ break;
1617 case 'm': /* in a syslog, it doesn't consume an argument */
1618 /* should check we're really doing syslog */
1620 /*@switchbreak@*/ break;
1624 expecttype = ctype_unknown;
1628 message ("Unrecognized format code: %s",
1629 cstring_fromChars (origcode)),
1630 fileloc_isDefined (formatloc)
1631 ? formatloc : g_currentloc);
1633 /*@switchbreak@*/ break;
1636 if (!(exprNode_matchArgType (expecttype, a)))
1638 if (ctype_isVoidPointer (expecttype)
1639 && ctype_isRealAbstract (a->typ)
1640 && (context_getFlag (FLG_ABSTVOIDP)))
1646 if (llgenformattypeerror
1647 (expecttype, exprNode_undefined,
1649 message ("Format argument %d to %q (%%%s) expects "
1652 uentry_getName (fcn),
1655 a->typ, exprNode_unparse (a)),
1658 if (fileloc_isDefined (formatloc)
1659 && context_getFlag (FLG_SHOWCOL))
1662 (cstring_makeLiteral
1663 ("Corresponding format code"),
1670 uentry_setType (regArg, expecttype);
1671 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1673 if (ctype_equal (expecttype, ctype_string))
1675 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1678 uentry_setType (regArg, ctype_unknown);
1679 uentry_fixupSref (regArg);
1683 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1694 cstring_free (codetext);
1699 voptgenerror (FLG_TYPE,
1700 message ("Format string for %q has %d arg%&, given %d",
1701 uentry_getName (fcn), i - argno, nargs - argno),
1707 /* no checking possible for compile-time unknown format strings */
1708 if (exprNode_isDefined (a))
1712 message ("Format string parameter to %s is not a compile-time constant: %s",
1713 exprNode_unparse (f),
1714 exprNode_unparse (a)),
1719 fileloc_free (formatloc);
1723 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1724 exprNodeList args, exprNode ret, int argno)
1728 int nargs = exprNodeList_size (args);
1729 uentryList params = uentry_getParams (fcn);
1733 ** These should be ensured by checkSpecialFunction
1736 llassert (uentryList_size (params) == argno + 1);
1737 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1739 a = exprNodeList_getN (args, argno - 1);
1740 formatloc = fileloc_copy (exprNode_loc (a));
1742 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1743 && exprNode_knownStringValue (a))
1745 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1746 char *code = format;
1749 nargs = exprNodeList_size (args);
1751 while ((code = strchr (code, '%')) != NULL)
1753 char *origcode = code;
1754 char key = *(++code);
1755 cstring codetext = cstring_newEmpty ();
1756 ctype modtype = ctype_int;
1757 char modifier = '\0';
1758 bool modified = TRUE;
1759 bool ignore = FALSE;
1761 codetext = cstring_appendChar (codetext, key);
1762 fileloc_addColumn (formatloc, code - ocode);
1765 ** this is based on ANSI standard library description of fscanf
1766 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1769 /* '*' suppresses assignment (does not need match argument) */
1774 codetext = cstring_appendChar (codetext, key);
1777 fileloc_incColumn (formatloc);
1780 /* ignore field width */
1781 while (isdigit ((int) key) != 0)
1784 codetext = cstring_appendChar (codetext, key);
1785 fileloc_incColumn (formatloc);
1790 modtype = ctype_sint; /* short */
1792 codetext = cstring_appendChar (codetext, key);
1793 fileloc_incColumn (formatloc);
1795 else if (key == 'l' || key == 'L')
1797 modtype = ctype_lint; /* long */
1801 codetext = cstring_appendChar (codetext, key);
1803 fileloc_incColumn (formatloc);
1805 if (key == 'l' || key == 'L') {
1806 modtype = ctype_llint; /* long long */
1808 codetext = cstring_appendChar (codetext, key);
1809 fileloc_incColumn (formatloc);
1817 /* now, key = type of conversion to apply */
1819 fileloc_incColumn (formatloc);
1833 message ("No argument corresponding to %q format "
1834 "code %d (%%%s): \"%s\"",
1835 uentry_getName (fcn),
1837 cstring_fromChars (format)),
1840 if (fileloc_isDefined (formatloc)
1841 && context_getFlag (FLG_SHOWCOL))
1844 (cstring_makeLiteral ("Corresponding format code"),
1852 a = exprNodeList_getN (args, i);
1855 if (!exprNode_isError (a))
1861 case '*': /* int argument for fieldwidth */
1862 expecttype = ctype_makePointer (ctype_int);
1863 *(--code) = '%'; /* convert it for next code */
1864 fileloc_subColumn (formatloc, 1);
1865 /*@switchbreak@*/ break;
1868 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1869 /*@switchbreak@*/ break;
1874 case 'X': /* unsigned int */
1875 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1876 /*@switchbreak@*/ break;
1883 /* printf is double, scanf is float! */
1885 if (modifier == 'l')
1887 expecttype = ctype_makePointer (ctype_double);
1889 else if (modifier == 'L')
1891 expecttype = ctype_makePointer (ctype_ldouble);
1895 llassert (modifier == '\0');
1896 expecttype = ctype_makePointer (ctype_float);
1898 /*@switchbreak@*/ break;
1900 case 'c': /* int converted to char (check its a char?) */
1901 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1902 /*@switchbreak@*/ break;
1904 case 's': /* string */
1905 expecttype = ctype_string;
1906 /*@switchbreak@*/ break;
1910 while (((key = *(++code)) != ']')
1913 codetext = cstring_appendChar (codetext, key);
1914 fileloc_incColumn (formatloc);
1920 (message ("Bad character set format: %s",
1921 cstring_fromChars (origcode)));
1924 expecttype = ctype_string;
1925 /*@switchbreak@*/ break;
1928 case 'p': /* pointer */
1931 message ("Format code should not be used in scanf: %s",
1932 cstring_fromChars (origcode)),
1933 fileloc_isDefined (formatloc)
1934 ? formatloc : g_currentloc);
1936 expecttype = ctype_unknown;
1937 /*@switchbreak@*/ break;
1939 case 'n': /* pointer to int, modified by call! */
1940 expecttype = ctype_makePointer (ctype_int);
1941 /*@switchbreak@*/ break;
1944 expecttype = ctype_unknown;
1948 message ("Unrecognized format code: %s",
1949 cstring_fromChars (origcode)),
1950 fileloc_isDefined (formatloc)
1951 ? formatloc : g_currentloc);
1953 /*@switchbreak@*/ break;
1956 if (!(exprNode_matchArgType (expecttype, a)))
1958 if (ctype_isVoidPointer (expecttype)
1959 && ctype_isRealAbstract (a->typ)
1960 && (context_getFlag (FLG_ABSTVOIDP)))
1966 if (llgenformattypeerror
1967 (expecttype, exprNode_undefined,
1969 message ("Format argument %d to %q (%%%s) expects "
1972 uentry_getName (fcn),
1973 codetext, expecttype,
1974 a->typ, exprNode_unparse (a)),
1977 if (fileloc_isDefined (formatloc)
1978 && context_getFlag (FLG_SHOWCOL))
1981 (cstring_makeLiteral
1982 ("Corresponding format code"),
1989 uentry_setType (outArg, expecttype);
1990 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
1991 uentry_setType (outArg, ctype_unknown);
1992 uentry_fixupSref (outArg);
1996 exprNode_checkCallModifyVal (a->sref, args, f, ret);
2001 /* a->sref = defref; */
2008 cstring_free (codetext);
2013 voptgenerror (FLG_TYPE,
2014 message ("Format string for %q has %d arg%&, given %d",
2015 uentry_getName (fcn), i - argno, nargs - argno),
2021 /* no checking possible for compile-time unknown format strings */
2024 fileloc_free (formatloc);
2028 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
2031 /*@unused@*/ int argno)
2034 ** the last argument before the elips is the format string
2037 int nargs = exprNodeList_size (args);
2042 a = exprNodeList_getN (args, argno - 1);
2043 formatloc = fileloc_copy (exprNode_loc (a));
2045 if (ctype_isUnknown (cstringType)) {
2046 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
2048 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
2052 if (ctype_isUnknown (ctypeType)) {
2053 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
2055 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
2059 if (ctype_isUnknown (filelocType)) {
2060 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
2062 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
2066 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
2067 && exprNode_knownStringValue (a))
2069 cstring format = multiVal_forceString (exprNode_getValue (a));
2070 char *code = cstring_toCharsSafe (format);
2073 nargs = exprNodeList_size (args);
2075 while ((code = strchr (code, '%')) != NULL)
2077 char *origcode = code;
2078 char key = *(++code);
2079 cstring codetext = cstring_newEmpty ();
2080 bool isOnly = FALSE;
2082 codetext = cstring_appendChar (codetext, key);
2084 fileloc_addColumn (formatloc, code - ocode);
2086 while (key >= '0' && key <= '9')
2089 codetext = cstring_appendChar (codetext, key);
2090 fileloc_incColumn (formatloc);
2094 fileloc_incColumn (formatloc);
2098 if (key == '&') /* plural marker */
2107 message ("Message missing format arg %d (%%%s): \"%s\"",
2108 i + 1, codetext, format),
2114 a = exprNodeList_getN (args, i);
2118 if (!exprNode_isError (a))
2122 /*@-loopswitchbreak@*/
2128 expecttype = ctype_char; break;
2130 expecttype = cstringType; break;
2132 expecttype = cstringType; isOnly = TRUE; break;
2134 expecttype = cstringType; isOnly = TRUE; break;
2135 case 'd': expecttype = ctype_int; break;
2136 case 'u': expecttype = ctype_uint; break;
2137 case 'w': expecttype = ctype_ulint; break;
2138 case 'f': expecttype = ctype_float; break;
2139 case 'b': expecttype = ctype_bool; break;
2140 case 't': expecttype = ctypeType; break;
2141 case 'l': expecttype = filelocType; break;
2142 case '&': /* a wee bit of a hack methinks */
2143 expecttype = ctype_int;
2145 case 'r': expecttype = ctype_bool; break;
2147 expecttype = ctype_unknown;
2150 message ("Unrecognized format code: %s",
2151 cstring_fromChars (origcode)),
2152 fileloc_isDefined (formatloc)
2153 ? formatloc : g_currentloc);
2156 /*@=loopswitchbreak@*/
2158 if (!(exprNode_matchArgType (expecttype, a)))
2160 if (ctype_isVoidPointer (expecttype)
2161 && ctype_isRealAbstract (a->typ)
2162 && (context_getFlag (FLG_ABSTVOIDP)))
2168 if (llgenformattypeerror
2169 (expecttype, exprNode_undefined,
2171 message ("Format argument %d to %q (%%%s) expects "
2174 uentry_getName (fcn),
2175 codetext, expecttype,
2176 a->typ, exprNode_unparse (a)),
2179 if (fileloc_isDefined (formatloc)
2180 && context_getFlag (FLG_SHOWCOL))
2183 (cstring_makeLiteral
2184 ("Corresponding format code"),
2191 if (ctype_equal (expecttype, cstringType))
2195 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2196 uentry_fixupSref (csOnlyArg);
2200 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2201 uentry_fixupSref (csArg);
2206 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2207 uentry_fixupSref (regArg);
2213 cstring_free (codetext);
2218 voptgenerror (FLG_TYPE,
2219 message ("Format string for %q has %d arg%&, given %d",
2220 uentry_getName (fcn), i - argno, nargs -argno),
2226 /* no checking possible for compile-time unknown format strings */
2229 fileloc_free (formatloc);
2233 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2234 /*@notnull@*/ exprNode e2,
2240 bool hadUncon = FALSE;
2242 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
2243 sRefSet_hasUnconstrained (sets2))
2246 (FLG_EVALORDERUNCON,
2248 ("Expression may have undefined behavior (%q used in right operand "
2249 "may set global variable %q used in left operand): %s %s %s",
2250 sRefSet_unparseUnconstrained (sets2),
2251 sRef_unparse (sRef_getRootBase (e1->sref)),
2252 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2256 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
2257 sRefSet_hasUnconstrained (sets1))
2260 (FLG_EVALORDERUNCON,
2262 ("Expression has undefined behavior (%q used in left operand "
2263 "may set global variable %q used in right operand): %s %s %s",
2264 sRefSet_unparseUnconstrained (sets1),
2265 sRef_unparse (e2->sref),
2266 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2270 sRefSet_realElements (e1->uses, sr)
2272 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2277 ("Expression has undefined behavior (left operand uses %q, "
2278 "modified by right operand): %s %s %s",
2280 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2283 } end_sRefSet_realElements;
2285 sRefSet_realElements (sets1, sr)
2287 if (sRef_isMeaningful (sr))
2289 if (sRef_same (sr, e2->sref))
2294 ("Expression has undefined behavior (value of right operand "
2295 "modified by left operand): %s %s %s",
2296 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2299 else if (sRefSet_member (e2->uses, sr))
2304 ("Expression has undefined behavior (left operand modifies %q, "
2305 "used by right operand): %s %s %s",
2307 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2312 if (sRefSet_member (sets2, sr))
2314 if (sRef_isUnconstrained (sr))
2322 hadUncon = optgenerror
2323 (FLG_EVALORDERUNCON,
2325 ("Expression may have undefined behavior. Left operand "
2326 "calls %q; right operand calls %q. The unconstrained "
2327 "functions may modify global state used by "
2328 "the other operand): %s %s %s",
2329 sRefSet_unparseUnconstrained (sets1),
2330 sRefSet_unparseUnconstrained (sets2),
2331 exprNode_unparse (e1), lltok_unparse (op),
2332 exprNode_unparse (e2)),
2341 ("Expression has undefined behavior (both "
2342 "operands modify %q): %s %s %s",
2344 exprNode_unparse (e1),
2345 lltok_unparse (op), exprNode_unparse (e2)),
2351 } end_sRefSet_realElements;
2354 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2356 bool hasError = FALSE;
2358 if (exprNode_isError (e1) || exprNode_isError (e2))
2363 if (sRefSet_member (e2->sets, e1->sref))
2365 if (e2->kind == XPR_CALL)
2371 hasError = optgenerror
2373 message ("Expression has undefined behavior "
2374 "(value of left operand %s is modified "
2375 "by right operand %s): %s %s %s",
2376 exprNode_unparse (e1),
2377 exprNode_unparse (e2),
2378 exprNode_unparse (e1), lltok_unparse (op),
2379 exprNode_unparse (e2)),
2384 if (context_getFlag (FLG_EVALORDERUNCON))
2386 if (sRefSet_member (e2->msets, e1->sref))
2388 if (e2->kind == XPR_CALL)
2394 hasError = optgenerror
2397 ("Expression has undefined behavior (value of left "
2398 "operand may be modified by right operand): %s %s %s",
2399 exprNode_unparse (e1), lltok_unparse (op),
2400 exprNode_unparse (e2)),
2408 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2410 if (context_maybeSet (FLG_EVALORDERUNCON))
2412 checkExpressionDefinedAux (e1, e2, e1->msets,
2413 e2->msets, op, FLG_EVALORDERUNCON);
2418 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2421 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2422 exprNodeList args, bool isIter, exprNode ret)
2426 if (!exprNode_isError (f))
2428 if (!uentryList_isMissingParams (cl))
2430 int nargs = exprNodeList_size (args);
2431 int expectargs = uentryList_size (cl);
2435 if (expectargs == 0)
2443 message ("Iter %q invoked with %d args, "
2445 uentry_getName (fcn),
2453 message ("Function %s called with %d args, "
2455 exprNode_unparse (f), nargs),
2462 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2464 exprNodeList_reset (args);
2466 uentryList_elements (cl, current)
2468 ctype ct = uentry_getType (current);
2471 if (ctype_isElips (ct))
2474 ** do special checking for printf/scanf library functions
2476 ** this is kludgey code, just for handling the special case
2480 if (uentry_isPrintfLike (fcn))
2482 checkPrintfArgs (f, fcn, args, ret, i);
2485 else if (uentry_isScanfLike (fcn))
2487 checkScanfArgs (f, fcn, args, ret, i);
2490 else if (uentry_isMessageLike (fcn))
2492 checkMessageArgs (f, fcn, args, i);
2497 llassert (!uentry_isSpecialFunction (fcn));
2500 nargs = expectargs; /* avoid errors */
2505 if (i >= nargs) break;
2507 a = exprNodeList_current (args);
2508 exprNodeList_advance (args);
2512 if (exprNode_isError (a))
2519 probably necessary? I'm not sure about this one
2520 checkMacroParen (a);
2523 f->guards = guardSet_union (f->guards, a->guards);
2525 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2527 if (!(exprNode_matchArgType (ct, a)))
2529 DPRINTF (("Args mismatch!"));
2531 if (ctype_isVoidPointer (ct)
2532 && (ctype_isPointer (a->typ)
2533 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2538 ("Pointer to abstract type (%t) used "
2540 "(arg %d to %q): %s",
2542 uentry_getName (fcn),
2543 exprNode_unparse (a)),
2551 (ct, exprNode_undefined,
2554 ("Iter %q expects arg %d to "
2555 "be %t gets %t: %s",
2556 uentry_getName (fcn),
2557 i, ct, a->typ, exprNode_unparse (a)),
2568 ("Function %q expects arg %d to be %t gets %t: %s",
2569 uentry_getName (fcn),
2570 i, ct, a->typ, exprNode_unparse (a)),
2573 DPRINTF (("Types: %s / %s",
2575 ctype_unparse (a->typ)));
2579 ** Clear null marker for abstract types.
2580 ** (It is not revealed, so suppress future messages.)
2583 if (ctype_isAbstract (a->typ))
2585 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2592 } end_uentryList_elements ;
2595 if (expectargs != nargs) /* note: not != since we may have ... */
2597 if (ctype_isElips (last))
2601 message ("Function %s called with %d args, expects at least %d",
2602 exprNode_unparse (f),
2603 nargs, expectargs - 1),
2612 message ("Iter %q invoked with %d args, expects %d",
2613 uentry_getName (fcn), nargs, expectargs),
2620 message ("Function %s called with %d args, expects %d",
2621 exprNode_unparse (f),
2634 ** Check for undefined code sequences in function arguments:
2636 ** one parameter sets something used by another parameter
2637 ** one parameter sets something set by another parameter
2641 checkSequencingOne (exprNode f, exprNodeList args,
2642 /*@notnull@*/ exprNode el, int argno)
2645 ** Do second loop, iff +undefunspec
2649 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2651 for (checkloop = 0; checkloop < numloops; checkloop++)
2657 thissets = el->sets;
2661 llassert (checkloop == 1);
2662 thissets = el->msets;
2665 sRefSet_realElements (thissets, thisset)
2669 /*@access exprNodeList@*/
2670 for (j = 0; j < args->nelements; j++)
2672 exprNode jl = args->elements[j];
2673 int thisargno = j + 1;
2675 if (thisargno != argno && exprNode_isDefined (jl))
2677 sRefSet otheruses = jl->uses;
2679 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
2680 sRefSet_hasUnconstrained (thissets))
2683 (FLG_EVALORDERUNCON,
2686 ("%q used in argument %d may set "
2687 "global variable %q used by argument %d: %s(%q)",
2688 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2691 sRef_unparse (sRef_getRootBase (jl->sref)),
2693 exprNode_unparse (f), exprNodeList_unparse (args)),
2697 if (sRefSet_member (otheruses, thisset))
2699 if (sRef_isUnconstrained (thisset))
2702 (FLG_EVALORDERUNCON,
2704 ("Unconstrained functions used in arguments %d (%q) "
2705 "and %d (%s) may modify "
2706 "or use global state in undefined way: %s(%q)",
2708 sRefSet_unparseUnconstrainedPlain (otheruses),
2710 sRef_unconstrainedName (thisset),
2711 exprNode_unparse (f),
2712 exprNodeList_unparse (args)),
2720 ("Argument %d modifies %q, used by argument %d "
2721 "(order of evaluation of actual parameters is "
2722 "undefined): %s(%q)",
2723 argno, sRef_unparse (thisset), thisargno,
2724 exprNode_unparse (f), exprNodeList_unparse (args)),
2730 sRefSet othersets = jl->sets;
2732 if (sRefSet_member (othersets, thisset))
2734 if (sRef_isUnconstrained (thisset))
2737 (FLG_EVALORDERUNCON,
2739 ("Unconstrained functions used in "
2740 "arguments %d (%q) and %d (%s) may modify "
2741 "or use global state in undefined way: %s(%q)",
2743 sRefSet_unparseUnconstrainedPlain (othersets),
2745 sRef_unconstrainedName (thisset),
2746 exprNode_unparse (f), exprNodeList_unparse (args)),
2754 ("Argument %d modifies %q, set by argument %d (order of"
2755 " evaluation of actual parameters is undefined): %s(%q)",
2756 argno, sRef_unparse (thisset), thisargno,
2757 exprNode_unparse (f), exprNodeList_unparse (args)),
2764 /*@noaccess exprNodeList@*/
2765 } end_sRefSet_realElements;
2770 checkSequencing (exprNode f, exprNodeList args)
2772 if (exprNodeList_size (args) > 1)
2777 /*@access exprNodeList*/
2779 for (i = 0; i < args->nelements; i++)
2781 el = args->elements[i];
2783 if (!exprNode_isError (el))
2785 checkSequencingOne (f, args, el, i + 1);
2788 /*@noaccess exprNodeList*/
2793 ** requires le = exprNode_getUentry (f)
2797 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2798 uentry le, exprNodeList args,
2799 /*@notnull@*/ exprNode ret, int specialArgs)
2801 bool isSpec = FALSE;
2802 bool hasMods = FALSE;
2804 globSet usesGlobs = globSet_undefined;
2805 sRefSet mods = sRefSet_undefined;
2806 bool freshMods = FALSE;
2807 uentryList params = uentryList_undefined;
2809 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2812 ** check globals and modifies
2817 if (!uentry_isValid (le))
2819 ctype fr = ctype_realType (f->typ);
2821 if (ctype_isFunction (fr))
2823 params = ctype_argsFunction (fr);
2827 params = uentryList_missingParams;
2830 if (!context_getFlag (FLG_MODNOMODS)
2831 && !context_getFlag (FLG_GLOBUNSPEC))
2833 checkUnspecCall (f, params, args);
2839 fname = uentry_rawName (le);
2843 if (uentry_isFunction (le))
2845 params = uentry_getParams (le);
2846 mods = uentry_getMods (le);
2847 hasMods = uentry_hasMods (le);
2848 usesGlobs = uentry_getGlobs (le);
2849 isSpec = uentry_isSpecified (le);
2851 else /* not a function */
2853 ctype ct = ctype_realType (uentry_getType (le));
2855 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2856 ("checkModGlobs: uentry not a function: %s",
2857 uentry_unparse (le)));
2859 params = ctype_argsFunction (ct);
2860 return; /*@32 ! remove this? */
2869 globSet_allElements (usesGlobs, el)
2871 if (sRef_isValid (el))
2873 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2875 context_usedGlobal (el);
2876 exprNode_checkUse (f, el, f->loc);
2878 if (context_checkInternalUse ())
2880 if (!context_globAccess (el))
2882 if (sRef_isSystemState (el)
2883 && !context_getFlag (FLG_MODFILESYSTEM))
2892 ("Called procedure %s may access %q, but "
2893 "globals list does not include globals %s",
2894 exprNode_unparse (f),
2896 cstring_makeLiteralTemp (sRef_isInternalState (el)
2904 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2910 uentry gle = sRef_getUentry (el);
2911 sRef sr = sRef_updateSref (el);
2913 if (sRef_isUndefGlob (el))
2915 sRef_setDefined (sr, f->loc);
2916 exprNode_checkSet (f, sr);
2924 if (sRef_isAllocated (el))
2926 exprNode_checkSet (f, sr);
2930 if (sRef_isStateUndefined (sr))
2935 ("%s %q used by function undefined before call: %s",
2936 sRef_getScopeName (sr),
2938 exprNode_unparse (f)),
2940 sRef_setDefined (sr, f->loc);
2942 exprNode_checkUse (f, sr, f->loc);
2945 checkGlobUse (gle, TRUE, f);
2948 if (sRef_isKilledGlob (el))
2950 sRef_kill (sr, f->loc);
2951 context_usedGlobal (sr);
2955 } end_globSet_allElements;
2961 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
2963 sRefSet smods = sRefSet_undefined;
2966 ** NEED to check for modifies anything
2970 ** check each sRef that called function modifies (ml), is
2976 sRefSet_allElements (mods, s) /* s is something which may be modified */
2978 DPRINTF (("Check modify: %s", sRef_unparse (s)));
2980 if (sRef_isKindSpecial (s))
2982 if (sRef_isSpecInternalState (s))
2984 if (context_getFlag (FLG_MODINTERNALSTRICT))
2986 exprNode_checkCallModifyVal (s, args, f, ret);
2990 sRefSet mmods = context_modList ();
2992 sRefSet_allElements (mmods, el)
2994 if (sRef_isInternalState (el))
2996 sRef_setModified (el);
2998 } end_sRefSet_allElements ;
3003 exprNode_checkCallModifyVal (s, args, f, ret);
3008 sRef rb = sRef_getRootBase (s);
3010 if (sRef_isFileOrGlobalScope (rb))
3012 context_usedGlobal (rb);
3015 if (sRef_isFileStatic (s)
3016 && !fileId_equal (fileloc_fileId (f->loc),
3017 fileloc_fileId (uentry_whereDefined (le))))
3019 smods = sRefSet_insert (smods, s);
3023 exprNode_checkCallModifyVal (s, args, f, ret);
3026 } end_sRefSet_allElements;
3031 ** Static elements in modifies set can have nasty consequences.
3032 ** (I think...have not been able to reproduce a possible bug.)
3035 if (!sRefSet_isDefined (smods))
3037 mods = sRefSet_newCopy (mods);
3040 sRefSet_allElements (smods, el)
3042 bool res = sRefSet_delete (mods, el);
3045 } end_sRefSet_allElements;
3047 sRefSet_free (smods);
3052 else if (sRefSet_isDefined (mods))
3053 { /* just check observers */
3056 sRefSet_allElements (mods, s) /* s is something which may be modified */
3058 sRef rb = sRef_getRootBase (s);
3062 if (sRef_isParam (rb))
3064 sRef b = sRef_fixBaseParam (s, args);
3066 if (sRef_isObserver (b))
3068 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
3072 message ("Function call may modify observer%q: %s",
3073 sRef_unparsePreOpt (b), exprNode_unparse (e)),
3076 sRef_showExpInfo (b);
3080 } end_sRefSet_allElements;
3084 if (!hasMods) /* no specified modifications */
3086 if (context_getFlag (FLG_MODOBSERVERUNCON))
3088 exprNodeList_elements (args, e)
3090 if (exprNode_isDefined (e))
3092 sRef s = exprNode_getSref (e);
3094 if (sRef_isObserver (s)
3095 && ctype_isMutable (sRef_getType (s)))
3098 (FLG_MODOBSERVERUNCON,
3100 ("Call to unconstrained function %s may modify observer%q: %s",
3101 exprNode_unparse (f),
3102 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3105 sRef_showExpInfo (s);
3109 } end_exprNodeList_elements;
3114 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3116 ret->uses = sRefSet_union (ret->uses, f->uses);
3117 ret->sets = sRefSet_union (ret->sets, f->sets);
3118 ret->msets = sRefSet_union (ret->msets, f->msets);
3123 ** Spurious errors reported, because lclint can't tell
3124 ** mods must be fresh if freshMods is true.
3127 /*@i@*/ sRefSet_free (mods);
3133 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3135 if (uentry_isVar (glob))
3137 if (context_inFunctionLike ())
3139 sRef sr = uentry_getSref (glob);
3141 context_usedGlobal (sr);
3143 if (context_checkGlobUse (glob))
3145 if (!context_globAccess (sr))
3151 message ("Called procedure %s may access %s %q",
3152 exprNode_unparse (e),
3153 sRef_unparseScope (sr),
3154 uentry_getName (glob)),
3161 message ("Undocumented use of %s %s",
3162 sRef_unparseScope (sr),
3163 exprNode_unparse (e)),
3172 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3177 reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
3179 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3180 exprNode_unparse (f), exprNodeList_unparse (args),
3181 uentry_unparseFull (le),
3182 stateClauseList_unparse (uentry_getStateClauseList (le))));
3184 if (uentry_isValid (le) && uentry_isFunction (le))
3186 stateClauseList sclauses = uentry_getStateClauseList (le);
3188 if (stateClauseList_isDefined (sclauses))
3190 DPRINTF (("Reflect ensures: %s / %s / %s",
3191 uentry_unparse (le),
3192 exprNode_unparse (f), exprNodeList_unparse (args)));
3194 stateClauseList_elements (sclauses, cl)
3196 if (stateClause_hasEnsures (cl))
3198 /* Same in usymtab.c:1904 */
3199 if (stateClause_setsMetaState (cl))
3201 qual q = stateClause_getMetaQual (cl);
3202 annotationInfo ainfo = qual_getAnnotationInfo (q);
3203 metaStateInfo minfo = annotationInfo_getState (ainfo);
3204 cstring key = metaStateInfo_getName (minfo);
3205 int mvalue = annotationInfo_getValue (ainfo);
3207 sRefSet osrs = sRefSet_undefined;
3210 if (stateClause_isGlobal (cl))
3212 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3217 srs = stateClause_getRefs (cl);
3220 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3223 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3225 sRefSet_elements (srs, sel)
3229 if (sRef_isResult (sRef_getRootBase (sel)))
3231 s = exprNode_getSref (ret);
3235 s = sRef_fixBaseParam (sel, args);
3238 DPRINTF (("Reflecting state clause on: %s / %s",
3239 sRef_unparse (sel), sRef_unparse (s)));
3241 sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3242 } end_sRefSet_elements;
3244 sRefSet_free (osrs);
3248 sRefSet srs = stateClause_getRefs (cl);
3249 sRefModVal modf = stateClause_getEnsuresFunction (cl);
3250 int eparam = stateClause_getStateParameter (cl);
3252 DPRINTF (("Reflect after clause: %s / %s",
3253 stateClause_unparse (cl),
3254 sRefSet_unparse (srs)));
3256 sRefSet_elements (srs, sel)
3260 DPRINTF (("elements: %s", sRef_unparse (sel)));
3261 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3263 if (sRef_isResult (sRef_getRootBase (sel)))
3265 DPRINTF (("Fix base: %s / %s",
3266 sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
3267 s = sRef_fixBase (sel, exprNode_getSref (ret));
3268 DPRINTF (("==> %s", sRef_unparseFull (s)));
3272 s = sRef_fixBaseParam (sel, args);
3275 DPRINTF (("elements: %s", sRef_unparse (s)));
3276 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3278 DPRINTF (("Reflecting state clause on: %s / %s",
3279 sRef_unparseFull (sel), sRef_unparseFull (s)));
3281 /* evans 2001-08-24 - added aliasSetCompleteParam */
3282 sRef_aliasSetCompleteParam (modf, s, eparam, exprNode_loc (f));
3284 DPRINTF (("After reflecting state clause on: %s / %s",
3285 sRef_unparseFull (sel), sRef_unparseFull (s)));
3286 } end_sRefSet_elements;
3289 } end_stateClauseList_elements ;
3292 DPRINTF (("Here: %s / %s",
3293 uentry_unparseFull (le),
3294 bool_unparse (uentry_hasMetaStateEnsures (le))));
3296 if (uentry_hasMetaStateEnsures (le))
3298 fileloc loc = exprNode_loc (f);
3300 metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3302 metaStateConstraintList_elements (mscl, msc)
3304 metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3305 metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3306 metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
3307 cstring key = metaStateInfo_getName (msinfo);
3308 sRef mlsr = metaStateSpecifier_getSref (msspec);
3310 sRef lastref = sRef_undefined;
3311 stateValue sval = stateValue_undefined;
3313 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3314 metaStateConstraint_unparse (msc)));
3315 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3317 if (sRef_isResult (sRef_getRootBase (mlsr)))
3319 s = exprNode_getSref (ret);
3323 s = sRef_fixBaseParam (mlsr, args);
3326 DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3328 while (metaStateExpression_isDefined (msexpr))
3330 metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
3331 metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
3334 DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3336 if (metaStateExpression_isMerge (msexpr))
3338 msexpr = metaStateExpression_getRest (msexpr);
3342 msexpr = metaStateExpression_undefined;
3345 if (metaStateInfo_isDefined (msi))
3347 /* Must match lhs state */
3348 llassert (metaStateInfo_equal (msinfo, msi));
3351 if (metaStateSpecifier_isElipsis (ms))
3354 ** For elipsis, we need to merge all the relevant elipsis parameters
3358 uentryList params = uentry_getParams (le);
3359 int paramno = uentryList_size (params) - 1;
3361 if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
3365 message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3366 uentry_getName (le)),
3367 uentry_whereLast (le));
3368 /*@innerbreak@*/ break;
3371 while (paramno < exprNodeList_size (args))
3373 exprNode arg = exprNodeList_getN (args, paramno);
3374 fs = exprNode_getSref (arg);
3375 DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3377 /* cut and pasted... gack*/
3378 if (stateValue_isDefined (sval))
3380 /* Use combination table to merge old state value with new one: */
3381 stateValue tval = sRef_getMetaStateValue (fs, key);
3383 if (stateValue_isDefined (tval))
3385 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3386 cstring msg = cstring_undefined;
3387 int nval = stateCombinationTable_lookup (sctable,
3388 stateValue_getValue (sval),
3389 stateValue_getValue (tval),
3391 DPRINTF (("Combining: %s + %s -> %d",
3392 stateValue_unparseValue (sval, msinfo),
3393 stateValue_unparseValue (tval, msinfo),
3396 if (nval == stateValue_error)
3401 ("Attributes merged in ensures clause in states that "
3402 "cannot be combined (%q is %q, %q is %q)%q",
3403 sRef_unparse (lastref),
3404 stateValue_unparseValue (sval, msinfo),
3406 stateValue_unparseValue (tval, msinfo),
3407 cstring_isDefined (msg) ?
3408 message (": %s", msg) : cstring_undefined),
3411 sRef_showMetaStateInfo (fs, key);
3415 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3416 loc = exprNode_loc (arg);
3420 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3425 sval = sRef_getMetaStateValue (fs, key);
3430 if (stateValue_isError (sval))
3432 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3441 msr = metaStateSpecifier_getSref (ms);
3444 llassert (sRef_isParam (sRef_getRootBase (msr)));
3445 fs = sRef_fixBaseParam (msr, args);
3447 if (stateValue_isDefined (sval))
3449 /* Use combination table to merge old state value with new one: */
3450 stateValue tval = sRef_getMetaStateValue (fs, key);
3452 if (stateValue_isDefined (tval))
3454 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3455 cstring msg = cstring_undefined;
3456 int nval = stateCombinationTable_lookup (sctable,
3457 stateValue_getValue (sval),
3458 stateValue_getValue (tval),
3460 DPRINTF (("Combining: %s + %s -> %d",
3461 stateValue_unparseValue (sval, msinfo),
3462 stateValue_unparseValue (tval, msinfo),
3465 if (nval == stateValue_error)
3470 ("Attributes merged in ensures clause in states that "
3471 "cannot be combined (%q is %q, %q is %q)%q",
3472 sRef_unparse (lastref),
3473 stateValue_unparseValue (sval, msinfo),
3475 stateValue_unparseValue (tval, msinfo),
3476 cstring_isDefined (msg)
3477 ? message (": %s", msg) : cstring_undefined),
3480 sRef_showMetaStateInfo (fs, key);
3484 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3488 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3493 sval = sRef_getMetaStateValue (fs, key);
3498 if (stateValue_isError (sval))
3500 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3505 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3507 if (stateValue_isDefined (sval))
3509 sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
3513 DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
3515 } end_metaStateConstraintList_elements ;
3517 metaStateConstraintList_free (mscl);
3523 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3525 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3526 exprNode_unparse (f), exprNodeList_unparse (args),
3527 uentry_unparseFull (le),
3528 stateClauseList_unparse (uentry_getStateClauseList (le))));
3530 if (uentry_isValid (le) && uentry_isFunction (le))
3532 stateClauseList sclauses = uentry_getStateClauseList (le);
3534 if (stateClauseList_isDefined (sclauses))
3536 DPRINTF (("Check requires: %s / %s / %s",
3537 uentry_unparse (le),
3538 exprNode_unparse (f), exprNodeList_unparse (args)));
3540 stateClauseList_elements (sclauses, cl)
3542 DPRINTF (("Check clause: %s / %s",
3543 stateClause_unparse (cl),
3544 bool_unparse (stateClause_hasRequires (cl))));
3546 if (stateClause_hasRequires (cl))
3548 sRefSet osrs = sRefSet_undefined;
3551 if (stateClause_isGlobal (cl))
3553 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3558 srs = stateClause_getRefs (cl);
3561 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3563 if (stateClause_setsMetaState (cl))
3565 qual q = stateClause_getMetaQual (cl);
3566 annotationInfo ainfo = qual_getAnnotationInfo (q);
3567 metaStateInfo minfo = annotationInfo_getState (ainfo);
3568 cstring key = metaStateInfo_getName (minfo);
3569 int mvalue = annotationInfo_getValue (ainfo);
3571 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3573 sRefSet_elements (srs, sel)
3575 sRef s = sRef_fixBaseParam (sel, args);
3577 if (sRef_isResult (sRef_getRootBase (sel)))
3583 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3584 sRef_unparseFull (sel), sRef_unparseFull (s),
3587 if (!sRef_checkMetaStateValue (s, key, mvalue))
3589 DPRINTF (("HERE: %s", sRef_unparse (s)));
3593 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3594 uentry_getName (le),
3595 sRef_isGlobalMarker (s)
3597 : message (" by %q", sRef_unparse (s)),
3598 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3600 stateClause_unparse (cl)),
3603 sRef_showAliasInfo (s);
3607 DPRINTF (("Error supressed!"));
3608 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3609 DPRINTF (("Context supress: %s",
3610 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3614 } end_sRefSet_elements;
3618 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3619 int eparam = stateClause_getStateParameter (cl);
3621 DPRINTF (("Reflect after clause: %s / %s",
3622 stateClause_unparse (cl),
3623 sRefSet_unparse (srs)));
3625 sRefSet_elements (srs, sel)
3629 DPRINTF (("elements: %s", sRef_unparse (sel)));
3630 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3632 s = sRef_fixBaseParam (sel, args);
3634 DPRINTF (("elements: %s", sRef_unparse (s)));
3635 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3637 if (sRef_isResult (sRef_getRootBase (sel)))
3639 ; /*@i423 what do we do about results */
3643 DPRINTF (("Reflecting state clause on: %s / %s",
3644 sRef_unparse (sel), sRef_unparse (s)));
3646 modf (s, eparam, exprNode_loc (f));
3648 } end_sRefSet_elements;
3651 sRefSet_free (osrs);
3653 } end_stateClauseList_elements ;
3658 static /*@only@*/ exprNode
3659 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3660 ctype t, /*@keep@*/ exprNodeList args)
3662 /* requires f is a non-error exprNode, with type function */
3663 cstring fname = exprNode_unparse (f);
3664 uentry le = exprNode_getUentry (f);
3665 exprNode ret = exprNode_createPartialCopy (f);
3670 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3672 ret->typ = ctype_getReturnType (t);
3673 ret->kind = XPR_CALL;
3675 ret->edata = exprData_makeCall (f, args);
3678 ** Order of these steps is very important!
3680 ** Must check for argument dependencies before messing up uses and sets.
3683 if (context_getFlag (FLG_EVALORDER))
3685 exprNodeList_elements (args, current)
3687 if (exprNode_isDefined (current))
3689 exprNode_addUse (current, current->sref);
3691 } end_exprNodeList_elements;
3693 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3695 checkSequencing (f, args);
3698 exprNodeList_elements (args, current)
3700 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3702 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3704 } end_exprNodeList_elements ;
3707 special = checkArgs (le, f, t, args, ret);
3708 checkGlobMods (f, le, args, ret, special);
3709 checkRequiresClause (le, f, args);
3712 if (uentry_isValid (le)
3713 && (uentry_isFunction (le)
3714 || (uentry_isVariable (le)
3715 && ctype_isFunction (uentry_getType (le)))))
3717 exitkind exk = uentry_getExitCode (le);
3719 /* f->typ is already set to the return type */
3721 DPRINTF (("Function: %s", uentry_unparseFull (le)));
3722 ret->sref = uentry_returnedRef (le, args);
3723 DPRINTF (("Returned: %s / %s",
3724 uentry_unparseFull (le),
3725 sRef_unparseFull (ret->sref)));
3727 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3729 qual nullPred = uentry_nullPred (le);
3731 if (qual_isTrueNull (nullPred))
3733 exprNode arg = exprNodeList_head (args);
3735 if (exprNode_isDefined (arg))
3737 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3740 else if (qual_isFalseNull (nullPred))
3742 exprNode arg = exprNodeList_head (args);
3744 if (exprNode_isDefined (arg))
3746 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3751 llassert (qual_isUnknown (nullPred));
3755 if (exitkind_isConditionalExit (exk))
3759 ** if (arg0) then { exit! } else { ; }
3761 ** if (arg0) then { ; } else { exit! }
3766 llassert (!exprNodeList_isEmpty (args));
3767 firstArg = exprNodeList_head (args);
3769 if (exprNode_isDefined (firstArg)
3770 && !guardSet_isEmpty (firstArg->guards))
3772 usymtab_trueBranch (guardSet_undefined);
3773 usymtab_altBranch (guardSet_undefined);
3775 if (exitkind_isTrueExit (exk))
3777 usymtab_popBranches (firstArg,
3778 exprNode_makeMustExit (),
3780 TRUE, TRUEEXITCLAUSE);
3784 usymtab_popBranches (firstArg,
3786 exprNode_makeMustExit (),
3787 TRUE, FALSEEXITCLAUSE);
3791 ret->exitCode = XK_MAYEXIT;
3793 else if (exitkind_mustExit (exk))
3795 ret->exitCode = XK_MUSTEXIT;
3797 else if (exitkind_couldExit (exk))
3799 ret->exitCode = XK_MAYEXIT;
3806 if (cstring_equalLit (fname, "exit"))
3808 if (exprNodeList_size (args) == 1)
3810 exprNode arg = exprNodeList_head (args);
3812 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3814 long int val = multiVal_forceInt (exprNode_getValue (arg));
3821 ("Argument to exit has implementation defined behavior: %s",
3822 exprNode_unparse (arg)),
3823 exprNode_loc (arg));
3832 exprNode_checkSetAny (ret, uentry_rawName (le));
3835 DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3836 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3837 reflectEnsuresClause (ret, le, f, args);
3844 ** this is yucky! should keep the uentry as part of exprNode!
3847 uentry exprNode_getUentry (exprNode e)
3849 if (exprNode_isError (e))
3851 return uentry_undefined;
3855 cstring s = exprNode_rootVarName (e);
3856 uentry ue = usymtab_lookupSafe (s);
3863 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3865 exprNode ret = exprNode_createPlain (ctype_unknown);
3867 ret->kind = XPR_INITBLOCK;
3868 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3869 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3875 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3881 if (exprNode_isUndefined (f))
3884 exprNodeList_free (args);
3885 return exprNode_undefined;
3888 t = exprNode_getType (f);
3890 if (sRef_isLocalVar (f->sref))
3892 exprNode_checkUse (f, f->sref, f->loc);
3894 if (sRef_possiblyNull (f->sref))
3896 if (!usymtab_isGuarded (f->sref))
3898 if (optgenerror (FLG_NULLDEREF,
3899 message ("Function call using %s pointer %q",
3900 sRef_nullMessage (f->sref),
3901 sRef_unparse (f->sref)),
3904 sRef_showNullInfo (f->sref);
3905 sRef_setNullError (f->sref);
3913 if (ctype_isRealFunction (t))
3915 exprNode ret = functionCallSafe (f, t, args);
3919 else if (ctype_isUnknown (t))
3921 exprNode ret = exprNode_createPartialCopy (f);
3927 exprNodeList_elements (args, current)
3929 if (exprNode_isDefined (current))
3931 exprNode_checkUse (ret, current->sref, ret->loc);
3934 ** also, anything derivable from current->sref may be used
3937 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3938 exprNode_mergeUSs (ret, current);
3940 } end_exprNodeList_elements;
3942 ret->edata = exprData_makeCall (f, args);
3943 ret->kind = XPR_CALL;
3945 tstring = cstring_copy (exprNode_unparse (f));
3947 cstring_markOwned (tstring);
3948 exprNode_checkSetAny (ret, tstring);
3954 voptgenerror (FLG_TYPE,
3955 message ("Call to non-function (type %t): %s", t,
3956 exprNode_unparse (f)),
3959 exprNodeList_free (args);
3961 return (exprNode_makeError ());
3966 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
3967 /*@only@*/ cstring f)
3969 exprNode ret = exprNode_createPartialCopy (s);
3971 ret->kind = XPR_FACCESS;
3973 if (exprNode_isError (s))
3975 ret->edata = exprData_makeField (s, f);
3980 ctype t = exprNode_getType (s);
3981 ctype tr = ctype_realType (t);
3983 checkMacroParen (s);
3985 ret->edata = exprData_makeField (s, f);
3987 if (ctype_isStructorUnion (tr))
3989 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
3991 if (uentry_isUndefined (tf))
3993 voptgenerror (FLG_TYPE,
3994 message ("Access non-existent field %s of %t: %s", f, t,
3995 exprNode_unparse (ret)),
3997 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
4002 uentry_setUsed (tf, exprNode_loc (ret));
4004 ret->typ = uentry_getType (tf);
4005 checkSafeUse (ret, s->sref);
4007 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
4008 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
4012 else /* isStructorUnion */
4014 if (ctype_isRealAbstract (tr))
4018 message ("Access field of abstract type (%t): %s.%s",
4019 t, exprNode_unparse (s), f),
4021 ret->typ = ctype_unknown;
4025 if (ctype_isKnown (tr))
4030 ("Access field of non-struct or union (%t): %s.%s",
4031 t, exprNode_unparse (s), f),
4034 ret->typ = ctype_unknown;
4038 cstring sn = cstring_copy (f);
4040 checkSafeUse (ret, s->sref);
4041 cstring_markOwned (sn);
4042 ret->sref = sRef_makeField (s->sref, sn);
4054 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
4055 /*@only@*/ cstring f)
4057 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
4058 lltok_release (dot);
4063 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
4065 exprNode ret = exprNode_createPartialCopy (e);
4067 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
4068 ret->kind = XPR_PARENS;
4069 ret->edata = exprData_makeUop (e, lpar);
4071 if (!exprNode_isError (e))
4073 ret->exitCode = e->exitCode;
4074 ret->canBreak = e->canBreak;
4075 ret->mustBreak = e->mustBreak;
4076 ret->isJumpPoint = e->isJumpPoint;
4077 ret->sref = e->sref;
4084 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4085 /*@only@*/ cstring f)
4087 exprNode ret = exprNode_createPartialCopy (s);
4089 ret->edata = exprData_makeField (s, f);
4090 ret->kind = XPR_ARROW;
4092 if (exprNode_isError (s))
4098 ctype t = exprNode_getType (s);
4099 ctype tr = ctype_realType (t);
4101 checkMacroParen (s);
4103 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4105 if (ctype_isRealPointer (tr))
4107 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4109 if (ctype_isStructorUnion (b))
4111 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4113 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4115 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4119 message ("Arrow access from %s pointer%q: %s",
4120 sRef_nullMessage (s->sref),
4121 sRef_unparsePreOpt (s->sref),
4122 exprNode_unparse (ret)),
4125 sRef_showNullInfo (s->sref);
4126 sRef_setNullError (s->sref);
4131 if (uentry_isUndefined (fentry))
4135 message ("Access non-existent field %s of %t: %s",
4136 f, t, exprNode_unparse (ret)),
4138 ret->typ = ctype_unknown;
4144 ** was safeUse: shouldn't be safe!
4147 ** rec must be defined,
4148 ** *rec must be allocated
4149 ** rec->field need only be defined it if is an rvalue
4152 uentry_setUsed (fentry, exprNode_loc (ret));
4153 ret->typ = uentry_getType (fentry);
4155 exprNode_checkUse (ret, s->sref, s->loc);
4157 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4158 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4162 else /* Pointer to something that is not a struct or union*/
4164 if (ctype_isRealAbstract (tr))
4166 ctype xrt = ctype_forceRealType (tr);
4170 message ("Arrow access field of abstract type (%t): %s->%s",
4171 t, exprNode_unparse (s), f),
4175 ** Set the state correctly, as if the abstraction is broken.
4178 if (ctype_isRealPointer (xrt) &&
4179 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4180 ctype_isStructorUnion (b)))
4182 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4183 ret->typ = uentry_getType (fentry);
4184 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4188 ret->typ = ctype_unknown;
4189 ret->sref = sRef_undefined;
4192 else /* not a struct, union or abstract */
4194 if (ctype_isUnknown (tr)) {
4195 cstring sn = cstring_copy (f);
4197 DPRINTF (("Here: %s", exprNode_unparse (s)));
4199 exprNode_checkUse (ret, s->sref, s->loc);
4200 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4202 cstring_markOwned (sn);
4203 ret->sref = sRef_makeArrow (s->sref, sn);
4205 ret->kind = XPR_ARROW;
4210 message ("Arrow access field of non-struct or union "
4211 "pointer (%t): %s->%s",
4212 t, exprNode_unparse (s), f),
4215 ret->typ = ctype_unknown;
4216 ret->sref = sRef_undefined;
4221 else /* its not a pointer */
4223 if (!ctype_isUnknown (tr))
4227 message ("Arrow access of non-pointer (%t): %s->%s",
4228 t, exprNode_unparse (s), f),
4231 ret->typ = ctype_unknown;
4232 ret->sref = sRef_undefined;
4236 cstring sn = cstring_copy (f);
4238 DPRINTF (("Here: %s", exprNode_unparse (s)));
4240 exprNode_checkUse (ret, s->sref, s->loc);
4241 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4243 cstring_markOwned (sn);
4244 ret->sref = sRef_makeArrow (s->sref, sn);
4246 ret->kind = XPR_ARROW;
4257 exprNode_arrowAccess (/*@only@*/ exprNode s,
4258 /*@only@*/ lltok arrow,
4259 /*@only@*/ cstring f)
4261 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4262 lltok_release (arrow);
4267 ** only postOp's in C: i++ and i--
4271 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4273 /* check modification also */
4274 /* cstring opname = lltok_unparse (op);*/
4276 exprNode ret = exprNode_createPartialCopy (e);
4278 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4279 ret->kind = XPR_POSTOP;
4280 ret->edata = exprData_makeUop (e, op);
4282 if (!exprNode_isDefined (e))
4287 checkMacroParen (e);
4289 exprNode_checkUse (ret, e->sref, e->loc);
4290 exprNode_checkSet (ret, e->sref);
4292 t = exprNode_getType (e);
4294 if (sRef_isUnsafe (e->sref))
4296 voptgenerror (FLG_MACROPARAMS,
4297 message ("Operand of %s is macro parameter (non-functional): %s%s",
4298 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4300 sRef_makeSafe (e->sref);
4301 sRef_makeSafe (ret->sref);
4304 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4310 if (ctype_isRealAbstract (t))
4314 message ("Operand of %s is abstract type (%t): %s",
4315 lltok_unparse (op), t, exprNode_unparse (e)),
4322 message ("Operand of %s is non-numeric (%t): %s",
4323 lltok_unparse (op), t, exprNode_unparse (e)),
4326 ret->typ = ctype_unknown;
4329 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4331 exprNode_checkModify (e, ret);
4333 /* added 7/11/2000 D.L */
4335 /*DRL 6/8/01 I decided to disable all Splint warnings here since the code
4336 probably needs a rewrite any way */
4341 /* updateEnvironmentForPostOp (e); */
4343 /* start modifications */
4344 /* added by Seejo on 4/16/2000 */
4346 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4348 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4350 ret->sref = sRef_copy (e->sref);
4353 if (lltok_getTok (op) == INC_OP) {
4354 if (sRef_getSize(e->sref) > 0) {
4356 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4358 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4359 /* Assumption: there is only 1 \0 in the buffer */
4360 /* This will not be correct if there are 2 \0's in the buffer */
4361 sRef_setNotNullTerminatedState(ret->sref);
4362 sRef_resetLen(ret->sref);
4364 sRef_setNullTerminatedState(ret->sref);
4365 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4367 if (sRef_isNullTerminated (ret->sref))
4368 printf ("ret->sref is Null Terminated\n");
4369 else if (sRef_isPossiblyNullTerminated (ret->sref))
4370 printf ("ret->sref is Possibly Null Terminated\n");
4371 else if (sRef_isNotNullTerminated (ret->sref))
4372 printf ("ret->sref is Not Null Terminated\n");
4377 if (lltok_getTok (op) == DEC_OP) {
4378 if (sRef_getSize(e->sref) >= 0) {
4379 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4380 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4385 /* end modifications */
4391 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4393 bool checkMod = FALSE;
4395 int opid = lltok_getTok (op);
4396 exprNode ret = exprNode_createSemiCopy (e);
4398 exprNode_copySets (ret, e);
4400 multiVal_free (ret->val);
4401 ret->val = multiVal_undefined;
4402 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4403 ret->kind = XPR_PREOP;
4404 ret->edata = exprData_makeUop (e, op);
4406 if (exprNode_isError (e))
4411 checkMacroParen (e);
4413 te = exprNode_getType (e);
4414 tr = ctype_realType (te);
4416 if (opid != TAMPERSAND)
4418 exprNode_checkUse (ret, e->sref, e->loc);
4420 if (ctype_isRealAbstract (tr)
4421 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4423 if (optgenerror (FLG_ABSTRACT,
4424 message ("Operand of %s is abstract type (%t): %s",
4425 lltok_unparse (op), tr,
4426 exprNode_unparse (ret)),
4429 tr = te = ctype_unknown;
4430 ret->typ = ctype_unknown;
4431 sRef_setNullError (e->sref);
4439 case DEC_OP: /* should also check modification! */
4440 if (sRef_isMacroParamRef (e->sref))
4444 message ("Operand of %s is macro parameter (non-functional): %s",
4445 lltok_unparse (op), exprNode_unparse (ret)),
4450 exprNode_checkSet (ret, e->sref);
4453 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4458 if (context_msgStrictOps ())
4462 message ("Operand of %s is non-numeric (%t): %s",
4463 lltok_unparse (op), te, exprNode_unparse (ret)),
4466 ret->typ = ctype_int;
4469 /* start modifications */
4470 /* added by Seejo on 4/16/2000 */
4472 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4474 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4476 ret->sref = sRef_copy (e->sref);
4479 if (lltok_getTok (op) == INC_OP) {
4480 if (sRef_getSize(e->sref) > 0) {
4482 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4484 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4485 /* Assumption: there is only 1 \0 in the buffer */
4486 /* This will not be correct if there are 2 \0's in the buffer */
4487 sRef_setNotNullTerminatedState(ret->sref);
4488 sRef_resetLen (ret->sref);
4490 sRef_setNullTerminatedState(ret->sref);
4491 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4497 if (lltok_getTok (op) == DEC_OP) {
4498 if (sRef_getSize(e->sref) >= 0) {
4499 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4500 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4505 /* end modifications */
4512 if (ctype_isForceRealNumeric (&tr))
4516 ret->val = multiVal_invert (exprNode_getValue (e));
4520 ret->val = multiVal_copy (exprNode_getValue (e));
4525 if (context_msgStrictOps ())
4529 message ("Operand of %s is non-numeric (%t): %s",
4530 lltok_unparse (op), te, exprNode_unparse (ret)),
4534 ret->typ = ctype_int;
4538 case TEXCL: /* maybe this should be restricted */
4539 guardSet_flip (ret->guards);
4541 if (ctype_isRealBool (te) || ctype_isUnknown (te))
4547 if (ctype_isRealPointer (tr))
4549 if (sRef_isKnown (e->sref))
4551 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4555 (FLG_BOOLOPS, FLG_PTRNEGATE,
4556 message ("Operand of %s is non-boolean (%t): %s",
4557 lltok_unparse (op), te, exprNode_unparse (ret)),
4564 message ("Operand of %s is non-boolean (%t): %s",
4565 lltok_unparse (op), te, exprNode_unparse (ret)),
4569 ret->typ = ctype_bool;
4574 if (ctype_isForceRealInt (&tr))
4579 if (context_msgStrictOps ())
4583 message ("Operand of %s is non-integer (%t): %s",
4584 lltok_unparse (op), te, exprNode_unparse (ret)),
4588 if (ctype_isInt (e->typ))
4594 ret->typ = ctype_int;
4600 ret->typ = ctype_makePointer (e->typ);
4602 if (sRef_isKnown (e->sref))
4604 ret->sref = sRef_makeAddress (e->sref);
4611 if (ctype_isAP (tr))
4613 ret->typ = ctype_baseArrayPtr (e->typ);
4617 if (ctype_isKnown (te))
4619 if (ctype_isFunction (te))
4625 message ("Dereference of function type (%t): %s",
4626 te, exprNode_unparse (ret)),
4631 voptgenerror (FLG_TYPE,
4632 message ("Dereference of non-pointer (%t): %s",
4633 te, exprNode_unparse (ret)),
4635 ret->typ = ctype_unknown;
4640 ret->typ = ctype_unknown;
4645 if (sRef_isKnown (e->sref))
4647 DPRINTF (("Checking possibly null: %s", sRef_unparseFull (e->sref)));
4649 if (sRef_possiblyNull (e->sref))
4651 DPRINTF (("Checking possibly null: %s", sRef_unparse (e->sref)));
4652 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4656 message ("Dereference of %s pointer %q: %s",
4657 sRef_nullMessage (e->sref),
4658 sRef_unparse (e->sref),
4659 exprNode_unparse (ret)),
4662 sRef_showNullInfo (e->sref);
4663 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4668 ret->sref = sRef_makePointer (e->sref);
4673 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4678 exprNode_checkModify (e, ret);
4685 ** any reason to disallow sizeof (abstract type) ?
4689 ** used by both sizeof
4693 ctype sizeof_resultType (void)
4695 static ctype sizet = ctype_unknown;
4697 if (ctype_isUnknown (sizet))
4699 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4701 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4705 sizet = ctype_ulint;
4712 exprNode_sizeofType (/*@only@*/ qtype qt)
4714 exprNode ret = exprNode_create (sizeof_resultType ());
4715 ctype ct = qtype_getType (qt);
4717 ret->kind = XPR_SIZEOFT;
4718 ret->edata = exprData_makeSizeofType (qt);
4720 voptgenerror (FLG_SIZEOFTYPE,
4721 message ("Parameter to sizeof is type %s: %s",
4723 exprNode_unparse (ret)),
4730 exprNode_alignofType (/*@only@*/ qtype qt)
4732 exprNode ret = exprNode_create (sizeof_resultType ());
4733 ctype ct = qtype_getType (qt);
4735 ret->kind = XPR_ALIGNOFT;
4736 ret->edata = exprData_makeSizeofType (qt);
4738 voptgenerror (FLG_SIZEOFTYPE,
4739 message ("Parameter to alignof is type %s: %s",
4741 exprNode_unparse (ret)),
4747 exprNode exprNode_offsetof (qtype qt, cstringList s)
4749 exprNode ret = exprNode_create (sizeof_resultType ());
4750 ctype ct = qtype_getType (qt);
4752 ret->kind = XPR_OFFSETOF;
4753 ret->edata = exprData_makeOffsetof (qt, s);
4755 if (!ctype_isRealSU (ct))
4757 voptgenerror (FLG_TYPE,
4758 message ("First parameter to offsetof is not a "
4759 "struct or union type (type %s): %s",
4761 exprNode_unparse (ret)),
4768 cstringList_elements (s, el) {
4772 if (ctype_isUndefined (lt))
4776 else if (!ctype_isRealSU (lt))
4778 voptgenerror (FLG_TYPE,
4779 message ("Inner offsetof type is not a "
4780 "struct or union type (type %s before field %s): %s",
4781 ctype_unparse (lt), el,
4782 exprNode_unparse (ret)),
4788 fields = ctype_getFields (ctype_realType (lt));
4789 fld = uentryList_lookupField (fields, el);
4790 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4792 if (uentry_isUndefined (fld))
4794 if (ctype_equal (lt, ct)) {
4795 voptgenerror (FLG_TYPE,
4796 message ("Field %s in offsetof is not the "
4797 "name of a field of %s: %s",
4800 exprNode_unparse (ret)),
4803 voptgenerror (FLG_TYPE,
4804 message ("Deep field %s in offsetof is not the "
4805 "name of a field of %s: %s",
4808 exprNode_unparse (ret)),
4814 lt = uentry_getType (fld);
4817 } end_cstringList_elements;
4819 /* Should report error if its a bit field - behavior is undefined! */
4826 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4830 if (exprNode_isUndefined (e))
4832 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4833 ret->edata = exprData_makeSingle (e);
4834 ret->typ = sizeof_resultType ();
4835 ret->kind = XPR_SIZEOF;
4839 uentry u = exprNode_getUentry (e);
4841 ret = exprNode_createPartialCopy (e);
4842 ret->edata = exprData_makeSingle (e);
4844 ret->typ = sizeof_resultType ();
4845 ret->kind = XPR_SIZEOF;
4847 if (uentry_isValid (u)
4848 && uentry_isRefParam (u)
4849 && ctype_isRealArray (uentry_getType (u)))
4852 (FLG_SIZEOFFORMALARRAY,
4853 message ("Parameter to sizeof is an array-type function parameter: %s",
4854 exprNode_unparse (ret)),
4860 ** sizeof (x) doesn't "really" use x
4867 exprNode_alignofExpr (/*@only@*/ exprNode e)
4871 if (exprNode_isUndefined (e))
4873 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4877 ret = exprNode_createPartialCopy (e);
4880 ret->edata = exprData_makeSingle (e);
4881 ret->typ = sizeof_resultType ();
4882 ret->kind = XPR_ALIGNOF;
4885 ** sizeof (x) doesn't "really" use x
4892 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4898 if (exprNode_isError (e))
4901 lltok_release (tok);
4902 return exprNode_undefined;
4905 checkMacroParen (e);
4907 c = qtype_getType (q);
4908 t = exprNode_getType (e);
4910 ret = exprNode_createPartialCopy (e);
4912 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4914 ret->kind = XPR_CAST;
4915 ret->edata = exprData_makeCast (tok, e, q);
4917 if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
4920 ** This is a bit of a hack to avoid a problem
4921 ** when the code does,
4922 ** (some other struct) x
4927 ret->sref = sRef_copy (e->sref);
4928 usymtab_addForceMustAlias (ret->sref, e->sref);
4929 sRef_setTypeFull (ret->sref, c);
4930 DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
4931 sRef_unparseFull (ret->sref)));
4935 ret->sref = e->sref;
4936 sRef_setTypeFull (ret->sref, c);
4937 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
4944 ** void * <-> abstract * (if FLG_ABSTVOIDP)
4945 ** abstract * <-> void * (if FLG_ABSTVOIDP)
4948 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
4952 else if (ctype_isRealAP (c)) /* casting to array or pointer */
4954 ctype bc = ctype_getBaseType (c);
4955 ctype bt = ctype_getBaseType (t);
4956 ctype rt = ctype_realType (t);
4958 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
4959 && (ctype_isArrayPtr (rt)
4960 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4964 message ("Cast from function pointer type (%t) to "
4965 "non-function pointer (%t): %s",
4966 c, t, exprNode_unparse (ret)),
4970 if (!ctype_isFunction (ctype_baseArrayPtr (c))
4971 && (ctype_isArrayPtr (rt)
4972 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4976 message ("Cast from non-function pointer type (%t) to "
4977 "function pointer (%t): %s",
4978 c, t, exprNode_unparse (ret)),
4982 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
4983 !(ctype_isRealAbstract (bc)
4984 && context_hasAccess (ctype_typeId (bc))))
4986 ; /* okay to cast zero */
4990 if (ctype_isRealAbstract (bc)
4991 && !context_hasAccess (ctype_typeId (bc)))
4993 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
4997 message ("Cast to underlying abstract type %t: %s",
4998 c, exprNode_unparse (ret)),
5005 message ("Cast to underlying abstract type %t: %s",
5006 c, exprNode_unparse (ret)),
5011 if (ctype_isRealAbstract (bt)
5012 && !context_hasAccess (ctype_typeId (bt)))
5014 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
5018 message ("Cast from underlying abstract type %t: %s",
5019 t, exprNode_unparse (ret)),
5026 message ("Cast from underlying abstract type %t: %s",
5027 t, exprNode_unparse (ret)),
5035 ctype bt = ctype_realType (ctype_getBaseType (t));
5036 ctype bc = ctype_realType (ctype_getBaseType (c));
5038 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
5040 if (ctype_match (c, t))
5042 if (ctype_equal (c, t))
5046 message ("Redundant cast involving abstract type %t: %s",
5047 bt, exprNode_unparse (ret)),
5055 message ("Cast from abstract type %t: %s",
5056 bt, exprNode_unparse (ret)),
5061 if (ctype_isAbstract (bc)
5062 && !context_hasAccess (ctype_typeId (bc)))
5064 if (ctype_match (c, t))
5070 DPRINTF (("No access to: %s / %d",
5071 ctype_unparse (bc), ctype_typeId (bc)));
5072 DPRINTF (("Context %s %s",
5073 bool_unparse (context_inFunctionLike ()),
5074 context_unparse ()));
5077 message ("Cast to abstract type %t: %s", bc,
5078 exprNode_unparse (ret)),
5084 if (ctype_isAbstract (c))
5086 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
5088 /* okay, cast exposed to abstract */
5089 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
5093 if (ctype_isVisiblySharable (t)
5094 && sRef_isExternallyVisible (e->sref)
5095 && !(ctype_isAbstract (t)
5096 && context_hasAccess (ctype_typeId (t))))
5100 message ("Cast to abstract type from externally visible "
5101 "mutable storage exposes rep of %s: %s",
5103 exprNode_unparse (e)),
5113 evaluationOrderUndefined (lltok op)
5115 int opid = lltok_getTok (op);
5117 return (opid != AND_OP && opid != OR_OP);
5120 static bool checkIntegral (/*@notnull@*/ exprNode e1,
5121 /*@notnull@*/ exprNode e2,
5122 /*@notnull@*/ exprNode ret,
5127 ctype te1 = exprNode_getType (e1);
5128 ctype te2 = exprNode_getType (e2);
5130 ctype tr1 = ctype_realishType (te1);
5131 ctype tr2 = ctype_realishType (te2);
5133 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5139 if (context_msgStrictOps ())
5141 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5143 if (ctype_sameName (te1, te2))
5147 message ("Operands of %s are non-integer (%t): %s",
5148 lltok_unparse (op), te1,
5149 exprNode_unparse (ret)),
5156 message ("Operands of %s are non-integers (%t, %t): %s",
5157 lltok_unparse (op), te1, te2,
5158 exprNode_unparse (ret)),
5162 else if (!ctype_isInt (tr1))
5166 message ("Left operand of %s is non-integer (%t): %s",
5167 lltok_unparse (op), te1, exprNode_unparse (ret)),
5171 /* !ctype_isInt (te2) */
5175 message ("Right operand of %s is non-integer (%t): %s",
5176 lltok_unparse (op), te2, exprNode_unparse (ret)),
5186 ** returns exprNode representing e1 op e2
5188 ** uses msg if there are errors
5189 ** can be used for both assignment ops and regular ops
5194 static /*@only@*/ /*@notnull@*/ exprNode
5195 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
5196 /*@keep@*/ lltok op)
5198 ctype te1, te2, tr1, tr2, tret;
5199 int opid = lltok_getTok (op);
5200 bool hasError = FALSE;
5203 if (exprNode_isError (e1))
5205 ret = exprNode_createPartialNVCopy (e2);
5209 ret = exprNode_createPartialNVCopy (e1);
5212 ret->val = multiVal_undefined;
5214 ret->edata = exprData_makeOp (e1, e2, op);
5216 if (exprNode_isError (e1) || exprNode_isError (e2))
5218 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5219 || opid == EQ_OP || opid == NE_OP
5220 || opid == AND_OP || opid == OR_OP)
5222 ret->typ = ctype_bool;
5225 if (exprNode_isDefined (e1))
5227 exprNode_checkUse (ret, e1->sref, e1->loc);
5230 if (exprNode_isDefined (e2))
5232 exprNode_mergeUSs (ret, e2);
5233 exprNode_checkUse (ret, e2->sref, e2->loc);
5239 tret = ctype_unknown;
5240 te1 = exprNode_getType (e1);
5242 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5244 te2 = exprNode_getType (e2);
5246 tr1 = ctype_realishType (te1);
5247 tr2 = ctype_realishType (te2);
5251 ret->guards = guardSet_or (ret->guards, e2->guards);
5253 else if (opid == AND_OP)
5255 ret->guards = guardSet_and (ret->guards, e2->guards);
5262 if (opid == EQ_OP || opid == NE_OP)
5264 exprNode temp1 = e1, temp2 = e2;
5266 /* could do NULL == x */
5268 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5270 temp1 = e2; temp2 = e1;
5273 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5275 reflectNullTest (temp1, (opid == NE_OP));
5276 guardSet_free (ret->guards);
5277 ret->guards = guardSet_copy (temp1->guards);
5281 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5282 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5287 if (anyAbstract (tr1, tr2) &&
5288 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
5289 (opid == AND_OP || opid == OR_OP
5290 || opid == EQ_OP || opid == NE_OP))))
5292 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
5294 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5296 /* unknown types, no comparisons possible */
5302 case TMULT: /* multiplication and division: */
5304 case MUL_ASSIGN: /* numeric, numeric -> numeric */
5305 case DIV_ASSIGN: /* */
5307 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5310 case TPLUS: /* addition and subtraction: */
5311 case TMINUS: /* pointer, int -> pointer */
5312 case SUB_ASSIGN: /* int, pointer -> pointer */
5313 case ADD_ASSIGN: /* numeric, numeric -> numeric */
5315 tr1 = ctype_fixArrayPtr (tr1);
5317 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5318 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5322 if (context_msgPointerArith ())
5326 message ("Pointer arithmetic (%t, %t): %s",
5327 te1, te2, exprNode_unparse (ret)),
5332 ** Swap terms so e1 is always the pointer
5335 if (ctype_isRealPointer (tr1))
5341 exprNode_swap (e1, e2);
5345 if (sRef_possiblyNull (e1->sref)
5346 && !usymtab_isGuarded (e1->sref))
5349 (FLG_NULLPOINTERARITH,
5350 message ("Pointer arithmetic involving possibly "
5351 "null pointer %s: %s",
5352 exprNode_unparse (e1),
5353 exprNode_unparse (ret)),
5357 ret->sref = sRef_copy (e1->sref);
5359 /* start modifications */
5360 /* added by Seejo on 4/16/2000 */
5362 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5364 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5367 added ugly fixed to stop
5368 program from crashing on point + int +int
5369 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5371 if (!multiVal_isInt (e2->val) )
5375 val = (int) multiVal_forceInt (e2->val);
5377 /* Operator : + or += */
5378 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5379 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5380 val should not result in a
5381 size < 0 (size = 0 is ok !) */
5383 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5385 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5386 sRef_setNotNullTerminatedState(ret->sref);
5387 sRef_resetLen (ret->sref);
5389 sRef_setNullTerminatedState(ret->sref);
5390 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5395 /* Operator : - or -= */
5396 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5397 if (sRef_getSize(e1->sref) >= 0) {
5398 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5399 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5404 /* end modifications */
5406 sRef_setNullError (ret->sref);
5409 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5410 ** since is points to storage that should not be deallocated
5411 ** through this pointer.
5414 if (sRef_isOnly (ret->sref)
5415 || sRef_isFresh (ret->sref))
5417 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5422 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5423 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5425 if (context_msgPointerArith ())
5429 message ("Pointer arithmetic (%t, %t): %s",
5430 te1, te2, exprNode_unparse (ret)),
5434 if (sRef_possiblyNull (e1->sref)
5435 && !usymtab_isGuarded (e1->sref))
5438 (FLG_NULLPOINTERARITH,
5439 message ("Pointer arithmetic involving possibly "
5440 "null pointer %s: %s",
5441 exprNode_unparse (e2),
5442 exprNode_unparse (ret)),
5446 ret->sref = sRef_copy (e2->sref);
5448 /* start modifications */
5449 /* added by Seejo on 4/16/2000 */
5451 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5454 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5455 int val = (int) multiVal_forceInt (e1->val);
5457 /* Operator : + or += */
5458 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5459 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5460 val should not result in a
5461 size < 0 (size = 0 is ok !) */
5463 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5465 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5466 sRef_setNotNullTerminatedState(ret->sref);
5467 sRef_resetLen (ret->sref);
5469 sRef_setNullTerminatedState(ret->sref);
5470 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5475 /* Operator : - or -= */
5476 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5477 if (sRef_getSize(e2->sref) >= 0) {
5478 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5479 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5483 /* end modifications */
5485 sRef_setNullError (ret->sref);
5488 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5489 ** since is points to storage that should not be deallocated
5490 ** through this pointer.
5493 if (sRef_isOnly (ret->sref)
5494 || sRef_isFresh (ret->sref)) {
5495 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5499 ret->sref = e2->sref;
5503 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5508 case LEFT_ASSIGN: /* Shifts: should be unsigned values */
5512 case TAMPERSAND: /* bitwise & */
5514 case TCIRC: /* ^ (XOR) */
5519 bool reported = FALSE;
5520 flagcode code = FLG_BITWISEOPS;
5522 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5523 || opid == RIGHT_OP || opid == RIGHT_ASSIGN) {
5524 code = FLG_SHIFTSIGNED;
5527 if (!ctype_isUnsigned (tr1))
5529 if (exprNode_isNonNegative (e1)) {
5532 reported = optgenerror
5534 message ("Left operand of %s is not unsigned value (%t): %s",
5535 lltok_unparse (op), te1,
5536 exprNode_unparse (ret)),
5546 /* right need not be signed for shifts */
5547 if (code != FLG_SHIFTSIGNED
5548 && !ctype_isUnsigned (tr2))
5550 if (!exprNode_isNonNegative (e2)) {
5551 reported = optgenerror
5553 message ("Right operand of %s is not unsigned value (%t): %s",
5554 lltok_unparse (op), te2,
5555 exprNode_unparse (ret)),
5563 if (!checkIntegral (e1, e2, ret, op)) {
5564 te1 = ctype_unknown;
5568 DPRINTF (("Set: %s", ctype_unparse (te1)));
5571 ** tret is the widest type of te1 and te2
5574 tret = ctype_widest (te1, te2);
5579 if (checkIntegral (e1, e2, ret, op)) {
5582 tret = ctype_unknown;
5587 case TLT: /* comparisons */
5588 case TGT: /* numeric, numeric -> bool */
5590 DPRINTF (("Here we go: %s / %s",
5591 ctype_unparse (tr1), ctype_unparse (tr2)));
5593 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5594 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5597 bool fepsilon = FALSE;
5599 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5604 if (opid == TLT || opid == TGT)
5606 uentry ue1 = exprNode_getUentry (e1);
5607 uentry ue2 = exprNode_getUentry (e2);
5610 ** FLT_EPSILON, etc. really is a variable, not
5614 if (uentry_isVariable (ue1))
5616 cstring uname = uentry_rawName (ue1);
5618 if (cstring_equalLit (uname, "FLT_EPSILON")
5619 || cstring_equalLit (uname, "DBL_EPSILON")
5620 || cstring_equalLit (uname, "LDBL_EPSILON"))
5626 if (uentry_isVariable (ue2))
5628 cstring uname = uentry_rawName (ue2);
5630 if (cstring_equalLit (uname, "FLT_EPSILON")
5631 || cstring_equalLit (uname, "DBL_EPSILON")
5632 || cstring_equalLit (uname, "LDBL_EPSILON"))
5641 ; /* Don't complain. */
5647 message ("Dangerous comparison involving %s types: %s",
5648 ctype_unparse (rtype),
5649 exprNode_unparse (ret)),
5658 ** Types should match.
5661 DPRINTF (("Match types: %s / %s", exprNode_unparse (e1),
5662 exprNode_unparse (e2)));
5664 if (!exprNode_matchTypes (e1, e2))
5666 hasError = gentypeerror
5668 message ("Operands of %s have incompatible types (%t, %t): %s",
5669 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5675 || (ctype_isForceRealNumeric (&tr1)
5676 && ctype_isForceRealNumeric (&tr2)) ||
5677 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5683 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5684 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5688 message ("Comparison of pointer and numeric (%t, %t): %s",
5689 te1, te2, exprNode_unparse (ret)),
5694 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5699 /* certain comparisons on unsigned's and zero look suspicious */
5701 if (opid == TLT || opid == LE_OP || opid == GE_OP)
5703 if ((ctype_isUnsigned (tr1) && exprNode_isZero (e2))
5704 || (ctype_isUnsigned (tr2) && exprNode_isZero (e1)))
5707 (FLG_UNSIGNEDCOMPARE,
5708 message ("Comparison of unsigned value involving zero: %s",
5709 exprNode_unparse (ret)),
5714 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5716 if ((opid == EQ_OP || opid == NE_OP) &&
5717 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5720 ** is one a variable?
5723 if (uentry_isVariable (exprNode_getUentry (e1))
5724 || uentry_isVariable (exprNode_getUentry (e2)))
5727 ** comparisons with FALSE are okay
5730 if (exprNode_isFalseConstant (e1)
5731 || exprNode_isFalseConstant (e2))
5740 ("Use of %q with %s variables (risks inconsistency because "
5741 "of multiple true values): %s",
5742 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5743 context_printBoolName (), exprNode_unparse (ret)),
5750 case AND_OP: /* bool, bool -> bool */
5753 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5759 if (context_maybeSet (FLG_BOOLOPS))
5761 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5763 if (ctype_sameName (te1, te2))
5767 message ("Operands of %s are non-boolean (%t): %s",
5768 lltok_unparse (op), te1,
5769 exprNode_unparse (ret)),
5777 ("Operands of %s are non-booleans (%t, %t): %s",
5778 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5782 else if (!ctype_isRealBool (te1))
5786 message ("Left operand of %s is non-boolean (%t): %s",
5787 lltok_unparse (op), te1, exprNode_unparse (ret)),
5790 else if (!ctype_isRealBool (te2))
5794 message ("Right operand of %s is non-boolean (%t): %s",
5795 lltok_unparse (op), te2, exprNode_unparse (ret)),
5808 (cstring_makeLiteral
5809 ("There has been a problem in the parser. This is believed to result "
5810 "from a problem with bison v. 1.25. Please try rebuidling Splint "
5811 "using the pre-compiled grammar files by commenting out the "
5812 "BISON= line in the top-level Makefile."));
5817 DPRINTF (("Return type: %s", ctype_unparse (tret)));
5820 exprNode_checkUse (ret, e1->sref, e1->loc);
5821 exprNode_mergeUSs (ret, e2);
5822 exprNode_checkUse (ret, e2->sref, e2->loc);
5828 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5829 /*@only@*/ lltok op)
5833 checkMacroParen (e1);
5834 checkMacroParen (e2);
5836 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5838 checkExpressionDefined (e1, e2, op);
5841 ret = exprNode_makeOp (e1, e2, op);
5846 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5849 ** This is somewhat bogus!
5851 ** Assigning to a nested observer in a non-observer datatype
5852 ** should not produce an error.
5855 sRef ref = exprNode_getSref (e1);
5857 DPRINTF (("Check assign mod: %s",
5858 sRef_unparseFull (ref)));
5860 if (sRef_isObserver (ref)
5861 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
5862 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5864 sRef base = sRef_getBase (ref);
5866 if (sRef_isValid (base) && sRef_isObserver (base))
5868 exprNode_checkModify (e1, ret);
5872 exprNode_checkModifyVal (e1, ret);
5877 exprNode_checkModify (e1, ret);
5882 exprNode_assign (/*@only@*/ exprNode e1,
5883 /*@only@*/ exprNode e2, /*@only@*/ lltok op)
5885 bool isalloc = FALSE;
5886 bool isjustalloc = FALSE;
5887 bool noalias = FALSE;
5890 DPRINTF (("%s [%s] <- %s [%s]",
5891 exprNode_unparse (e1),
5892 ctype_unparse (e1->typ),
5893 exprNode_unparse (e2),
5894 ctype_unparse (e2->typ)));
5896 if (lltok_getTok (op) != TASSIGN)
5898 ret = exprNode_makeOp (e1, e2, op);
5900 DPRINTF (("Here goes: %s %s",
5901 ctype_unparse (e1->typ),
5902 ctype_unparse (e2->typ)));
5904 if (ctype_isNumeric (e2->typ)
5905 || ctype_isNumeric (e1->typ))
5907 /* Its a pointer arithmetic expression like ptr += i */
5913 ret = exprNode_createPartialCopy (e1);
5914 ret->kind = XPR_ASSIGN;
5915 ret->edata = exprData_makeOp (e1, e2, op);
5917 if (!exprNode_isError (e2))
5919 ret->sets = sRefSet_union (ret->sets, e2->sets);
5920 ret->msets = sRefSet_union (ret->msets, e2->msets);
5921 ret->uses = sRefSet_union (ret->uses, e2->uses);
5925 checkExpressionDefined (e1, e2, op);
5927 if (exprNode_isError (e1))
5929 if (!exprNode_isError (e2))
5931 ret->loc = fileloc_update (ret->loc, e2->loc);
5935 ret->loc = fileloc_update (ret->loc, g_currentloc);
5939 if (!exprNode_isError (e2))
5941 checkMacroParen (e2);
5944 if (exprNode_isDefined (e1))
5946 if (sRef_isMacroParamRef (e1->sref))
5948 if (context_inIterDef ())
5950 uentry ue = sRef_getUentry (e1->sref);
5952 if (uentry_isYield (ue))
5958 if (fileloc_isDefined (e1->loc))
5962 message ("Assignment to non-yield iter parameter: %q",
5963 sRef_unparse (e1->sref)),
5970 message ("Assignment to non-yield iter parameter: %q",
5971 sRef_unparse (e1->sref)),
5978 if (fileloc_isDefined (e1->loc))
5982 message ("Assignment to macro parameter: %q",
5983 sRef_unparse (e1->sref)),
5990 message ("Assignment to macro parameter: %q",
5991 sRef_unparse (e1->sref)),
5995 exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
6000 exprNode_checkAssignMod (e1, ret);
6003 if (exprNode_isDefined (e2))
6005 if (lltok_getTok (op) == TASSIGN)
6007 ctype te1 = exprNode_getType (e1);
6008 ctype te2 = exprNode_getType (e2);
6010 if (!ctype_forceMatch (te1, te2))
6012 if (exprNode_matchLiteral (te1, e2))
6020 message ("Assignment of %t to %t: %s %s %s",
6021 te2, te1, exprNode_unparse (e1),
6023 exprNode_unparse (e2)),
6029 exprNode_mergeUSs (ret, e2);
6030 exprNode_checkUse (ret, e2->sref, e2->loc);
6032 DPRINTF (("Do assign! %s %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6039 doAssign (e1, e2, FALSE);
6042 ret->sref = e1->sref;
6046 if (exprNode_isDefined (e2))
6048 exprNode_mergeUSs (ret, e2);
6049 exprNode_checkUse (ret, e2->sref, e2->loc);
6053 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
6055 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
6058 isjustalloc = sRef_isJustAllocated (e1->sref);
6059 isalloc = sRef_isAllocated (e1->sref);
6061 if (sRef_isField (e1->sref))
6063 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
6065 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
6067 exprNode_checkUse (ret, root, e1->loc);
6073 ** be careful! this defines e1->sref.
6076 /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
6078 DPRINTF (("Setting: %s -> %s", exprNode_unparse (ret), sRef_unparse (e1->sref)));
6079 exprNode_checkSet (ret, e1->sref);
6083 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
6084 ? e2->loc : e1->loc);
6090 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
6099 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
6100 /*@keep@*/ exprNode elseclause)
6104 if (!exprNode_isError (pred))
6106 ret = exprNode_createPartialCopy (pred);
6107 checkMacroParen (pred);
6108 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
6110 if (!exprNode_isError (ifclause))
6112 checkMacroParen (ifclause); /* update macro counts! */
6114 if (!exprNode_isError (elseclause))
6116 checkMacroParen (elseclause);
6118 if (!exprNode_matchTypes (ifclause, elseclause))
6121 (exprNode_getType (ifclause),
6123 exprNode_getType (elseclause),
6125 message ("Conditional clauses are not of same type: "
6127 exprNode_unparse (ifclause),
6128 exprNode_getType (ifclause),
6129 exprNode_unparse (elseclause),
6130 exprNode_getType (elseclause)),
6133 ret->sref = sRef_undefined;
6134 ret->typ = ctype_unknown;
6139 /* for now...should merge the states */
6140 ret->sref = ifclause->sref;
6141 ret->typ = ifclause->typ;
6143 if (exprNode_isNullValue (ifclause))
6145 ret->typ = elseclause->typ;
6149 exprNode_checkUse (ret, pred->sref, pred->loc);
6150 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6151 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6153 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6158 ret->typ = ifclause->typ;
6160 exprNode_checkUse (pred, pred->sref, pred->loc);
6161 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6163 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6168 if (!exprNode_isError (elseclause))
6170 ret->typ = elseclause->typ;
6172 exprNode_checkUse (pred, pred->sref, pred->loc);
6173 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6175 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6179 else /* pred is error */
6181 if (!exprNode_isError (ifclause))
6183 ret = exprNode_createSemiCopy (ifclause);
6185 checkMacroParen (ifclause); /* update macro counts! */
6187 if (!exprNode_isError (elseclause))
6189 checkMacroParen (elseclause);
6191 ret->typ = ifclause->typ;
6193 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6196 (exprNode_getType (ifclause),
6198 exprNode_getType (elseclause),
6200 message ("Conditional clauses are not of same type: "
6202 exprNode_unparse (ifclause),
6203 exprNode_getType (ifclause),
6204 exprNode_unparse (elseclause),
6205 exprNode_getType (elseclause)),
6208 ret->typ = ctype_unknown;
6212 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6213 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6215 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6218 else if (!exprNode_isError (elseclause)) /* pred, if errors */
6220 ret = exprNode_createSemiCopy (ifclause);
6222 ret->typ = elseclause->typ;
6223 checkMacroParen (elseclause);
6225 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6226 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6228 else /* all errors! */
6230 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6234 ret->kind = XPR_COND;
6235 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
6237 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6239 exprNode_combineControl (ret, ifclause, elseclause);
6246 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6248 ctype totype = qtype_getType (qt);
6250 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6254 ** check use of va_arg : <valist>, type -> type
6257 if (exprNode_isError (arg))
6262 targ = exprNode_getType (arg);
6265 ** arg should have be a pointer
6268 if (!ctype_isUA (targ) ||
6269 (!usymId_equal (ctype_typeId (targ),
6270 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6274 message ("First argument to va_arg is not a va_list (type %t): %s",
6275 targ, exprNode_unparse (arg)),
6279 exprNode_checkSet (ret, arg->sref);
6283 ** return type is totype
6287 ret->kind = XPR_VAARG;
6288 ret->edata = exprData_makeCast (tok, arg, qt);
6293 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6295 exprNode ret = exprNode_createPlain (ctype_undefined);
6296 ret->kind = XPR_LABEL;
6297 ret->edata = exprData_makeLiteral (label);
6298 ret->isJumpPoint = TRUE;
6300 return (ret); /* for now, ignore label */
6303 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6305 if (exprNode_isDefined (stmt))
6307 stmt->isJumpPoint = TRUE;
6309 /* This prevent stray no return path errors, etc. */
6310 stmt->exitCode = XK_MUSTEXIT;
6316 bool exprNode_isDefaultMarker (exprNode e)
6318 if (exprNode_isDefined (e))
6320 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6326 bool exprNode_isCaseMarker (exprNode e)
6328 if (exprNode_isDefined (e))
6330 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6336 bool exprNode_isLabelMarker (exprNode e)
6338 if (exprNode_isDefined (e))
6340 return (e->kind == XPR_LABEL);
6346 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6348 exprNode ret = exprNode_createPartialCopy (test);
6350 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6352 if (exprNode_isError (test)) {
6356 exprNode_checkUse (ret, test->sref, test->loc);
6358 usymtab_setExitCode (ret->exitCode);
6362 usymtab_setMustBreak ();
6365 ret->edata = exprData_makeSingle (test);
6366 ret->isJumpPoint = TRUE;
6372 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6374 exprNode ret = exprNode_createPartialCopy (test);
6376 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6377 ret->edata = exprData_makePair (test, stmt);
6378 ret->isJumpPoint = TRUE;
6380 if (exprNode_isError (test))
6385 exprNode_checkUse (ret, test->sref, test->loc);
6387 if (exprNode_isError (stmt))
6392 exprNode_mergeUSs (ret, stmt);
6394 ret->exitCode = stmt->exitCode;
6395 ret->mustBreak = stmt->mustBreak;
6396 ret->canBreak = stmt->canBreak;
6398 usymtab_setExitCode (ret->exitCode);
6402 usymtab_setMustBreak ();
6409 /*@notnull@*/ /*@only@*/ exprNode
6410 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6412 exprNode ret = exprNode_createTok (def);
6414 ret->isJumpPoint = TRUE;
6415 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6420 exprNode_mayEscape (exprNode e)
6422 if (exprNode_isDefined (e))
6424 return exitkind_couldEscape (e->exitCode);
6430 exprNode_mustBreak (exprNode e)
6432 if (exprNode_isDefined (e))
6434 return e->mustBreak;
6441 exprNode_mustEscape (exprNode e)
6443 if (exprNode_isDefined (e))
6445 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6452 exprNode_errorEscape (exprNode e)
6454 if (exprNode_isDefined (e))
6456 return exitkind_isError (e->exitCode);
6462 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6464 exprNode ret = exprNode_createPartialCopy (e1);
6466 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6468 ret->edata = exprData_makePair (e1, e2);
6469 ret->kind = XPR_STMTLIST;
6471 if (exprNode_isDefined (e1))
6473 ret->isJumpPoint = e1->isJumpPoint;
6474 ret->canBreak = e1->canBreak;
6478 if (exprNode_isDefined (e2))
6480 ret->loc = fileloc_update (ret->loc, e2->loc);
6484 if (exprNode_isDefined (e2))
6486 ret->exitCode = e2->exitCode;
6487 ret->mustBreak = e2->mustBreak;
6488 if (e2->canBreak) ret->canBreak = TRUE;
6492 ** if e1 must return, then e2 is unreachable!
6495 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6497 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6498 && !(e2->isJumpPoint))
6500 if (context_getFlag (FLG_UNREACHABLE))
6504 if (e2->kind == XPR_STMT)
6506 nr = exprData_getUopNode (e2->edata);
6509 if ((nr->kind == XPR_TOK
6510 && lltok_isSemi (exprData_getTok (nr->edata))))
6512 /* okay to have unreachable ";" */
6513 ret->exitCode = XK_MUSTEXIT;
6514 ret->canBreak = TRUE;
6518 if (optgenerror (FLG_UNREACHABLE,
6519 message ("Unreachable code: %s",
6520 exprNode_unparseFirst (nr)),
6523 ret->isJumpPoint = TRUE;
6524 ret->mustBreak = FALSE;
6525 ret->exitCode = XK_ERROR;
6526 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6530 ret->exitCode = XK_MUSTEXIT;
6531 ret->canBreak = TRUE;
6539 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6542 ** We want a warning anytime we have:
6544 ** yyy; <<<- no break or return
6548 exprNode lastStmt = exprNode_lastStatement (e1);
6550 if (exprNode_isDefined (lastStmt)
6551 && !exprNode_mustEscape (lastStmt)
6552 && !exprNode_mustBreak (lastStmt)
6553 && !exprNode_isCaseMarker (lastStmt)
6554 && !exprNode_isDefaultMarker (lastStmt)
6555 && !exprNode_isLabelMarker (lastStmt))
6557 voptgenerror (FLG_CASEBREAK,
6559 ("Fall through case (no preceding break)"),
6566 exprNode_mergeUSs (ret, e2);
6568 usymtab_setExitCode (ret->exitCode);
6572 usymtab_setMustBreak ();
6578 exprNode exprNode_createTok (/*@only@*/ lltok t)
6580 exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6581 ret = exprNode_create (ctype_unknown);
6582 ret->kind = XPR_TOK;
6583 ret->edata = exprData_makeTok (t);
6587 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6589 if (!exprNode_isError (e))
6591 exprNode_checkStatement(e);
6594 return (exprNode_statementError (e, t));
6597 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6599 exprNode ret = exprNode_createPartialCopy (e);
6601 if (!exprNode_isError (e))
6603 if (e->kind != XPR_ASSIGN)
6605 exprNode_checkUse (ret, e->sref, e->loc);
6608 ret->exitCode = e->exitCode;
6609 ret->canBreak = e->canBreak;
6610 ret->mustBreak = e->mustBreak;
6613 ret->edata = exprData_makeUop (e, t);
6614 ret->kind = XPR_STMT;
6619 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6621 if (!exprNode_isError (e))
6623 if (e->kind != XPR_ASSIGN)
6625 exprNode_checkUse (e, e->sref, e->loc);
6632 void exprNode_produceGuards (exprNode pred)
6634 if (!exprNode_isError (pred))
6636 if (ctype_isRealPointer (pred->typ))
6638 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6641 exprNode_checkUse (pred, pred->sref, pred->loc);
6642 exprNode_resetSref (pred);
6646 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6648 exprNode ret = exprNode_createPartialCopy (e);
6650 if (!exprNode_isError (e))
6652 ret->exitCode = e->exitCode;
6653 ret->canBreak = e->canBreak;
6654 ret->mustBreak = e->mustBreak;
6657 ret->edata = exprData_makeSingle (e);
6658 ret->kind = XPR_BLOCK;
6662 bool exprNode_isBlock (exprNode e)
6664 return (exprNode_isDefined (e)
6665 && ((e)->kind == XPR_BLOCK));
6668 bool exprNode_isAssign (exprNode e)
6670 if (exprNode_isDefined (e))
6672 return (e->kind == XPR_ASSIGN);
6678 bool exprNode_isEmptyStatement (exprNode e)
6680 return (exprNode_isDefined (e)
6681 && (e->kind == XPR_TOK)
6682 && (lltok_isSemi (exprData_getTok (e->edata))));
6685 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6688 bool emptyErr = FALSE;
6690 if (context_maybeSet (FLG_IFEMPTY))
6692 if (exprNode_isEmptyStatement (tclause))
6694 emptyErr = optgenerror (FLG_IFEMPTY,
6696 ("Body of if statement is empty"),
6697 exprNode_loc (tclause));
6701 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6703 if (exprNode_isDefined (tclause)
6704 && !exprNode_isBlock (tclause))
6706 voptgenerror (FLG_IFBLOCK,
6708 ("Body of if statement is not a block: %s",
6709 exprNode_unparse (tclause)),
6710 exprNode_loc (tclause));
6714 if (exprNode_isError (pred))
6716 if (exprNode_isError (tclause))
6718 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6722 ret = exprNode_createPartialCopy (tclause);
6727 if (exprNode_mustEscape (pred))
6731 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6732 exprNode_loc (pred));
6735 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6736 exprNode_checkUse (pred, pred->sref, pred->loc);
6738 if (!exprNode_isError (tclause))
6740 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
6743 ret = exprNode_createPartialCopy (pred);
6747 ret->edata = exprData_makePair (pred, tclause);
6749 ret->exitCode = XK_UNKNOWN;
6751 if (exprNode_isDefined (tclause))
6753 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
6754 ret->canBreak = tclause->canBreak;
6755 ret->sets = sRefSet_union (ret->sets, tclause->sets);
6756 ret->msets = sRefSet_union (ret->msets, tclause->msets);
6757 ret->uses = sRefSet_union (ret->uses, tclause->uses);
6760 ret->mustBreak = FALSE;
6765 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
6766 /*@only@*/ exprNode tclause,
6767 /*@only@*/ exprNode eclause)
6770 bool tEmptyErr = FALSE;
6771 bool eEmptyErr = FALSE;
6773 if (context_maybeSet (FLG_IFEMPTY))
6775 if (exprNode_isEmptyStatement (tclause))
6777 tEmptyErr = optgenerror
6780 ("Body of if clause of if statement is empty"),
6781 exprNode_loc (tclause));
6784 if (exprNode_isEmptyStatement (eclause))
6786 eEmptyErr = optgenerror
6789 ("Body of else clause of if statement is empty"),
6790 exprNode_loc (eclause));
6794 if (context_maybeSet (FLG_IFBLOCK))
6797 && exprNode_isDefined (tclause)
6798 && !exprNode_isBlock (tclause))
6800 voptgenerror (FLG_IFBLOCK,
6802 ("Body of if clause of if statement is not a block: %s",
6803 exprNode_unparse (tclause)),
6804 exprNode_loc (tclause));
6808 && exprNode_isDefined (eclause)
6809 && !exprNode_isBlock (eclause)
6810 && !(eclause->kind == XPR_IF)
6811 && !(eclause->kind == XPR_IFELSE))
6816 ("Body of else clause of if statement is not a block: %s",
6817 exprNode_unparse (eclause)),
6818 exprNode_loc (eclause));
6822 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
6824 if (exprNode_isDefined (eclause)
6825 && (eclause->kind == XPR_IF))
6827 voptgenerror (FLG_ELSEIFCOMPLETE,
6828 message ("Incomplete else if logic (no final else): %s",
6829 exprNode_unparse (eclause)),
6830 exprNode_loc (eclause));
6834 if (exprNode_isError (pred))
6836 if (exprNode_isError (tclause))
6838 if (exprNode_isError (eclause))
6840 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6844 ret = exprNode_createPartialCopy (eclause);
6849 ret = exprNode_createPartialCopy (tclause);
6852 else /* pred is okay */
6854 ret = exprNode_createPartialCopy (pred);
6856 if (exprNode_mustEscape (pred))
6860 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6861 exprNode_loc (pred));
6864 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6865 exprNode_checkUse (ret, pred->sref, pred->loc);
6867 exprNode_mergeCondUSs (ret, tclause, eclause);
6870 ret->kind = XPR_IFELSE;
6871 ret->edata = exprData_makeCond (pred, tclause, eclause);
6873 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
6875 exprNode_combineControl (ret, tclause, eclause);
6876 ret->loc = fileloc_update (ret->loc, eclause->loc);
6883 ** *allpaths <- TRUE iff all executions paths must go through the switch
6887 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
6889 exprNodeSList el = exprNode_flatten (e);
6890 bool mustReturn = TRUE; /* find a branch that doesn't */
6891 bool thisReturn = FALSE;
6892 bool hasDefault = FALSE;
6893 bool hasAllMembers = FALSE;
6894 bool inSwitch = FALSE;
6895 bool isEnumSwitch = FALSE;
6896 bool canBreak = FALSE;
6897 bool fallThrough = FALSE;
6898 ctype ct = ctype_unknown;
6899 enumNameSList usedEnums;
6902 if (exprNode_isDefined (test))
6907 ttype = ctype_realType (ct);
6909 if (ctype_isEnum (ttype))
6911 isEnumSwitch = TRUE;
6912 enums = ctype_elist (ttype);
6913 usedEnums = enumNameSList_new ();
6917 exprNodeSList_elements (el, current)
6919 if (exprNode_isDefined (current))
6921 switch (current->kind)
6929 message ("Duplicate default cases in switch"),
6930 exprNode_loc (current));
6935 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
6943 exprNode st = exprData_getSingle (current->edata);
6944 uentry ue = exprNode_getUentry (st);
6946 if (uentry_isValid (ue))
6948 cstring cname = uentry_rawName (ue);
6950 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
6952 if (enumNameSList_member
6953 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
6957 message ("Duplicate case in switch: %s",
6963 enumNameSList_addh (usedEnums, cname);
6970 message ("Case in switch not %s member: %s",
6971 ctype_unparse (ct), cname),
6978 if (inSwitch && !fallThrough)
6980 if (!thisReturn || canBreak)
6990 /*@switchbreak@*/ break;
6992 thisReturn = thisReturn || exprNode_mustEscape (current);
6993 canBreak = canBreak || current->canBreak;
6994 if (canBreak) fallThrough = FALSE;
6997 } end_exprNodeSList_elements;
6999 if (inSwitch) /* check the last one! */
7001 if (!thisReturn || canBreak)
7010 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
7011 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
7013 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
7015 voptgenerror (FLG_MISSCASE,
7016 message ("Missing case%s in switch: %q",
7017 cstring_makeLiteralTemp
7018 ((enumNameSList_size (unused) > 1) ? "s" : ""),
7019 enumNameSList_unparse (unused)),
7022 enumNameSList_free (unused);
7026 hasAllMembers = TRUE;
7030 enumNameSList_free (usedEnums);
7034 *allpaths = hasDefault;
7037 exprNodeSList_free (el);
7038 return ((hasDefault || hasAllMembers) && mustReturn);
7041 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
7043 exprNode ret = exprNode_createPartialCopy (e);
7046 DPRINTF (("Switch: %s", exprNode_unparse (s)));
7048 ret->kind = XPR_SWITCH;
7049 ret->edata = exprData_makePair (e, s);
7051 if (!exprNode_isError (s))
7053 exprNode fs = exprNode_firstStatement (s);
7054 ret->loc = fileloc_update (ret->loc, s->loc);
7056 if (exprNode_isUndefined (fs)
7057 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
7058 || exprNode_isDefaultMarker (fs)) {
7061 voptgenerror (FLG_FIRSTCASE,
7063 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
7068 if (!exprNode_isError (e))
7070 if (checkSwitchExpr (e, s, &allpaths))
7072 ret->exitCode = XK_MUSTRETURN;
7076 ret->exitCode = e->exitCode;
7079 ret->canBreak = e->canBreak;
7080 ret->mustBreak = e->mustBreak;
7084 ** exprNode.c:3883,32: Variable allpaths used before definition
7091 DPRINTF (("Context exit switch!"));
7092 context_exitSwitch (ret, allpaths);
7093 DPRINTF (("Context exit switch done!"));
7098 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
7099 /*@notnull@*/ exprNode body)
7101 sRefSet tuses = test->uses;
7103 if (!sRefSet_isEmpty (test->uses))
7105 sRefSet sets = sRefSet_newCopy (body->sets);
7106 bool hasError = TRUE;
7107 bool innerState = FALSE;
7108 sRefSet tuncon = sRefSet_undefined;
7110 sets = sRefSet_union (sets, test->sets);
7111 sets = sRefSet_union (sets, body->msets);
7112 sets = sRefSet_union (sets, test->msets);
7114 sRefSet_allElements (tuses, el)
7116 if (sRef_isUnconstrained (el))
7118 tuncon = sRefSet_insert (tuncon, el);
7122 if (sRefSet_member (sets, el))
7129 if (sRef_isInternalState (el)
7130 || sRef_isFileStatic (sRef_getRootBase (el)))
7134 } end_sRefSet_allElements ;
7138 sRefSet suncon = sRefSet_undefined;
7139 bool sinner = FALSE;
7141 sRefSet_allElements (sets, el)
7143 if (sRef_isUnconstrained (el))
7145 suncon = sRefSet_insert (suncon, el);
7147 else if (sRef_isInternalState (el))
7155 } end_sRefSet_allElements ;
7157 if (sinner && innerState)
7161 else if (sRefSet_isEmpty (tuncon)
7162 && sRefSet_isEmpty (suncon))
7167 ("Suspected infinite loop. No value used in loop test (%q) "
7168 "is modified by test or loop body.",
7169 sRefSet_unparsePlain (tuses)),
7174 if (sRefSet_isEmpty (tuncon))
7178 message ("Suspected infinite loop. No condition values "
7179 "modified. Modification possible through "
7180 "unconstrained calls: %q",
7181 sRefSet_unparsePlain (suncon)),
7188 message ("Suspected infinite loop. No condition values "
7189 "modified. Possible undetected dependency through "
7190 "unconstrained calls in loop test: %q",
7191 sRefSet_unparsePlain (tuncon)),
7197 sRefSet_free (sets);
7201 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7204 bool emptyErr = FALSE;
7206 if (context_maybeSet (FLG_WHILEEMPTY))
7208 if (exprNode_isEmptyStatement (b))
7210 emptyErr = optgenerror
7213 ("Body of while statement is empty"),
7218 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7220 if (exprNode_isDefined (b)
7221 && !exprNode_isBlock (b))
7223 if (context_inIterDef ()
7224 && (b->kind == XPR_STMTLIST
7225 || b->kind == XPR_TOK))
7231 voptgenerror (FLG_WHILEBLOCK,
7233 ("Body of while statement is not a block: %s",
7234 exprNode_unparse (b)),
7240 if (exprNode_isError (t))
7242 if (exprNode_isError (b))
7244 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7248 ret = exprNode_createPartialCopy (b);
7255 ret = exprNode_createPartialCopy (t);
7257 llassert (t->kind == XPR_WHILEPRED);
7259 test = exprData_getSingle (t->edata);
7261 if (!exprNode_isError (b) && exprNode_isDefined (test))
7263 if (context_maybeSet (FLG_INFLOOPS)
7264 || context_maybeSet (FLG_INFLOOPSUNCON))
7267 ** check that some variable in the predicate is set by the body
7268 ** if the predicate uses any variables
7271 checkInfiniteLoop (test, b);
7274 exprNode_mergeUSs (ret, b);
7276 if (exprNode_isDefined (b))
7278 ret->exitCode = exitkind_makeConditional (b->exitCode);
7283 ret->edata = exprData_makePair (t, b);
7284 ret->kind = XPR_WHILE;
7286 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7290 message ("Predicate always exits: %s", exprNode_unparse (t)),
7294 ret->exitCode = XK_NEVERESCAPE;
7297 ** If loop is infinite, and there is no break inside,
7298 ** exit code is never reach.
7301 if (exprNode_knownIntValue (t))
7303 if (!exprNode_isZero (t))
7305 if (exprNode_isDefined (b))
7309 /* Really, it means never reached. */
7310 ret->exitCode = XK_MUSTEXIT;
7320 ret->canBreak = FALSE;
7321 ret->mustBreak = FALSE;
7327 ** do { b } while (t);
7329 ** note: body passed as first argument
7332 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7336 DPRINTF (("Do while: %s / %s",
7337 exprNode_unparse (b), exprNode_unparse (t)));
7339 if (exprNode_isError (t))
7341 if (exprNode_isError (b))
7343 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7347 ret = exprNode_createPartialCopy (b);
7349 ret->exitCode = exitkind_makeConditional (b->exitCode);
7350 exprNode_checkUse (ret, b->sref, b->loc);
7351 ret->exitCode = b->exitCode;
7352 ret->canBreak = b->canBreak;
7353 ret->mustBreak = FALSE;
7358 DPRINTF (("Do while: %s / %s",
7359 exitkind_unparse (t->exitCode),
7360 exitkind_unparse (b->exitCode)));
7362 ret = exprNode_createPartialCopy (t);
7363 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7365 if (!exprNode_isError (b))
7368 ** forgot the copy's --- why wasn't this detected??
7371 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7372 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7373 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
7375 /* left this out --- causes and aliasing bug (infinite loop)
7376 should be detected?? */
7378 exprNode_checkUse (ret, b->sref, b->loc);
7379 exprNode_mergeUSs (ret, t);
7380 exprNode_checkUse (ret, t->sref, t->loc);
7382 /* evans 2001-10-05: while loop can break */
7383 ret->exitCode = exitkind_makeConditional (b->exitCode);
7385 DPRINTF (("Do while: %s",
7386 exitkind_unparse (ret->exitCode)));
7388 ret->canBreak = b->canBreak;
7390 /* Always FALSE for doWhile loops - break's when test is false */
7391 ret->mustBreak = FALSE; /* b->mustBreak; */
7395 context_exitDoWhileClause (t);
7397 ret->kind = XPR_DOWHILE;
7398 ret->edata = exprData_makePair (t, b);
7402 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7405 bool emptyErr = FALSE;
7407 if (context_maybeSet (FLG_FOREMPTY))
7409 if (exprNode_isEmptyStatement (body))
7411 emptyErr = optgenerror
7414 ("Body of for statement is empty"),
7415 exprNode_loc (body));
7419 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7421 if (exprNode_isDefined (body)
7422 && !exprNode_isBlock (body))
7424 if (context_inIterDef ()
7425 && (body->kind == XPR_STMTLIST
7426 || body->kind == XPR_TOK))
7432 voptgenerror (FLG_FORBLOCK,
7434 ("Body of for statement is not a block: %s",
7435 exprNode_unparse (body)),
7436 exprNode_loc (body));
7442 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7445 if (exprNode_isError (body))
7447 ret = exprNode_createPartialCopy (inc);
7451 ret = exprNode_createPartialCopy (body);
7453 ret->exitCode = exitkind_makeConditional (body->exitCode);
7455 exprNode_mergeUSs (inc, body);
7457 if (exprNode_isDefined (inc))
7461 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7464 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7465 exprNode_freeShallow (tmp);
7467 context_clearMessageAnnote ();
7468 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7470 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7471 exprNode_freeShallow (tmp);
7473 context_clearMessageAnnote ();
7475 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7476 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7477 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7481 ret->kind = XPR_FOR;
7482 ret->edata = exprData_makePair (inc, body);
7484 if (exprNode_isDefined (inc)) {
7485 exprNode test = exprData_getTripleTest (inc->edata);
7487 if (exprNode_isUndefined (test)) {
7488 if (exprNode_isDefined (body)) {
7489 if (!body->canBreak) {
7490 /* Really, it means never reached. */
7491 ret->exitCode = XK_MUSTEXIT;
7501 ** for (init; test; inc)
7504 ** while (test) { body; inc; }
7506 ** Now: check use of init (may set vars for test)
7507 ** check use of test
7511 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7515 if (exprNode_isError (pred)) return guardSet_undefined;
7517 llassert (pred->kind == XPR_FORPRED);
7519 test = exprData_getTripleTest (pred->edata);
7521 if (!exprNode_isError (test))
7523 return (test->guards);
7526 return guardSet_undefined;
7529 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7531 exprNode ret = exprNode_createSemiCopy (test);
7533 if (exprNode_isDefined (test))
7535 exprNode_copySets (ret, test);
7536 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7537 exprNode_checkUse (ret, test->sref, test->loc);
7539 exprNode_produceGuards (test);
7541 ret->guards = guardSet_copy (test->guards);
7544 ret->edata = exprData_makeSingle (test);
7545 ret->kind = XPR_WHILEPRED;
7549 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7550 /*@only@*/ exprNode inc)
7555 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7558 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7560 if (!exprNode_isError (inc))
7562 ret = exprNode_createPartialCopy (inc);
7566 if (!exprNode_isError (init))
7568 ret = exprNode_createPartialCopy (init);
7570 else if (!exprNode_isError (test))
7572 ret = exprNode_createPartialCopy (test);
7576 ret = exprNode_createUnknown ();
7580 exprNode_mergeUSs (ret, init);
7582 if (exprNode_isDefined (init))
7584 exprNode_checkUse (ret, init->sref, init->loc);
7587 exprNode_mergeUSs (ret, test);
7589 if (exprNode_isDefined (test))
7591 exprNode_checkUse (ret, test->sref, test->loc);
7594 ret->kind = XPR_FORPRED;
7595 ret->edata = exprData_makeFor (init, test, inc);
7599 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7601 exprNode ret = exprNode_createUnknown ();
7603 if (context_inMacro ())
7605 voptgenerror (FLG_MACROSTMT,
7606 message ("Macro %s uses goto (not functional)",
7607 context_inFunctionName ()),
7611 ret->kind = XPR_GOTO;
7612 ret->edata = exprData_makeLiteral (label);
7613 ret->mustBreak = TRUE;
7614 ret->exitCode = XK_GOTO;
7615 ret->canBreak = TRUE;
7619 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7621 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7623 ret->kind = XPR_CONTINUE;
7624 ret->edata = exprData_makeTok (l);
7625 ret->canBreak = TRUE;
7626 ret->mustBreak = TRUE;
7628 if (qcontinue == QSAFEBREAK)
7632 else if (qcontinue == QINNERCONTINUE)
7634 if (!context_inDeepLoop ())
7637 (FLG_LOOPLOOPCONTINUE,
7638 cstring_makeLiteral ("Continue statement marked with innercontinue "
7639 "is not inside a nested loop"),
7640 exprNode_loc (ret));
7643 else if (qcontinue == BADTOK)
7645 if (context_inDeepLoop ())
7648 (FLG_LOOPLOOPCONTINUE,
7649 cstring_makeLiteral ("Continue statement in nested loop"),
7650 exprNode_loc (ret));
7655 llbuglit ("exprNode_continue: bad qcontinue");
7661 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
7663 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7664 clause breakClause = context_breakClause ();
7666 ret->kind = XPR_BREAK;
7667 ret->edata = exprData_makeTok (l);
7668 ret->canBreak = TRUE;
7669 ret->mustBreak = TRUE;
7671 if (breakClause == NOCLAUSE)
7675 cstring_makeLiteral ("Break not inside while, for or switch statement"),
7676 exprNode_loc (ret));
7680 if (bqual != BADTOK)
7687 if (breakClause == SWITCHCLAUSE)
7689 if (!context_inDeepSwitch ())
7691 voptgenerror (FLG_SYNTAX,
7693 ("Break preceded by innerbreak is not in a deep switch"),
7694 exprNode_loc (ret));
7699 if (!context_inDeepLoop ())
7701 voptgenerror (FLG_SYNTAX,
7703 ("Break preceded by innerbreak is not in a deep loop"),
7704 exprNode_loc (ret));
7709 if (breakClause == SWITCHCLAUSE)
7711 voptgenerror (FLG_SYNTAX,
7713 ("Break preceded by loopbreak is breaking a switch"),
7714 exprNode_loc (ret));
7718 if (breakClause != SWITCHCLAUSE)
7722 message ("Break preceded by switchbreak is breaking %s",
7723 cstring_makeLiteralTemp
7724 ((breakClause == WHILECLAUSE
7725 || breakClause == DOWHILECLAUSE) ? "a while loop"
7726 : (breakClause == FORCLAUSE) ? "a for loop"
7727 : (breakClause == ITERCLAUSE) ? "an iterator"
7729 exprNode_loc (ret));
7737 if (breakClause == SWITCHCLAUSE)
7739 clause nextBreakClause = context_nextBreakClause ();
7741 switch (nextBreakClause)
7743 case NOCLAUSE: break;
7749 (FLG_LOOPSWITCHBREAK,
7750 cstring_makeLiteral ("Break statement in switch inside loop"),
7751 exprNode_loc (ret));
7755 (FLG_SWITCHSWITCHBREAK,
7756 cstring_makeLiteral ("Break statement in switch inside switch"),
7757 exprNode_loc (ret));
7764 if (context_inDeepLoop ())
7768 cstring_makeLiteral ("Break statement in nested loop"),
7769 exprNode_loc (ret));
7773 if (context_inDeepLoopSwitch ())
7776 (FLG_SWITCHLOOPBREAK,
7777 cstring_makeLiteral ("Break statement in loop inside switch"),
7778 exprNode_loc (ret));
7788 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
7790 fileloc loc = lltok_getLoc (t);
7791 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
7793 context_returnFunction ();
7794 exprChecks_checkNullReturn (loc);
7796 ret->kind = XPR_NULLRETURN;
7797 ret->edata = exprData_makeTok (t);
7798 ret->exitCode = XK_MUSTRETURN;
7802 exprNode exprNode_return (/*@only@*/ exprNode e)
7806 if (exprNode_isError (e))
7808 ret = exprNode_createUnknown ();
7812 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
7814 exprNode_checkUse (ret, e->sref, e->loc);
7815 exprNode_checkReturn (e);
7818 context_returnFunction ();
7819 ret->kind = XPR_RETURN;
7820 ret->edata = exprData_makeSingle (e);
7821 ret->exitCode = XK_MUSTRETURN;
7826 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
7830 if (exprNode_isError (e1))
7832 if (exprNode_isError (e2))
7834 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7838 ret = exprNode_createPartialCopy (e2);
7839 exprNode_checkUse (ret, e2->sref, e2->loc);
7840 ret->sref = e2->sref;
7845 ret = exprNode_createPartialCopy (e1);
7847 exprNode_checkUse (ret, e1->sref, e1->loc);
7849 if (!exprNode_isError (e2))
7851 exprNode_mergeUSs (ret, e2);
7852 exprNode_checkUse (ret, e2->sref, e2->loc);
7853 ret->sref = e2->sref;
7857 ret->kind = XPR_COMMA;
7858 ret->edata = exprData_makePair (e1, e2);
7860 if (exprNode_isDefined (e1))
7862 if (exprNode_isDefined (e2))
7866 if (exprNode_mustEscape (e1) || e1->mustBreak)
7870 message ("Second clause of comma expression is unreachable: %s",
7871 exprNode_unparse (e2)),
7875 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
7876 ret->mustBreak = e1->mustBreak || e2->mustBreak;
7877 ret->canBreak = e1->canBreak || e2->canBreak;
7881 if (exprNode_mustEscape (e1) || e1->mustBreak)
7885 message ("Second clause of comma expression is unreachable: %s",
7886 exprNode_unparse (e2)),
7890 ret->exitCode = e1->exitCode;
7891 ret->canBreak = e1->canBreak;
7896 if (exprNode_isDefined (e2))
7898 ret->exitCode = e2->exitCode;
7899 ret->mustBreak = e2->mustBreak;
7900 ret->canBreak = e2->canBreak;
7907 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
7909 ctype t1 = exprNode_getType (el);
7910 ctype t2 = exprNode_getType (val);
7911 bool hasError = FALSE;
7913 DPRINTF (("Check one init: %s / %s",
7914 exprNode_unparse (el),
7915 exprNode_unparse (val)));
7917 if (ctype_isUnknown (t1))
7919 voptgenerror (FLG_IMPTYPE,
7920 message ("Variable has unknown (implicitly int) type: %s",
7921 exprNode_unparse (el)),
7925 el->typ = ctype_int;
7928 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
7930 exprNodeList vals = exprData_getArgs (val->edata);
7932 DPRINTF (("Check one init: %s", exprNodeList_unparse (vals)));
7933 DPRINTF (("Type: %s", ctype_unparse (t1)));
7935 if (ctype_isRealAP (t1))
7940 if (ctype_isFixedArray (t1))
7942 int nelements = long_toInt (ctype_getArraySize (t1));
7944 if (exprNode_isStringLiteral (val))
7946 exprNode_checkStringLiteralLength (t1, val);
7950 if (exprNodeList_size (vals) != nelements)
7952 hasError = optgenerror
7953 (exprNodeList_size (vals) > nelements ? FLG_INITSIZE : FLG_INITALLELEMENTS,
7954 message ("Initializer block for "
7955 "%s has %d element%&, but declared as %s: %q",
7956 exprNode_unparse (el),
7957 exprNodeList_size (vals),
7959 exprNodeList_unparse (vals)),
7965 exprNodeList_elements (vals, oneval)
7967 cstring istring = message ("%d", i);
7970 (exprNode_fakeCopy (el),
7971 exprNode_numLiteral (ctype_int, istring,
7972 fileloc_copy (el->loc), i));
7974 if (exprNode_isDefined (newel))
7976 if (exprNodeList_size (vals) == 1
7977 && ctype_isString (exprNode_getType (oneval))
7978 && ctype_isChar (exprNode_getType (newel)))
7980 exprNode_freeIniter (newel);
7984 if (exprNode_checkOneInit (newel, oneval))
7989 if (nerrors > 3 && exprNodeList_size (vals) > 6)
7992 (message ("Additional initialization errors "
7993 "for %s not reported",
7994 exprNode_unparse (el)),
7996 exprNode_freeIniter (newel);
8001 exprNode_freeIniter (newel);
8006 exprNode_freeIniter (newel);
8011 cstring_free (istring);
8014 } end_exprNodeList_elements;
8017 else if (ctype_isStruct (ctype_realType (t1)))
8019 uentryList fields = ctype_getFields (t1);
8022 if (uentryList_size (fields) != exprNodeList_size (vals))
8024 if (uentryList_size (fields) > exprNodeList_size (vals))
8026 hasError = optgenerror
8028 message ("Initializer block for "
8029 "%s has %d field%&, but %s has %d field%&: %q",
8030 exprNode_unparse (el),
8031 exprNodeList_size (vals),
8033 uentryList_size (fields),
8034 exprNodeList_unparse (vals)),
8039 hasError = optgenerror
8041 message ("Initializer block for "
8042 "%s has %d field%&, but %s has %d field%&: %q",
8043 exprNode_unparse (el),
8044 exprNodeList_size (vals),
8046 uentryList_size (fields),
8047 exprNodeList_unparse (vals)),
8053 exprNodeList_elements (vals, oneval)
8055 uentry thisfield = uentryList_getN (fields, i);
8057 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8059 uentry_getName (thisfield));
8061 if (exprNode_isDefined (newel))
8063 if (exprNode_checkOneInit (newel, oneval))
8068 exprNode_freeIniter (newel);
8072 } end_exprNodeList_elements;
8075 /* evans 2001-12-30: added to fix bug reported by Jim Zelenka */
8076 else if (ctype_isUnion (ctype_realType (t1)))
8078 uentryList fields = ctype_getFields (t1);
8082 ** Union initializers set the first member always.
8085 DPRINTF (("Union initializer: %s / %s",
8086 exprNode_unparse (el), ctype_unparse (ctype_realType (t1))));
8088 if (exprNodeList_size (vals) != 1)
8090 hasError = optgenerror
8092 message ("Initializer block for union "
8093 "%s has %d elements, union initializers should have one element: %q",
8094 exprNode_unparse (el),
8095 exprNodeList_size (vals),
8096 exprNodeList_unparse (vals)),
8101 exprNode oneval = exprNodeList_head (vals);
8102 uentry thisfield = uentryList_getN (fields, i);
8104 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
8106 uentry_getName (thisfield));
8108 if (exprNode_isDefined (newel))
8110 if (exprNode_checkOneInit (newel, oneval))
8115 exprNode_freeIniter (newel);
8121 hasError = optgenerror
8123 message ("Initializer block used for "
8124 "%s where %t is expected: %s",
8125 exprNode_unparse (el), t1, exprNode_unparse (val)),
8131 if (exprNode_isDefined (val))
8133 doAssign (el, val, TRUE);
8135 if (!exprNode_matchType (t1, val))
8137 hasError = gentypeerror
8139 message ("Initial value of %s is type %t, "
8141 exprNode_unparse (el),
8142 t2, t1, exprNode_unparse (val)),
8152 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
8156 DPRINTF (("Initialization: %s", idDecl_unparse (t)));
8158 if (usymtab_exists (idDecl_observeId (t)))
8160 uentry ue = usymtab_lookup (idDecl_observeId (t));
8161 ret = exprNode_createId (ue);
8163 /*@i723 don't do this...but why? */
8165 ct = ctype_realishType (ret->typ);
8167 DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
8169 if (ctype_isUnknown (ct))
8171 if (uentry_isAnyTag (ue))
8175 message ("%s used but not previously declared: %s",
8176 uentry_ekindName (ue),
8177 idDecl_getName (t)),
8185 message ("Variable has unknown (implicitly int) type: %s",
8186 idDecl_getName (t)),
8198 DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
8200 ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
8201 /*!! fileloc_copy (g_currentloc)); */
8202 /*@i32!!! should get error without this */
8204 ret = exprNode_fromIdentifierAux (ue);
8207 ** No error - this happens in old style declarations:
8211 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8218 exprData_free (ret->edata, ret->kind);
8219 ret->edata = exprData_undefined;
8221 ret->exitCode = XK_NEVERESCAPE;
8222 ret->mustBreak = FALSE;
8223 ret->kind = XPR_INIT;
8227 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8229 exprNode ret = exprNode_makeInitializationAux (t);
8230 llassert (ret->edata == exprData_undefined);
8231 ret->edata = exprData_makeInit (t, exprNode_undefined);
8235 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8236 /*@only@*/ exprNode e)
8238 uentry ue = usymtab_lookup (idDecl_observeId (t));
8239 exprNode ret = exprNode_makeInitializationAux (t);
8240 fileloc loc = exprNode_loc (e);
8242 if (exprNode_isError (e))
8244 e = exprNode_createUnknown ();
8247 /* error: assume initializer is defined */
8248 sRef_setDefined (ret->sref, g_currentloc);
8252 ctype ct = ctype_realishType (ret->typ);
8257 ** was addSafeUse --- what's the problem?
8259 ** int x = 3, y = x ?
8262 exprData_free (ret->edata, ret->kind);
8263 ret->edata = exprData_makeInit (t, e);
8265 exprNode_checkUse (ret, e->sref, e->loc);
8267 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8269 exprNode lhs = exprNode_createId (ue);
8272 ** static storage should be undefined before initializing
8275 if (uentry_isStatic (ue))
8277 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8280 (void) exprNode_checkOneInit (lhs, e);
8282 if (uentry_isStatic (ue))
8284 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8287 exprNode_free (lhs);
8291 if (!exprNode_matchType (ct, e))
8293 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
8300 (exprNode_getType (e), e, exprNode_getType (ret), ret,
8302 ("Variable %q initialized to type %t, expects %t: %s",
8303 uentry_getName (ue), exprNode_getType (e),
8304 exprNode_getType (ret),
8305 exprNode_unparse (e)),
8311 if (uentry_isStatic (ue))
8313 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8316 doAssign (ret, e, TRUE);
8318 if (uentry_isStatic (ue))
8320 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8324 if (context_inIterDef ())
8326 /* should check if it is yield */
8327 uentry_setUsed (ue, loc);
8334 exprNode_mergeUSs (ret, e);
8338 exprNode exprNode_iter (/*@observer@*/ uentry name,
8339 /*@only@*/ exprNodeList alist,
8340 /*@only@*/ exprNode body,
8341 /*@observer@*/ uentry end)
8346 llassert (uentry_isValid (name));
8348 uentry_setUsed (name, exprNode_loc (body));
8350 ret = exprNode_createPartialCopy (body);
8351 iname = uentry_getName (name);
8353 if (uentry_isInvalid (end))
8356 message ("Iter %s not balanced with end_%s", iname, iname));
8360 cstring ename = uentry_getName (end);
8362 if (!cstring_equalPrefixLit (ename, "end_"))
8364 llerror (FLG_ITER, message ("Iter %s not balanced with end_%s: %s",
8365 iname, iname, ename));
8369 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8372 message ("Iter %s not balanced with end_%s: %s",
8373 iname, iname, ename));
8377 cstring_free (ename);
8380 context_exitIterClause (body);
8382 ret->kind = XPR_ITER;
8383 ret->edata = exprData_makeIter (name, alist, body, end);
8385 if (uentry_isIter (name))
8387 (void) checkArgsReal (name, body,
8388 uentry_getParams (name), alist, TRUE, ret);
8391 cstring_free (iname);
8397 exprNode_iterNewId (/*@only@*/ cstring s)
8399 exprNode e = exprNode_new ();
8400 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8402 llassert (processingIterVars ());
8404 e->loc = context_getSaveLocation ();
8406 if (fileloc_isUndefined (e->loc))
8408 fileloc_free (e->loc);
8409 e->loc = fileloc_copy (g_currentloc);
8412 e->uses = sRefSet_new ();
8413 e->sets = sRefSet_new ();
8414 e->msets = sRefSet_new ();
8416 e->val = multiVal_unknown ();
8417 e->guards = guardSet_new ();
8419 e->isJumpPoint = FALSE;
8420 e->exitCode = XK_NEVERESCAPE;
8422 /*> missing fields, detected by lclint <*/
8423 e->canBreak = FALSE;
8424 e->mustBreak = FALSE;
8425 e->etext = cstring_undefined;
8427 if (uentry_isYield (ue))
8429 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8430 fileloc_copy (e->loc),
8434 uue = usymtab_supEntrySrefReturn (uue);
8436 sr = uentry_getSref (uue);
8437 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8438 sr = uentry_getSref (uue);
8439 sRef_setDefined (sr, e->loc);
8441 e->typ = uentry_getType (uue);
8443 e->edata = exprData_makeId (uue);
8444 uentry_setUsed (uue, g_currentloc);
8450 sRef_setGlobalScope ();
8451 uue = uentry_makeVariableLoc (s, ctype_unknown);
8453 e->typ = ctype_unknown;
8454 e->edata = exprData_makeId (uue);
8456 uentry_setUsed (uue, e->loc);
8457 uentry_setHasNameError (uue);
8459 if (context_getFlag (FLG_REPEATUNRECOG))
8461 uentry_markOwned (uue);
8465 usymtab_supGlobalEntry (uue);
8468 sRef_clearGlobalScope ();
8470 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8477 exprNode_defineConstraints(e);
8482 exprNode_iterExpr (/*@returned@*/ exprNode e)
8484 if (!processingIterVars ())
8486 llcontbuglit ("checkIterParam: not in iter");
8490 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8493 if (exprNode_isDefined (e))
8495 if (fileloc_isDefined (e->loc))
8499 message ("Yield parameter is not simple identifier: %s",
8500 exprNode_unparse (e)),
8507 message ("Yield parameter is not simple identifier: %s",
8508 exprNode_unparse (e)),
8518 exprNode_iterId (/*@observer@*/ uentry c)
8522 llassert (processingIterVars ());
8524 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8527 if (uentry_isYield (ue))
8529 ctype ct = uentry_getType (ue);
8530 exprNode e = exprNode_createPlain (ct);
8531 cstring name = uentry_getName (c);
8532 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8534 uentry_setUsed (ue, g_currentloc);
8535 uentry_setHasNameError (ue);
8537 cstring_free (name);
8540 e->edata = exprData_makeId (le);
8541 e->loc = context_getSaveLocation ();
8542 e->sref = uentry_getSref (le);
8544 usymtab_supEntrySref (le);
8546 if (!context_inHeader ())
8550 message ("Yield parameter shadows local declaration: %q",
8551 uentry_getName (c)),
8552 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8554 uentry_showWhereDeclared (c);
8561 return (exprNode_fromIdentifierAux (c));
8564 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8566 exprNode ret = exprNode_create (ctype_unknown);
8568 ret->kind = XPR_ITERCALL;
8569 ret->edata = exprData_makeIterCall (name, alist);
8571 if (uentry_isIter (name))
8573 uentryList params = uentry_getParams (name);
8575 if (context_inIterDef ()
8576 && uentryList_size (params) == exprNodeList_size (alist))
8580 exprNodeList_elements (alist, arg)
8582 uentry parg = uentryList_getN (params, i);
8584 if (uentry_isYield (parg))
8586 uentry ue = exprNode_getUentry (arg);
8588 if (uentry_isValid (ue))
8595 } end_exprNodeList_elements;
8598 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8599 checkUnspecCall (ret, params, alist);
8605 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8607 if (exprNode_isDefined (e))
8610 if (e->sref == defref) /*@noaccess sRef@*/
8613 e->sref = sRef_makeUnknown ();
8614 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8625 return sRef_undefined;
8629 /*@observer@*/ cstring
8630 exprNode_unparseFirst (exprNode e)
8632 if (exprNode_isDefined (e))
8636 if (e->kind == XPR_STMTLIST
8637 || e->kind == XPR_COMMA || e->kind == XPR_COND)
8639 exprNode first = exprData_getPairA (e->edata);
8641 if (exprNode_isDefined (first))
8643 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8647 return (cstring_makeLiteralTemp ("..."));
8651 ret = cstring_elide (exprNode_unparse (e), 20);
8652 cstring_markOwned (ret);
8658 return cstring_makeLiteralTemp ("<error>");
8662 /*@observer@*/ cstring
8663 exprNode_unparse (/*@temp@*/ exprNode e)
8665 if (exprNode_isError (e))
8667 return cstring_makeLiteralTemp ("<error>");
8670 if (cstring_isDefined (e->etext))
8676 cstring ret = exprNode_doUnparse (e);
8678 /*@-modifies@*/ /* benevolent */
8685 /*@observer@*/ fileloc
8686 exprNode_loc (exprNode e)
8688 if (exprNode_isError (e))
8690 return (g_currentloc);
8699 ** executes exprNode e
8700 ** recursively rexecutes as though in original parse using
8701 ** information in e->edata
8704 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
8706 exprNodeList ret = exprNodeList_new ();
8708 exprNodeList_elements (e, current)
8710 exprNodeList_addh (ret, exprNode_effect (current));
8711 } end_exprNodeList_elements;
8716 static /*@only@*/ exprNode exprNode_effect (exprNode e)
8717 /*@globals internalState@*/
8719 bool innerEffect = inEffect;
8725 context_clearJustPopped ();
8727 if (exprNode_isError (e))
8729 ret = exprNode_undefined;
8734 ** Turn off expose and dependent transfer checking.
8735 ** Need to pass exposed internal nodes,
8736 ** [ copying would be a waste! ]
8737 ** [ Actually, I think I wasted a lot more time than its worth ]
8738 ** [ trying to do this. ]
8742 /*@-observertrans@*/
8743 /*@-dependenttrans@*/
8750 ret = exprNode_addParens (exprData_getUopTok (data),
8751 exprNode_effect (exprData_getUopNode (data)));
8754 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
8755 exprNode_effect (exprData_getOpB (data)),
8756 exprData_getOpTok (data));
8759 ret = exprNode_undefined;
8762 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
8763 exprNodeList_effect (exprData_getArgs (data)));
8776 cstring id = exprData_getId (data);
8777 uentry ue = usymtab_lookupSafe (id);
8779 ret = exprNode_fromIdentifierAux (ue);
8780 ret->loc = fileloc_update (ret->loc, e->loc);
8787 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
8788 exprNode_effect (exprData_getPairB (data)));
8791 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
8792 exprNode_effect (exprData_getOpB (data)),
8793 exprData_getOpTok (data));
8797 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
8798 exprData_getUopTok (data));
8801 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
8802 exprData_getUopTok (data));
8814 ret = exprNode_vaArg (exprData_getCastTok (data),
8815 exprNode_effect (exprData_getCastNode (data)),
8816 exprData_getCastType (data));
8820 ret = exprNode_cast (exprData_getCastTok (data),
8821 exprNode_effect (exprData_getCastNode (data)),
8822 exprData_getCastType (data));
8825 ret = exprNode_iterStart (exprData_getIterCallIter (data),
8827 (exprData_getIterCallArgs (data)));
8831 ret = exprNode_iter (exprData_getIterSname (data),
8832 exprNodeList_effect (exprData_getIterAlist (data)),
8833 exprNode_effect (exprData_getIterBody (data)),
8834 exprData_getIterEname (data));
8838 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
8839 exprNode_effect (exprData_getPairB (data)));
8843 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
8844 exprNode_effect (exprData_getTripleTest (data)),
8845 exprNode_effect (exprData_getTripleInc (data)));
8849 ret = exprNode_createTok (exprData_getTok (data));
8853 ret = exprNode_goto (exprData_getLiteral (data));
8854 ret->loc = fileloc_update (ret->loc, e->loc);
8858 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
8862 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
8866 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
8869 case XPR_NULLRETURN:
8870 ret = exprNode_nullReturn (exprData_getTok (data));
8874 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
8875 exprNode_effect (exprData_getPairB (data)));
8879 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
8880 exprNode_effect (exprData_getTripleTrue (data)),
8881 exprNode_effect (exprData_getTripleFalse (data)));
8884 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
8885 exprNode_effect (exprData_getPairB (data)));
8889 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
8890 exprNode_effect (exprData_getTripleTrue (data)),
8891 exprNode_effect (exprData_getTripleFalse (data)));
8894 ret = exprNode_whilePred (exprData_getSingle (data));
8898 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
8899 exprNode_effect (exprData_getPairB (data)));
8903 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
8904 exprNode_effect (exprData_getPairB (data)));
8908 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
8912 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
8913 exprData_getUopTok (data));
8917 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
8918 exprNode_effect (exprData_getPairB (data)));
8923 ret = exprNode_caseMarker
8924 (exprNode_effect (exprData_getSingle (data)),
8930 ret = exprNode_createTok (exprData_getTok (data));
8934 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
8935 exprNode_effect (exprData_getPairB (data)));
8939 ret = exprNode_makeInitialization
8940 (exprData_getInitId (data),
8941 exprNode_effect (exprData_getInitNode (data)));
8945 ret = exprNode_fieldAccessAux
8946 (exprNode_effect (exprData_getFieldNode (data)),
8947 exprNode_loc (exprData_getFieldNode (data)),
8948 cstring_copy (exprData_getFieldName (data)));
8952 ret = exprNode_arrowAccessAux
8953 (exprNode_effect (exprData_getFieldNode (data)),
8954 exprNode_loc (exprData_getFieldNode (data)),
8955 cstring_copy (exprData_getFieldName (data)));
8958 case XPR_STRINGLITERAL:
8972 /*@=observertrans@*/
8974 /*@=dependenttrans@*/
8985 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
8990 if (exprNode_isError (e))
8992 return cstring_undefined;
9000 ret = exprNode_rootVarName (exprData_getUopNode (data));
9003 ret = exprNode_rootVarName (exprData_getOpA (data));
9007 ret = exprData_getId (data);
9010 ret = idDecl_getName (exprData_getInitId (data));
9035 case XPR_NULLRETURN:
9057 case XPR_STRINGLITERAL:
9058 ret = cstring_undefined;
9065 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
9070 if (exprNode_isError (e))
9072 static /*@only@*/ cstring error = cstring_undefined;
9074 if (!cstring_isDefined (error))
9076 error = cstring_makeLiteral ("<error>");
9087 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
9090 ret = message ("%s %s %s",
9091 exprNode_unparse (exprData_getOpA (data)),
9092 lltok_unparse (exprData_getOpTok (data)),
9093 exprNode_unparse (exprData_getOpB (data)));
9096 ret = message ("%s(%q)",
9097 exprNode_unparse (exprData_getFcn (data)),
9098 exprNodeList_unparse (exprData_getArgs (data)));
9101 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
9104 ret = cstring_undefined;
9107 ret = message ("%s:", exprData_getId (data));
9111 ret = cstring_copy (exprData_getId (data));
9114 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
9115 exprNode_unparse (exprData_getPairB (data)));
9118 ret = message ("<body>");
9121 ret = message ("%s %s %s",
9122 exprNode_unparse (exprData_getOpA (data)),
9123 lltok_unparse (exprData_getOpTok (data)),
9124 exprNode_unparse (exprData_getOpB (data)));
9128 ret = message ("%s%s",
9129 lltok_unparse (exprData_getUopTok (data)),
9130 exprNode_unparse (exprData_getUopNode (data)));
9134 ret = message ("%s%s",
9135 exprNode_unparse (exprData_getUopNode (data)),
9136 lltok_unparse (exprData_getUopTok (data)));
9140 ret = message ("offsetof(%s,%q)",
9141 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
9142 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
9146 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9150 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
9154 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
9158 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
9162 ret = message ("va_arg(%s, %q)",
9163 exprNode_unparse (exprData_getCastNode (data)),
9164 qtype_unparse (exprData_getCastType (data)));
9168 ret = message ("%q(%q)",
9169 uentry_getName (exprData_getIterCallIter (data)),
9170 exprNodeList_unparse (exprData_getIterCallArgs (data)));
9173 ret = message ("%q(%q) %s %q",
9174 uentry_getName (exprData_getIterSname (data)),
9175 exprNodeList_unparse (exprData_getIterAlist (data)),
9176 exprNode_unparse (exprData_getIterBody (data)),
9177 uentry_getName (exprData_getIterEname (data)));
9180 ret = message ("(%q)%s",
9181 qtype_unparse (exprData_getCastType (data)),
9182 exprNode_unparse (exprData_getCastNode (data)));
9186 ret = message ("%s %s",
9187 exprNode_unparse (exprData_getPairA (data)),
9188 exprNode_unparse (exprData_getPairB (data)));
9192 ret = message ("for (%s; %s; %s)",
9193 exprNode_unparse (exprData_getTripleInit (data)),
9194 exprNode_unparse (exprData_getTripleTest (data)),
9195 exprNode_unparse (exprData_getTripleInc (data)));
9199 ret = message ("goto %s", exprData_getLiteral (data));
9203 ret = cstring_makeLiteral ("continue");
9207 ret = cstring_makeLiteral ("break");
9211 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
9214 case XPR_NULLRETURN:
9215 ret = cstring_makeLiteral ("return");
9219 ret = message ("%s, %s",
9220 exprNode_unparse (exprData_getPairA (data)),
9221 exprNode_unparse (exprData_getPairB (data)));
9225 ret = message ("%s ? %s : %s",
9226 exprNode_unparse (exprData_getTriplePred (data)),
9227 exprNode_unparse (exprData_getTripleTrue (data)),
9228 exprNode_unparse (exprData_getTripleFalse (data)));
9231 ret = message ("if (%s) %s",
9232 exprNode_unparse (exprData_getPairA (data)),
9233 exprNode_unparse (exprData_getPairB (data)));
9237 ret = message ("if (%s) %s else %s",
9238 exprNode_unparse (exprData_getTriplePred (data)),
9239 exprNode_unparse (exprData_getTripleTrue (data)),
9240 exprNode_unparse (exprData_getTripleFalse (data)));
9243 ret = message ("while (%s) %s",
9244 exprNode_unparse (exprData_getPairA (data)),
9245 exprNode_unparse (exprData_getPairB (data)));
9249 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9253 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9257 ret = message ("do { %s } while (%s)",
9258 exprNode_unparse (exprData_getPairB (data)),
9259 exprNode_unparse (exprData_getPairA (data)));
9263 ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
9267 ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
9271 ret = message ("%s; %s",
9272 exprNode_unparse (exprData_getPairA (data)),
9273 exprNode_unparse (exprData_getPairB (data)));
9278 ret = cstring_makeLiteral ("default:");
9282 ret = message ("switch (%s) %s",
9283 exprNode_unparse (exprData_getPairA (data)),
9284 exprNode_unparse (exprData_getPairB (data)));
9289 ret = message ("case %s:",
9290 exprNode_unparse (exprData_getSingle (data)));
9294 if (exprNode_isError (exprData_getInitNode (data)))
9296 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9300 ret = message ("%q = %s",
9301 idDecl_unparseC (exprData_getInitId (data)),
9302 exprNode_unparse (exprData_getInitNode (data)));
9307 ret = message ("%s.%s",
9308 exprNode_unparse (exprData_getFieldNode (data)),
9309 exprData_getFieldName (data));
9313 ret = message ("%s->%s",
9314 exprNode_unparse (exprData_getFieldNode (data)),
9315 exprData_getFieldName (data));
9318 case XPR_STRINGLITERAL:
9319 ret = message ("\"%s\"", exprData_getLiteral (data));
9323 ret = cstring_copy (exprData_getLiteral (data));
9327 ret = cstring_makeLiteral ("<node>");
9335 exprNode_isInitializer (exprNode e)
9337 return (exprNode_isDefined (e)
9338 && e->kind == XPR_INIT);
9342 exprNode_isCharLit (exprNode e)
9344 if (exprNode_isDefined (e))
9346 return (multiVal_isChar (exprNode_getValue (e)));
9355 exprNode_isNumLit (exprNode e)
9357 if (exprNode_isDefined (e))
9359 return (multiVal_isInt (exprNode_getValue (e)));
9368 exprNode_isFalseConstant (exprNode e)
9370 if (exprNode_isDefined (e))
9372 cstring s = exprNode_rootVarName (e);
9374 if (cstring_equal (s, context_getFalseName ()))
9384 exprNode_matchLiteral (ctype expected, exprNode e)
9386 if (exprNode_isDefined (e))
9388 multiVal m = exprNode_getValue (e);
9390 if (multiVal_isDefined (m))
9392 if (multiVal_isInt (m))
9394 long int val = multiVal_forceInt (m);
9396 if (ctype_isDirectBool (ctype_realishType (expected)))
9400 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9408 if (ctype_isRealInt (expected))
9411 ** unsigned <- [ constant >= 0 is okay ]
9414 if (ctype_isUnsigned (expected))
9423 ** No checks on sizes of integers...maybe add
9427 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9428 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9429 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9431 if (context_getFlag (FLG_NUMLITERAL)
9432 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9438 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9442 else if (ctype_isChar (expected))
9446 else if (ctype_isArrayPtr (expected))
9449 ** evans 2001-10-14: We allow 0 to match any pointer, but only if the type matches or is void *.
9454 if (ctype_match (exprNode_getType (e), expected)
9455 || ctype_isVoidPointer (exprNode_getType (e)))
9465 else if (ctype_isAnyFloat (expected))
9467 return (context_getFlag (FLG_NUMLITERAL));
9474 else if (multiVal_isDouble (m))
9476 if (ctype_isAnyFloat (expected))
9481 else if (multiVal_isChar (m))
9483 char val = multiVal_forceChar (m);
9485 if (ctype_isChar (expected))
9487 if (ctype_isUnsigned (expected) && ((int)val) < 0)
9508 exprNode_matchType (ctype expected, exprNode e)
9512 if (!exprNode_isDefined (e)) return TRUE;
9514 actual = ctype_realishType (exprNode_getType (e));
9516 if (ctype_match (ctype_realishType (expected), actual))
9521 llassert (!exprNode_isError (e));
9522 return (exprNode_matchLiteral (expected, e));
9526 exprNode_matchTypes (exprNode e1, exprNode e2)
9531 if (!exprNode_isDefined (e1)) return TRUE;
9532 if (!exprNode_isDefined (e2)) return TRUE;
9535 ** realish type --- keep bools, bools
9538 t1 = ctype_realishType (exprNode_getType (e1));
9539 t2 = ctype_realishType (exprNode_getType (e2));
9541 if (ctype_match (t1, t2))
9546 DPRINTF (("Matching literal! %s %s %s %s",
9547 ctype_unparse (t1), exprNode_unparse (e2),
9548 ctype_unparse (t2), exprNode_unparse (e1)));
9550 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9558 exprNode_matchArgType (ctype ct, exprNode e)
9562 if (!exprNode_isDefined (e))
9567 et = ctype_realType (exprNode_getType (e));
9569 if (ctype_matchArg (ct, et)) return TRUE;
9571 llassert (!exprNode_isError (e));
9572 return (exprNode_matchLiteral (ct, e));
9575 static /*@only@*/ exprNodeSList
9576 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9578 if (exprNode_isDefined (e))
9580 if (e->kind == XPR_STMTLIST)
9582 return (exprNodeSList_append
9583 (exprNode_flatten (exprData_getPairA (e->edata)),
9584 exprNode_flatten (exprData_getPairB (e->edata))));
9586 else if (e->kind == XPR_BLOCK)
9588 return (exprNode_flatten (exprData_getSingle (e->edata)));
9592 return (exprNodeSList_singleton (e));
9596 return exprNodeSList_new ();
9599 static /*@exposed@*/ exprNode
9600 exprNode_lastStatement (/*@returned@*/ exprNode e)
9602 if (exprNode_isDefined (e))
9604 if (e->kind == XPR_STMTLIST)
9606 exprNode b = exprData_getPairB (e->edata);
9608 if (exprNode_isDefined (b))
9610 return exprNode_lastStatement (b);
9614 return exprNode_lastStatement (exprData_getPairA (e->edata));
9617 else if (e->kind == XPR_BLOCK)
9619 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
9627 return exprNode_undefined;
9630 static /*@exposed@*/ exprNode
9631 exprNode_firstStatement (/*@returned@*/ exprNode e)
9633 if (exprNode_isDefined (e))
9635 if (e->kind == XPR_STMTLIST)
9637 exprNode b = exprData_getPairA (e->edata);
9639 if (exprNode_isDefined (b))
9641 return exprNode_firstStatement (b);
9645 return exprNode_firstStatement (exprData_getPairB (e->edata));
9648 else if (e->kind == XPR_BLOCK)
9650 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
9658 return exprNode_undefined;
9662 exprNode_mergeUSs (exprNode res, exprNode other)
9664 if (exprNode_isDefined (res) && exprNode_isDefined (other))
9666 res->msets = sRefSet_union (res->msets, other->msets);
9667 res->sets = sRefSet_union (res->sets, other->sets);
9668 res->uses = sRefSet_union (res->uses, other->uses);
9673 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
9675 if (exprNode_isDefined (res))
9677 if (exprNode_isDefined (other1))
9679 res->sets = sRefSet_union (res->sets, other1->sets);
9680 res->msets = sRefSet_union (res->msets, other1->msets);
9681 res->uses = sRefSet_union (res->uses, other1->uses);
9683 if (exprNode_isDefined (other2))
9685 res->sets = sRefSet_union (res->sets, other2->sets);
9686 res->msets = sRefSet_union (res->msets, other2->msets);
9687 res->uses = sRefSet_union (res->uses, other2->uses);
9695 ** Reports errors is s is not defined.
9699 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
9701 if (exprNode_isDefined (e))
9703 e->uses = sRefSet_insert (e->uses, s);
9708 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
9710 if (sRef_isKnown (s) && !sRef_isConst (s))
9713 ** need to check all outer types are useable
9716 DPRINTF (("Check use: %s / %s",
9717 exprNode_unparse (e), sRef_unparse (s)));
9719 exprNode_addUse (e, s);
9721 if (!context_inProtectVars ())
9724 ** only report the deepest error
9727 sRef errorRef = sRef_undefined;
9728 sRef lastRef = sRef_undefined;
9729 bool deadRef = FALSE;
9730 bool unuseable = FALSE;
9731 bool errorMaybe = FALSE;
9733 while (sRef_isValid (s) && sRef_isKnown (s))
9735 ynm readable = sRef_isReadable (s);
9737 DPRINTF (("Readable: %s / %s",
9738 sRef_unparseFull (s), ynm_unparse (readable)));
9740 if (!(ynm_toBoolStrict (readable)))
9742 if (ynm_isMaybe (readable))
9746 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
9747 deadRef = sRef_isPossiblyDead (errorRef);
9748 unuseable = sRef_isUnuseable (errorRef);
9755 deadRef = sRef_isDead (errorRef);
9756 unuseable = sRef_isUnuseable (errorRef);
9760 if (!sRef_isPartial (s))
9762 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
9763 sRef_setDefined (s, fileloc_undefined);
9767 s = sRef_getBaseSafe (s);
9770 if (sRef_isValid (errorRef))
9772 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
9773 && sRef_isPointer (errorRef))
9780 if (sRef_isThroughArrayFetch (errorRef))
9783 (FLG_STRICTUSERELEASED,
9784 message ("%q %q may be used after being released",
9785 sRef_unparseKindNamePlain (errorRef),
9786 sRef_unparse (errorRef)),
9789 sRef_showRefKilled (errorRef);
9791 if (sRef_isKept (errorRef))
9793 sRef_clearAliasState (errorRef, loc);
9799 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
9803 message ("%q %q %qused after being released",
9804 sRef_unparseKindNamePlain (errorRef),
9805 sRef_unparse (errorRef),
9806 cstring_makeLiteral (errorMaybe
9810 sRef_showRefKilled (errorRef);
9812 if (sRef_isKept (errorRef))
9814 sRef_clearAliasState (errorRef, loc);
9823 message ("%q %q%qused in inconsistent state",
9824 sRef_unparseKindName (errorRef),
9825 sRef_unparseOpt (errorRef),
9826 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9829 sRef_showStateInconsistent (errorRef);
9834 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
9838 message ("%q %q%qused before definition",
9839 sRef_unparseKindName (errorRef),
9840 sRef_unparseOpt (errorRef),
9841 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9844 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
9847 sRef_setDefined (errorRef, loc);
9849 if (sRef_isAddress (errorRef))
9851 sRef_setDefined (sRef_getRootBase (errorRef), loc);
9853 } /* end is error */
9861 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
9863 if (exprNode_isDefined (e) && sRef_isKnown (s))
9865 e->uses = sRefSet_insert (e->uses, s);
9870 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
9872 if (exprNode_isDefined (e))
9874 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
9879 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
9881 sRef defines = sRef_undefined;
9883 if (sRef_isValid (s) && !sRef_isNothing (s))
9885 uentry ue = sRef_getBaseUentry (s);
9887 if (uentry_isValid (ue))
9889 uentry_setLset (ue);
9892 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9894 voptgenerror (FLG_USEDEF,
9895 message ("Attempt to set unuseable storage: %q",
9900 if (sRef_isMeaningful (s))
9902 if (sRef_isDead (s))
9904 sRef base = sRef_getBaseSafe (s);
9906 if (sRef_isValid (base)
9907 && sRef_isDead (base))
9909 sRef_setPartial (s, exprNode_loc (e));
9912 defines = s; /* okay - modifies for only param */
9914 else if (sRef_isPartial (s))
9916 sRef eref = exprNode_getSref (e);
9918 if (!sRef_isPartial (eref))
9921 ** should do something different here???
9924 sRef_setDefinedComplete (eref, exprNode_loc (e));
9928 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
9931 if (sRef_isMeaningful (eref))
9940 else if (sRef_isAllocated (s))
9942 sRef eref = exprNode_getSref (e);
9945 if (!sRef_isAllocated (eref))
9947 sRef_setDefinedComplete (eref, exprNode_loc (e));
9951 sRef base = sRef_getBaseSafe (eref);
9953 if (sRef_isValid (base))
9955 sRef_setPdefined (base, exprNode_loc (e));
9963 sRef_setDefinedNCComplete (s, exprNode_loc (e));
9968 else /* not meaningful...but still need to insert it */
9974 if (exprNode_isDefined (e) && sRef_isValid (defines))
9976 e->sets = sRefSet_insert (e->sets, defines);
9981 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
9983 if (sRef_isValid (s) && !sRef_isNothing (s))
9985 uentry ue = sRef_getBaseUentry (s);
9987 if (uentry_isValid (ue))
9989 uentry_setLset (ue);
9992 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9994 voptgenerror (FLG_USEDEF,
9995 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
9999 if (sRef_isMeaningful (s))
10001 sRef_setDefinedComplete (s, exprNode_loc (e));
10004 if (exprNode_isDefined (e))
10006 e->msets = sRefSet_insert (e->msets, s);
10012 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
10014 checkAnyCall (fcn, cstring_undefined, params, args,
10015 FALSE, sRefSet_undefined, FALSE, 0);
10019 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
10020 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
10024 if (uentry_isYield (ucurrent))
10026 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
10027 exprNode_checkSet (current, current->sref);
10031 if (uentry_isSefParam (ucurrent))
10033 sRefSet sets = current->sets;
10034 sRef ref = exprNode_getSref (current);
10036 if (sRef_isMacroParamRef (ref))
10038 uentry ue = sRef_getUentry (ref);
10040 if (!uentry_isSefParam (ue))
10045 ("Parameter %d to %s is declared sef, but "
10046 "the argument is a macro parameter declared "
10048 argno, exprNode_unparse (fcn),
10049 exprNode_unparse (current)),
10050 exprNode_loc (current));
10054 if (!sRefSet_isEmpty (sets))
10056 sRefSet reported = sRefSet_undefined;
10058 sRefSet_realElements (current->sets, el)
10060 if (sRefSet_isSameNameMember (reported, el))
10062 ; /* don't report again */
10066 if (sRef_isUnconstrained (el))
10071 ("Parameter %d to %s is declared sef, but "
10072 "the argument calls unconstrained function %s "
10073 "(no guarantee it will not modify something): %s",
10074 argno, exprNode_unparse (fcn),
10075 sRef_unconstrainedName (el),
10076 exprNode_unparse (current)),
10077 exprNode_loc (current));
10084 ("Parameter %d to %s is declared sef, but "
10085 "the argument may modify %q: %s",
10086 argno, exprNode_unparse (fcn),
10088 exprNode_unparse (current)),
10089 exprNode_loc (current));
10092 } end_sRefSet_realElements;
10096 checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs);
10097 exprNode_mergeUSs (fcn, current);
10102 checkAnyCall (/*@dependent@*/ exprNode fcn,
10103 /*@dependent@*/ cstring fname,
10106 bool hasMods, sRefSet mods,
10111 int nargs = exprNodeList_size (args);
10116 ** concat all args ud's to f, add each arg sref as a use unless
10117 ** it was specified as "out", in which case it is a def.
10120 uentryList_reset (pn);
10123 ** aliasing checks:
10125 ** if paramn is only or unique, no other arg may alias argn
10128 exprNodeList_elements (args, current)
10132 if (exprNode_isDefined (current))
10134 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
10136 uentry ucurrent = uentryList_current (pn);
10138 if (specialArgs == 0
10139 || (paramno < specialArgs))
10141 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
10143 if (context_maybeSet (FLG_ALIASUNIQUE))
10145 if (uentry_isOnly (ucurrent)
10146 || uentry_isUnique (ucurrent))
10148 checkUniqueParams (fcn, current, args,
10149 paramno, ucurrent);
10154 else /* uentry is undefined */
10156 if (specialArgs == 0)
10158 exprNode_checkUseParam (current);
10161 exprNode_mergeUSs (fcn, current);
10164 uentryList_advanceSafe (pn);
10165 } end_exprNodeList_elements;
10171 sRefSet_allElements (mods, s)
10174 sRef rb = sRef_getRootBase (s);
10176 if (sRef_isFileOrGlobalScope (rb))
10178 context_usedGlobal (rb);
10181 fb = sRef_fixBaseParam (s, args);
10183 if (!sRef_isMacroParamRef (fb))
10185 if (sRef_isNothing (fb))
10191 if (sRef_isValid (fb))
10193 uentry ue = sRef_getBaseUentry (s);
10195 if (uentry_isValid (ue))
10197 uentry_setLset (ue);
10201 fcn->sets = sRefSet_insert (fcn->sets, fb);
10204 sRef_clearDerivedComplete (s);
10205 } end_sRefSet_allElements;
10211 if (context_hasMods ())
10213 if (context_maybeSet (FLG_MODUNCON))
10217 message ("Undetected modification possible "
10218 "from call to unconstrained function %s: %s",
10220 exprNode_unparse (fcn)),
10221 exprNode_loc (fcn));
10226 if (context_maybeSet (FLG_MODUNCONNOMODS)
10227 && !(context_inIterDef () || context_inIterEnd ()))
10230 (FLG_MODUNCONNOMODS,
10231 message ("Undetected modification possible "
10232 "from call to unconstrained function %s: %s",
10234 exprNode_unparse (fcn)),
10235 exprNode_loc (fcn));
10239 exprNode_checkSetAny (fcn, fname);
10243 void exprNode_checkUseParam (exprNode current)
10245 if (exprNode_isDefined (current))
10247 exprNode_checkUse (current, current->sref, current->loc);
10252 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10253 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10258 if (!ctype_match (tr1, tr2))
10260 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10261 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10263 DPRINTF (("No error: [%s] %s / [%s] %s",
10264 exprNode_unparse (e1), ctype_unparse (tr1),
10265 exprNode_unparse (e2), ctype_unparse (tr2)));
10269 (void) gentypeerror
10271 message ("Incompatible types for %s (%s, %s): %s %s %s",
10272 lltok_unparse (op),
10273 ctype_unparse (te1),
10274 ctype_unparse (te2),
10275 exprNode_unparse (e1), lltok_unparse (op),
10276 exprNode_unparse (e2)),
10279 ret = ctype_unknown;
10283 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
10285 ret = ctype_resolveNumerics (tr1, tr2);
10287 else if (!context_msgStrictOps ())
10289 if (ctype_isPointer (tr1))
10291 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10295 else if (ctype_isInt (tr2))
10301 ret = ctype_unknown;
10304 else if (ctype_isPointer (tr2))
10306 if (ctype_isPointer (tr1))
10310 else if (ctype_isInt (tr1))
10316 ret = ctype_unknown;
10321 ret = ctype_resolveNumerics (tr1, tr2);
10326 int opid = lltok_getTok (op);
10327 bool comparop = (opid == EQ_OP || opid == NE_OP
10328 || opid == TLT || opid == TGT
10329 || opid == LE_OP || opid == GE_OP);
10331 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10334 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10335 || (ctype_isBool (tr1) && ctype_isBool (tr2))
10336 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10342 if (ctype_sameName (te1, te2))
10346 message ("Operands of %s are non-numeric (%t): %s %s %s",
10347 lltok_unparse (op), te1,
10348 exprNode_unparse (e1), lltok_unparse (op),
10349 exprNode_unparse (e2)),
10356 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10357 lltok_unparse (op), te1, te2,
10358 exprNode_unparse (e1), lltok_unparse (op),
10359 exprNode_unparse (e2)),
10364 else if (!ctype_isNumeric (tr1))
10368 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10369 lltok_unparse (op), te1,
10370 exprNode_unparse (e1), lltok_unparse (op),
10371 exprNode_unparse (e2)),
10376 if (!ctype_isNumeric (tr2))
10380 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10381 lltok_unparse (op), te2,
10382 exprNode_unparse (e1), lltok_unparse (op),
10383 exprNode_unparse (e2)),
10388 ret = ctype_unknown;
10396 abstractOpError (ctype tr1, ctype tr2, lltok op,
10397 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10398 fileloc loc1, fileloc loc2)
10400 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10402 if (ctype_match (tr1, tr2))
10406 message ("Operands of %s are abstract type (%t): %s %s %s",
10407 lltok_unparse (op), tr1,
10408 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10415 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10416 lltok_unparse (op), tr1, tr2,
10417 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10421 else if (ctype_isRealAbstract (tr1))
10425 message ("Left operand of %s is abstract type (%t): %s %s %s",
10426 lltok_unparse (op), tr1,
10427 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10432 if (ctype_isRealAbstract (tr2))
10436 message ("Right operand of %s is abstract type (%t): %s %s %s",
10437 lltok_unparse (op), tr2,
10438 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10447 ** requies e1 and e2 and not error exprNode's.
10451 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10452 ** the rep of the abstract type is exposed.
10454 ** The order is very important:
10456 ** check rep expose (move into check transfer)
10462 ** This isn't really a sensible procedure, but the indententation
10463 ** was getting too deep.
10467 checkOneRepExpose (sRef ysr, sRef base,
10468 /*@notnull@*/ exprNode e1,
10469 /*@notnull@*/ exprNode e2, ctype ct,
10472 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
10473 || sRef_isOwned (ysr)
10474 || sRef_isExposed (ysr)))
10476 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10477 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10480 if (sRef_isIReference (ysr))
10482 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10487 ("Assignment of mutable component of parameter %q "
10488 "to component of abstract "
10489 "type %s exposes rep: %s = %s",
10490 sRef_unparse (base),
10491 ctype_unparse (ct),
10492 exprNode_unparse (e1), exprNode_unparse (e2)),
10500 ("Assignment of mutable component of parameter %q "
10501 "(through alias %q) to component of abstract "
10502 "type %s exposes rep: %s = %s",
10503 sRef_unparse (base),
10504 sRef_unparse (e2->sref),
10505 ctype_unparse (ct),
10506 exprNode_unparse (e1), exprNode_unparse (e2)),
10512 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10516 message ("Assignment of mutable parameter %q "
10517 "to component of abstract type %s "
10518 "exposes rep: %s = %s",
10519 sRef_unparse (base),
10520 ctype_unparse (ct),
10521 exprNode_unparse (e1),
10522 exprNode_unparse (e2)),
10529 message ("Assignment of mutable parameter %q "
10530 "(through alias %q) to "
10531 "component of abstract type %s exposes "
10533 sRef_unparse (base),
10534 sRef_unparse (e2->sref),
10535 ctype_unparse (ct),
10536 exprNode_unparse (e1),
10537 exprNode_unparse (e2)),
10543 if (sRef_isFileOrGlobalScope (s2b))
10545 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10549 message ("Assignment of global %q "
10551 "abstract type %s exposes rep: %s = %s",
10552 sRef_unparse (base),
10553 ctype_unparse (ct),
10554 exprNode_unparse (e1), exprNode_unparse (e2)),
10561 message ("Assignment of global %q (through alias %q) "
10563 "abstract type %s exposes rep: %s = %s",
10564 sRef_unparse (base),
10565 sRef_unparse (e2->sref),
10566 ctype_unparse (ct),
10567 exprNode_unparse (e1), exprNode_unparse (e2)),
10575 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
10577 DPRINTF (("Do assign: %s <- %s",
10578 exprNode_unparse (e1), exprNode_unparse (e2)));
10579 DPRINTF (("Ctype: %s", ctype_unparse (exprNode_getType (e1))));
10581 if (ctype_isRealFunction (exprNode_getType (e1))
10582 && !ctype_isRealPointer (exprNode_getType (e1)))
10586 message ("Invalid left-hand side of assignment (function type %s): %s",
10587 ctype_unparse (exprNode_getType (e1)),
10588 exprNode_unparse (e1)),
10592 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
10594 ctype t2 = exprNode_getType (e2);
10595 sRef sr = sRef_getRootBase (e1->sref);
10596 ctype ct = sRef_getType (sr);
10598 if (ctype_isAbstract (t2)
10599 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
10601 /* it is immutable, okay to reference */
10602 goto donerepexpose;
10605 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
10607 sRef s2b = sRef_getRootBase (e2->sref);
10608 sRef s1 = e1->sref;
10609 sRef s1b = sRef_getRootBase (s1);
10612 aliases = usymtab_canAlias (e2->sref);
10614 if (!sRef_similar (s2b, s1b)
10615 && !sRef_isExposed (s1)
10616 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
10618 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
10619 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
10620 && !sRef_isExposed (s2b))
10622 if (sRef_isIReference (e2->sref))
10627 ("Assignment of mutable component of parameter %q "
10628 "to component of abstract type %s exposes rep: %s = %s",
10629 sRef_unparse (s2b),
10630 ctype_unparse (ct),
10631 exprNode_unparse (e1), exprNode_unparse (e2)),
10638 message ("Assignment of mutable parameter %q to "
10639 "component of abstract type %s exposes rep: %s = %s",
10640 sRef_unparse (s2b),
10641 ctype_unparse (ct),
10642 exprNode_unparse (e1), exprNode_unparse (e2)),
10647 if (sRef_isFileOrGlobalScope (s2b))
10651 message ("Assignment of global %q to component of "
10652 "abstract type %s exposes rep: %s = %s",
10653 sRef_unparse (s2b),
10654 ctype_unparse (ct),
10655 exprNode_unparse (e1), exprNode_unparse (e2)),
10659 sRefSet_realElements (aliases, ysr)
10661 sRef base = sRef_getRootBase (ysr);
10663 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
10664 || sRef_sameName (base, s1b))
10666 ; /* error already reported or same sref */
10670 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
10672 } end_sRefSet_realElements;
10674 sRefSet_free (aliases);
10681 ** function variables don't really work...
10684 if (!ctype_isFunction (ctype_realType (e2->typ)))
10688 DPRINTF (("Check init: %s / %s",
10689 exprNode_unparse (e1), exprNode_unparse (e2)));
10690 checkInitTransfer (e1, e2);
10694 checkAssignTransfer (e1, e2);
10699 sRef fref = e2->sref;
10701 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
10702 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
10704 /* Need to typecheck the annotation on the parameters */
10706 if (ctype_isRealFunction (e1->typ)) {
10707 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
10708 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
10710 if (!uentryList_isMissingParams (e1p)
10711 && !uentryList_isMissingParams (e2p)
10712 && uentryList_size (e1p) > 0) {
10713 if (uentryList_size (e1p) == uentryList_size (e2p)) {
10716 uentryList_elements (e1p, el1) {
10719 el2 = uentryList_getN (e2p, n);
10721 uentry_checkMatchParam (el1, el2, n, e2);
10722 } end_uentryList_elements;
10728 if (exprNode_isStringLiteral (e2))
10730 exprNode_checkStringLiteralLength (exprNode_getType (e1), e2);
10733 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
10739 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
10740 updateAliases (e1, e2);
10745 checkMacroParen (exprNode e)
10747 if (exprNode_isError (e) || e->kind == XPR_CAST)
10753 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
10757 message ("Macro parameter used without parentheses: %s",
10758 exprNode_unparse (e)),
10765 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
10769 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
10773 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
10780 ** if e2 is a parameter or global derived location which
10781 ** can be modified (that is, e2 is a mutable abstract type,
10782 ** or a derived pointer), then e1 can alias e2.
10784 ** e1 can alias everything which e2 can alias.
10786 ** Also, if e1 is guarded, remove from guard sets!
10789 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
10791 if (!context_inProtectVars ())
10794 ** depends on types of e1 and e2
10797 sRef s1 = e1->sref;
10798 sRef s2 = e2->sref;
10799 ctype t1 = exprNode_getType (e1);
10801 /* handle pointer sRefs, record fields, arrays, etc... */
10803 if (!ctype_isRealSU (t1))
10805 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
10806 sRef_copyRealDerivedComplete (s1, s2);
10811 ** Fields should alias
10814 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
10817 if (ctype_isMutable (t1) && sRef_isKnown (s1))
10819 usymtab_clearAlias (s1);
10820 usymtab_addMustAlias (s1, s2);
10821 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
10825 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
10828 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
10830 usymtab_unguard (s1);
10835 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
10837 if (exprNode_isDefined (e))
10839 e->loc = fileloc_update (e->loc, loc);
10843 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
10849 static void checkUniqueParams (exprNode fcn,
10850 /*@notnull@*/ exprNode current,
10852 int paramno, uentry ucurrent)
10855 sRef thisref = exprNode_getSref (current);
10858 ** Check if any argument could match this argument.
10861 exprNodeList_elements (args, icurrent)
10865 if (iparamno != paramno)
10867 sRef sr = exprNode_getSref (icurrent);
10869 if (sRef_similarRelaxed (thisref, sr))
10871 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
10876 ("Parameter %d (%s) to function %s is declared %s but "
10877 "is aliased by parameter %d (%s)",
10879 exprNode_unparse (current),
10880 exprNode_unparse (fcn),
10881 alkind_unparse (uentry_getAliasKind (ucurrent)),
10882 iparamno, exprNode_unparse (icurrent)),
10888 sRefSet aliases = usymtab_canAlias (sr);
10890 sRefSet_allElements (aliases, asr)
10892 if (ctype_isUnknown (sRef_getType (thisref)))
10894 sRef_setType (thisref, uentry_getType (ucurrent));
10897 if (sRef_similarRelaxed (thisref, asr))
10899 if (sRef_isExternal (asr))
10901 if (sRef_isLocalState (thisref))
10907 sRef base = sRef_getRootBase (asr);
10909 if (!sRef_similar (sRef_getBase (asr), thisref))
10911 if (sRef_isUnique (base) || sRef_isOnly (base)
10912 || sRef_isKept (base)
10913 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
10914 || (sRef_isAddress (thisref)
10915 && sRef_isLocalVar (sRef_getRootBase (thisref))))
10917 ; /* okay, no error */
10922 (FLG_MAYALIASUNIQUE,
10924 ("Parameter %d (%s) to function %s is declared %s but "
10925 "may be aliased externally by parameter %d (%s)",
10927 exprNode_unparse (current),
10928 exprNode_unparse (fcn),
10929 alkind_unparse (uentry_getAliasKind (ucurrent)),
10930 iparamno, exprNode_unparse (icurrent)),
10941 ("Parameter %d (%s) to function %s is declared %s but "
10942 "is aliased externally by parameter %d (%s) through "
10945 exprNode_unparse (current),
10946 exprNode_unparse (fcn),
10947 alkind_unparse (uentry_getAliasKind (ucurrent)),
10948 iparamno, exprNode_unparse (icurrent),
10949 sRef_unparse (asr)),
10953 } end_sRefSet_allElements;
10954 sRefSet_free (aliases);
10957 } end_exprNodeList_elements;
10960 long exprNode_getLongValue (exprNode e) {
10963 if (exprNode_hasValue (e)
10964 && multiVal_isInt (exprNode_getValue (e)))
10966 value = multiVal_forceInt (exprNode_getValue (e));
10977 /*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
10979 if (exprNode_isDefined (p_e) )
10980 return ( p_e->loc );
10982 return fileloc_undefined;
10985 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
10988 ** Returns the location of the sequence point following e.
10990 ** Only works for statements (for now).
10993 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
10994 lltok t = exprData_getUopTok (e->edata);
10995 return fileloc_copy(lltok_getLoc (t));
10997 /* drl possible problem : warning fix
10998 llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
11000 return fileloc_undefined;
11004 exprNode exprNode_createNew(ctype c)
11008 ret = exprNode_createPlain (c);
11013 bool exprNode_isInitBlock (exprNode e)
11015 return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);