2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
28 # include <ctype.h> /* for isdigit */
29 # include "lclintMacros.nf"
31 # include "cgrammar.h"
32 # include "cgrammar_tokens.h"
34 # include "exprChecks.h"
35 # include "transferChecks.h"
36 # include "exprNodeSList.h"
38 static bool exprNode_isEmptyStatement (exprNode p_e);
39 static /*@exposed@*/ exprNode exprNode_firstStatement (/*@returned@*/ exprNode p_e);
40 static bool exprNode_isFalseConstant (exprNode p_e) /*@*/ ;
41 static bool exprNode_isBlock (exprNode p_e);
42 static void checkGlobUse (uentry p_glob, bool p_isCall, /*@notnull@*/ exprNode p_e);
43 static void exprNode_addUse (exprNode p_e, /*@exposed@*/ sRef p_s);
44 static bool exprNode_matchArgType (ctype p_ct, exprNode p_e);
45 static exprNode exprNode_fakeCopy (exprNode p_e) /*@*/ ;
46 static exprNode exprNode_statementError (/*@only@*/ exprNode p_e, /*@only@*/ lltok p_t);
47 static bool exprNode_matchTypes (exprNode p_e1, exprNode p_e2);
48 static void checkUniqueParams (exprNode p_fcn,
49 /*@notnull@*/ exprNode p_current, exprNodeList p_args,
50 int p_paramno, uentry p_ucurrent);
51 static void updateAliases (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2);
52 static void abstractOpError (ctype p_tr1, ctype p_tr2, lltok p_op,
53 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2,
54 fileloc p_loc1, fileloc p_loc2);
55 static ctype checkNumerics (ctype p_tr1, ctype p_tr2, ctype p_te1, ctype p_te2,
56 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, lltok p_op);
57 static void doAssign (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, bool p_isInit);
58 static void checkSafeUse (exprNode p_e, /*@exposed@*/ sRef p_s);
59 static void reflectNullTest (/*@notnull@*/ exprNode p_e, bool p_isnull);
60 static void checkMacroParen (exprNode p_e);
61 static exprNodeSList exprNode_flatten (/*@dependent@*/ exprNode p_e);
62 static void exprNode_checkSetAny (exprNode p_e, /*@dependent@*/ cstring p_name);
63 static void exprNode_checkUse (exprNode p_e, /*@exposed@*/ sRef p_s, fileloc p_loc);
64 static void exprNode_mergeUSs (exprNode p_res, exprNode p_other);
65 static void exprNode_mergeCondUSs (exprNode p_res, exprNode p_other1, exprNode p_other2);
66 static /*@only@*/ /*@notnull@*/ exprNode exprNode_fromIdentifierAux (/*@observer@*/ uentry p_c);
67 static void checkAnyCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn,
68 /*@dependent@*/ cstring p_fname,
69 uentryList p_pn, exprNodeList p_args,
70 bool p_hasMods, sRefSet p_mods, bool p_isSpec,
72 static void checkOneArg (uentry p_ucurrent, /*@notnull@*/ exprNode p_current,
73 /*@dependent@*/ exprNode p_fcn, bool p_isSpec, int p_argno, int p_totargs);
75 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn, uentryList p_params, exprNodeList p_args);
77 static /*@only@*/ exprNode exprNode_effect (exprNode p_e)
78 /*@globals internalState@*/ ;
79 static /*@only@*/ cstring exprNode_doUnparse (exprNode p_e);
80 static /*@observer@*/ cstring exprNode_rootVarName (exprNode p_e);
81 static /*@exposed@*/ exprNode
82 exprNode_lastStatement (/*@returned@*/ exprNode p_e);
84 static /*@null@*/ sRef defref = sRef_undefined;
85 static /*@only@*/ exprNode mustExitNode = exprNode_undefined;
87 static int checkArgsReal (uentry p_fcn, /*@dependent@*/ exprNode p_f,
89 exprNodeList p_args, bool p_isIter, exprNode p_ret);
91 static bool inEffect = FALSE;
92 static int nowalloc = 0;
93 static int totalloc = 0;
94 static int maxalloc = 0;
96 static /*@only@*/ uentry regArg;
97 static /*@only@*/ uentry outArg;
98 static /*@only@*/ uentry outStringArg;
99 static /*@exposed@*/ sRef stdinRef;
100 static /*@exposed@*/ sRef stdoutRef;
101 static /*@only@*/ uentry csArg;
102 static /*@only@*/ uentry csOnlyArg;
103 static ctype cstringType;
104 static ctype ctypeType;
105 static ctype filelocType;
106 static bool initMod = FALSE;
108 /*@function void exprNode_swap (sef exprNode, sef exprNode)@*/
110 # define exprNode_swap(e1,e2) do { exprNode m_tmp = (e1); (e1) = (e2); (e2) = m_tmp; } while (FALSE)
113 static void exprNode_defineConstraints(/*@sef@*/ /*@special@*/ /*@notnull@*/ exprNode e)
114 /*@defines e->requiresConstraints, e->ensuresConstraints,
115 e->trueEnsuresConstraints, e->falseEnsuresConstraints @*/
117 e->requiresConstraints = constraintList_makeNew ();
118 e->ensuresConstraints = constraintList_makeNew ();
119 e->trueEnsuresConstraints = constraintList_makeNew ();
120 e->falseEnsuresConstraints = constraintList_makeNew ();
124 ** must occur after library has been read
127 void exprNode_initMod (void)
128 /*@globals undef regArg, undef outArg, undef outStringArg,
129 undef csOnlyArg, undef csArg;
136 cstringType = ctype_unknown;
137 ctypeType = ctype_unknown;
138 filelocType = ctype_unknown;
140 defref = sRef_undefined;
142 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
144 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
147 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
149 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
152 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
154 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
157 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdin")))
159 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdin"));
161 else /* define stdin */
163 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdin"),
165 fileloc_getBuiltin (),
167 uentry_setHasNameError (ue);
168 ue = usymtab_supGlobalEntryReturn (ue);
171 stdinRef = sRef_makePointer (uentry_getSref (ue));
173 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdout")))
175 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdout"));
179 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdout"),
181 fileloc_getBuiltin (),
183 uentry_setHasNameError (ue);
184 ue = usymtab_supGlobalEntryReturn (ue);
187 stdoutRef = sRef_makePointer (uentry_getSref (ue));
189 tmp = idDecl_create (cstring_undefined, qtype_create (ctype_unknown));
191 regArg = uentry_makeParam (tmp, PARAMUNKNOWN);
194 qtype_addQual (qtype_create (ctype_makePointer (ctype_unknown)),
197 outArg = uentry_makeParam (tmp, PARAMUNKNOWN);
199 idDecl_setTyp (tmp, qtype_addQual (qtype_create (ctype_string),
202 outStringArg = uentry_makeParam (tmp, PARAMUNKNOWN);
204 idDecl_setTyp (tmp, qtype_addQual (qtype_addQual (qtype_create (cstringType),
206 qual_createNull ()));
208 csOnlyArg = uentry_makeParam (tmp, PARAMUNKNOWN);
210 idDecl_setTyp (tmp, qtype_addQual (qtype_create (cstringType), qual_createNull ()));
211 csArg = uentry_makeParam (tmp, PARAMUNKNOWN);
217 exprNode_destroyMod (void)
218 /*@globals killed regArg, killed outArg, killed outStringArg,
219 killed mustExitNode, initMod @*/
223 uentry_free (regArg);
224 uentry_free (outArg);
225 uentry_free (outStringArg);
227 exprNode_free (mustExitNode);
234 static void exprNode_resetSref (/*@notnull@*/ exprNode e)
239 exprNode exprNode_fakeCopy (exprNode e)
241 /*@-temptrans@*/ /*@-retalias@*/
243 /*@=temptrans@*/ /*@=retalias@*/
246 static bool isFlagKey (char key)
248 return (key == '-' || key == '+' || key == ' ' || key == '#');
251 static void exprNode_combineControl (/*@notnull@*/ exprNode ret,
252 /*@notnull@*/ exprNode ifclause,
253 /*@notnull@*/ exprNode elseclause)
255 ret->canBreak = ifclause->canBreak || elseclause->canBreak;
258 (ifclause->mustBreak || exprNode_mustEscape (ifclause))
259 && (elseclause->mustBreak || exprNode_mustEscape (elseclause));
261 ret->exitCode = exitkind_combine (ifclause->exitCode,
262 elseclause->exitCode);
267 ** For exprNode's returned by exprNode_effect.
270 static bool shallowKind (exprKind kind)
272 return (kind == XPR_STRINGLITERAL
273 || kind == XPR_NUMLIT
276 || kind == XPR_NODE);
280 exprNode_freeIniter (/*@only@*/ exprNode e)
282 if (!exprNode_isError (e))
288 ** Its a fake copy, don't free the field->rec and field->field
293 sfree (e->edata->field);
299 exprNode_free (e->edata->op->b);
300 /*@-compdestroy@*/ sfree (e->edata->op); /*@=compdestroy@*/
304 llbug (message ("other: %s", exprNode_unparse (e)));
307 multiVal_free (e->val);
308 cstring_free (e->etext);
309 fileloc_free (e->loc);
310 sRefSet_free (e->uses);
311 sRefSet_free (e->sets);
312 sRefSet_free (e->msets);
313 guardSet_free (e->guards);
315 constraintList_free(e->requiresConstraints);
316 constraintList_free(e->ensuresConstraints);
317 constraintList_free(e->trueEnsuresConstraints);
318 constraintList_free(e->falseEnsuresConstraints);
320 e->requiresConstraints = NULL;
321 e->ensuresConstraints = NULL;
322 e->trueEnsuresConstraints = NULL;
323 e->falseEnsuresConstraints = NULL;
330 exprNode_freeShallow (/*@only@*/ exprNode e)
332 if (!exprNode_isError (e))
334 if (shallowKind (e->kind))
341 if (e->kind == XPR_EMPTY
342 || e->kind == XPR_BODY
343 || e->kind == XPR_STRINGLITERAL
344 || e->kind == XPR_NUMLIT
345 || e->kind == XPR_NODE
346 || e->kind == XPR_OFFSETOF
347 || e->kind == XPR_ALIGNOFT
348 || e->kind == XPR_ALIGNOF
349 || e->kind == XPR_SIZEOFT
350 || e->kind == XPR_SIZEOF)
352 /* don't free anything */
356 /* multiVal_free (e->val); */
357 cstring_free (e->etext);
358 fileloc_free (e->loc);
359 sRefSet_free (e->uses);
360 sRefSet_free (e->sets);
361 sRefSet_free (e->msets);
362 guardSet_free (e->guards);
363 exprData_freeShallow (e->edata, e->kind);
365 /*@-compdestroy@*/ sfree (e); /*@=compdestroy@*/
374 exprNode_free (exprNode e)
376 if (!exprNode_isError (e))
380 multiVal_free (e->val);
381 cstring_free (e->etext);
382 fileloc_free (e->loc);
383 sRefSet_free (e->uses);
384 sRefSet_free (e->sets);
385 sRefSet_free (e->msets);
386 guardSet_free (e->guards);
387 exprData_free (e->edata, e->kind);
389 constraintList_free(e->requiresConstraints);
390 constraintList_free(e->ensuresConstraints);
391 constraintList_free(e->trueEnsuresConstraints);
392 constraintList_free(e->falseEnsuresConstraints);
394 e->requiresConstraints = NULL;
395 e->ensuresConstraints = NULL;
396 e->trueEnsuresConstraints = NULL;
397 e->falseEnsuresConstraints = NULL;
407 exprNode_makeError ()
409 return exprNode_undefined;
412 static /*@out@*/ /*@only@*/ /*@notnull@*/ exprNode
415 exprNode ret = (exprNode) dmalloc (sizeof (*ret));
416 /* static int lastexpnodes = 0; */
421 if (nowalloc > maxalloc)
429 static /*@notnull@*/ /*@special@*/ exprNode
430 exprNode_createPlain (ctype c)
432 /*@ensures isnull result->edata, result->loc, result->val, result->guards,
433 result->uses, result->sets, result->msets, result->etext @*/
436 exprNode e = exprNode_new ();
440 e->val = multiVal_undefined;
442 e->etext = cstring_undefined;
443 e->loc = fileloc_undefined;
444 e->guards = guardSet_undefined;
445 e->uses = sRefSet_undefined;
446 e->sets = sRefSet_undefined;
447 e->msets = sRefSet_undefined;
448 e->edata = exprData_undefined;
449 e->exitCode = XK_NEVERESCAPE;
451 e->mustBreak = FALSE;
452 e->isJumpPoint = FALSE;
454 exprNode_defineConstraints(e);
459 /*@observer@*/ exprNode exprNode_makeMustExit (void)
461 if (exprNode_isUndefined (mustExitNode))
463 mustExitNode = exprNode_createPlain (ctype_unknown);
464 mustExitNode->exitCode = XK_MUSTEXIT;
471 static /*@notnull@*/ /*@special@*/ exprNode exprNode_create (ctype c)
473 /*@post:isnull result->edata, result->guards, result->val,
474 result->uses, result->sets, result->msets@*/
477 exprNode e = exprNode_createPlain (c);
478 e->loc = fileloc_copy (g_currentloc);
482 static /*@notnull@*/ /*@special@*/ exprNode exprNode_createUnknown (void)
484 /*@post:isnull result->edata, result->guards,
485 result->uses, result->sets, result->msets@*/
488 return (exprNode_create (ctype_unknown));
491 static /*@notnull@*/ /*@special@*/ exprNode
492 exprNode_createLoc (ctype c, /*@keep@*/ fileloc loc)
494 /*@post:isnull result->edata, result->guards, result->val,
495 result->uses, result->sets, result->msets@*/
498 exprNode e = exprNode_createPlain (c);
504 exprNode_copySets (/*@special@*/ /*@notnull@*/ exprNode ret, exprNode e)
505 /*@defines ret->guards, ret->uses, ret->sets, ret->msets@*/
507 if (exprNode_isDefined (e))
509 ret->guards = guardSet_copy (e->guards);
510 ret->uses = sRefSet_newCopy (e->uses);
511 ret->sets = sRefSet_newCopy (e->sets);
512 ret->msets = sRefSet_newCopy (e->msets);
516 ret->guards = guardSet_undefined;
517 ret->uses = sRefSet_undefined;
518 ret->sets = sRefSet_undefined;
519 ret->msets = sRefSet_undefined;
523 static /*@notnull@*/ /*@special@*/ exprNode
524 exprNode_createPartialLocCopy (exprNode e, /*@only@*/ fileloc loc)
526 /*@post:isnull result->edata, result->etext@*/
529 exprNode ret = exprNode_new ();
531 if (exprNode_isError (e))
533 ret->typ = ctype_unknown;
534 ret->val = multiVal_undefined;
536 ret->guards = guardSet_undefined;
537 ret->uses = sRefSet_undefined;
538 ret->sets = sRefSet_undefined;
539 ret->msets = sRefSet_undefined;
544 ret->val = multiVal_copy (e->val);
546 ret->guards = guardSet_copy (e->guards);
547 ret->uses = sRefSet_newCopy (e->uses);
548 ret->sets = sRefSet_newCopy (e->sets);
549 ret->msets = sRefSet_newCopy (e->msets);
552 ret->kind = XPR_EMPTY;
554 ret->etext = cstring_undefined;
555 ret->exitCode = XK_NEVERESCAPE;
556 ret->canBreak = FALSE;
557 ret->mustBreak = FALSE;
558 ret->isJumpPoint = FALSE;
559 ret->edata = exprData_undefined;
561 exprNode_defineConstraints(ret);
567 static /*@notnull@*/ /*@special@*/ exprNode
568 exprNode_createPartialCopy (exprNode e)
570 /*@post:isnull result->edata, result->etext@*/
573 return (exprNode_createPartialLocCopy (e, fileloc_copy (exprNode_loc (e))));
576 static /*@notnull@*/ /*@special@*/ exprNode
577 exprNode_createPartialNVCopy (exprNode e)
579 /*@post:isnull result->edata, result->etext, result->val @*/
582 exprNode ret = exprNode_new ();
584 if (exprNode_isError (e))
586 ret->typ = ctype_unknown;
587 ret->loc = fileloc_undefined;
588 ret->guards = guardSet_undefined;
589 ret->uses = sRefSet_undefined;
590 ret->sets = sRefSet_undefined;
591 ret->msets = sRefSet_undefined;
596 ret->loc = fileloc_copy (e->loc);
597 ret->guards = guardSet_copy (e->guards);
598 ret->uses = sRefSet_newCopy (e->uses);
599 ret->sets = sRefSet_newCopy (e->sets);
600 ret->msets = sRefSet_newCopy (e->msets);
603 ret->val = multiVal_undefined;
604 ret->kind = XPR_EMPTY;
606 ret->etext = cstring_undefined;
607 ret->exitCode = XK_NEVERESCAPE;
608 ret->canBreak = FALSE;
609 ret->mustBreak = FALSE;
610 ret->isJumpPoint = FALSE;
611 ret->edata = exprData_undefined;
613 exprNode_defineConstraints(ret);
618 static /*@notnull@*/ /*@special@*/ exprNode
619 exprNode_createSemiCopy (exprNode e)
621 /*@post:isnull result->edata, result->etext, result->sets,
622 result->msets, result->uses, result->guards@*/
625 if (exprNode_isError (e))
627 return exprNode_createPlain (ctype_unknown);
631 exprNode ret = exprNode_new ();
634 ret->val = multiVal_copy (e->val);
635 ret->loc = fileloc_copy (e->loc);
636 ret->guards = guardSet_undefined;
637 ret->uses = sRefSet_undefined;
638 ret->sets = sRefSet_undefined;
639 ret->msets = sRefSet_undefined;
641 ret->kind = XPR_EMPTY;
643 ret->etext = cstring_undefined;
644 ret->exitCode = XK_NEVERESCAPE;
645 ret->canBreak = FALSE;
646 ret->mustBreak = FALSE;
647 ret->isJumpPoint = FALSE;
648 ret->edata = exprData_undefined;
650 exprNode_defineConstraints(ret);
657 exprNode_isNullValue (exprNode e)
659 if (exprNode_isDefined (e))
661 multiVal m = exprNode_getValue (e);
663 if (multiVal_isInt (m))
665 return (multiVal_forceInt (m) == 0);
673 exprNode_isUnknownConstant (/*@notnull@*/ exprNode e)
675 while (e->kind == XPR_PARENS)
677 e = exprData_getUopNode (e->edata);
678 llassert (exprNode_isDefined (e));
681 if (e->kind == XPR_CONST)
683 multiVal m = exprNode_getValue (e);
685 if (multiVal_isUnknown (m))
695 exprNode_numLiteral (ctype c, /*@temp@*/ cstring t,
696 /*@only@*/ fileloc loc, long val)
698 exprNode e = exprNode_createLoc (c, loc);
700 e->kind = XPR_NUMLIT;
702 llassert (multiVal_isUndefined (e->val));
703 e->val = multiVal_makeInt (val);
704 e->edata = exprData_makeLiteral (cstring_copy (t));
708 e->sref = sRef_makeUnknown ();
709 sRef_setDefNull (e->sref, e->loc);
712 DPRINTF (("Num lit: %s / %s", exprNode_unparse (e), ctype_unparse (exprNode_getType (e))));
717 exprNode_charLiteral (char c, cstring text, /*@only@*/ fileloc loc)
719 exprNode e = exprNode_createLoc (ctype_char, loc);
721 if (context_getFlag (FLG_CHARINTLITERAL))
723 e->typ = ctype_makeConj (ctype_char, ctype_int);
726 e->kind = XPR_NUMLIT;
727 e->val = multiVal_makeChar (c);
729 e->edata = exprData_makeLiteral (cstring_copy (text));
734 exprNode_floatLiteral (double d, ctype ct, cstring text, /*@only@*/ fileloc loc)
736 exprNode e = exprNode_createLoc (ct, loc);
738 e->kind = XPR_NUMLIT;
739 e->val = multiVal_makeDouble (d);
740 e->edata = exprData_makeLiteral (cstring_copy (text));
744 multiVal exprNode_getValue (exprNode e)
746 while (exprNode_isInParens (e)) {
747 if (e->edata != NULL) {
748 e = exprData_getUopNode (e->edata);
754 if (exprNode_isDefined (e)) {
757 return multiVal_undefined;
762 exprNode_combineLiterals (exprNode e, exprNode rest)
766 /* Both must be string literals. */
768 if (exprNode_isUndefined (rest) || exprNode_isUndefined (e))
770 exprNode_free (rest);
774 if (!exprNode_isStringLiteral (e))
778 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e),
779 exprNode_unparse (rest)),
781 exprNode_free (rest);
785 if (!exprNode_isStringLiteral (rest))
789 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e), exprNode_unparse (rest)),
792 exprNode_free (rest);
796 ns = cstring_concat (multiVal_forceString (exprNode_getValue (e)),
797 multiVal_forceString (exprNode_getValue (rest)));
799 multiVal_free (e->val);
800 exprData_free (e->edata, e->kind);
801 e->edata = exprData_makeLiteral (cstring_copy (ns));
802 e->val = multiVal_makeString (ns);
803 exprNode_free (rest);
808 exprNode_rawStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
810 exprNode e = exprNode_createLoc (ctype_string, loc);
811 int len = cstring_length (t);
813 if (context_getFlag (FLG_STRINGLITERALLEN))
815 if (len > context_getValue (FLG_STRINGLITERALLEN))
817 voptgenerror (FLG_STRINGLITERALLEN,
819 ("String literal length (%d) exceeds maximum "
820 "length (%d): \"%s\"",
822 context_getValue (FLG_STRINGLITERALLEN),
828 e->kind = XPR_STRINGLITERAL;
829 e->val = multiVal_makeString (cstring_copy (t));
830 e->edata = exprData_makeLiteral (t);
831 e->sref = sRef_makeConst (ctype_string);
833 if (context_getFlag (FLG_READONLYSTRINGS))
835 sRef_setAliasKind (e->sref, AK_STATIC, fileloc_undefined);
836 sRef_setExKind (e->sref, XO_OBSERVER, loc);
840 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
843 return (e); /* s released */
847 exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
849 int len = cstring_length (t) - 2;
850 char *ts = cstring_toCharsSafe (t);
851 char *s = cstring_toCharsSafe (cstring_create (len + 1));
853 llassert (*ts == '\"' && *(ts + len + 1) == '\"');
854 strncpy (s, ts+1, size_fromInt (len));
857 return exprNode_rawStringLiteral (cstring_fromCharsO (s), loc);
860 exprNode exprNode_fromUIO (cstring c)
862 fileloc loc = context_getSaveLocation ();
863 exprNode e = exprNode_createPlain (ctype_unknown);
867 if (fileloc_isUndefined (loc))
869 loc = fileloc_copy (g_currentloc);
872 e->loc = loc; /* save loc was mangled */
875 if (usymtab_exists (c))
877 uentry ue = usymtab_lookupEither (c);
879 if (uentry_isDatatype (ue)
880 && uentry_isSpecified (ue))
883 (message ("%q: Specified datatype %s used in code, but not defined. "
884 "(Cannot continue reasonably from this error.)",
885 fileloc_unparse (e->loc), c));
893 llassertprint (!usymtab_exists (c), ("Entry exists: %s", c));
896 ** was supercedeGlobalEntry...is this better?
899 if (!context_inIterEnd ())
901 if (context_inMacro ())
903 if (context_getFlag (FLG_UNRECOG))
907 message ("Unrecognized identifier in macro definition: %s", c), e->loc);
911 flagcode_recordSuppressed (FLG_UNRECOG);
917 (FLG_UNRECOG, message ("Unrecognized identifier: %s", c), e->loc);
921 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
923 /* No alias errors for unrecognized identifiers */
924 sRef_setAliasKind (e->sref, AK_ERROR, loc);
929 exprNode exprNode_createId (/*@observer@*/ uentry c)
931 if (uentry_isValid (c))
933 exprNode e = exprNode_new ();
935 e->typ = uentry_getType (c);
937 if (uentry_isFunction (c)
938 && !sRef_isLocalVar (uentry_getSref (c)))
940 e->sref = sRef_undefined;
944 e->sref = uentry_getSref (c);
947 if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
949 sRef_setDefined (e->sref, fileloc_undefined);
953 ** yoikes! leaving this out was a heinous bug...that would have been
954 ** caught if i had lclint working first. gag!
957 e->etext = cstring_undefined;
959 if (uentry_isEitherConstant (c))
962 e->val = multiVal_copy (uentry_getConstantValue (c));
967 e->val = multiVal_unknown ();
970 e->edata = exprData_makeId (c);
971 e->loc = context_getSaveLocation ();
973 if (fileloc_isUndefined (e->loc))
975 fileloc_free (e->loc);
976 e->loc = fileloc_copy (g_currentloc);
979 e->guards = guardSet_new ();
980 e->sets = sRefSet_new ();
981 e->msets = sRefSet_new ();
982 e->uses = sRefSet_new ();
984 /*> missing fields, detected by lclint <*/
985 e->exitCode = XK_NEVERESCAPE;
986 e->isJumpPoint = FALSE;
988 e->mustBreak = FALSE;
990 exprNode_defineConstraints(e);
996 return exprNode_createUnknown ();
1000 /*@notnull@*/ exprNode
1001 exprNode_fromIdentifier (/*@observer@*/ uentry c)
1005 if (context_justPopped ()) /* watch out! c could be dead */
1007 uentry ce = usymtab_lookupSafe (LastIdentifier ());
1009 if (uentry_isValid (ce))
1015 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
1019 ret = exprNode_fromIdentifierAux (c);
1024 static /*@only@*/ /*@notnull@*/ exprNode
1025 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
1027 exprNode e = exprNode_createId (c);
1030 uentry_setUsed (c, e->loc);
1032 if (uentry_isVar (c) && sRef_isFileOrGlobalScope (sr))
1034 checkGlobUse (c, FALSE, e);
1041 exprNode_isZero (exprNode e)
1043 if (exprNode_isDefined (e))
1045 multiVal m = exprNode_getValue (e);
1047 if (multiVal_isInt (m))
1049 return (multiVal_forceInt (m) == 0);
1057 exprNode_isNonNegative (exprNode e)
1059 if (exprNode_isDefined (e))
1061 multiVal m = exprNode_getValue (e);
1063 if (multiVal_isInt (m))
1065 return (multiVal_forceInt (m) >= 0);
1073 ** a[x] - uses a but NOT a[]
1074 ** result sref = a[] (set/use in assignment)
1076 ** The syntax x[a] is also legal in C, and has the same
1077 ** semantics. If ind is an array, and arr is an int, flip
1082 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
1085 ** error in arr, error propagates (no new messages)
1086 ** error in ind, assume valid and continue
1089 if (exprNode_isError (e1))
1092 return (exprNode_makeError ());
1098 ctype carr = exprNode_getType (e1);
1099 ctype crarr = ctype_realType (carr);
1102 ** this sets up funny aliasing, that leads to spurious
1103 ** lclint errors. Hence, the i2 comments.
1106 if (!ctype_isRealArray (crarr)
1107 && ctype_isRealNumeric (crarr)
1108 && !exprNode_isError (e2)
1109 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1114 carr = exprNode_getType (arr);
1115 crarr = ctype_realType (carr);
1123 if (sRef_possiblyNull (arr->sref))
1125 if (!usymtab_isGuarded (arr->sref))
1127 if (optgenerror (FLG_NULLDEREF,
1128 message ("Index of %s pointer %q: %s",
1129 sRef_nullMessage (arr->sref),
1130 sRef_unparse (arr->sref),
1131 exprNode_unparse (arr)),
1134 sRef_showNullInfo (arr->sref);
1136 /* suppress future messages */
1137 sRef_setNullError (arr->sref);
1142 if (exprNode_isError (ind))
1144 if ((ctype_isArrayPtr (crarr)
1145 && !ctype_isFunction (crarr))
1146 || ctype_isUnknown (carr))
1148 exprNode ret = exprNode_createPartialCopy (arr);
1150 if (ctype_isKnown (carr))
1152 ret->typ = ctype_baseArrayPtr (crarr);
1156 ret->typ = ctype_unknown;
1159 ret->sref = sRef_makeArrayFetch (arr->sref);
1161 ret->kind = XPR_FETCH;
1164 ** Because of funny aliasing (when arr and ind are
1165 ** flipped) spurious errors would be reported here.
1168 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1169 checkSafeUse (ret, arr->sref);
1174 voptgenerror (FLG_TYPE,
1175 message ("Array fetch from non-array (%t): %s[%s]", carr,
1176 exprNode_unparse (e1), exprNode_unparse (e2)),
1178 exprNode_free (arr);
1179 return (exprNode_makeError ());
1184 if (!ctype_isForceRealInt (&(ind->typ)))
1186 ctype rt = ctype_realType (ind->typ);
1188 if (ctype_isChar (rt))
1192 message ("Array fetch using non-integer, %t: %s[%s]",
1194 exprNode_unparse (e1), exprNode_unparse (e2)),
1197 else if (ctype_isEnum (rt))
1201 message ("Array fetch using non-integer, %t: %s[%s]",
1203 exprNode_unparse (e1), exprNode_unparse (e2)),
1210 message ("Array fetch using non-integer, %t: %s[%s]",
1212 exprNode_unparse (e1), exprNode_unparse (e2)),
1216 multiVal_free (ind->val);
1217 ind->val = multiVal_unknown ();
1220 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1222 exprNode ret = exprNode_createSemiCopy (arr);
1223 multiVal m = exprNode_getValue (ind);
1225 ret->typ = ctype_baseArrayPtr (crarr);
1226 ret->kind = XPR_FETCH;
1228 if (multiVal_isInt (m))
1230 int i = (int) multiVal_forceInt (m);
1232 if (sRef_isValid (arr->sref)) {
1233 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1235 ret->sref = sRef_undefined;
1240 ret->sref = sRef_makeArrayFetch (arr->sref);
1243 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1244 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1245 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1247 /* (see comment on spurious errors above) */
1248 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1250 exprNode_checkUse (ret, ind->sref, ind->loc);
1251 exprNode_checkUse (ret, arr->sref, arr->loc);
1257 if (ctype_isUnknown (carr))
1259 exprNode ret = exprNode_createPartialCopy (arr);
1261 ret->kind = XPR_FETCH;
1262 ret->typ = ctype_unknown;
1263 ret->sets = sRefSet_union (ret->sets, ind->sets);
1264 ret->msets = sRefSet_union (ret->msets, ind->msets);
1265 ret->uses = sRefSet_union (ret->uses, ind->uses);
1267 /* (see comment on spurious errors above) */
1268 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1270 exprNode_checkUse (ret, ind->sref, ind->loc);
1271 exprNode_checkUse (ret, arr->sref, arr->loc);
1278 message ("Array fetch from non-array (%t): %s[%s]", carr,
1279 exprNode_unparse (e1), exprNode_unparse (e2)),
1282 exprNode_free (arr);
1283 exprNode_free (ind);
1285 return (exprNode_makeError ());
1295 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1296 exprNodeList args, exprNode ret)
1298 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1302 ** checkPrintfArgs --- checks arguments for printf-like functions
1303 ** Arguments before ... have already been checked.
1304 ** The argument before the ... is a char *.
1305 ** argno is the format string argument.
1309 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1310 exprNodeList args, exprNode ret, int argno)
1313 ** the last argument before the elips is the format string
1318 int nargs = exprNodeList_size (args);
1319 uentryList params = uentry_getParams (fcn);
1323 ** These should be ensured by checkSpecialFunction
1326 llassert (uentryList_size (params) == argno + 1);
1327 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1329 a = exprNodeList_getN (args, argno - 1);
1330 formatloc = fileloc_copy (exprNode_loc (a));
1332 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1333 && exprNode_knownStringValue (a))
1335 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1336 char *code = format;
1339 nargs = exprNodeList_size (args);
1341 while ((code = strchr (code, '%')) != NULL)
1343 char *origcode = code;
1344 cstring codetext = cstring_newEmpty ();
1345 char key = *(++code);
1346 ctype modtype = ctype_int;
1347 bool modified = FALSE;
1349 fileloc_addColumn (formatloc, code - ocode);
1351 codetext = cstring_appendChar (codetext, key);
1354 while (isFlagKey (key))
1357 codetext = cstring_appendChar (codetext, key);
1358 fileloc_incColumn (formatloc);
1361 if (key == 'm') /* skipped in syslog */
1366 /* ignore field width */
1367 while (isdigit ((int) key) != 0)
1370 codetext = cstring_appendChar (codetext, key);
1371 fileloc_incColumn (formatloc);
1374 /* ignore precision */
1378 codetext = cstring_appendChar (codetext, key);
1379 fileloc_incColumn (formatloc);
1382 ** In printf, '*' means: read the next arg as an int for the
1383 ** field width. This seems to be missing from my copy of the
1384 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1385 ** later) but never does.
1390 ; /* don't do anything --- handle later */
1394 while (isdigit ((int) key) != 0)
1397 codetext = cstring_appendChar (codetext, key);
1398 fileloc_incColumn (formatloc);
1405 modtype = ctype_sint; /* short */
1407 codetext = cstring_appendChar (codetext, key);
1408 fileloc_incColumn (formatloc);
1410 else if (key == 'l' || key == 'L')
1412 modtype = ctype_lint; /* long */
1414 codetext = cstring_appendChar (codetext, key);
1415 fileloc_incColumn (formatloc);
1417 if (key == 'l' || key == 'L') {
1418 modtype = ctype_llint; /* long long */
1420 codetext = cstring_appendChar (codetext, key);
1421 fileloc_incColumn (formatloc);
1429 /* now, key = type of conversion to apply */
1431 fileloc_incColumn (formatloc);
1439 message ("No argument corresponding to %q format "
1440 "code %d (%%%s): \"%s\"",
1441 uentry_getName (fcn),
1443 cstring_fromChars (format)),
1446 if (fileloc_isDefined (formatloc)
1447 && context_getFlag (FLG_SHOWCOL))
1449 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1457 a = exprNodeList_getN (args, i);
1460 if (!exprNode_isError (a))
1466 case '*': /* int argument for fieldwidth */
1467 expecttype = ctype_int;
1468 *(--code) = '%'; /* convert it for next code */
1469 fileloc_subColumn (formatloc, 1);
1470 /*@switchbreak@*/ break;
1473 expecttype = ctype_combine (ctype_uint, modtype);
1474 /*@switchbreak@*/ break;
1476 case 'i': /* int argument */
1478 expecttype = ctype_combine (ctype_int, modtype);
1479 /*@switchbreak@*/ break;
1481 case 'x': /* unsigned int */
1483 expecttype = ctype_combine (ctype_uint, modtype);
1485 /*@switchbreak@*/ break;
1491 case 'f': /* double */
1492 expecttype = ctype_combine (ctype_double, modtype);
1493 /*@switchbreak@*/ break;
1495 case 'c': /* int converted to char (check its a char?) */
1496 expecttype = ctype_makeConj (ctype_char, ctype_uchar);
1497 /*@switchbreak@*/ break;
1499 case 's': /* string */
1500 expecttype = ctype_string;
1501 /*@switchbreak@*/ break;
1504 while (((key = *(++code)) != ']')
1507 codetext = cstring_appendChar (codetext, key);
1508 fileloc_incColumn (formatloc);
1514 (message ("Bad character set format: %s",
1515 cstring_fromChars (origcode)));
1518 expecttype = ctype_string;
1519 /*@switchbreak@*/ break;
1521 case 'p': /* pointer */
1522 expecttype = ctype_makePointer (ctype_void);
1523 uentry_setDefState (regArg, SS_RELDEF); /* need not be defined */
1524 sRef_setPosNull (uentry_getSref (regArg), fileloc_undefined); /* could be null */
1525 /*@switchbreak@*/ break;
1527 case 'n': /* pointer to int, modified by call! */
1528 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1530 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1531 /*@switchbreak@*/ break;
1533 case 'm': /* in a syslog, it doesn't consume an argument */
1534 /* should check we're really doing syslog */
1536 /*@switchbreak@*/ break;
1540 expecttype = ctype_unknown;
1544 message ("Unrecognized format code: %s",
1545 cstring_fromChars (origcode)),
1546 fileloc_isDefined (formatloc)
1547 ? formatloc : g_currentloc);
1549 /*@switchbreak@*/ break;
1552 if (!(exprNode_matchArgType (expecttype, a)))
1554 if (ctype_isVoidPointer (expecttype)
1555 && ctype_isRealAbstract (a->typ)
1556 && (context_getFlag (FLG_ABSTVOIDP)))
1562 if (llgenformattypeerror
1563 (expecttype, exprNode_undefined,
1565 message ("Format argument %d to %q (%%%s) expects "
1568 uentry_getName (fcn),
1571 a->typ, exprNode_unparse (a)),
1574 if (fileloc_isDefined (formatloc)
1575 && context_getFlag (FLG_SHOWCOL))
1578 (cstring_makeLiteral
1579 ("Corresponding format code"),
1586 uentry_setType (regArg, expecttype);
1587 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1589 if (ctype_equal (expecttype, ctype_string))
1591 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1594 uentry_setType (regArg, ctype_unknown);
1595 uentry_fixupSref (regArg);
1599 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1610 cstring_free (codetext);
1615 voptgenerror (FLG_TYPE,
1616 message ("Format string for %q has %d arg%&, given %d",
1617 uentry_getName (fcn), i - argno, nargs - argno),
1623 /* no checking possible for compile-time unknown format strings */
1624 if (exprNode_isDefined (a))
1628 message ("Format string parameter to %s is not a compile-time constant: %s",
1629 exprNode_unparse (f),
1630 exprNode_unparse (a)),
1635 fileloc_free (formatloc);
1639 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1640 exprNodeList args, exprNode ret, int argno)
1644 int nargs = exprNodeList_size (args);
1645 uentryList params = uentry_getParams (fcn);
1649 ** These should be ensured by checkSpecialFunction
1652 llassert (uentryList_size (params) == argno + 1);
1653 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1655 a = exprNodeList_getN (args, argno - 1);
1656 formatloc = fileloc_copy (exprNode_loc (a));
1658 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1659 && exprNode_knownStringValue (a))
1661 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1662 char *code = format;
1665 nargs = exprNodeList_size (args);
1667 while ((code = strchr (code, '%')) != NULL)
1669 char *origcode = code;
1670 char key = *(++code);
1671 cstring codetext = cstring_newEmpty ();
1672 ctype modtype = ctype_int;
1673 char modifier = '\0';
1674 bool modified = TRUE;
1675 bool ignore = FALSE;
1677 codetext = cstring_appendChar (codetext, key);
1678 fileloc_addColumn (formatloc, code - ocode);
1681 ** this is based on ANSI standard library description of fscanf
1682 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1685 /* '*' suppresses assignment (does not need match argument) */
1690 codetext = cstring_appendChar (codetext, key);
1693 fileloc_incColumn (formatloc);
1696 /* ignore field width */
1697 while (isdigit ((int) key) != 0)
1700 codetext = cstring_appendChar (codetext, key);
1701 fileloc_incColumn (formatloc);
1706 modtype = ctype_sint; /* short */
1708 codetext = cstring_appendChar (codetext, key);
1709 fileloc_incColumn (formatloc);
1711 else if (key == 'l' || key == 'L')
1713 modtype = ctype_lint; /* long */
1717 codetext = cstring_appendChar (codetext, key);
1719 fileloc_incColumn (formatloc);
1721 if (key == 'l' || key == 'L') {
1722 modtype = ctype_llint; /* long long */
1724 codetext = cstring_appendChar (codetext, key);
1725 fileloc_incColumn (formatloc);
1733 /* now, key = type of conversion to apply */
1735 fileloc_incColumn (formatloc);
1749 message ("No argument corresponding to %q format "
1750 "code %d (%%%s): \"%s\"",
1751 uentry_getName (fcn),
1753 cstring_fromChars (format)),
1756 if (fileloc_isDefined (formatloc)
1757 && context_getFlag (FLG_SHOWCOL))
1760 (cstring_makeLiteral ("Corresponding format code"),
1768 a = exprNodeList_getN (args, i);
1771 if (!exprNode_isError (a))
1777 case '*': /* int argument for fieldwidth */
1778 expecttype = ctype_makePointer (ctype_int);
1779 *(--code) = '%'; /* convert it for next code */
1780 fileloc_subColumn (formatloc, 1);
1781 /*@switchbreak@*/ break;
1784 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1785 /*@switchbreak@*/ break;
1790 case 'X': /* unsigned int */
1791 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1792 /*@switchbreak@*/ break;
1799 /* printf is double, scanf is float! */
1801 if (modifier == 'l')
1803 expecttype = ctype_makePointer (ctype_double);
1805 else if (modifier == 'L')
1807 expecttype = ctype_makePointer (ctype_ldouble);
1811 llassert (modifier == '\0');
1812 expecttype = ctype_makePointer (ctype_float);
1814 /*@switchbreak@*/ break;
1816 case 'c': /* int converted to char (check its a char?) */
1817 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1818 /*@switchbreak@*/ break;
1820 case 's': /* string */
1821 expecttype = ctype_string;
1822 /*@switchbreak@*/ break;
1826 while (((key = *(++code)) != ']')
1829 codetext = cstring_appendChar (codetext, key);
1830 fileloc_incColumn (formatloc);
1836 (message ("Bad character set format: %s",
1837 cstring_fromChars (origcode)));
1840 expecttype = ctype_string;
1841 /*@switchbreak@*/ break;
1844 case 'p': /* pointer */
1847 message ("Format code should not be used in scanf: %s",
1848 cstring_fromChars (origcode)),
1849 fileloc_isDefined (formatloc)
1850 ? formatloc : g_currentloc);
1852 expecttype = ctype_unknown;
1853 /*@switchbreak@*/ break;
1855 case 'n': /* pointer to int, modified by call! */
1856 expecttype = ctype_makePointer (ctype_int);
1857 /*@switchbreak@*/ break;
1860 expecttype = ctype_unknown;
1864 message ("Unrecognized format code: %s",
1865 cstring_fromChars (origcode)),
1866 fileloc_isDefined (formatloc)
1867 ? formatloc : g_currentloc);
1869 /*@switchbreak@*/ break;
1872 if (!(exprNode_matchArgType (expecttype, a)))
1874 if (ctype_isVoidPointer (expecttype)
1875 && ctype_isRealAbstract (a->typ)
1876 && (context_getFlag (FLG_ABSTVOIDP)))
1882 if (llgenformattypeerror
1883 (expecttype, exprNode_undefined,
1885 message ("Format argument %d to %q (%%%s) expects "
1888 uentry_getName (fcn),
1889 codetext, expecttype,
1890 a->typ, exprNode_unparse (a)),
1893 if (fileloc_isDefined (formatloc)
1894 && context_getFlag (FLG_SHOWCOL))
1897 (cstring_makeLiteral
1898 ("Corresponding format code"),
1905 uentry_setType (outArg, expecttype);
1906 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
1907 uentry_setType (outArg, ctype_unknown);
1908 uentry_fixupSref (outArg);
1912 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1917 /* a->sref = defref; */
1924 cstring_free (codetext);
1929 voptgenerror (FLG_TYPE,
1930 message ("Format string for %q has %d arg%&, given %d",
1931 uentry_getName (fcn), i - argno, nargs - argno),
1937 /* no checking possible for compile-time unknown format strings */
1940 fileloc_free (formatloc);
1944 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
1947 /*@unused@*/ int argno)
1950 ** the last argument before the elips is the format string
1953 int nargs = exprNodeList_size (args);
1958 a = exprNodeList_getN (args, argno - 1);
1959 formatloc = fileloc_copy (exprNode_loc (a));
1961 if (ctype_isUnknown (cstringType)) {
1962 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
1964 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
1968 if (ctype_isUnknown (ctypeType)) {
1969 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
1971 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
1975 if (ctype_isUnknown (filelocType)) {
1976 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
1978 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
1982 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1983 && exprNode_knownStringValue (a))
1985 cstring format = multiVal_forceString (exprNode_getValue (a));
1986 char *code = cstring_toCharsSafe (format);
1989 nargs = exprNodeList_size (args);
1991 while ((code = strchr (code, '%')) != NULL)
1993 char *origcode = code;
1994 char key = *(++code);
1995 cstring codetext = cstring_newEmpty ();
1996 bool isOnly = FALSE;
1998 codetext = cstring_appendChar (codetext, key);
2000 fileloc_addColumn (formatloc, code - ocode);
2002 while (key >= '0' && key <= '9')
2005 codetext = cstring_appendChar (codetext, key);
2006 fileloc_incColumn (formatloc);
2010 fileloc_incColumn (formatloc);
2014 if (key == '&') /* plural marker */
2023 message ("Message missing format arg %d (%%%s): \"%s\"",
2024 i + 1, codetext, format),
2030 a = exprNodeList_getN (args, i);
2034 if (!exprNode_isError (a))
2038 /*@-loopswitchbreak@*/
2044 expecttype = ctype_char; break;
2046 expecttype = cstringType; break;
2048 expecttype = cstringType; isOnly = TRUE; break;
2050 expecttype = cstringType; isOnly = TRUE; break;
2051 case 'd': expecttype = ctype_int; break;
2052 case 'u': expecttype = ctype_uint; break;
2053 case 'w': expecttype = ctype_ulint; break;
2054 case 'f': expecttype = ctype_float; break;
2055 case 'b': expecttype = ctype_bool; break;
2056 case 't': expecttype = ctypeType; break;
2057 case 'l': expecttype = filelocType; break;
2058 case '&': /* a wee bit of a hack methinks */
2059 expecttype = ctype_int;
2061 case 'r': expecttype = ctype_bool; break;
2063 expecttype = ctype_unknown;
2066 message ("Unrecognized format code: %s",
2067 cstring_fromChars (origcode)),
2068 fileloc_isDefined (formatloc)
2069 ? formatloc : g_currentloc);
2072 /*@=loopswitchbreak@*/
2074 if (!(exprNode_matchArgType (expecttype, a)))
2076 if (ctype_isVoidPointer (expecttype)
2077 && ctype_isRealAbstract (a->typ)
2078 && (context_getFlag (FLG_ABSTVOIDP)))
2084 if (llgenformattypeerror
2085 (expecttype, exprNode_undefined,
2087 message ("Format argument %d to %q (%%%s) expects "
2090 uentry_getName (fcn),
2091 codetext, expecttype,
2092 a->typ, exprNode_unparse (a)),
2095 if (fileloc_isDefined (formatloc)
2096 && context_getFlag (FLG_SHOWCOL))
2099 (cstring_makeLiteral
2100 ("Corresponding format code"),
2107 if (ctype_equal (expecttype, cstringType))
2111 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2112 uentry_fixupSref (csOnlyArg);
2116 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2117 uentry_fixupSref (csArg);
2122 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2123 uentry_fixupSref (regArg);
2129 cstring_free (codetext);
2134 voptgenerror (FLG_TYPE,
2135 message ("Format string for %q has %d arg%&, given %d",
2136 uentry_getName (fcn), i - argno, nargs -argno),
2142 /* no checking possible for compile-time unknown format strings */
2145 fileloc_free (formatloc);
2149 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2150 /*@notnull@*/ exprNode e2,
2156 bool hadUncon = FALSE;
2158 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
2159 sRefSet_hasUnconstrained (sets2))
2162 (FLG_EVALORDERUNCON,
2164 ("Expression may have undefined behavior (%q used in right operand "
2165 "may set global variable %q used in left operand): %s %s %s",
2166 sRefSet_unparseUnconstrained (sets2),
2167 sRef_unparse (sRef_getRootBase (e1->sref)),
2168 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2172 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
2173 sRefSet_hasUnconstrained (sets1))
2176 (FLG_EVALORDERUNCON,
2178 ("Expression has undefined behavior (%q used in left operand "
2179 "may set global variable %q used in right operand): %s %s %s",
2180 sRefSet_unparseUnconstrained (sets1),
2181 sRef_unparse (e2->sref),
2182 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2186 sRefSet_realElements (e1->uses, sr)
2188 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2193 ("Expression has undefined behavior (left operand uses %q, "
2194 "modified by right operand): %s %s %s",
2196 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2199 } end_sRefSet_realElements;
2201 sRefSet_realElements (sets1, sr)
2203 if (sRef_isMeaningful (sr))
2205 if (sRef_same (sr, e2->sref))
2210 ("Expression has undefined behavior (value of right operand "
2211 "modified by left operand): %s %s %s",
2212 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2215 else if (sRefSet_member (e2->uses, sr))
2220 ("Expression has undefined behavior (left operand modifies %q, "
2221 "used by right operand): %s %s %s",
2223 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2228 if (sRefSet_member (sets2, sr))
2230 if (sRef_isUnconstrained (sr))
2238 hadUncon = optgenerror
2239 (FLG_EVALORDERUNCON,
2241 ("Expression may have undefined behavior. Left operand "
2242 "calls %q; right operand calls %q. The unconstrained "
2243 "functions may modify global state used by "
2244 "the other operand): %s %s %s",
2245 sRefSet_unparseUnconstrained (sets1),
2246 sRefSet_unparseUnconstrained (sets2),
2247 exprNode_unparse (e1), lltok_unparse (op),
2248 exprNode_unparse (e2)),
2257 ("Expression has undefined behavior (both "
2258 "operands modify %q): %s %s %s",
2260 exprNode_unparse (e1),
2261 lltok_unparse (op), exprNode_unparse (e2)),
2267 } end_sRefSet_realElements;
2270 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2272 bool hasError = FALSE;
2274 if (exprNode_isError (e1) || exprNode_isError (e2))
2279 if (sRefSet_member (e2->sets, e1->sref))
2281 if (e2->kind == XPR_CALL)
2287 hasError = optgenerror
2289 message ("Expression has undefined behavior "
2290 "(value of left operand %s is modified "
2291 "by right operand %s): %s %s %s",
2292 exprNode_unparse (e1),
2293 exprNode_unparse (e2),
2294 exprNode_unparse (e1), lltok_unparse (op),
2295 exprNode_unparse (e2)),
2300 if (context_getFlag (FLG_EVALORDERUNCON))
2302 if (sRefSet_member (e2->msets, e1->sref))
2304 if (e2->kind == XPR_CALL)
2310 hasError = optgenerror
2313 ("Expression has undefined behavior (value of left "
2314 "operand may be modified by right operand): %s %s %s",
2315 exprNode_unparse (e1), lltok_unparse (op),
2316 exprNode_unparse (e2)),
2324 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2326 if (context_maybeSet (FLG_EVALORDERUNCON))
2328 checkExpressionDefinedAux (e1, e2, e1->msets,
2329 e2->msets, op, FLG_EVALORDERUNCON);
2334 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2337 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2338 exprNodeList args, bool isIter, exprNode ret)
2342 if (!exprNode_isError (f))
2344 if (!uentryList_isMissingParams (cl))
2346 int nargs = exprNodeList_size (args);
2347 int expectargs = uentryList_size (cl);
2351 if (expectargs == 0)
2359 message ("Iter %q invoked with %d args, "
2361 uentry_getName (fcn),
2369 message ("Function %s called with %d args, "
2371 exprNode_unparse (f), nargs),
2378 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2380 exprNodeList_reset (args);
2382 uentryList_elements (cl, current)
2384 ctype ct = uentry_getType (current);
2387 if (ctype_isElips (ct))
2390 ** do special checking for printf/scanf library functions
2392 ** this is kludgey code, just for handling the special case
2396 if (uentry_isPrintfLike (fcn))
2398 checkPrintfArgs (f, fcn, args, ret, i);
2401 else if (uentry_isScanfLike (fcn))
2403 checkScanfArgs (f, fcn, args, ret, i);
2406 else if (uentry_isMessageLike (fcn))
2408 checkMessageArgs (f, fcn, args, i);
2413 llassert (!uentry_isSpecialFunction (fcn));
2416 nargs = expectargs; /* avoid errors */
2421 if (i >= nargs) break;
2423 a = exprNodeList_current (args);
2424 exprNodeList_advance (args);
2428 if (exprNode_isError (a))
2435 probably necessary? I'm not sure about this one
2436 checkMacroParen (a);
2439 f->guards = guardSet_union (f->guards, a->guards);
2441 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2443 if (!(exprNode_matchArgType (ct, a)))
2445 DPRINTF (("Args mismatch!"));
2447 if (ctype_isVoidPointer (ct)
2448 && (ctype_isPointer (a->typ)
2449 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2454 ("Pointer to abstract type (%t) used "
2456 "(arg %d to %q): %s",
2458 uentry_getName (fcn),
2459 exprNode_unparse (a)),
2467 (ct, exprNode_undefined,
2470 ("Iter %q expects arg %d to "
2471 "be %t gets %t: %s",
2472 uentry_getName (fcn),
2473 i, ct, a->typ, exprNode_unparse (a)),
2484 ("Function %q expects arg %d to be %t gets %t: %s",
2485 uentry_getName (fcn),
2486 i, ct, a->typ, exprNode_unparse (a)),
2489 DPRINTF (("Types: %s / %s",
2491 ctype_unparse (a->typ)));
2495 ** Clear null marker for abstract types.
2496 ** (It is not revealed, so suppress future messages.)
2499 if (ctype_isAbstract (a->typ))
2501 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2508 } end_uentryList_elements ;
2511 if (expectargs != nargs) /* note: not != since we may have ... */
2513 if (ctype_isElips (last))
2517 message ("Function %s called with %d args, expects at least %d",
2518 exprNode_unparse (f),
2519 nargs, expectargs - 1),
2528 message ("Iter %q invoked with %d args, expects %d",
2529 uentry_getName (fcn), nargs, expectargs),
2536 message ("Function %s called with %d args, expects %d",
2537 exprNode_unparse (f),
2550 ** Check for undefined code sequences in function arguments:
2552 ** one parameter sets something used by another parameter
2553 ** one parameter sets something set by another parameter
2557 checkSequencingOne (exprNode f, exprNodeList args,
2558 /*@notnull@*/ exprNode el, int argno)
2561 ** Do second loop, iff +undefunspec
2565 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2567 for (checkloop = 0; checkloop < numloops; checkloop++)
2573 thissets = el->sets;
2577 llassert (checkloop == 1);
2578 thissets = el->msets;
2581 sRefSet_realElements (thissets, thisset)
2585 /*@access exprNodeList@*/
2586 for (j = 0; j < args->nelements; j++)
2588 exprNode jl = args->elements[j];
2589 int thisargno = j + 1;
2591 if (thisargno != argno && exprNode_isDefined (jl))
2593 sRefSet otheruses = jl->uses;
2595 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
2596 sRefSet_hasUnconstrained (thissets))
2599 (FLG_EVALORDERUNCON,
2602 ("%q used in argument %d may set "
2603 "global variable %q used by argument %d: %s(%q)",
2604 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2607 sRef_unparse (sRef_getRootBase (jl->sref)),
2609 exprNode_unparse (f), exprNodeList_unparse (args)),
2613 if (sRefSet_member (otheruses, thisset))
2615 if (sRef_isUnconstrained (thisset))
2618 (FLG_EVALORDERUNCON,
2620 ("Unconstrained functions used in arguments %d (%q) "
2621 "and %d (%s) may modify "
2622 "or use global state in undefined way: %s(%q)",
2624 sRefSet_unparseUnconstrainedPlain (otheruses),
2626 sRef_unconstrainedName (thisset),
2627 exprNode_unparse (f),
2628 exprNodeList_unparse (args)),
2636 ("Argument %d modifies %q, used by argument %d "
2637 "(order of evaluation of actual parameters is "
2638 "undefined): %s(%q)",
2639 argno, sRef_unparse (thisset), thisargno,
2640 exprNode_unparse (f), exprNodeList_unparse (args)),
2646 sRefSet othersets = jl->sets;
2648 if (sRefSet_member (othersets, thisset))
2650 if (sRef_isUnconstrained (thisset))
2653 (FLG_EVALORDERUNCON,
2655 ("Unconstrained functions used in "
2656 "arguments %d (%q) and %d (%s) may modify "
2657 "or use global state in undefined way: %s(%q)",
2659 sRefSet_unparseUnconstrainedPlain (othersets),
2661 sRef_unconstrainedName (thisset),
2662 exprNode_unparse (f), exprNodeList_unparse (args)),
2670 ("Argument %d modifies %q, set by argument %d (order of"
2671 " evaluation of actual parameters is undefined): %s(%q)",
2672 argno, sRef_unparse (thisset), thisargno,
2673 exprNode_unparse (f), exprNodeList_unparse (args)),
2680 /*@noaccess exprNodeList@*/
2681 } end_sRefSet_realElements;
2686 checkSequencing (exprNode f, exprNodeList args)
2688 if (exprNodeList_size (args) > 1)
2693 /*@access exprNodeList*/
2695 for (i = 0; i < args->nelements; i++)
2697 el = args->elements[i];
2699 if (!exprNode_isError (el))
2701 checkSequencingOne (f, args, el, i + 1);
2704 /*@noaccess exprNodeList*/
2709 ** requires le = exprNode_getUentry (f)
2713 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2714 uentry le, exprNodeList args,
2715 /*@notnull@*/ exprNode ret, int specialArgs)
2717 bool isSpec = FALSE;
2718 bool hasMods = FALSE;
2720 globSet usesGlobs = globSet_undefined;
2721 sRefSet mods = sRefSet_undefined;
2722 bool freshMods = FALSE;
2723 uentryList params = uentryList_undefined;
2725 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2728 ** check globals and modifies
2733 if (!uentry_isValid (le))
2735 ctype fr = ctype_realType (f->typ);
2737 if (ctype_isFunction (fr))
2739 params = ctype_argsFunction (fr);
2743 params = uentryList_missingParams;
2746 if (!context_getFlag (FLG_MODNOMODS)
2747 && !context_getFlag (FLG_GLOBUNSPEC))
2749 checkUnspecCall (f, params, args);
2755 fname = uentry_rawName (le);
2759 if (uentry_isFunction (le))
2761 params = uentry_getParams (le);
2762 mods = uentry_getMods (le);
2763 hasMods = uentry_hasMods (le);
2764 usesGlobs = uentry_getGlobs (le);
2765 isSpec = uentry_isSpecified (le);
2767 else /* not a function */
2769 ctype ct = ctype_realType (uentry_getType (le));
2771 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2772 ("checkModGlobs: uentry not a function: %s",
2773 uentry_unparse (le)));
2775 params = ctype_argsFunction (ct);
2776 return; /*@32 ! remove this? */
2785 globSet_allElements (usesGlobs, el)
2787 if (sRef_isValid (el))
2789 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2791 context_usedGlobal (el);
2792 exprNode_checkUse (f, el, f->loc);
2794 if (context_checkInternalUse ())
2796 if (!context_globAccess (el))
2798 if (sRef_isSystemState (el)
2799 && !context_getFlag (FLG_MODFILESYSTEM))
2808 ("Called procedure %s may access %q, but "
2809 "globals list does not include globals %s",
2810 exprNode_unparse (f),
2812 cstring_makeLiteralTemp (sRef_isInternalState (el)
2820 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2826 uentry gle = sRef_getUentry (el);
2827 sRef sr = sRef_updateSref (el);
2829 if (sRef_isUndefGlob (el))
2831 sRef_setDefined (sr, f->loc);
2832 exprNode_checkSet (f, sr);
2840 if (sRef_isAllocated (el))
2842 exprNode_checkSet (f, sr);
2846 if (sRef_isStateUndefined (sr))
2851 ("%s %q used by function undefined before call: %s",
2852 sRef_getScopeName (sr),
2854 exprNode_unparse (f)),
2856 sRef_setDefined (sr, f->loc);
2858 exprNode_checkUse (f, sr, f->loc);
2861 checkGlobUse (gle, TRUE, f);
2864 if (sRef_isKilledGlob (el))
2866 sRef_kill (sr, f->loc);
2867 context_usedGlobal (sr);
2871 } end_globSet_allElements;
2877 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
2879 sRefSet smods = sRefSet_undefined;
2882 ** NEED to check for modifies anything
2886 ** check each sRef that called function modifies (ml), is
2892 sRefSet_allElements (mods, s) /* s is something which may be modified */
2894 DPRINTF (("Check modify: %s", sRef_unparse (s)));
2896 if (sRef_isKindSpecial (s))
2898 if (sRef_isSpecInternalState (s))
2900 if (context_getFlag (FLG_MODINTERNALSTRICT))
2902 exprNode_checkCallModifyVal (s, args, f, ret);
2906 sRefSet mmods = context_modList ();
2908 sRefSet_allElements (mmods, el)
2910 if (sRef_isInternalState (el))
2912 sRef_setModified (el);
2914 } end_sRefSet_allElements ;
2919 exprNode_checkCallModifyVal (s, args, f, ret);
2924 sRef rb = sRef_getRootBase (s);
2926 if (sRef_isFileOrGlobalScope (rb))
2928 context_usedGlobal (rb);
2931 if (sRef_isFileStatic (s)
2932 && !fileId_equal (fileloc_fileId (f->loc),
2933 fileloc_fileId (uentry_whereDefined (le))))
2935 smods = sRefSet_insert (smods, s);
2939 exprNode_checkCallModifyVal (s, args, f, ret);
2942 } end_sRefSet_allElements;
2947 ** Static elements in modifies set can have nasty consequences.
2948 ** (I think...have not been able to reproduce a possible bug.)
2951 if (!sRefSet_isDefined (smods))
2953 mods = sRefSet_newCopy (mods);
2956 sRefSet_allElements (smods, el)
2958 bool res = sRefSet_delete (mods, el);
2961 } end_sRefSet_allElements;
2963 sRefSet_free (smods);
2968 else if (sRefSet_isDefined (mods))
2969 { /* just check observers */
2972 sRefSet_allElements (mods, s) /* s is something which may be modified */
2974 sRef rb = sRef_getRootBase (s);
2978 if (sRef_isParam (rb))
2980 sRef b = sRef_fixBaseParam (s, args);
2982 if (sRef_isObserver (b))
2984 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
2988 message ("Function call may modify observer%q: %s",
2989 sRef_unparsePreOpt (b), exprNode_unparse (e)),
2992 sRef_showExpInfo (b);
2996 } end_sRefSet_allElements;
3000 if (!hasMods) /* no specified modifications */
3002 if (context_getFlag (FLG_MODOBSERVERUNCON))
3004 exprNodeList_elements (args, e)
3006 if (exprNode_isDefined (e))
3008 sRef s = exprNode_getSref (e);
3010 if (sRef_isObserver (s)
3011 && ctype_isMutable (sRef_getType (s)))
3014 (FLG_MODOBSERVERUNCON,
3016 ("Call to unconstrained function %s may modify observer%q: %s",
3017 exprNode_unparse (f),
3018 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3021 sRef_showExpInfo (s);
3025 } end_exprNodeList_elements;
3030 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3032 ret->uses = sRefSet_union (ret->uses, f->uses);
3033 ret->sets = sRefSet_union (ret->sets, f->sets);
3034 ret->msets = sRefSet_union (ret->msets, f->msets);
3039 ** Spurious errors reported, because lclint can't tell
3040 ** mods must be fresh if freshMods is true.
3043 /*@i@*/ sRefSet_free (mods);
3049 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3051 if (uentry_isVar (glob))
3053 if (context_inFunctionLike ())
3055 sRef sr = uentry_getSref (glob);
3057 context_usedGlobal (sr);
3059 if (context_checkGlobUse (glob))
3061 if (!context_globAccess (sr))
3067 message ("Called procedure %s may access %s %q",
3068 exprNode_unparse (e),
3069 sRef_unparseScope (sr),
3070 uentry_getName (glob)),
3077 message ("Undocumented use of %s %s",
3078 sRef_unparseScope (sr),
3079 exprNode_unparse (e)),
3088 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3093 reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
3095 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3096 exprNode_unparse (f), exprNodeList_unparse (args),
3097 uentry_unparseFull (le),
3098 stateClauseList_unparse (uentry_getStateClauseList (le))));
3100 if (uentry_isValid (le) && uentry_isFunction (le))
3102 stateClauseList sclauses = uentry_getStateClauseList (le);
3104 if (stateClauseList_isDefined (sclauses))
3106 DPRINTF (("Reflect ensures: %s / %s / %s",
3107 uentry_unparse (le),
3108 exprNode_unparse (f), exprNodeList_unparse (args)));
3110 stateClauseList_elements (sclauses, cl)
3112 if (stateClause_hasEnsures (cl))
3114 /* Same in usymtab.c:1904 */
3115 if (stateClause_setsMetaState (cl))
3117 qual q = stateClause_getMetaQual (cl);
3118 annotationInfo ainfo = qual_getAnnotationInfo (q);
3119 metaStateInfo minfo = annotationInfo_getState (ainfo);
3120 cstring key = metaStateInfo_getName (minfo);
3121 int mvalue = annotationInfo_getValue (ainfo);
3123 sRefSet osrs = sRefSet_undefined;
3126 if (stateClause_isGlobal (cl))
3128 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3133 srs = stateClause_getRefs (cl);
3136 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3139 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3141 sRefSet_elements (srs, sel)
3145 if (sRef_isResult (sRef_getRootBase (sel)))
3147 s = exprNode_getSref (ret);
3151 s = sRef_fixBaseParam (sel, args);
3154 DPRINTF (("Reflecting state clause on: %s / %s",
3155 sRef_unparse (sel), sRef_unparse (s)));
3157 sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3158 } end_sRefSet_elements;
3160 sRefSet_free (osrs);
3164 sRefSet srs = stateClause_getRefs (cl);
3165 sRefModVal modf = stateClause_getEnsuresFunction (cl);
3166 int eparam = stateClause_getStateParameter (cl);
3168 DPRINTF (("Reflect after clause: %s / %s",
3169 stateClause_unparse (cl),
3170 sRefSet_unparse (srs)));
3172 sRefSet_elements (srs, sel)
3176 DPRINTF (("elements: %s", sRef_unparse (sel)));
3177 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3179 if (sRef_isResult (sRef_getRootBase (sel)))
3181 DPRINTF (("Fix base: %s / %s",
3182 sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
3183 s = sRef_fixBase (sel, exprNode_getSref (ret));
3184 DPRINTF (("==> %s", sRef_unparseFull (s)));
3188 s = sRef_fixBaseParam (sel, args);
3191 DPRINTF (("elements: %s", sRef_unparse (s)));
3192 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3194 DPRINTF (("Reflecting state clause on: %s / %s",
3195 sRef_unparse (sel), sRef_unparse (s)));
3197 modf (s, eparam, exprNode_loc (f));
3198 } end_sRefSet_elements;
3201 } end_stateClauseList_elements ;
3204 DPRINTF (("Here: %s / %s",
3205 uentry_unparseFull (le),
3206 bool_unparse (uentry_hasMetaStateEnsures (le))));
3208 if (uentry_hasMetaStateEnsures (le))
3210 fileloc loc = exprNode_loc (f);
3212 metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3214 metaStateConstraintList_elements (mscl, msc)
3216 metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3217 metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3218 metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
3219 cstring key = metaStateInfo_getName (msinfo);
3220 sRef mlsr = metaStateSpecifier_getSref (msspec);
3222 sRef lastref = sRef_undefined;
3223 stateValue sval = stateValue_undefined;
3225 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3226 metaStateConstraint_unparse (msc)));
3227 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3229 if (sRef_isResult (sRef_getRootBase (mlsr)))
3231 s = exprNode_getSref (ret);
3235 s = sRef_fixBaseParam (mlsr, args);
3238 DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3240 while (metaStateExpression_isDefined (msexpr))
3242 metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
3243 metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
3246 DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3248 if (metaStateExpression_isMerge (msexpr))
3250 msexpr = metaStateExpression_getRest (msexpr);
3254 msexpr = metaStateExpression_undefined;
3257 if (metaStateInfo_isDefined (msi))
3259 /* Must match lhs state */
3260 llassert (metaStateInfo_equal (msinfo, msi));
3263 if (metaStateSpecifier_isElipsis (ms))
3266 ** For elipsis, we need to merge all the relevant elipsis parameters
3270 uentryList params = uentry_getParams (le);
3271 int paramno = uentryList_size (params) - 1;
3273 if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
3277 message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3278 uentry_getName (le)),
3279 uentry_whereLast (le));
3280 /*@innerbreak@*/ break;
3283 while (paramno < exprNodeList_size (args))
3285 exprNode arg = exprNodeList_getN (args, paramno);
3286 fs = exprNode_getSref (arg);
3287 DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3289 /* cut and pasted... gack*/
3290 if (stateValue_isDefined (sval))
3292 /* Use combination table to merge old state value with new one: */
3293 stateValue tval = sRef_getMetaStateValue (fs, key);
3295 if (stateValue_isDefined (tval))
3297 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3298 cstring msg = cstring_undefined;
3299 int nval = stateCombinationTable_lookup (sctable,
3300 stateValue_getValue (sval),
3301 stateValue_getValue (tval),
3303 DPRINTF (("Combining: %s + %s -> %d",
3304 stateValue_unparseValue (sval, msinfo),
3305 stateValue_unparseValue (tval, msinfo),
3308 if (nval == stateValue_error)
3310 llassert (cstring_isDefined (msg));
3315 ("Attributes merged in ensures clause in states that "
3316 "cannot be combined (%q is %q, %q is %q): %s",
3317 sRef_unparse (lastref),
3318 stateValue_unparseValue (sval, msinfo),
3320 stateValue_unparseValue (tval, msinfo),
3324 sRef_showMetaStateInfo (fs, key);
3328 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3329 loc = exprNode_loc (arg);
3333 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3338 sval = sRef_getMetaStateValue (fs, key);
3343 if (stateValue_isError (sval))
3345 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3354 msr = metaStateSpecifier_getSref (ms);
3357 llassert (sRef_isParam (sRef_getRootBase (msr)));
3358 fs = sRef_fixBaseParam (msr, args);
3360 if (stateValue_isDefined (sval))
3362 /* Use combination table to merge old state value with new one: */
3363 stateValue tval = sRef_getMetaStateValue (fs, key);
3365 if (stateValue_isDefined (tval))
3367 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3368 cstring msg = cstring_undefined;
3369 int nval = stateCombinationTable_lookup (sctable,
3370 stateValue_getValue (sval),
3371 stateValue_getValue (tval),
3373 DPRINTF (("Combining: %s + %s -> %d",
3374 stateValue_unparseValue (sval, msinfo),
3375 stateValue_unparseValue (tval, msinfo),
3378 if (nval == stateValue_error)
3380 llassert (cstring_isDefined (msg));
3385 ("Attributes merged in ensures clause in states that "
3386 "cannot be combined (%q is %q, %q is %q): %s",
3387 sRef_unparse (lastref),
3388 stateValue_unparseValue (sval, msinfo),
3390 stateValue_unparseValue (tval, msinfo),
3394 sRef_showMetaStateInfo (fs, key);
3398 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3402 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3407 sval = sRef_getMetaStateValue (fs, key);
3412 if (stateValue_isError (sval))
3414 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3419 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3421 if (stateValue_isDefined (sval))
3423 sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
3427 DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
3429 } end_metaStateConstraintList_elements ;
3431 metaStateConstraintList_free (mscl);
3437 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3439 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3440 exprNode_unparse (f), exprNodeList_unparse (args),
3441 uentry_unparseFull (le),
3442 stateClauseList_unparse (uentry_getStateClauseList (le))));
3444 if (uentry_isValid (le) && uentry_isFunction (le))
3446 stateClauseList sclauses = uentry_getStateClauseList (le);
3448 if (stateClauseList_isDefined (sclauses))
3450 DPRINTF (("Check requires: %s / %s / %s",
3451 uentry_unparse (le),
3452 exprNode_unparse (f), exprNodeList_unparse (args)));
3454 stateClauseList_elements (sclauses, cl)
3456 DPRINTF (("Check clause: %s / %s",
3457 stateClause_unparse (cl),
3458 bool_unparse (stateClause_hasRequires (cl))));
3460 if (stateClause_hasRequires (cl))
3462 sRefSet osrs = sRefSet_undefined;
3465 if (stateClause_isGlobal (cl))
3467 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3472 srs = stateClause_getRefs (cl);
3475 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3477 if (stateClause_setsMetaState (cl))
3479 qual q = stateClause_getMetaQual (cl);
3480 annotationInfo ainfo = qual_getAnnotationInfo (q);
3481 metaStateInfo minfo = annotationInfo_getState (ainfo);
3482 cstring key = metaStateInfo_getName (minfo);
3483 int mvalue = annotationInfo_getValue (ainfo);
3485 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3487 sRefSet_elements (srs, sel)
3489 sRef s = sRef_fixBaseParam (sel, args);
3491 if (sRef_isResult (sRef_getRootBase (sel)))
3497 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3498 sRef_unparseFull (sel), sRef_unparseFull (s),
3501 if (!sRef_checkMetaStateValue (s, key, mvalue))
3503 DPRINTF (("HERE: %s", sRef_unparse (s)));
3507 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3508 uentry_getName (le),
3509 sRef_isGlobalMarker (s)
3511 : message (" by %q", sRef_unparse (s)),
3512 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3514 stateClause_unparse (cl)),
3517 sRef_showAliasInfo (s);
3521 DPRINTF (("Error supressed!"));
3522 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3523 DPRINTF (("Context supress: %s",
3524 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3528 } end_sRefSet_elements;
3532 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3533 int eparam = stateClause_getStateParameter (cl);
3535 DPRINTF (("Reflect after clause: %s / %s",
3536 stateClause_unparse (cl),
3537 sRefSet_unparse (srs)));
3539 sRefSet_elements (srs, sel)
3543 DPRINTF (("elements: %s", sRef_unparse (sel)));
3544 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3546 s = sRef_fixBaseParam (sel, args);
3548 DPRINTF (("elements: %s", sRef_unparse (s)));
3549 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3551 if (sRef_isResult (sRef_getRootBase (sel)))
3553 ; /*@i423 what do we do about results */
3557 DPRINTF (("Reflecting state clause on: %s / %s",
3558 sRef_unparse (sel), sRef_unparse (s)));
3560 modf (s, eparam, exprNode_loc (f));
3562 } end_sRefSet_elements;
3565 sRefSet_free (osrs);
3567 } end_stateClauseList_elements ;
3572 static /*@only@*/ exprNode
3573 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3574 ctype t, /*@keep@*/ exprNodeList args)
3576 /* requires f is a non-error exprNode, with type function */
3577 cstring fname = exprNode_unparse (f);
3578 uentry le = exprNode_getUentry (f);
3579 exprNode ret = exprNode_createPartialCopy (f);
3584 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3586 ret->typ = ctype_getReturnType (t);
3587 ret->kind = XPR_CALL;
3589 ret->edata = exprData_makeCall (f, args);
3592 ** Order of these steps is very important!
3594 ** Must check for argument dependencies before messing up uses and sets.
3597 if (context_getFlag (FLG_EVALORDER))
3599 exprNodeList_elements (args, current)
3601 if (exprNode_isDefined (current))
3603 exprNode_addUse (current, current->sref);
3605 } end_exprNodeList_elements;
3607 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3609 checkSequencing (f, args);
3612 exprNodeList_elements (args, current)
3614 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3616 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3618 } end_exprNodeList_elements ;
3621 special = checkArgs (le, f, t, args, ret);
3622 checkGlobMods (f, le, args, ret, special);
3623 checkRequiresClause (le, f, args);
3626 if (uentry_isValid (le)
3627 && (uentry_isFunction (le)
3628 || (uentry_isVariable (le)
3629 && ctype_isFunction (uentry_getType (le)))))
3631 exitkind exk = uentry_getExitCode (le);
3633 /* f->typ is already set to the return type */
3635 DPRINTF (("Function: %s", uentry_unparseFull (le)));
3636 ret->sref = uentry_returnedRef (le, args);
3637 DPRINTF (("Returned: %s / %s",
3638 uentry_unparseFull (le),
3639 sRef_unparseFull (ret->sref)));
3641 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3643 qual nullPred = uentry_nullPred (le);
3645 if (qual_isTrueNull (nullPred))
3647 exprNode arg = exprNodeList_head (args);
3649 if (exprNode_isDefined (arg))
3651 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3654 else if (qual_isFalseNull (nullPred))
3656 exprNode arg = exprNodeList_head (args);
3658 if (exprNode_isDefined (arg))
3660 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3665 llassert (qual_isUnknown (nullPred));
3669 if (exitkind_isConditionalExit (exk))
3673 ** if (arg0) then { exit! } else { ; }
3675 ** if (arg0) then { ; } else { exit! }
3680 llassert (!exprNodeList_isEmpty (args));
3681 firstArg = exprNodeList_head (args);
3683 if (exprNode_isDefined (firstArg)
3684 && !guardSet_isEmpty (firstArg->guards))
3686 usymtab_trueBranch (guardSet_undefined);
3687 usymtab_altBranch (guardSet_undefined);
3689 if (exitkind_isTrueExit (exk))
3691 usymtab_popBranches (firstArg,
3692 exprNode_makeMustExit (),
3694 TRUE, TRUEEXITCLAUSE);
3698 usymtab_popBranches (firstArg,
3700 exprNode_makeMustExit (),
3701 TRUE, FALSEEXITCLAUSE);
3705 ret->exitCode = XK_MAYEXIT;
3707 else if (exitkind_mustExit (exk))
3709 ret->exitCode = XK_MUSTEXIT;
3711 else if (exitkind_couldExit (exk))
3713 ret->exitCode = XK_MAYEXIT;
3720 if (cstring_equalLit (fname, "exit"))
3722 if (exprNodeList_size (args) == 1)
3724 exprNode arg = exprNodeList_head (args);
3726 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3728 long int val = multiVal_forceInt (exprNode_getValue (arg));
3735 ("Argument to exit has implementation defined behavior: %s",
3736 exprNode_unparse (arg)),
3737 exprNode_loc (arg));
3746 exprNode_checkSetAny (ret, uentry_rawName (le));
3749 DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3750 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3751 reflectEnsuresClause (ret, le, f, args);
3758 ** this is yucky! should keep the uentry as part of exprNode!
3761 uentry exprNode_getUentry (exprNode e)
3763 if (exprNode_isError (e))
3765 return uentry_undefined;
3769 cstring s = exprNode_rootVarName (e);
3770 uentry ue = usymtab_lookupSafe (s);
3777 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3779 exprNode ret = exprNode_createPlain (ctype_unknown);
3781 ret->kind = XPR_INITBLOCK;
3782 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3783 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3789 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3795 if (exprNode_isUndefined (f))
3798 exprNodeList_free (args);
3799 return exprNode_undefined;
3802 t = exprNode_getType (f);
3804 if (sRef_isLocalVar (f->sref))
3806 exprNode_checkUse (f, f->sref, f->loc);
3808 if (sRef_possiblyNull (f->sref))
3810 if (!usymtab_isGuarded (f->sref))
3812 if (optgenerror (FLG_NULLDEREF,
3813 message ("Function call using %s pointer %q",
3814 sRef_nullMessage (f->sref),
3815 sRef_unparse (f->sref)),
3818 sRef_showNullInfo (f->sref);
3819 sRef_setNullError (f->sref);
3827 if (ctype_isRealFunction (t))
3829 exprNode ret = functionCallSafe (f, t, args);
3833 else if (ctype_isUnknown (t))
3835 exprNode ret = exprNode_createPartialCopy (f);
3841 exprNodeList_elements (args, current)
3843 if (exprNode_isDefined (current))
3845 exprNode_checkUse (ret, current->sref, ret->loc);
3848 ** also, anything derivable from current->sref may be used
3851 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3852 exprNode_mergeUSs (ret, current);
3854 } end_exprNodeList_elements;
3856 ret->edata = exprData_makeCall (f, args);
3857 ret->kind = XPR_CALL;
3859 tstring = cstring_copy (exprNode_unparse (f));
3861 cstring_markOwned (tstring);
3862 exprNode_checkSetAny (ret, tstring);
3868 voptgenerror (FLG_TYPE,
3869 message ("Call to non-function (type %t): %s", t,
3870 exprNode_unparse (f)),
3873 exprNodeList_free (args);
3875 return (exprNode_makeError ());
3880 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
3881 /*@only@*/ cstring f)
3883 exprNode ret = exprNode_createPartialCopy (s);
3885 ret->kind = XPR_FACCESS;
3887 if (exprNode_isError (s))
3889 ret->edata = exprData_makeField (s, f);
3894 ctype t = exprNode_getType (s);
3895 ctype tr = ctype_realType (t);
3897 checkMacroParen (s);
3899 ret->edata = exprData_makeField (s, f);
3901 if (ctype_isStructorUnion (tr))
3903 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
3905 if (uentry_isUndefined (tf))
3907 voptgenerror (FLG_TYPE,
3908 message ("Access non-existent field %s of %t: %s", f, t,
3909 exprNode_unparse (ret)),
3911 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
3916 uentry_setUsed (tf, exprNode_loc (ret));
3918 ret->typ = uentry_getType (tf);
3919 checkSafeUse (ret, s->sref);
3921 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
3922 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
3926 else /* isStructorUnion */
3928 if (ctype_isRealAbstract (tr))
3932 message ("Access field of abstract type (%t): %s.%s",
3933 t, exprNode_unparse (s), f),
3935 ret->typ = ctype_unknown;
3939 if (ctype_isKnown (tr))
3944 ("Access field of non-struct or union (%t): %s.%s",
3945 t, exprNode_unparse (s), f),
3948 ret->typ = ctype_unknown;
3952 cstring sn = cstring_copy (f);
3954 checkSafeUse (ret, s->sref);
3955 cstring_markOwned (sn);
3956 ret->sref = sRef_makeField (s->sref, sn);
3968 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
3969 /*@only@*/ cstring f)
3971 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
3972 lltok_release (dot);
3977 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
3979 exprNode ret = exprNode_createPartialCopy (e);
3981 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
3982 ret->kind = XPR_PARENS;
3983 ret->edata = exprData_makeUop (e, lpar);
3985 if (!exprNode_isError (e))
3987 ret->exitCode = e->exitCode;
3988 ret->canBreak = e->canBreak;
3989 ret->mustBreak = e->mustBreak;
3990 ret->isJumpPoint = e->isJumpPoint;
3991 ret->sref = e->sref;
3998 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
3999 /*@only@*/ cstring f)
4001 exprNode ret = exprNode_createPartialCopy (s);
4003 ret->edata = exprData_makeField (s, f);
4004 ret->kind = XPR_ARROW;
4006 if (exprNode_isError (s))
4012 ctype t = exprNode_getType (s);
4013 ctype tr = ctype_realType (t);
4015 checkMacroParen (s);
4017 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4019 if (ctype_isRealPointer (tr))
4021 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4023 if (ctype_isStructorUnion (b))
4025 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4027 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4029 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4033 message ("Arrow access from %s pointer%q: %s",
4034 sRef_nullMessage (s->sref),
4035 sRef_unparsePreOpt (s->sref),
4036 exprNode_unparse (ret)),
4039 sRef_showNullInfo (s->sref);
4040 sRef_setNullError (s->sref);
4045 if (uentry_isUndefined (fentry))
4049 message ("Access non-existent field %s of %t: %s",
4050 f, t, exprNode_unparse (ret)),
4052 ret->typ = ctype_unknown;
4058 ** was safeUse: shouldn't be safe!
4061 ** rec must be defined,
4062 ** *rec must be allocated
4063 ** rec->field need only be defined it if is an rvalue
4066 uentry_setUsed (fentry, exprNode_loc (ret));
4067 ret->typ = uentry_getType (fentry);
4069 exprNode_checkUse (ret, s->sref, s->loc);
4071 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4072 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4076 else /* Pointer to something that is not a struct or union*/
4078 if (ctype_isRealAbstract (tr))
4080 ctype xrt = ctype_forceRealType (tr);
4084 message ("Arrow access field of abstract type (%t): %s->%s",
4085 t, exprNode_unparse (s), f),
4089 ** Set the state correctly, as if the abstraction is broken.
4092 if (ctype_isRealPointer (xrt) &&
4093 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4094 ctype_isStructorUnion (b)))
4096 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4097 ret->typ = uentry_getType (fentry);
4098 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4102 ret->typ = ctype_unknown;
4103 ret->sref = sRef_undefined;
4106 else /* not a struct, union or abstract */
4108 if (ctype_isUnknown (tr)) {
4109 cstring sn = cstring_copy (f);
4111 DPRINTF (("Here: %s", exprNode_unparse (s)));
4113 exprNode_checkUse (ret, s->sref, s->loc);
4114 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4116 cstring_markOwned (sn);
4117 ret->sref = sRef_makeArrow (s->sref, sn);
4119 ret->kind = XPR_ARROW;
4124 message ("Arrow access field of non-struct or union "
4125 "pointer (%t): %s->%s",
4126 t, exprNode_unparse (s), f),
4129 ret->typ = ctype_unknown;
4130 ret->sref = sRef_undefined;
4135 else /* its not a pointer */
4137 if (!ctype_isUnknown (tr))
4141 message ("Arrow access of non-pointer (%t): %s->%s",
4142 t, exprNode_unparse (s), f),
4145 ret->typ = ctype_unknown;
4146 ret->sref = sRef_undefined;
4150 cstring sn = cstring_copy (f);
4152 DPRINTF (("Here: %s", exprNode_unparse (s)));
4154 exprNode_checkUse (ret, s->sref, s->loc);
4155 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4157 cstring_markOwned (sn);
4158 ret->sref = sRef_makeArrow (s->sref, sn);
4160 ret->kind = XPR_ARROW;
4171 exprNode_arrowAccess (/*@only@*/ exprNode s,
4172 /*@only@*/ lltok arrow,
4173 /*@only@*/ cstring f)
4175 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4176 lltok_release (arrow);
4181 ** only postOp's in C: i++ and i--
4185 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4187 /* check modification also */
4188 /* cstring opname = lltok_unparse (op);*/
4190 exprNode ret = exprNode_createPartialCopy (e);
4192 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4193 ret->kind = XPR_POSTOP;
4194 ret->edata = exprData_makeUop (e, op);
4196 if (!exprNode_isDefined (e))
4201 checkMacroParen (e);
4203 exprNode_checkUse (ret, e->sref, e->loc);
4204 exprNode_checkSet (ret, e->sref);
4206 t = exprNode_getType (e);
4208 if (sRef_isUnsafe (e->sref))
4210 voptgenerror (FLG_MACROPARAMS,
4211 message ("Operand of %s is macro parameter (non-functional): %s%s",
4212 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4214 sRef_makeSafe (e->sref);
4215 sRef_makeSafe (ret->sref);
4218 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4224 if (ctype_isRealAbstract (t))
4228 message ("Operand of %s is abstract type (%t): %s",
4229 lltok_unparse (op), t, exprNode_unparse (e)),
4236 message ("Operand of %s is non-numeric (%t): %s",
4237 lltok_unparse (op), t, exprNode_unparse (e)),
4240 ret->typ = ctype_unknown;
4243 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4245 exprNode_checkModify (e, ret);
4247 /* added 7/11/2000 D.L */
4249 /*DRL 6/8/01 I decided to disable all LCLint Warning here since the code
4250 probably needs a rewrite any way */
4254 // updateEnvironmentForPostOp (e);
4256 /* start modifications */
4257 /* added by Seejo on 4/16/2000 */
4259 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4261 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4263 ret->sref = sRef_copy (e->sref);
4266 if (lltok_getTok (op) == INC_OP) {
4267 if (sRef_getSize(e->sref) > 0) {
4269 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4271 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4272 /* Assumption: there is only 1 \0 in the buffer */
4273 /* This will not be correct if there are 2 \0's in the buffer */
4274 sRef_setNotNullTerminatedState(ret->sref);
4275 sRef_resetLen(ret->sref);
4277 sRef_setNullTerminatedState(ret->sref);
4278 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4280 if (sRef_isNullTerminated (ret->sref))
4281 printf ("ret->sref is Null Terminated\n");
4282 else if (sRef_isPossiblyNullTerminated (ret->sref))
4283 printf ("ret->sref is Possibly Null Terminated\n");
4284 else if (sRef_isNotNullTerminated (ret->sref))
4285 printf ("ret->sref is Not Null Terminated\n");
4290 if (lltok_getTok (op) == DEC_OP) {
4291 if (sRef_getSize(e->sref) >= 0) {
4292 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4293 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4298 /* end modifications */
4304 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4306 bool checkMod = FALSE;
4308 int opid = lltok_getTok (op);
4309 exprNode ret = exprNode_createSemiCopy (e);
4311 exprNode_copySets (ret, e);
4313 multiVal_free (ret->val);
4314 ret->val = multiVal_undefined;
4315 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4316 ret->kind = XPR_PREOP;
4317 ret->edata = exprData_makeUop (e, op);
4319 if (exprNode_isError (e))
4324 checkMacroParen (e);
4326 te = exprNode_getType (e);
4327 tr = ctype_realType (te);
4329 if (opid != TAMPERSAND)
4331 exprNode_checkUse (ret, e->sref, e->loc);
4333 if (ctype_isRealAbstract (tr)
4334 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4336 if (optgenerror (FLG_ABSTRACT,
4337 message ("Operand of %s is abstract type (%t): %s",
4338 lltok_unparse (op), tr,
4339 exprNode_unparse (ret)),
4342 tr = te = ctype_unknown;
4343 ret->typ = ctype_unknown;
4344 sRef_setNullError (e->sref);
4352 case DEC_OP: /* should also check modification! */
4353 if (sRef_isMacroParamRef (e->sref))
4357 message ("Operand of %s is macro parameter (non-functional): %s",
4358 lltok_unparse (op), exprNode_unparse (ret)),
4363 exprNode_checkSet (ret, e->sref);
4366 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4371 if (context_msgStrictOps ())
4375 message ("Operand of %s is non-numeric (%t): %s",
4376 lltok_unparse (op), te, exprNode_unparse (ret)),
4379 ret->typ = ctype_int;
4382 /* start modifications */
4383 /* added by Seejo on 4/16/2000 */
4385 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4387 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4389 ret->sref = sRef_copy (e->sref);
4392 if (lltok_getTok (op) == INC_OP) {
4393 if (sRef_getSize(e->sref) > 0) {
4395 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4397 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4398 /* Assumption: there is only 1 \0 in the buffer */
4399 /* This will not be correct if there are 2 \0's in the buffer */
4400 sRef_setNotNullTerminatedState(ret->sref);
4401 sRef_resetLen (ret->sref);
4403 sRef_setNullTerminatedState(ret->sref);
4404 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4410 if (lltok_getTok (op) == DEC_OP) {
4411 if (sRef_getSize(e->sref) >= 0) {
4412 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4413 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4418 /* end modifications */
4425 if (ctype_isForceRealNumeric (&tr))
4429 ret->val = multiVal_invert (exprNode_getValue (e));
4433 ret->val = multiVal_copy (exprNode_getValue (e));
4438 if (context_msgStrictOps ())
4442 message ("Operand of %s is non-numeric (%t): %s",
4443 lltok_unparse (op), te, exprNode_unparse (ret)),
4447 ret->typ = ctype_int;
4451 case TEXCL: /* maybe this should be restricted */
4452 guardSet_flip (ret->guards);
4454 if (ctype_isRealBool (te) || ctype_isUnknown (te))
4460 if (ctype_isRealPointer (tr))
4462 if (sRef_isKnown (e->sref))
4464 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4468 (FLG_BOOLOPS, FLG_PTRNEGATE,
4469 message ("Operand of %s is non-boolean (%t): %s",
4470 lltok_unparse (op), te, exprNode_unparse (ret)),
4477 message ("Operand of %s is non-boolean (%t): %s",
4478 lltok_unparse (op), te, exprNode_unparse (ret)),
4482 ret->typ = ctype_bool;
4487 if (ctype_isForceRealInt (&tr))
4492 if (context_msgStrictOps ())
4496 message ("Operand of %s is non-integer (%t): %s",
4497 lltok_unparse (op), te, exprNode_unparse (ret)),
4501 if (ctype_isInt (e->typ))
4507 ret->typ = ctype_int;
4513 ret->typ = ctype_makePointer (e->typ);
4515 if (sRef_isKnown (e->sref))
4517 ret->sref = sRef_makeAddress (e->sref);
4524 if (ctype_isAP (tr))
4526 ret->typ = ctype_baseArrayPtr (e->typ);
4530 if (ctype_isKnown (te))
4532 if (ctype_isFunction (te))
4538 message ("Dereference of function type (%t): %s",
4539 te, exprNode_unparse (ret)),
4544 voptgenerror (FLG_TYPE,
4545 message ("Dereference of non-pointer (%t): %s",
4546 te, exprNode_unparse (ret)),
4548 ret->typ = ctype_unknown;
4553 ret->typ = ctype_unknown;
4558 if (sRef_isKnown (e->sref))
4560 if (sRef_possiblyNull (e->sref))
4562 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4566 message ("Dereference of %s pointer %q: %s",
4567 sRef_nullMessage (e->sref),
4568 sRef_unparse (e->sref),
4569 exprNode_unparse (ret)),
4572 sRef_showNullInfo (e->sref);
4573 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4578 ret->sref = sRef_makePointer (e->sref);
4583 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4588 exprNode_checkModify (e, ret);
4595 ** any reason to disallow sizeof (abstract type) ?
4599 ** used by both sizeof
4603 ctype sizeof_resultType (void)
4605 static ctype sizet = ctype_unknown;
4607 if (ctype_isUnknown (sizet))
4609 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4611 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4615 sizet = ctype_ulint;
4622 exprNode_sizeofType (/*@only@*/ qtype qt)
4624 exprNode ret = exprNode_create (sizeof_resultType ());
4625 ctype ct = qtype_getType (qt);
4627 ret->kind = XPR_SIZEOFT;
4628 ret->edata = exprData_makeSizeofType (qt);
4630 voptgenerror (FLG_SIZEOFTYPE,
4631 message ("Parameter to sizeof is type %s: %s",
4633 exprNode_unparse (ret)),
4640 exprNode_alignofType (/*@only@*/ qtype qt)
4642 exprNode ret = exprNode_create (sizeof_resultType ());
4643 ctype ct = qtype_getType (qt);
4645 ret->kind = XPR_ALIGNOFT;
4646 ret->edata = exprData_makeSizeofType (qt);
4648 voptgenerror (FLG_SIZEOFTYPE,
4649 message ("Parameter to alignof is type %s: %s",
4651 exprNode_unparse (ret)),
4657 exprNode exprNode_offsetof (qtype qt, cstringList s)
4659 exprNode ret = exprNode_create (sizeof_resultType ());
4660 ctype ct = qtype_getType (qt);
4662 ret->kind = XPR_OFFSETOF;
4663 ret->edata = exprData_makeOffsetof (qt, s);
4665 if (!ctype_isRealSU (ct))
4667 voptgenerror (FLG_TYPE,
4668 message ("First parameter to offsetof is not a "
4669 "struct or union type (type %s): %s",
4671 exprNode_unparse (ret)),
4678 cstringList_elements (s, el) {
4682 if (ctype_isUndefined (lt))
4686 else if (!ctype_isRealSU (lt))
4688 voptgenerror (FLG_TYPE,
4689 message ("Inner offsetof type is not a "
4690 "struct or union type (type %s before field %s): %s",
4691 ctype_unparse (lt), el,
4692 exprNode_unparse (ret)),
4698 fields = ctype_getFields (ctype_realType (lt));
4699 fld = uentryList_lookupField (fields, el);
4700 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4702 if (uentry_isUndefined (fld))
4704 if (ctype_equal (lt, ct)) {
4705 voptgenerror (FLG_TYPE,
4706 message ("Field %s in offsetof is not the "
4707 "name of a field of %s: %s",
4710 exprNode_unparse (ret)),
4713 voptgenerror (FLG_TYPE,
4714 message ("Deep field %s in offsetof is not the "
4715 "name of a field of %s: %s",
4718 exprNode_unparse (ret)),
4724 lt = uentry_getType (fld);
4727 } end_cstringList_elements;
4729 /* Should report error if its a bit field - behavior is undefined! */
4736 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4740 if (exprNode_isUndefined (e))
4742 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4743 ret->edata = exprData_makeSingle (e);
4744 ret->typ = sizeof_resultType ();
4745 ret->kind = XPR_SIZEOF;
4749 uentry u = exprNode_getUentry (e);
4751 ret = exprNode_createPartialCopy (e);
4752 ret->edata = exprData_makeSingle (e);
4754 ret->typ = sizeof_resultType ();
4755 ret->kind = XPR_SIZEOF;
4757 if (uentry_isValid (u)
4758 && uentry_isRefParam (u)
4759 && ctype_isRealArray (uentry_getType (u)))
4762 (FLG_SIZEOFFORMALARRAY,
4763 message ("Parameter to sizeof is an array-type function parameter: %s",
4764 exprNode_unparse (ret)),
4770 ** sizeof (x) doesn't "really" use x
4777 exprNode_alignofExpr (/*@only@*/ exprNode e)
4781 if (exprNode_isUndefined (e))
4783 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4787 ret = exprNode_createPartialCopy (e);
4790 ret->edata = exprData_makeSingle (e);
4791 ret->typ = sizeof_resultType ();
4792 ret->kind = XPR_ALIGNOF;
4795 ** sizeof (x) doesn't "really" use x
4802 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4808 if (exprNode_isError (e))
4811 lltok_release (tok);
4812 return exprNode_undefined;
4815 checkMacroParen (e);
4817 c = qtype_getType (q);
4818 t = exprNode_getType (e);
4820 ret = exprNode_createPartialCopy (e);
4822 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4824 ret->kind = XPR_CAST;
4825 ret->edata = exprData_makeCast (tok, e, q);
4827 if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
4830 ** This is a bit of a hack to avoid a problem
4831 ** when the code does,
4832 ** (some other struct) x
4837 ret->sref = sRef_copy (e->sref);
4838 usymtab_addForceMustAlias (ret->sref, e->sref);
4839 sRef_setTypeFull (ret->sref, c);
4840 DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
4841 sRef_unparseFull (ret->sref)));
4845 ret->sref = e->sref;
4846 sRef_setTypeFull (ret->sref, c);
4847 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
4854 ** void * <-> abstract * (if FLG_ABSTVOIDP)
4855 ** abstract * <-> void * (if FLG_ABSTVOIDP)
4858 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
4862 else if (ctype_isRealAP (c)) /* casting to array or pointer */
4864 ctype bc = ctype_getBaseType (c);
4865 ctype bt = ctype_getBaseType (t);
4866 ctype rt = ctype_realType (t);
4868 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
4869 && (ctype_isArrayPtr (rt)
4870 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4874 message ("Cast from function pointer type (%t) to "
4875 "non-function pointer (%t): %s",
4876 c, t, exprNode_unparse (ret)),
4880 if (!ctype_isFunction (ctype_baseArrayPtr (c))
4881 && (ctype_isArrayPtr (rt)
4882 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4886 message ("Cast from non-function pointer type (%t) to "
4887 "function pointer (%t): %s",
4888 c, t, exprNode_unparse (ret)),
4892 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
4893 !(ctype_isRealAbstract (bc)
4894 && context_hasAccess (ctype_typeId (bc))))
4896 ; /* okay to cast zero */
4900 if (ctype_isRealAbstract (bc)
4901 && !context_hasAccess (ctype_typeId (bc)))
4903 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
4907 message ("Cast to underlying abstract type %t: %s",
4908 c, exprNode_unparse (ret)),
4915 message ("Cast to underlying abstract type %t: %s",
4916 c, exprNode_unparse (ret)),
4921 if (ctype_isRealAbstract (bt)
4922 && !context_hasAccess (ctype_typeId (bt)))
4924 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
4928 message ("Cast from underlying abstract type %t: %s",
4929 t, exprNode_unparse (ret)),
4936 message ("Cast from underlying abstract type %t: %s",
4937 t, exprNode_unparse (ret)),
4945 ctype bt = ctype_realType (ctype_getBaseType (t));
4946 ctype bc = ctype_realType (ctype_getBaseType (c));
4948 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
4950 if (ctype_match (c, t))
4952 if (ctype_equal (c, t))
4956 message ("Redundant cast involving abstract type %t: %s",
4957 bt, exprNode_unparse (ret)),
4965 message ("Cast from abstract type %t: %s",
4966 bt, exprNode_unparse (ret)),
4971 if (ctype_isAbstract (bc)
4972 && !context_hasAccess (ctype_typeId (bc)))
4974 if (ctype_match (c, t))
4980 DPRINTF (("No access to: %s / %d",
4981 ctype_unparse (bc), ctype_typeId (bc)));
4982 DPRINTF (("Context %s %s",
4983 bool_unparse (context_inFunctionLike ()),
4984 context_unparse ()));
4987 message ("Cast to abstract type %t: %s", bc,
4988 exprNode_unparse (ret)),
4994 if (ctype_isAbstract (c))
4996 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
4998 /* okay, cast exposed to abstract */
4999 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
5003 if (ctype_isVisiblySharable (t)
5004 && sRef_isExternallyVisible (e->sref)
5005 && !(ctype_isAbstract (t)
5006 && context_hasAccess (ctype_typeId (t))))
5010 message ("Cast to abstract type from externally visible "
5011 "mutable storage exposes rep of %s: %s",
5013 exprNode_unparse (e)),
5023 evaluationOrderUndefined (lltok op)
5025 int opid = lltok_getTok (op);
5027 return (opid != AND_OP && opid != OR_OP);
5030 static bool checkIntegral (/*@notnull@*/ exprNode e1,
5031 /*@notnull@*/ exprNode e2,
5032 /*@notnull@*/ exprNode ret,
5037 ctype te1 = exprNode_getType (e1);
5038 ctype te2 = exprNode_getType (e2);
5040 ctype tr1 = ctype_realishType (te1);
5041 ctype tr2 = ctype_realishType (te2);
5043 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5049 if (context_msgStrictOps ())
5051 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5053 if (ctype_sameName (te1, te2))
5057 message ("Operands of %s are non-integer (%t): %s",
5058 lltok_unparse (op), te1,
5059 exprNode_unparse (ret)),
5066 message ("Operands of %s are non-integers (%t, %t): %s",
5067 lltok_unparse (op), te1, te2,
5068 exprNode_unparse (ret)),
5072 else if (!ctype_isInt (tr1))
5076 message ("Left operand of %s is non-integer (%t): %s",
5077 lltok_unparse (op), te1, exprNode_unparse (ret)),
5081 /* !ctype_isInt (te2) */
5085 message ("Right operand of %s is non-integer (%t): %s",
5086 lltok_unparse (op), te2, exprNode_unparse (ret)),
5096 ** returns exprNode representing e1 op e2
5098 ** uses msg if there are errors
5099 ** can be used for both assignment ops and regular ops
5104 static /*@only@*/ /*@notnull@*/ exprNode
5105 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
5106 /*@keep@*/ lltok op)
5108 ctype te1, te2, tr1, tr2, tret;
5109 int opid = lltok_getTok (op);
5110 bool hasError = FALSE;
5113 if (exprNode_isError (e1))
5115 ret = exprNode_createPartialNVCopy (e2);
5119 ret = exprNode_createPartialNVCopy (e1);
5122 ret->val = multiVal_undefined;
5124 ret->edata = exprData_makeOp (e1, e2, op);
5126 if (exprNode_isError (e1) || exprNode_isError (e2))
5128 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5129 || opid == EQ_OP || opid == NE_OP
5130 || opid == AND_OP || opid == OR_OP)
5132 ret->typ = ctype_bool;
5135 if (exprNode_isDefined (e1))
5137 exprNode_checkUse (ret, e1->sref, e1->loc);
5140 if (exprNode_isDefined (e2))
5142 exprNode_mergeUSs (ret, e2);
5143 exprNode_checkUse (ret, e2->sref, e2->loc);
5149 tret = ctype_unknown;
5150 te1 = exprNode_getType (e1);
5151 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5153 te2 = exprNode_getType (e2);
5155 tr1 = ctype_realishType (te1);
5156 tr2 = ctype_realishType (te2);
5160 ret->guards = guardSet_or (ret->guards, e2->guards);
5162 else if (opid == AND_OP)
5164 ret->guards = guardSet_and (ret->guards, e2->guards);
5171 if (opid == EQ_OP || opid == NE_OP)
5173 exprNode temp1 = e1, temp2 = e2;
5175 /* could do NULL == x */
5177 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5179 temp1 = e2; temp2 = e1;
5182 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5184 reflectNullTest (temp1, (opid == NE_OP));
5185 guardSet_free (ret->guards);
5186 ret->guards = guardSet_copy (temp1->guards);
5190 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5191 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5196 if (anyAbstract (tr1, tr2) &&
5197 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
5198 (opid == AND_OP || opid == OR_OP
5199 || opid == EQ_OP || opid == NE_OP))))
5201 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
5203 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5205 /* unknown types, no comparisons possible */
5211 case TMULT: /* multiplication and division: */
5213 case MUL_ASSIGN: /* numeric, numeric -> numeric */
5214 case DIV_ASSIGN: /* */
5216 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5219 case TPLUS: /* addition and subtraction: */
5220 case TMINUS: /* pointer, int -> pointer */
5221 case SUB_ASSIGN: /* int, pointer -> pointer */
5222 case ADD_ASSIGN: /* numeric, numeric -> numeric */
5224 tr1 = ctype_fixArrayPtr (tr1);
5226 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5227 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5231 if (context_msgPointerArith ())
5235 message ("Pointer arithmetic (%t, %t): %s",
5236 te1, te2, exprNode_unparse (ret)),
5241 ** Swap terms so e1 is always the pointer
5244 if (ctype_isRealPointer (tr1))
5250 exprNode_swap (e1, e2);
5254 if (sRef_possiblyNull (e1->sref)
5255 && !usymtab_isGuarded (e1->sref))
5258 (FLG_NULLPOINTERARITH,
5259 message ("Pointer arithmetic involving possibly "
5260 "null pointer %s: %s",
5261 exprNode_unparse (e1),
5262 exprNode_unparse (ret)),
5266 ret->sref = sRef_copy (e1->sref);
5268 /* start modifications */
5269 /* added by Seejo on 4/16/2000 */
5271 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5273 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5274 //if (sRef_isKnown (e->sref)) {
5275 //ret->sref = sRef_makeAddress (e->sref);
5280 added ugly fixed to stop
5281 program from crashing on point + int +int
5282 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5284 if (!multiVal_isInt (e2->val) )
5288 val = (int) multiVal_forceInt (e2->val);
5290 /* Operator : + or += */
5291 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5292 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5293 val should not result in a
5294 size < 0 (size = 0 is ok !) */
5296 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5298 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5299 sRef_setNotNullTerminatedState(ret->sref);
5300 sRef_resetLen (ret->sref);
5302 sRef_setNullTerminatedState(ret->sref);
5303 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5308 /* Operator : - or -= */
5309 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5310 if (sRef_getSize(e1->sref) >= 0) {
5311 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5312 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5317 /* end modifications */
5319 sRef_setNullError (ret->sref);
5322 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5323 ** since is points to storage that should not be deallocated
5324 ** through this pointer.
5327 if (sRef_isOnly (ret->sref)
5328 || sRef_isFresh (ret->sref))
5330 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5335 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5336 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5338 if (context_msgPointerArith ())
5342 message ("Pointer arithmetic (%t, %t): %s",
5343 te1, te2, exprNode_unparse (ret)),
5347 if (sRef_possiblyNull (e1->sref)
5348 && !usymtab_isGuarded (e1->sref))
5351 (FLG_NULLPOINTERARITH,
5352 message ("Pointer arithmetic involving possibly "
5353 "null pointer %s: %s",
5354 exprNode_unparse (e2),
5355 exprNode_unparse (ret)),
5359 ret->sref = sRef_copy (e2->sref);
5361 /* start modifications */
5362 /* added by Seejo on 4/16/2000 */
5364 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5367 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5368 //if (sRef_isKnown (e->sref)) {
5369 //ret->sref = sRef_makeAddress (e->sref);
5372 int val = (int) multiVal_forceInt (e1->val);
5374 /* Operator : + or += */
5375 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5376 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5377 val should not result in a
5378 size < 0 (size = 0 is ok !) */
5380 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5382 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5383 sRef_setNotNullTerminatedState(ret->sref);
5384 sRef_resetLen (ret->sref);
5386 sRef_setNullTerminatedState(ret->sref);
5387 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5392 /* Operator : - or -= */
5393 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5394 if (sRef_getSize(e2->sref) >= 0) {
5395 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5396 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5401 /* end modifications */
5403 sRef_setNullError (ret->sref);
5406 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5407 ** since is points to storage that should not be deallocated
5408 ** through this pointer.
5411 if (sRef_isOnly (ret->sref)
5412 || sRef_isFresh (ret->sref)) {
5413 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5417 ret->sref = e2->sref;
5421 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5426 case LEFT_ASSIGN: /* Shifts: should be unsigned values */
5430 case TAMPERSAND: /* bitwise & */
5432 case TCIRC: /* ^ (XOR) */
5437 bool reported = FALSE;
5438 flagcode code = FLG_BITWISEOPS;
5440 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5441 || opid == RIGHT_OP || opid == RIGHT_ASSIGN) {
5442 code = FLG_SHIFTSIGNED;
5445 if (!ctype_isUnsigned (tr1))
5447 if (exprNode_isNonNegative (e1)) {
5450 reported = optgenerror
5452 message ("Left operand of %s is not unsigned value (%t): %s",
5453 lltok_unparse (op), te1,
5454 exprNode_unparse (ret)),
5464 /* right need not be signed for shifts */
5465 if (code != FLG_SHIFTSIGNED
5466 && !ctype_isUnsigned (tr2))
5468 if (!exprNode_isNonNegative (e2)) {
5469 reported = optgenerror
5471 message ("Right operand of %s is not unsigned value (%t): %s",
5472 lltok_unparse (op), te2,
5473 exprNode_unparse (ret)),
5481 if (!checkIntegral (e1, e2, ret, op)) {
5482 te1 = ctype_unknown;
5486 DPRINTF (("Set: %s", ctype_unparse (te1)));
5489 ** tret is the widest type of te1 and te2
5492 tret = ctype_widest (te1, te2);
5497 if (checkIntegral (e1, e2, ret, op)) {
5500 tret = ctype_unknown;
5505 case TLT: /* comparisons */
5506 case TGT: /* numeric, numeric -> bool */
5507 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5508 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5511 bool fepsilon = FALSE;
5513 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5518 if (opid == TLT || opid == TGT)
5520 uentry ue1 = exprNode_getUentry (e1);
5521 uentry ue2 = exprNode_getUentry (e2);
5524 ** FLT_EPSILON, etc. really is a variable, not
5528 if (uentry_isVariable (ue1))
5530 cstring uname = uentry_rawName (ue1);
5532 if (cstring_equalLit (uname, "FLT_EPSILON")
5533 || cstring_equalLit (uname, "DBL_EPSILON")
5534 || cstring_equalLit (uname, "LDBL_EPSILON"))
5540 if (uentry_isVariable (ue2))
5542 cstring uname = uentry_rawName (ue2);
5544 if (cstring_equalLit (uname, "FLT_EPSILON")
5545 || cstring_equalLit (uname, "DBL_EPSILON")
5546 || cstring_equalLit (uname, "LDBL_EPSILON"))
5555 ; /* Don't complain. */
5561 message ("Dangerous comparison involving %s types: %s",
5562 ctype_unparse (rtype),
5563 exprNode_unparse (ret)),
5572 ** Types should match.
5575 if (!exprNode_matchTypes (e1, e2))
5577 hasError = gentypeerror
5579 message ("Operands of %s have incompatible types (%t, %t): %s",
5580 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5586 || (ctype_isForceRealNumeric (&tr1)
5587 && ctype_isForceRealNumeric (&tr2)) ||
5588 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5594 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5595 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5599 message ("Comparison of pointer and numeric (%t, %t): %s",
5600 te1, te2, exprNode_unparse (ret)),
5605 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5610 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5612 if ((opid == EQ_OP || opid == NE_OP) &&
5613 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5616 ** is one a variable?
5619 if (uentry_isVariable (exprNode_getUentry (e1))
5620 || uentry_isVariable (exprNode_getUentry (e2)))
5623 ** comparisons with FALSE are okay
5626 if (exprNode_isFalseConstant (e1)
5627 || exprNode_isFalseConstant (e2))
5636 ("Use of %q with %s variables (risks inconsistency because "
5637 "of multiple true values): %s",
5638 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5639 context_printBoolName (), exprNode_unparse (ret)),
5646 case AND_OP: /* bool, bool -> bool */
5649 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5655 if (context_maybeSet (FLG_BOOLOPS))
5657 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5659 if (ctype_sameName (te1, te2))
5663 message ("Operands of %s are non-boolean (%t): %s",
5664 lltok_unparse (op), te1,
5665 exprNode_unparse (ret)),
5673 ("Operands of %s are non-booleans (%t, %t): %s",
5674 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5678 else if (!ctype_isRealBool (te1))
5682 message ("Left operand of %s is non-boolean (%t): %s",
5683 lltok_unparse (op), te1, exprNode_unparse (ret)),
5686 else if (!ctype_isRealBool (te2))
5690 message ("Right operand of %s is non-boolean (%t): %s",
5691 lltok_unparse (op), te2, exprNode_unparse (ret)),
5704 (cstring_makeLiteral
5705 ("There has been a problem in the parser. This is believed to result "
5706 "from a problem with bison v. 1.25. Please try rebuidling LCLint "
5707 "using the pre-compiled grammar files by commenting out the "
5708 "BISON= line in the top-level Makefile."));
5713 DPRINTF (("Return type: %s", ctype_unparse (tret)));
5716 exprNode_checkUse (ret, e1->sref, e1->loc);
5717 exprNode_mergeUSs (ret, e2);
5718 exprNode_checkUse (ret, e2->sref, e2->loc);
5724 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5725 /*@only@*/ lltok op)
5729 checkMacroParen (e1);
5730 checkMacroParen (e2);
5732 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5734 checkExpressionDefined (e1, e2, op);
5737 ret = exprNode_makeOp (e1, e2, op);
5742 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5745 ** This is somewhat bogus!
5747 ** Assigning to a nested observer in a non-observer datatype
5748 ** should not produce an error.
5751 sRef ref = exprNode_getSref (e1);
5753 DPRINTF (("Check assign mod: %s",
5754 sRef_unparseFull (ref)));
5756 if (sRef_isObserver (ref)
5757 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
5758 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5760 sRef base = sRef_getBase (ref);
5762 if (sRef_isValid (base) && sRef_isObserver (base))
5764 exprNode_checkModify (e1, ret);
5768 exprNode_checkModifyVal (e1, ret);
5773 exprNode_checkModify (e1, ret);
5778 exprNode_assign (/*@only@*/ exprNode e1,
5779 /*@only@*/ exprNode e2, /*@only@*/ lltok op)
5781 bool isalloc = FALSE;
5782 bool isjustalloc = FALSE;
5785 DPRINTF (("%s [%s] <- %s [%s]",
5786 exprNode_unparse (e1),
5787 ctype_unparse (e1->typ),
5788 exprNode_unparse (e2),
5789 ctype_unparse (e2->typ)));
5791 if (lltok_getTok (op) != TASSIGN)
5793 ret = exprNode_makeOp (e1, e2, op);
5797 ret = exprNode_createPartialCopy (e1);
5798 ret->kind = XPR_ASSIGN;
5799 ret->edata = exprData_makeOp (e1, e2, op);
5801 if (!exprNode_isError (e2))
5803 ret->sets = sRefSet_union (ret->sets, e2->sets);
5804 ret->msets = sRefSet_union (ret->msets, e2->msets);
5805 ret->uses = sRefSet_union (ret->uses, e2->uses);
5809 checkExpressionDefined (e1, e2, op);
5811 if (exprNode_isError (e1))
5813 if (!exprNode_isError (e2))
5815 ret->loc = fileloc_update (ret->loc, e2->loc);
5819 ret->loc = fileloc_update (ret->loc, g_currentloc);
5823 if (!exprNode_isError (e2))
5825 checkMacroParen (e2);
5828 if (exprNode_isDefined (e1))
5830 if (sRef_isMacroParamRef (e1->sref))
5832 if (context_inIterDef ())
5834 uentry ue = sRef_getUentry (e1->sref);
5836 if (uentry_isYield (ue))
5842 if (fileloc_isDefined (e1->loc))
5846 message ("Assignment to non-yield iter parameter: %q",
5847 sRef_unparse (e1->sref)),
5854 message ("Assignment to non-yield iter parameter: %q",
5855 sRef_unparse (e1->sref)),
5862 if (fileloc_isDefined (e1->loc))
5866 message ("Assignment to macro parameter: %q",
5867 sRef_unparse (e1->sref)),
5874 message ("Assignment to macro parameter: %q",
5875 sRef_unparse (e1->sref)),
5879 exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
5884 exprNode_checkAssignMod (e1, ret);
5887 if (exprNode_isDefined (e2))
5889 if (lltok_getTok (op) == TASSIGN)
5891 ctype te1 = exprNode_getType (e1);
5892 ctype te2 = exprNode_getType (e2);
5894 if (!ctype_forceMatch (te1, te2))
5896 if (exprNode_matchLiteral (te1, e2))
5904 message ("Assignment of %t to %t: %s %s %s",
5905 te2, te1, exprNode_unparse (e1),
5907 exprNode_unparse (e2)),
5913 exprNode_mergeUSs (ret, e2);
5914 exprNode_checkUse (ret, e2->sref, e2->loc);
5916 doAssign (e1, e2, FALSE);
5917 ret->sref = e1->sref;
5921 if (exprNode_isDefined (e2))
5923 exprNode_mergeUSs (ret, e2);
5924 exprNode_checkUse (ret, e2->sref, e2->loc);
5928 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
5930 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
5933 isjustalloc = sRef_isJustAllocated (e1->sref);
5934 isalloc = sRef_isAllocated (e1->sref);
5936 if (sRef_isField (e1->sref))
5938 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
5940 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
5942 exprNode_checkUse (ret, root, e1->loc);
5948 ** be careful! this defines e1->sref.
5951 /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
5953 exprNode_checkSet (ret, e1->sref);
5957 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
5958 ? e2->loc : e1->loc);
5964 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
5973 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
5974 /*@keep@*/ exprNode elseclause)
5978 if (!exprNode_isError (pred))
5980 ret = exprNode_createPartialCopy (pred);
5981 checkMacroParen (pred);
5982 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
5984 if (!exprNode_isError (ifclause))
5986 checkMacroParen (ifclause); /* update macro counts! */
5988 if (!exprNode_isError (elseclause))
5990 checkMacroParen (elseclause);
5992 if (!exprNode_matchTypes (ifclause, elseclause))
5995 (exprNode_getType (ifclause),
5997 exprNode_getType (elseclause),
5999 message ("Conditional clauses are not of same type: "
6001 exprNode_unparse (ifclause),
6002 exprNode_getType (ifclause),
6003 exprNode_unparse (elseclause),
6004 exprNode_getType (elseclause)),
6007 ret->sref = sRef_undefined;
6008 ret->typ = ctype_unknown;
6013 /* for now...should merge the states */
6014 ret->sref = ifclause->sref;
6015 ret->typ = ifclause->typ;
6017 if (exprNode_isNullValue (ifclause))
6019 ret->typ = elseclause->typ;
6023 exprNode_checkUse (ret, pred->sref, pred->loc);
6024 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6025 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6027 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6032 ret->typ = ifclause->typ;
6034 exprNode_checkUse (pred, pred->sref, pred->loc);
6035 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6037 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6042 if (!exprNode_isError (elseclause))
6044 ret->typ = elseclause->typ;
6046 exprNode_checkUse (pred, pred->sref, pred->loc);
6047 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6049 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6053 else /* pred is error */
6055 if (!exprNode_isError (ifclause))
6057 ret = exprNode_createSemiCopy (ifclause);
6059 checkMacroParen (ifclause); /* update macro counts! */
6061 if (!exprNode_isError (elseclause))
6063 checkMacroParen (elseclause);
6065 ret->typ = ifclause->typ;
6067 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6070 (exprNode_getType (ifclause),
6072 exprNode_getType (elseclause),
6074 message ("Conditional clauses are not of same type: "
6076 exprNode_unparse (ifclause),
6077 exprNode_getType (ifclause),
6078 exprNode_unparse (elseclause),
6079 exprNode_getType (elseclause)),
6082 ret->typ = ctype_unknown;
6086 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6087 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6089 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6092 else if (!exprNode_isError (elseclause)) /* pred, if errors */
6094 ret = exprNode_createSemiCopy (ifclause);
6096 ret->typ = elseclause->typ;
6097 checkMacroParen (elseclause);
6099 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6100 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6102 else /* all errors! */
6104 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6108 ret->kind = XPR_COND;
6109 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
6111 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6113 exprNode_combineControl (ret, ifclause, elseclause);
6120 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6122 ctype totype = qtype_getType (qt);
6124 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6128 ** check use of va_arg : <valist>, type -> type
6131 if (exprNode_isError (arg))
6136 targ = exprNode_getType (arg);
6139 ** arg should have be a pointer
6142 if (!ctype_isUA (targ) ||
6143 (!usymId_equal (ctype_typeId (targ),
6144 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6148 message ("First argument to va_arg is not a va_list (type %t): %s",
6149 targ, exprNode_unparse (arg)),
6153 exprNode_checkSet (ret, arg->sref);
6157 ** return type is totype
6161 ret->kind = XPR_VAARG;
6162 ret->edata = exprData_makeCast (tok, arg, qt);
6167 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6169 exprNode ret = exprNode_createPlain (ctype_undefined);
6170 ret->kind = XPR_LABEL;
6171 ret->edata = exprData_makeLiteral (label);
6172 ret->isJumpPoint = TRUE;
6174 return (ret); /* for now, ignore label */
6177 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6179 if (exprNode_isDefined (stmt))
6181 stmt->isJumpPoint = TRUE;
6183 /* This prevent stray no return path errors, etc. */
6184 stmt->exitCode = XK_MUSTEXIT;
6190 bool exprNode_isDefaultMarker (exprNode e)
6192 if (exprNode_isDefined (e))
6194 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6200 bool exprNode_isCaseMarker (exprNode e)
6202 if (exprNode_isDefined (e))
6204 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6210 bool exprNode_isLabelMarker (exprNode e)
6212 if (exprNode_isDefined (e))
6214 return (e->kind == XPR_LABEL);
6220 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6222 exprNode ret = exprNode_createPartialCopy (test);
6224 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6226 if (exprNode_isError (test)) {
6230 exprNode_checkUse (ret, test->sref, test->loc);
6232 usymtab_setExitCode (ret->exitCode);
6236 usymtab_setMustBreak ();
6239 ret->edata = exprData_makeSingle (test);
6240 ret->isJumpPoint = TRUE;
6246 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6248 exprNode ret = exprNode_createPartialCopy (test);
6250 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6251 ret->edata = exprData_makePair (test, stmt);
6252 ret->isJumpPoint = TRUE;
6254 if (exprNode_isError (test))
6259 exprNode_checkUse (ret, test->sref, test->loc);
6261 if (exprNode_isError (stmt))
6266 exprNode_mergeUSs (ret, stmt);
6268 ret->exitCode = stmt->exitCode;
6269 ret->mustBreak = stmt->mustBreak;
6270 ret->canBreak = stmt->canBreak;
6272 usymtab_setExitCode (ret->exitCode);
6276 usymtab_setMustBreak ();
6283 /*@notnull@*/ /*@only@*/ exprNode
6284 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6286 exprNode ret = exprNode_createTok (def);
6288 ret->isJumpPoint = TRUE;
6289 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6294 exprNode_mayEscape (exprNode e)
6296 if (exprNode_isDefined (e))
6298 return exitkind_couldEscape (e->exitCode);
6304 exprNode_mustBreak (exprNode e)
6306 if (exprNode_isDefined (e))
6308 return e->mustBreak;
6314 exprNode_mustEscape (exprNode e)
6316 if (exprNode_isDefined (e))
6318 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6325 exprNode_errorEscape (exprNode e)
6327 if (exprNode_isDefined (e))
6329 return exitkind_isError (e->exitCode);
6335 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6337 exprNode ret = exprNode_createPartialCopy (e1);
6339 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6341 ret->edata = exprData_makePair (e1, e2);
6342 ret->kind = XPR_STMTLIST;
6344 if (exprNode_isDefined (e1))
6346 ret->isJumpPoint = e1->isJumpPoint;
6347 ret->canBreak = e1->canBreak;
6351 if (exprNode_isDefined (e2))
6353 ret->loc = fileloc_update (ret->loc, e2->loc);
6357 if (exprNode_isDefined (e2))
6359 ret->exitCode = e2->exitCode;
6360 ret->mustBreak = e2->mustBreak;
6361 if (e2->canBreak) ret->canBreak = TRUE;
6365 ** if e1 must return, then e2 is unreachable!
6368 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6370 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6371 && !(e2->isJumpPoint))
6373 if (context_getFlag (FLG_UNREACHABLE))
6377 if (e2->kind == XPR_STMT)
6379 nr = exprData_getUopNode (e2->edata);
6382 if ((nr->kind == XPR_TOK
6383 && lltok_isSemi (exprData_getTok (nr->edata))))
6385 /* okay to have unreachable ";" */
6386 ret->exitCode = XK_MUSTEXIT;
6387 ret->canBreak = TRUE;
6391 if (optgenerror (FLG_UNREACHABLE,
6392 message ("Unreachable code: %s",
6393 exprNode_unparseFirst (nr)),
6396 ret->isJumpPoint = TRUE;
6397 ret->mustBreak = FALSE;
6398 ret->exitCode = XK_ERROR;
6399 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6403 ret->exitCode = XK_MUSTEXIT;
6404 ret->canBreak = TRUE;
6412 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6415 ** We want a warning anytime we have:
6417 ** yyy; <<<- no break or return
6421 exprNode lastStmt = exprNode_lastStatement (e1);
6423 if (exprNode_isDefined (lastStmt)
6424 && !exprNode_mustEscape (lastStmt)
6425 && !exprNode_mustBreak (lastStmt)
6426 && !exprNode_isCaseMarker (lastStmt)
6427 && !exprNode_isDefaultMarker (lastStmt)
6428 && !exprNode_isLabelMarker (lastStmt))
6430 voptgenerror (FLG_CASEBREAK,
6432 ("Fall through case (no preceeding break)"),
6439 exprNode_mergeUSs (ret, e2);
6441 usymtab_setExitCode (ret->exitCode);
6445 usymtab_setMustBreak ();
6451 exprNode exprNode_createTok (/*@only@*/ lltok t)
6453 exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6454 ret = exprNode_create (ctype_unknown);
6455 ret->kind = XPR_TOK;
6456 ret->edata = exprData_makeTok (t);
6460 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6462 if (!exprNode_isError (e))
6464 exprNode_checkStatement(e);
6467 return (exprNode_statementError (e, t));
6470 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6472 exprNode ret = exprNode_createPartialCopy (e);
6474 if (!exprNode_isError (e))
6476 if (e->kind != XPR_ASSIGN)
6478 exprNode_checkUse (ret, e->sref, e->loc);
6481 ret->exitCode = e->exitCode;
6482 ret->canBreak = e->canBreak;
6483 ret->mustBreak = e->mustBreak;
6486 ret->edata = exprData_makeUop (e, t);
6487 ret->kind = XPR_STMT;
6492 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6494 if (!exprNode_isError (e))
6496 if (e->kind != XPR_ASSIGN)
6498 exprNode_checkUse (e, e->sref, e->loc);
6505 void exprNode_produceGuards (exprNode pred)
6507 if (!exprNode_isError (pred))
6509 if (ctype_isRealPointer (pred->typ))
6511 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6514 exprNode_checkUse (pred, pred->sref, pred->loc);
6515 exprNode_resetSref (pred);
6519 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6521 exprNode ret = exprNode_createPartialCopy (e);
6523 if (!exprNode_isError (e))
6525 ret->exitCode = e->exitCode;
6526 ret->canBreak = e->canBreak;
6527 ret->mustBreak = e->mustBreak;
6530 ret->edata = exprData_makeSingle (e);
6531 ret->kind = XPR_BLOCK;
6535 bool exprNode_isBlock (exprNode e)
6537 return (exprNode_isDefined (e)
6538 && ((e)->kind == XPR_BLOCK));
6541 bool exprNode_isAssign (exprNode e)
6543 if (exprNode_isDefined (e))
6545 return (e->kind == XPR_ASSIGN);
6551 bool exprNode_isEmptyStatement (exprNode e)
6553 return (exprNode_isDefined (e)
6554 && (e->kind == XPR_TOK)
6555 && (lltok_isSemi (exprData_getTok (e->edata))));
6558 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6561 bool emptyErr = FALSE;
6563 if (context_maybeSet (FLG_IFEMPTY))
6565 if (exprNode_isEmptyStatement (tclause))
6567 emptyErr = optgenerror (FLG_IFEMPTY,
6569 ("Body of if statement is empty"),
6570 exprNode_loc (tclause));
6574 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6576 if (exprNode_isDefined (tclause)
6577 && !exprNode_isBlock (tclause))
6579 voptgenerror (FLG_IFBLOCK,
6581 ("Body of if statement is not a block: %s",
6582 exprNode_unparse (tclause)),
6583 exprNode_loc (tclause));
6587 if (exprNode_isError (pred))
6589 if (exprNode_isError (tclause))
6591 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6595 ret = exprNode_createPartialCopy (tclause);
6600 if (exprNode_mustEscape (pred))
6604 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6605 exprNode_loc (pred));
6608 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6609 exprNode_checkUse (pred, pred->sref, pred->loc);
6611 if (!exprNode_isError (tclause))
6613 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
6616 ret = exprNode_createPartialCopy (pred);
6620 ret->edata = exprData_makePair (pred, tclause);
6622 ret->exitCode = XK_UNKNOWN;
6624 if (exprNode_isDefined (tclause))
6626 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
6627 ret->canBreak = tclause->canBreak;
6628 ret->sets = sRefSet_union (ret->sets, tclause->sets);
6629 ret->msets = sRefSet_union (ret->msets, tclause->msets);
6630 ret->uses = sRefSet_union (ret->uses, tclause->uses);
6633 ret->mustBreak = FALSE;
6638 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
6639 /*@only@*/ exprNode tclause,
6640 /*@only@*/ exprNode eclause)
6643 bool tEmptyErr = FALSE;
6644 bool eEmptyErr = FALSE;
6646 if (context_maybeSet (FLG_IFEMPTY))
6648 if (exprNode_isEmptyStatement (tclause))
6650 tEmptyErr = optgenerror
6653 ("Body of if clause of if statement is empty"),
6654 exprNode_loc (tclause));
6657 if (exprNode_isEmptyStatement (eclause))
6659 eEmptyErr = optgenerror
6662 ("Body of else clause of if statement is empty"),
6663 exprNode_loc (eclause));
6667 if (context_maybeSet (FLG_IFBLOCK))
6670 && exprNode_isDefined (tclause)
6671 && !exprNode_isBlock (tclause))
6673 voptgenerror (FLG_IFBLOCK,
6675 ("Body of if clause of if statement is not a block: %s",
6676 exprNode_unparse (tclause)),
6677 exprNode_loc (tclause));
6681 && exprNode_isDefined (eclause)
6682 && !exprNode_isBlock (eclause)
6683 && !(eclause->kind == XPR_IF)
6684 && !(eclause->kind == XPR_IFELSE))
6689 ("Body of else clause of if statement is not a block: %s",
6690 exprNode_unparse (eclause)),
6691 exprNode_loc (eclause));
6695 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
6697 if (exprNode_isDefined (eclause)
6698 && (eclause->kind == XPR_IF))
6700 voptgenerror (FLG_ELSEIFCOMPLETE,
6701 message ("Incomplete else if logic (no final else): %s",
6702 exprNode_unparse (eclause)),
6703 exprNode_loc (eclause));
6707 if (exprNode_isError (pred))
6709 if (exprNode_isError (tclause))
6711 if (exprNode_isError (eclause))
6713 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6717 ret = exprNode_createPartialCopy (eclause);
6722 ret = exprNode_createPartialCopy (tclause);
6725 else /* pred is okay */
6727 ret = exprNode_createPartialCopy (pred);
6729 if (exprNode_mustEscape (pred))
6733 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6734 exprNode_loc (pred));
6737 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6738 exprNode_checkUse (ret, pred->sref, pred->loc);
6740 exprNode_mergeCondUSs (ret, tclause, eclause);
6743 ret->kind = XPR_IFELSE;
6744 ret->edata = exprData_makeCond (pred, tclause, eclause);
6746 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
6748 exprNode_combineControl (ret, tclause, eclause);
6749 ret->loc = fileloc_update (ret->loc, eclause->loc);
6756 ** *allpaths <- TRUE iff all executions paths must go through the switch
6760 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
6762 exprNodeSList el = exprNode_flatten (e);
6763 bool mustReturn = TRUE; /* find a branch that doesn't */
6764 bool thisReturn = FALSE;
6765 bool hasDefault = FALSE;
6766 bool hasAllMembers = FALSE;
6767 bool inSwitch = FALSE;
6768 bool isEnumSwitch = FALSE;
6769 bool canBreak = FALSE;
6770 bool fallThrough = FALSE;
6771 ctype ct = ctype_unknown;
6772 enumNameSList usedEnums;
6775 if (exprNode_isDefined (test))
6780 ttype = ctype_realType (ct);
6782 if (ctype_isEnum (ttype))
6784 isEnumSwitch = TRUE;
6785 enums = ctype_elist (ttype);
6786 usedEnums = enumNameSList_new ();
6790 exprNodeSList_elements (el, current)
6792 if (exprNode_isDefined (current))
6794 switch (current->kind)
6802 message ("Duplicate default cases in switch"),
6803 exprNode_loc (current));
6808 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
6816 exprNode st = exprData_getSingle (current->edata);
6817 uentry ue = exprNode_getUentry (st);
6819 if (uentry_isValid (ue))
6821 cstring cname = uentry_rawName (ue);
6823 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
6825 if (enumNameSList_member
6826 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
6830 message ("Duplicate case in switch: %s",
6836 enumNameSList_addh (usedEnums, cname);
6843 message ("Case in switch not %s member: %s",
6844 ctype_unparse (ct), cname),
6851 if (inSwitch && !fallThrough)
6853 if (!thisReturn || canBreak)
6863 /*@switchbreak@*/ break;
6865 thisReturn = thisReturn || exprNode_mustEscape (current);
6866 canBreak = canBreak || current->canBreak;
6867 if (canBreak) fallThrough = FALSE;
6870 } end_exprNodeSList_elements;
6872 if (inSwitch) /* check the last one! */
6874 if (!thisReturn || canBreak)
6883 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
6884 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
6886 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
6888 voptgenerror (FLG_MISSCASE,
6889 message ("Missing case%s in switch: %q",
6890 cstring_makeLiteralTemp
6891 ((enumNameSList_size (unused) > 1) ? "s" : ""),
6892 enumNameSList_unparse (unused)),
6895 enumNameSList_free (unused);
6899 hasAllMembers = TRUE;
6903 enumNameSList_free (usedEnums);
6907 *allpaths = hasDefault;
6910 exprNodeSList_free (el);
6911 return ((hasDefault || hasAllMembers) && mustReturn);
6914 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
6916 exprNode ret = exprNode_createPartialCopy (e);
6919 DPRINTF (("Switch: %s", exprNode_unparse (s)));
6921 ret->kind = XPR_SWITCH;
6922 ret->edata = exprData_makePair (e, s);
6924 if (!exprNode_isError (s))
6926 exprNode fs = exprNode_firstStatement (s);
6927 ret->loc = fileloc_update (ret->loc, s->loc);
6929 if (exprNode_isUndefined (fs)
6930 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
6931 || exprNode_isDefaultMarker (fs)) {
6934 voptgenerror (FLG_FIRSTCASE,
6936 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
6941 if (!exprNode_isError (e))
6943 if (checkSwitchExpr (e, s, &allpaths))
6945 ret->exitCode = XK_MUSTRETURN;
6949 ret->exitCode = e->exitCode;
6952 ret->canBreak = e->canBreak;
6953 ret->mustBreak = e->mustBreak;
6957 ** exprNode.c:3883,32: Variable allpaths used before definition
6964 DPRINTF (("Context exit switch!"));
6965 context_exitSwitch (ret, allpaths);
6966 DPRINTF (("Context exit switch done!"));
6971 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
6972 /*@notnull@*/ exprNode body)
6974 sRefSet tuses = test->uses;
6976 if (!sRefSet_isEmpty (test->uses))
6978 sRefSet sets = sRefSet_newCopy (body->sets);
6979 bool hasError = TRUE;
6980 bool innerState = FALSE;
6981 sRefSet tuncon = sRefSet_undefined;
6983 sets = sRefSet_union (sets, test->sets);
6984 sets = sRefSet_union (sets, body->msets);
6985 sets = sRefSet_union (sets, test->msets);
6987 sRefSet_allElements (tuses, el)
6989 if (sRef_isUnconstrained (el))
6991 tuncon = sRefSet_insert (tuncon, el);
6995 if (sRefSet_member (sets, el))
7002 if (sRef_isInternalState (el)
7003 || sRef_isFileStatic (sRef_getRootBase (el)))
7007 } end_sRefSet_allElements ;
7011 sRefSet suncon = sRefSet_undefined;
7012 bool sinner = FALSE;
7014 sRefSet_allElements (sets, el)
7016 if (sRef_isUnconstrained (el))
7018 suncon = sRefSet_insert (suncon, el);
7020 else if (sRef_isInternalState (el))
7028 } end_sRefSet_allElements ;
7030 if (sinner && innerState)
7034 else if (sRefSet_isEmpty (tuncon)
7035 && sRefSet_isEmpty (suncon))
7040 ("Suspected infinite loop. No value used in loop test (%q) "
7041 "is modified by test or loop body.",
7042 sRefSet_unparsePlain (tuses)),
7047 if (sRefSet_isEmpty (tuncon))
7051 message ("Suspected infinite loop. No condition values "
7052 "modified. Modification possible through "
7053 "unconstrained calls: %q",
7054 sRefSet_unparsePlain (suncon)),
7061 message ("Suspected infinite loop. No condition values "
7062 "modified. Possible undetected dependency through "
7063 "unconstrained calls in loop test: %q",
7064 sRefSet_unparsePlain (tuncon)),
7070 sRefSet_free (sets);
7074 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7077 bool emptyErr = FALSE;
7079 if (context_maybeSet (FLG_WHILEEMPTY))
7081 if (exprNode_isEmptyStatement (b))
7083 emptyErr = optgenerror
7086 ("Body of while statement is empty"),
7091 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7093 if (exprNode_isDefined (b)
7094 && !exprNode_isBlock (b))
7096 if (context_inIterDef ()
7097 && (b->kind == XPR_STMTLIST
7098 || b->kind == XPR_TOK))
7104 voptgenerror (FLG_WHILEBLOCK,
7106 ("Body of while statement is not a block: %s",
7107 exprNode_unparse (b)),
7113 if (exprNode_isError (t))
7115 if (exprNode_isError (b))
7117 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7121 ret = exprNode_createPartialCopy (b);
7128 ret = exprNode_createPartialCopy (t);
7130 llassert (t->kind == XPR_WHILEPRED);
7132 test = exprData_getSingle (t->edata);
7134 if (!exprNode_isError (b) && exprNode_isDefined (test))
7136 if (context_maybeSet (FLG_INFLOOPS)
7137 || context_maybeSet (FLG_INFLOOPSUNCON))
7140 ** check that some variable in the predicate is set by the body
7141 ** if the predicate uses any variables
7144 checkInfiniteLoop (test, b);
7147 exprNode_mergeUSs (ret, b);
7149 if (exprNode_isDefined (b))
7151 ret->exitCode = exitkind_makeConditional (b->exitCode);
7156 ret->edata = exprData_makePair (t, b);
7157 ret->kind = XPR_WHILE;
7159 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7163 message ("Predicate always exits: %s", exprNode_unparse (t)),
7167 ret->exitCode = XK_NEVERESCAPE;
7170 ** If loop is infinite, and there is no break inside,
7171 ** exit code is never reach.
7174 if (exprNode_knownIntValue (t))
7176 if (!exprNode_isZero (t))
7178 if (exprNode_isDefined (b))
7182 /* Really, it means never reached. */
7183 ret->exitCode = XK_MUSTEXIT;
7193 ret->canBreak = FALSE;
7194 ret->mustBreak = FALSE;
7200 ** do { b } while (t);
7202 ** note: body passed as first argument
7205 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7209 if (exprNode_isError (t))
7211 if (exprNode_isError (b))
7213 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7217 ret = exprNode_createPartialCopy (b);
7219 ret->exitCode = exitkind_makeConditional (b->exitCode);
7220 exprNode_checkUse (ret, b->sref, b->loc);
7221 ret->exitCode = b->exitCode;
7222 ret->canBreak = b->canBreak;
7223 ret->mustBreak = b->mustBreak;
7228 ret = exprNode_createPartialCopy (t);
7229 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7231 if (!exprNode_isError (b))
7234 ** forgot the copy's --- why wasn't this detected??
7237 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7238 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7239 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
7241 /* left this out --- causes and aliasing bug (infinite loop)
7242 should be detected?? */
7244 exprNode_checkUse (ret, b->sref, b->loc);
7245 exprNode_mergeUSs (ret, t);
7246 exprNode_checkUse (ret, t->sref, t->loc);
7248 ret->exitCode = b->exitCode;
7249 ret->canBreak = b->canBreak;
7250 ret->mustBreak = b->mustBreak;
7254 context_exitDoWhileClause (t);
7256 ret->kind = XPR_DOWHILE;
7257 ret->edata = exprData_makePair (t, b);
7261 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7264 bool emptyErr = FALSE;
7266 if (context_maybeSet (FLG_FOREMPTY))
7268 if (exprNode_isEmptyStatement (body))
7270 emptyErr = optgenerror
7273 ("Body of for statement is empty"),
7274 exprNode_loc (body));
7278 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7280 if (exprNode_isDefined (body)
7281 && !exprNode_isBlock (body))
7283 if (context_inIterDef ()
7284 && (body->kind == XPR_STMTLIST
7285 || body->kind == XPR_TOK))
7291 voptgenerror (FLG_FORBLOCK,
7293 ("Body of for statement is not a block: %s",
7294 exprNode_unparse (body)),
7295 exprNode_loc (body));
7301 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7304 if (exprNode_isError (body))
7306 ret = exprNode_createPartialCopy (inc);
7310 ret = exprNode_createPartialCopy (body);
7312 ret->exitCode = exitkind_makeConditional (body->exitCode);
7314 exprNode_mergeUSs (inc, body);
7316 if (exprNode_isDefined (inc))
7320 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7323 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7324 exprNode_freeShallow (tmp);
7326 context_clearMessageAnnote ();
7327 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7329 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7330 exprNode_freeShallow (tmp);
7332 context_clearMessageAnnote ();
7334 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7335 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7336 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7340 ret->kind = XPR_FOR;
7341 ret->edata = exprData_makePair (inc, body);
7343 if (exprNode_isDefined (inc)) {
7344 exprNode test = exprData_getTripleTest (inc->edata);
7346 if (exprNode_isUndefined (test)) {
7347 if (exprNode_isDefined (body)) {
7348 if (!body->canBreak) {
7349 /* Really, it means never reached. */
7350 ret->exitCode = XK_MUSTEXIT;
7360 ** for (init; test; inc)
7363 ** while (test) { body; inc; }
7365 ** Now: check use of init (may set vars for test)
7366 ** check use of test
7370 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7374 if (exprNode_isError (pred)) return guardSet_undefined;
7376 llassert (pred->kind == XPR_FORPRED);
7378 test = exprData_getTripleTest (pred->edata);
7380 if (!exprNode_isError (test))
7382 return (test->guards);
7385 return guardSet_undefined;
7388 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7390 exprNode ret = exprNode_createSemiCopy (test);
7392 if (exprNode_isDefined (test))
7394 exprNode_copySets (ret, test);
7395 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7396 exprNode_checkUse (ret, test->sref, test->loc);
7398 exprNode_produceGuards (test);
7400 ret->guards = guardSet_copy (test->guards);
7403 ret->edata = exprData_makeSingle (test);
7404 ret->kind = XPR_WHILEPRED;
7408 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7409 /*@only@*/ exprNode inc)
7414 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7417 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7419 if (!exprNode_isError (inc))
7421 ret = exprNode_createPartialCopy (inc);
7425 if (!exprNode_isError (init))
7427 ret = exprNode_createPartialCopy (init);
7429 else if (!exprNode_isError (test))
7431 ret = exprNode_createPartialCopy (test);
7435 ret = exprNode_createUnknown ();
7439 exprNode_mergeUSs (ret, init);
7441 if (exprNode_isDefined (init))
7443 exprNode_checkUse (ret, init->sref, init->loc);
7446 exprNode_mergeUSs (ret, test);
7448 if (exprNode_isDefined (test))
7450 exprNode_checkUse (ret, test->sref, test->loc);
7453 ret->kind = XPR_FORPRED;
7454 ret->edata = exprData_makeFor (init, test, inc);
7458 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7460 exprNode ret = exprNode_createUnknown ();
7462 if (context_inMacro ())
7464 voptgenerror (FLG_MACROSTMT,
7465 message ("Macro %s uses goto (not functional)",
7466 context_inFunctionName ()),
7470 ret->kind = XPR_GOTO;
7471 ret->edata = exprData_makeLiteral (label);
7472 ret->mustBreak = TRUE;
7473 ret->exitCode = XK_GOTO;
7474 ret->canBreak = TRUE;
7478 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7480 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7482 ret->kind = XPR_CONTINUE;
7483 ret->edata = exprData_makeTok (l);
7484 ret->canBreak = TRUE;
7485 ret->mustBreak = TRUE;
7487 if (qcontinue == QSAFEBREAK)
7491 else if (qcontinue == QINNERCONTINUE)
7493 if (!context_inDeepLoop ())
7496 (FLG_LOOPLOOPCONTINUE,
7497 cstring_makeLiteral ("Continue statement marked with innercontinue "
7498 "is not inside a nested loop"),
7499 exprNode_loc (ret));
7502 else if (qcontinue == BADTOK)
7504 if (context_inDeepLoop ())
7507 (FLG_LOOPLOOPCONTINUE,
7508 cstring_makeLiteral ("Continue statement in nested loop"),
7509 exprNode_loc (ret));
7514 llbuglit ("exprNode_continue: bad qcontinue");
7520 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
7522 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7523 clause breakClause = context_breakClause ();
7525 ret->kind = XPR_BREAK;
7526 ret->edata = exprData_makeTok (l);
7527 ret->canBreak = TRUE;
7528 ret->mustBreak = TRUE;
7530 if (breakClause == NOCLAUSE)
7534 cstring_makeLiteral ("Break not inside while, for or switch statement"),
7535 exprNode_loc (ret));
7539 if (bqual != BADTOK)
7546 if (breakClause == SWITCHCLAUSE)
7548 if (!context_inDeepSwitch ())
7550 voptgenerror (FLG_SYNTAX,
7552 ("Break preceded by innerbreak is not in a deep switch"),
7553 exprNode_loc (ret));
7558 if (!context_inDeepLoop ())
7560 voptgenerror (FLG_SYNTAX,
7562 ("Break preceded by innerbreak is not in a deep loop"),
7563 exprNode_loc (ret));
7568 if (breakClause == SWITCHCLAUSE)
7570 voptgenerror (FLG_SYNTAX,
7572 ("Break preceded by loopbreak is breaking a switch"),
7573 exprNode_loc (ret));
7577 if (breakClause != SWITCHCLAUSE)
7581 message ("Break preceded by switchbreak is breaking %s",
7582 cstring_makeLiteralTemp
7583 ((breakClause == WHILECLAUSE
7584 || breakClause == DOWHILECLAUSE) ? "a while loop"
7585 : (breakClause == FORCLAUSE) ? "a for loop"
7586 : (breakClause == ITERCLAUSE) ? "an iterator"
7588 exprNode_loc (ret));
7596 if (breakClause == SWITCHCLAUSE)
7598 clause nextBreakClause = context_nextBreakClause ();
7600 switch (nextBreakClause)
7602 case NOCLAUSE: break;
7608 (FLG_LOOPSWITCHBREAK,
7609 cstring_makeLiteral ("Break statement in switch inside loop"),
7610 exprNode_loc (ret));
7614 (FLG_SWITCHSWITCHBREAK,
7615 cstring_makeLiteral ("Break statement in switch inside switch"),
7616 exprNode_loc (ret));
7623 if (context_inDeepLoop ())
7627 cstring_makeLiteral ("Break statement in nested loop"),
7628 exprNode_loc (ret));
7632 if (context_inDeepLoopSwitch ())
7635 (FLG_SWITCHLOOPBREAK,
7636 cstring_makeLiteral ("Break statement in loop inside switch"),
7637 exprNode_loc (ret));
7647 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
7649 fileloc loc = lltok_getLoc (t);
7650 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
7652 context_returnFunction ();
7653 exprChecks_checkNullReturn (loc);
7655 ret->kind = XPR_NULLRETURN;
7656 ret->edata = exprData_makeTok (t);
7657 ret->exitCode = XK_MUSTRETURN;
7661 exprNode exprNode_return (/*@only@*/ exprNode e)
7665 if (exprNode_isError (e))
7667 ret = exprNode_createUnknown ();
7671 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
7673 exprNode_checkUse (ret, e->sref, e->loc);
7674 exprNode_checkReturn (e);
7677 context_returnFunction ();
7678 ret->kind = XPR_RETURN;
7679 ret->edata = exprData_makeSingle (e);
7680 ret->exitCode = XK_MUSTRETURN;
7685 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
7689 if (exprNode_isError (e1))
7691 if (exprNode_isError (e2))
7693 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7697 ret = exprNode_createPartialCopy (e2);
7698 exprNode_checkUse (ret, e2->sref, e2->loc);
7699 ret->sref = e2->sref;
7704 ret = exprNode_createPartialCopy (e1);
7706 exprNode_checkUse (ret, e1->sref, e1->loc);
7708 if (!exprNode_isError (e2))
7710 exprNode_mergeUSs (ret, e2);
7711 exprNode_checkUse (ret, e2->sref, e2->loc);
7712 ret->sref = e2->sref;
7716 ret->kind = XPR_COMMA;
7717 ret->edata = exprData_makePair (e1, e2);
7719 if (exprNode_isDefined (e1))
7721 if (exprNode_isDefined (e2))
7725 if (exprNode_mustEscape (e1) || e1->mustBreak)
7729 message ("Second clause of comma expression is unreachable: %s",
7730 exprNode_unparse (e2)),
7734 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
7735 ret->mustBreak = e1->mustBreak || e2->mustBreak;
7736 ret->canBreak = e1->canBreak || e2->canBreak;
7740 if (exprNode_mustEscape (e1) || e1->mustBreak)
7744 message ("Second clause of comma expression is unreachable: %s",
7745 exprNode_unparse (e2)),
7749 ret->exitCode = e1->exitCode;
7750 ret->canBreak = e1->canBreak;
7755 if (exprNode_isDefined (e2))
7757 ret->exitCode = e2->exitCode;
7758 ret->mustBreak = e2->mustBreak;
7759 ret->canBreak = e2->canBreak;
7766 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
7768 ctype t1 = exprNode_getType (el);
7769 ctype t2 = exprNode_getType (val);
7770 bool hasError = FALSE;
7772 if (ctype_isUnknown (t1))
7774 voptgenerror (FLG_IMPTYPE,
7775 message ("Variable has unknown (implicitly int) type: %s",
7776 exprNode_unparse (el)),
7780 el->typ = ctype_int;
7783 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
7785 exprNodeList vals = exprData_getArgs (val->edata);
7787 if (ctype_isRealAP (t1))
7792 /*@i423 check number of entries int a[3] = { 1, 2, 3, 4 } ; */
7794 exprNodeList_elements (vals, oneval)
7796 cstring istring = message ("%d", i);
7799 (exprNode_fakeCopy (el),
7800 exprNode_numLiteral (ctype_int, istring,
7801 fileloc_copy (el->loc), i));
7803 if (exprNode_isDefined (newel))
7805 if (exprNodeList_size (vals) == 1
7806 && ctype_isString (exprNode_getType (oneval))
7807 && ctype_isChar (exprNode_getType (newel)))
7809 exprNode_freeIniter (newel);
7813 if (exprNode_checkOneInit (newel, oneval))
7818 if (nerrors > 3 && exprNodeList_size (vals) > 6)
7821 (message ("Additional initialization errors "
7822 "for %s not reported",
7823 exprNode_unparse (el)),
7825 exprNode_freeIniter (newel);
7830 exprNode_freeIniter (newel);
7835 exprNode_freeIniter (newel);
7840 cstring_free (istring);
7843 } end_exprNodeList_elements;
7846 else if (ctype_isStruct (ctype_realType (t1)))
7848 uentryList fields = ctype_getFields (t1);
7851 if (uentryList_size (fields) != exprNodeList_size (vals))
7853 if (uentryList_size (fields) > exprNodeList_size (vals))
7855 hasError = optgenerror
7857 message ("Initializer block for "
7858 "%s has %d field%&, but %s has %d field%&: %q",
7859 exprNode_unparse (el),
7860 exprNodeList_size (vals),
7862 uentryList_size (fields),
7863 exprNodeList_unparse (vals)),
7868 hasError = optgenerror
7870 message ("Initializer block for "
7871 "%s has %d field%&, but %s has %d field%&: %q",
7872 exprNode_unparse (el),
7873 exprNodeList_size (vals),
7875 uentryList_size (fields),
7876 exprNodeList_unparse (vals)),
7882 exprNodeList_elements (vals, oneval)
7884 uentry thisfield = uentryList_getN (fields, i);
7886 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
7888 uentry_getName (thisfield));
7890 if (exprNode_isDefined (newel))
7892 if (exprNode_checkOneInit (newel, oneval))
7897 exprNode_freeIniter (newel);
7901 } end_exprNodeList_elements;
7906 hasError = optgenerror
7908 message ("Initializer block used for "
7909 "%s where %t is expected: %s",
7910 exprNode_unparse (el), t1, exprNode_unparse (val)),
7916 if (exprNode_isDefined (val))
7918 doAssign (el, val, TRUE);
7920 if (!exprNode_matchType (t1, val))
7922 hasError = gentypeerror
7924 message ("Initial value of %s is type %t, "
7926 exprNode_unparse (el),
7927 t2, t1, exprNode_unparse (val)),
7937 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
7941 if (usymtab_exists (idDecl_observeId (t)))
7943 uentry ue = usymtab_lookup (idDecl_observeId (t));
7944 ret = exprNode_createId (ue);
7946 /*@i723 don't do this...but why? */
7948 ct = ctype_realishType (ret->typ);
7950 DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
7952 if (ctype_isUnknown (ct))
7954 if (uentry_isAnyTag (ue))
7958 message ("%s used but not previously declared: %s",
7959 uentry_ekindName (ue),
7960 idDecl_getName (t)),
7968 message ("Variable has unknown (implicitly int) type: %s",
7969 idDecl_getName (t)),
7981 DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
7983 ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
7984 /*!! fileloc_copy (g_currentloc)); */
7985 /*@i32!!! should get error without this */
7986 ret = exprNode_fromIdentifierAux (ue);
7989 ** No error - this happens in old style declarations:
7993 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8000 exprData_free (ret->edata, ret->kind);
8001 ret->edata = exprData_undefined;
8003 ret->exitCode = XK_NEVERESCAPE;
8004 ret->mustBreak = FALSE;
8005 ret->kind = XPR_INIT;
8009 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8011 exprNode ret = exprNode_makeInitializationAux (t);
8012 llassert (ret->edata == exprData_undefined);
8013 ret->edata = exprData_makeInit (t, exprNode_undefined);
8017 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8018 /*@only@*/ exprNode e)
8020 uentry ue = usymtab_lookup (idDecl_observeId (t));
8021 exprNode ret = exprNode_makeInitializationAux (t);
8022 fileloc loc = exprNode_loc (e);
8024 if (exprNode_isError (e))
8026 e = exprNode_createUnknown ();
8029 /* error: assume initializer is defined */
8030 sRef_setDefined (ret->sref, g_currentloc);
8034 ctype ct = ctype_realishType (ret->typ);
8039 ** was addSafeUse --- what's the problem?
8041 ** int x = 3, y = x ?
8044 exprData_free (ret->edata, ret->kind);
8045 ret->edata = exprData_makeInit (t, e);
8047 exprNode_checkUse (ret, e->sref, e->loc);
8049 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8051 exprNode lhs = exprNode_createId (ue);
8054 ** static storage should be undefined before initializing
8057 if (uentry_isStatic (ue))
8059 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8062 (void) exprNode_checkOneInit (lhs, e);
8064 if (uentry_isStatic (ue))
8066 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8069 exprNode_free (lhs);
8073 if (!exprNode_matchType (ct, e))
8075 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
8082 (exprNode_getType (e), e, exprNode_getType (ret), ret,
8084 ("Variable %q initialized to type %t, expects %t: %s",
8085 uentry_getName (ue), exprNode_getType (e),
8086 exprNode_getType (ret),
8087 exprNode_unparse (e)),
8093 if (uentry_isStatic (ue))
8095 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8098 doAssign (ret, e, TRUE);
8100 if (uentry_isStatic (ue))
8102 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8106 if (context_inIterDef ())
8108 /* should check if it is yield */
8109 uentry_setUsed (ue, loc);
8116 exprNode_mergeUSs (ret, e);
8120 exprNode exprNode_iter (/*@observer@*/ uentry name,
8121 /*@only@*/ exprNodeList alist,
8122 /*@only@*/ exprNode body,
8123 /*@observer@*/ uentry end)
8128 llassert (uentry_isValid (name));
8130 uentry_setUsed (name, exprNode_loc (body));
8132 ret = exprNode_createPartialCopy (body);
8133 iname = uentry_getName (name);
8135 if (uentry_isInvalid (end))
8138 message ("Iter %s not balanced with end_%s", iname, iname));
8142 cstring ename = uentry_getName (end);
8144 if (!cstring_equalPrefix (ename, "end_"))
8146 llerror (FLG_ITER, message ("Iter %s not balanced with end_%s: %s",
8147 iname, iname, ename));
8151 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8154 message ("Iter %s not balanced with end_%s: %s",
8155 iname, iname, ename));
8159 cstring_free (ename);
8162 context_exitIterClause (body);
8164 ret->kind = XPR_ITER;
8165 ret->edata = exprData_makeIter (name, alist, body, end);
8167 if (uentry_isIter (name))
8169 (void) checkArgsReal (name, body,
8170 uentry_getParams (name), alist, TRUE, ret);
8173 cstring_free (iname);
8179 exprNode_iterNewId (/*@only@*/ cstring s)
8181 exprNode e = exprNode_new ();
8182 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8184 llassert (processingIterVars ());
8186 e->loc = context_getSaveLocation ();
8188 if (fileloc_isUndefined (e->loc))
8190 fileloc_free (e->loc);
8191 e->loc = fileloc_copy (g_currentloc);
8194 e->uses = sRefSet_new ();
8195 e->sets = sRefSet_new ();
8196 e->msets = sRefSet_new ();
8198 e->val = multiVal_unknown ();
8199 e->guards = guardSet_new ();
8201 e->isJumpPoint = FALSE;
8202 e->exitCode = XK_NEVERESCAPE;
8204 /*> missing fields, detected by lclint <*/
8205 e->canBreak = FALSE;
8206 e->mustBreak = FALSE;
8207 e->etext = cstring_undefined;
8209 if (uentry_isYield (ue))
8211 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8212 fileloc_copy (e->loc),
8216 uue = usymtab_supEntrySrefReturn (uue);
8218 sr = uentry_getSref (uue);
8219 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8220 sr = uentry_getSref (uue);
8221 sRef_setDefined (sr, e->loc);
8223 e->typ = uentry_getType (uue);
8225 e->edata = exprData_makeId (uue);
8226 uentry_setUsed (uue, g_currentloc);
8232 sRef_setGlobalScope ();
8233 uue = uentry_makeVariableLoc (s, ctype_unknown);
8235 e->typ = ctype_unknown;
8236 e->edata = exprData_makeId (uue);
8238 uentry_setUsed (uue, e->loc);
8239 uentry_setHasNameError (uue);
8241 if (context_getFlag (FLG_REPEATUNRECOG))
8243 uentry_markOwned (uue);
8247 usymtab_supGlobalEntry (uue);
8250 sRef_clearGlobalScope ();
8252 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8259 exprNode_defineConstraints(e);
8264 exprNode_iterExpr (/*@returned@*/ exprNode e)
8266 if (!processingIterVars ())
8268 llcontbuglit ("checkIterParam: not in iter");
8272 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8275 if (exprNode_isDefined (e))
8277 if (fileloc_isDefined (e->loc))
8281 message ("Yield parameter is not simple identifier: %s",
8282 exprNode_unparse (e)),
8289 message ("Yield parameter is not simple identifier: %s",
8290 exprNode_unparse (e)),
8300 exprNode_iterId (/*@observer@*/ uentry c)
8304 llassert (processingIterVars ());
8306 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8309 if (uentry_isYield (ue))
8311 ctype ct = uentry_getType (ue);
8312 exprNode e = exprNode_createPlain (ct);
8313 cstring name = uentry_getName (c);
8314 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8316 uentry_setUsed (ue, g_currentloc);
8317 uentry_setHasNameError (ue);
8319 cstring_free (name);
8322 e->edata = exprData_makeId (le);
8323 e->loc = context_getSaveLocation ();
8324 e->sref = uentry_getSref (le);
8326 usymtab_supEntrySref (le);
8328 if (!context_inHeader ())
8332 message ("Yield parameter shadows local declaration: %q",
8333 uentry_getName (c)),
8334 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8336 uentry_showWhereDeclared (c);
8343 return (exprNode_fromIdentifierAux (c));
8346 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8348 exprNode ret = exprNode_create (ctype_unknown);
8350 ret->kind = XPR_ITERCALL;
8351 ret->edata = exprData_makeIterCall (name, alist);
8353 if (uentry_isIter (name))
8355 uentryList params = uentry_getParams (name);
8357 if (context_inIterDef ()
8358 && uentryList_size (params) == exprNodeList_size (alist))
8362 exprNodeList_elements (alist, arg)
8364 uentry parg = uentryList_getN (params, i);
8366 if (uentry_isYield (parg))
8368 uentry ue = exprNode_getUentry (arg);
8370 if (uentry_isValid (ue))
8377 } end_exprNodeList_elements;
8380 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8381 checkUnspecCall (ret, params, alist);
8387 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8389 if (exprNode_isDefined (e))
8392 if (e->sref == defref) /*@noaccess sRef@*/
8395 e->sref = sRef_makeUnknown ();
8396 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8407 return sRef_undefined;
8411 /*@observer@*/ cstring
8412 exprNode_unparseFirst (exprNode e)
8414 if (exprNode_isDefined (e))
8418 if (e->kind == XPR_STMTLIST
8419 || e->kind == XPR_COMMA || e->kind == XPR_COND)
8421 exprNode first = exprData_getPairA (e->edata);
8423 if (exprNode_isDefined (first))
8425 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8429 return (cstring_makeLiteralTemp ("..."));
8433 ret = cstring_elide (exprNode_unparse (e), 20);
8434 cstring_markOwned (ret);
8440 return cstring_makeLiteralTemp ("<error>");
8444 /*@observer@*/ cstring
8445 exprNode_unparse (/*@temp@*/ exprNode e)
8447 if (exprNode_isError (e))
8449 return cstring_makeLiteralTemp ("<error>");
8452 if (cstring_isDefined (e->etext))
8458 cstring ret = exprNode_doUnparse (e);
8460 /*@-modifies@*/ /* benevolent */
8467 /*@observer@*/ fileloc
8468 exprNode_loc (exprNode e)
8470 if (exprNode_isError (e))
8472 return (g_currentloc);
8481 ** executes exprNode e
8482 ** recursively rexecutes as though in original parse using
8483 ** information in e->edata
8486 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
8488 exprNodeList ret = exprNodeList_new ();
8490 exprNodeList_elements (e, current)
8492 exprNodeList_addh (ret, exprNode_effect (current));
8493 } end_exprNodeList_elements;
8498 static /*@only@*/ exprNode exprNode_effect (exprNode e)
8499 /*@globals internalState@*/
8501 bool innerEffect = inEffect;
8507 context_clearJustPopped ();
8509 if (exprNode_isError (e))
8511 ret = exprNode_undefined;
8516 ** Turn off expose and dependent transfer checking.
8517 ** Need to pass exposed internal nodes,
8518 ** [ copying would be a waste! ]
8519 ** [ Actually, I think I wasted a lot more time than its worth ]
8520 ** [ trying to do this. ]
8524 /*@-observertrans@*/
8525 /*@-dependenttrans@*/
8532 ret = exprNode_addParens (exprData_getUopTok (data),
8533 exprNode_effect (exprData_getUopNode (data)));
8536 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
8537 exprNode_effect (exprData_getOpB (data)),
8538 exprData_getOpTok (data));
8541 ret = exprNode_undefined;
8544 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
8545 exprNodeList_effect (exprData_getArgs (data)));
8558 cstring id = exprData_getId (data);
8559 uentry ue = usymtab_lookupSafe (id);
8561 ret = exprNode_fromIdentifierAux (ue);
8562 ret->loc = fileloc_update (ret->loc, e->loc);
8569 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
8570 exprNode_effect (exprData_getPairB (data)));
8573 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
8574 exprNode_effect (exprData_getOpB (data)),
8575 exprData_getOpTok (data));
8579 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
8580 exprData_getUopTok (data));
8583 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
8584 exprData_getUopTok (data));
8596 ret = exprNode_vaArg (exprData_getCastTok (data),
8597 exprNode_effect (exprData_getCastNode (data)),
8598 exprData_getCastType (data));
8602 ret = exprNode_cast (exprData_getCastTok (data),
8603 exprNode_effect (exprData_getCastNode (data)),
8604 exprData_getCastType (data));
8607 ret = exprNode_iterStart (exprData_getIterCallIter (data),
8609 (exprData_getIterCallArgs (data)));
8613 ret = exprNode_iter (exprData_getIterSname (data),
8614 exprNodeList_effect (exprData_getIterAlist (data)),
8615 exprNode_effect (exprData_getIterBody (data)),
8616 exprData_getIterEname (data));
8620 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
8621 exprNode_effect (exprData_getPairB (data)));
8625 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
8626 exprNode_effect (exprData_getTripleTest (data)),
8627 exprNode_effect (exprData_getTripleInc (data)));
8631 ret = exprNode_createTok (exprData_getTok (data));
8635 ret = exprNode_goto (exprData_getLiteral (data));
8636 ret->loc = fileloc_update (ret->loc, e->loc);
8640 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
8644 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
8648 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
8651 case XPR_NULLRETURN:
8652 ret = exprNode_nullReturn (exprData_getTok (data));
8656 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
8657 exprNode_effect (exprData_getPairB (data)));
8661 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
8662 exprNode_effect (exprData_getTripleTrue (data)),
8663 exprNode_effect (exprData_getTripleFalse (data)));
8666 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
8667 exprNode_effect (exprData_getPairB (data)));
8671 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
8672 exprNode_effect (exprData_getTripleTrue (data)),
8673 exprNode_effect (exprData_getTripleFalse (data)));
8676 ret = exprNode_whilePred (exprData_getSingle (data));
8680 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
8681 exprNode_effect (exprData_getPairB (data)));
8685 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
8686 exprNode_effect (exprData_getPairB (data)));
8690 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
8694 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
8695 exprData_getUopTok (data));
8699 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
8700 exprNode_effect (exprData_getPairB (data)));
8705 ret = exprNode_caseMarker
8706 (exprNode_effect (exprData_getSingle (data)),
8712 ret = exprNode_createTok (exprData_getTok (data));
8716 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
8717 exprNode_effect (exprData_getPairB (data)));
8721 ret = exprNode_makeInitialization
8722 (exprData_getInitId (data),
8723 exprNode_effect (exprData_getInitNode (data)));
8727 ret = exprNode_fieldAccessAux
8728 (exprNode_effect (exprData_getFieldNode (data)),
8729 exprNode_loc (exprData_getFieldNode (data)),
8730 cstring_copy (exprData_getFieldName (data)));
8734 ret = exprNode_arrowAccessAux
8735 (exprNode_effect (exprData_getFieldNode (data)),
8736 exprNode_loc (exprData_getFieldNode (data)),
8737 cstring_copy (exprData_getFieldName (data)));
8740 case XPR_STRINGLITERAL:
8754 /*@=observertrans@*/
8756 /*@=dependenttrans@*/
8767 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
8772 if (exprNode_isError (e))
8774 return cstring_undefined;
8782 ret = exprNode_rootVarName (exprData_getUopNode (data));
8785 ret = exprNode_rootVarName (exprData_getOpA (data));
8789 ret = exprData_getId (data);
8792 ret = idDecl_getName (exprData_getInitId (data));
8817 case XPR_NULLRETURN:
8839 case XPR_STRINGLITERAL:
8840 ret = cstring_undefined;
8847 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
8852 if (exprNode_isError (e))
8854 static /*@only@*/ cstring error = cstring_undefined;
8856 if (!cstring_isDefined (error))
8858 error = cstring_makeLiteral ("<error>");
8869 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
8872 ret = message ("%s %s %s",
8873 exprNode_unparse (exprData_getOpA (data)),
8874 lltok_unparse (exprData_getOpTok (data)),
8875 exprNode_unparse (exprData_getOpB (data)));
8878 ret = message ("%s(%q)",
8879 exprNode_unparse (exprData_getFcn (data)),
8880 exprNodeList_unparse (exprData_getArgs (data)));
8883 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
8886 ret = cstring_undefined;
8889 ret = message ("%s:", exprData_getId (data));
8893 ret = cstring_copy (exprData_getId (data));
8896 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
8897 exprNode_unparse (exprData_getPairB (data)));
8900 ret = message ("<body>");
8903 ret = message ("%s %s %s",
8904 exprNode_unparse (exprData_getOpA (data)),
8905 lltok_unparse (exprData_getOpTok (data)),
8906 exprNode_unparse (exprData_getOpB (data)));
8910 ret = message ("%s%s",
8911 lltok_unparse (exprData_getUopTok (data)),
8912 exprNode_unparse (exprData_getUopNode (data)));
8916 ret = message ("%s%s",
8917 exprNode_unparse (exprData_getUopNode (data)),
8918 lltok_unparse (exprData_getUopTok (data)));
8922 ret = message ("offsetof(%s,%q)",
8923 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
8924 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
8928 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8932 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
8936 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8940 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
8944 ret = message ("va_arg(%s, %q)",
8945 exprNode_unparse (exprData_getCastNode (data)),
8946 qtype_unparse (exprData_getCastType (data)));
8950 ret = message ("%q(%q)",
8951 uentry_getName (exprData_getIterCallIter (data)),
8952 exprNodeList_unparse (exprData_getIterCallArgs (data)));
8955 ret = message ("%q(%q) %s %q",
8956 uentry_getName (exprData_getIterSname (data)),
8957 exprNodeList_unparse (exprData_getIterAlist (data)),
8958 exprNode_unparse (exprData_getIterBody (data)),
8959 uentry_getName (exprData_getIterEname (data)));
8962 ret = message ("(%q)%s",
8963 qtype_unparse (exprData_getCastType (data)),
8964 exprNode_unparse (exprData_getCastNode (data)));
8968 ret = message ("%s %s",
8969 exprNode_unparse (exprData_getPairA (data)),
8970 exprNode_unparse (exprData_getPairB (data)));
8974 ret = message ("for (%s; %s; %s)",
8975 exprNode_unparse (exprData_getTripleInit (data)),
8976 exprNode_unparse (exprData_getTripleTest (data)),
8977 exprNode_unparse (exprData_getTripleInc (data)));
8981 ret = message ("goto %s", exprData_getLiteral (data));
8985 ret = cstring_makeLiteral ("continue");
8989 ret = cstring_makeLiteral ("break");
8993 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
8996 case XPR_NULLRETURN:
8997 ret = cstring_makeLiteral ("return");
9001 ret = message ("%s, %s",
9002 exprNode_unparse (exprData_getPairA (data)),
9003 exprNode_unparse (exprData_getPairB (data)));
9007 ret = message ("%s ? %s : %s",
9008 exprNode_unparse (exprData_getTriplePred (data)),
9009 exprNode_unparse (exprData_getTripleTrue (data)),
9010 exprNode_unparse (exprData_getTripleFalse (data)));
9013 ret = message ("if (%s) %s",
9014 exprNode_unparse (exprData_getPairA (data)),
9015 exprNode_unparse (exprData_getPairB (data)));
9019 ret = message ("if (%s) %s else %s",
9020 exprNode_unparse (exprData_getTriplePred (data)),
9021 exprNode_unparse (exprData_getTripleTrue (data)),
9022 exprNode_unparse (exprData_getTripleFalse (data)));
9025 ret = message ("while (%s) %s",
9026 exprNode_unparse (exprData_getPairA (data)),
9027 exprNode_unparse (exprData_getPairB (data)));
9031 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9035 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9039 ret = message ("do { %s } while (%s)",
9040 exprNode_unparse (exprData_getPairB (data)),
9041 exprNode_unparse (exprData_getPairA (data)));
9045 ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
9049 ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
9053 ret = message ("%s; %s",
9054 exprNode_unparse (exprData_getPairA (data)),
9055 exprNode_unparse (exprData_getPairB (data)));
9060 ret = cstring_makeLiteral ("default:");
9064 ret = message ("switch (%s) %s",
9065 exprNode_unparse (exprData_getPairA (data)),
9066 exprNode_unparse (exprData_getPairB (data)));
9071 ret = message ("case %s:",
9072 exprNode_unparse (exprData_getSingle (data)));
9076 if (exprNode_isError (exprData_getInitNode (data)))
9078 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9082 ret = message ("%q = %s",
9083 idDecl_unparseC (exprData_getInitId (data)),
9084 exprNode_unparse (exprData_getInitNode (data)));
9089 ret = message ("%s.%s",
9090 exprNode_unparse (exprData_getFieldNode (data)),
9091 exprData_getFieldName (data));
9095 ret = message ("%s->%s",
9096 exprNode_unparse (exprData_getFieldNode (data)),
9097 exprData_getFieldName (data));
9100 case XPR_STRINGLITERAL:
9101 ret = message ("\"%s\"", exprData_getLiteral (data));
9105 ret = cstring_copy (exprData_getLiteral (data));
9109 ret = cstring_makeLiteral ("<node>");
9117 exprNode_isInitializer (exprNode e)
9119 return (exprNode_isDefined (e)
9120 && e->kind == XPR_INIT);
9124 exprNode_isCharLit (exprNode e)
9126 if (exprNode_isDefined (e))
9128 return (multiVal_isChar (exprNode_getValue (e)));
9137 exprNode_isNumLit (exprNode e)
9139 if (exprNode_isDefined (e))
9141 return (multiVal_isInt (exprNode_getValue (e)));
9150 exprNode_isFalseConstant (exprNode e)
9152 if (exprNode_isDefined (e))
9154 cstring s = exprNode_rootVarName (e);
9156 if (cstring_equal (s, context_getFalseName ()))
9166 exprNode_matchLiteral (ctype expected, exprNode e)
9168 if (exprNode_isDefined (e))
9170 multiVal m = exprNode_getValue (e);
9172 if (multiVal_isDefined (m))
9174 if (multiVal_isInt (m))
9176 long int val = multiVal_forceInt (m);
9178 if (ctype_isDirectBool (ctype_realishType (expected)))
9182 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9190 if (ctype_isRealInt (expected))
9193 ** unsigned <- [ constant >= 0 is okay ]
9196 if (ctype_isUnsigned (expected))
9205 ** No checks on sizes of integers...maybe add
9209 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9210 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9211 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9213 if (context_getFlag (FLG_NUMLITERAL)
9214 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9220 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9224 else if (ctype_isChar (expected))
9228 else if (ctype_isArrayPtr (expected))
9232 else if (ctype_isAnyFloat (expected))
9234 return (context_getFlag (FLG_NUMLITERAL));
9241 else if (multiVal_isDouble (m))
9243 if (ctype_isAnyFloat (expected))
9248 else if (multiVal_isChar (m))
9250 char val = multiVal_forceChar (m);
9252 if (ctype_isChar (expected))
9254 if (ctype_isUnsigned (expected) && ((int)val) < 0)
9275 exprNode_matchType (ctype expected, exprNode e)
9279 if (!exprNode_isDefined (e)) return TRUE;
9281 actual = ctype_realishType (exprNode_getType (e));
9283 if (ctype_match (ctype_realishType (expected), actual))
9288 llassert (!exprNode_isError (e));
9289 return (exprNode_matchLiteral (expected, e));
9293 exprNode_matchTypes (exprNode e1, exprNode e2)
9298 if (!exprNode_isDefined (e1)) return TRUE;
9299 if (!exprNode_isDefined (e2)) return TRUE;
9302 ** realish type --- keep bools, bools
9305 t1 = ctype_realishType (exprNode_getType (e1));
9306 t2 = ctype_realishType (exprNode_getType (e2));
9308 if (ctype_match (t1, t2))
9313 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9321 exprNode_matchArgType (ctype ct, exprNode e)
9325 if (!exprNode_isDefined (e))
9330 et = ctype_realType (exprNode_getType (e));
9332 if (ctype_matchArg (ct, et)) return TRUE;
9334 llassert (!exprNode_isError (e));
9335 return (exprNode_matchLiteral (ct, e));
9338 static /*@only@*/ exprNodeSList
9339 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9341 if (exprNode_isDefined (e))
9343 if (e->kind == XPR_STMTLIST)
9345 return (exprNodeSList_append
9346 (exprNode_flatten (exprData_getPairA (e->edata)),
9347 exprNode_flatten (exprData_getPairB (e->edata))));
9349 else if (e->kind == XPR_BLOCK)
9351 return (exprNode_flatten (exprData_getSingle (e->edata)));
9355 return (exprNodeSList_singleton (e));
9359 return exprNodeSList_new ();
9362 static /*@exposed@*/ exprNode
9363 exprNode_lastStatement (/*@returned@*/ exprNode e)
9365 if (exprNode_isDefined (e))
9367 if (e->kind == XPR_STMTLIST)
9369 exprNode b = exprData_getPairB (e->edata);
9371 if (exprNode_isDefined (b))
9373 return exprNode_lastStatement (b);
9377 return exprNode_lastStatement (exprData_getPairA (e->edata));
9380 else if (e->kind == XPR_BLOCK)
9382 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
9390 return exprNode_undefined;
9393 static /*@exposed@*/ exprNode
9394 exprNode_firstStatement (/*@returned@*/ exprNode e)
9396 if (exprNode_isDefined (e))
9398 if (e->kind == XPR_STMTLIST)
9400 exprNode b = exprData_getPairA (e->edata);
9402 if (exprNode_isDefined (b))
9404 return exprNode_firstStatement (b);
9408 return exprNode_firstStatement (exprData_getPairB (e->edata));
9411 else if (e->kind == XPR_BLOCK)
9413 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
9421 return exprNode_undefined;
9425 exprNode_mergeUSs (exprNode res, exprNode other)
9427 if (exprNode_isDefined (res) && exprNode_isDefined (other))
9429 res->msets = sRefSet_union (res->msets, other->msets);
9430 res->sets = sRefSet_union (res->sets, other->sets);
9431 res->uses = sRefSet_union (res->uses, other->uses);
9436 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
9438 if (exprNode_isDefined (res))
9440 if (exprNode_isDefined (other1))
9442 res->sets = sRefSet_union (res->sets, other1->sets);
9443 res->msets = sRefSet_union (res->msets, other1->msets);
9444 res->uses = sRefSet_union (res->uses, other1->uses);
9446 if (exprNode_isDefined (other2))
9448 res->sets = sRefSet_union (res->sets, other2->sets);
9449 res->msets = sRefSet_union (res->msets, other2->msets);
9450 res->uses = sRefSet_union (res->uses, other2->uses);
9458 ** Reports errors is s is not defined.
9462 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
9464 if (exprNode_isDefined (e))
9466 e->uses = sRefSet_insert (e->uses, s);
9471 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
9473 if (sRef_isKnown (s) && !sRef_isConst (s))
9476 ** need to check all outer types are useable
9479 DPRINTF (("Check use: %s / %s",
9480 exprNode_unparse (e), sRef_unparse (s)));
9482 exprNode_addUse (e, s);
9484 if (!context_inProtectVars ())
9487 ** only report the deepest error
9490 sRef errorRef = sRef_undefined;
9491 sRef lastRef = sRef_undefined;
9492 bool deadRef = FALSE;
9493 bool unuseable = FALSE;
9494 bool errorMaybe = FALSE;
9496 while (sRef_isValid (s) && sRef_isKnown (s))
9498 ynm readable = sRef_isReadable (s);
9500 DPRINTF (("Readable: %s / %s",
9501 sRef_unparseFull (s), ynm_unparse (readable)));
9503 if (!(ynm_toBoolStrict (readable)))
9505 if (ynm_isMaybe (readable))
9509 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
9510 deadRef = sRef_isPossiblyDead (errorRef);
9511 unuseable = sRef_isUnuseable (errorRef);
9518 deadRef = sRef_isDead (errorRef);
9519 unuseable = sRef_isUnuseable (errorRef);
9523 if (!sRef_isPartial (s))
9525 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
9526 sRef_setDefined (s, fileloc_undefined);
9530 s = sRef_getBaseSafe (s);
9533 if (sRef_isValid (errorRef))
9535 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
9536 && sRef_isPointer (errorRef))
9543 if (sRef_isThroughArrayFetch (errorRef))
9546 (FLG_STRICTUSERELEASED,
9547 message ("%q %q may be used after being released",
9548 sRef_unparseKindNamePlain (errorRef),
9549 sRef_unparse (errorRef)),
9552 sRef_showRefKilled (errorRef);
9554 if (sRef_isKept (errorRef))
9556 sRef_clearAliasState (errorRef, loc);
9562 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
9566 message ("%q %q %qused after being released",
9567 sRef_unparseKindNamePlain (errorRef),
9568 sRef_unparse (errorRef),
9569 cstring_makeLiteral (errorMaybe
9573 sRef_showRefKilled (errorRef);
9575 if (sRef_isKept (errorRef))
9577 sRef_clearAliasState (errorRef, loc);
9586 message ("%q %q%qused in inconsistent state",
9587 sRef_unparseKindName (errorRef),
9588 sRef_unparseOpt (errorRef),
9589 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9592 sRef_showStateInconsistent (errorRef);
9597 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
9601 message ("%q %q%qused before definition",
9602 sRef_unparseKindName (errorRef),
9603 sRef_unparseOpt (errorRef),
9604 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9607 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
9610 sRef_setDefined (errorRef, loc);
9612 if (sRef_isAddress (errorRef))
9614 sRef_setDefined (sRef_getRootBase (errorRef), loc);
9616 } /* end is error */
9624 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
9626 if (exprNode_isDefined (e) && sRef_isKnown (s))
9628 e->uses = sRefSet_insert (e->uses, s);
9633 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
9635 if (exprNode_isDefined (e))
9637 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
9642 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
9644 sRef defines = sRef_undefined;
9646 if (sRef_isValid (s) && !sRef_isNothing (s))
9648 uentry ue = sRef_getBaseUentry (s);
9650 if (uentry_isValid (ue))
9652 uentry_setLset (ue);
9655 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9657 voptgenerror (FLG_USEDEF,
9658 message ("Attempt to set unuseable storage: %q",
9663 if (sRef_isMeaningful (s))
9666 if (sRef_isDead (s))
9668 sRef base = sRef_getBaseSafe (s);
9670 if (sRef_isValid (base)
9671 && sRef_isDead (base))
9673 sRef_setPartial (s, exprNode_loc (e));
9676 defines = s; /* okay - modifies for only param */
9678 else if (sRef_isPartial (s))
9680 sRef eref = exprNode_getSref (e);
9682 if (!sRef_isPartial (eref))
9685 ** should do something different here???
9688 sRef_setDefinedComplete (eref, exprNode_loc (e));
9692 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
9695 if (sRef_isMeaningful (eref))
9704 else if (sRef_isAllocated (s))
9706 sRef eref = exprNode_getSref (e);
9709 if (!sRef_isAllocated (eref))
9711 sRef_setDefinedComplete (eref, exprNode_loc (e));
9715 sRef base = sRef_getBaseSafe (eref);
9717 if (sRef_isValid (base))
9719 sRef_setPdefined (base, exprNode_loc (e));
9727 sRef_setDefinedNCComplete (s, exprNode_loc (e));
9732 else /* not meaningful...but still need to insert it */
9738 if (exprNode_isDefined (e) && sRef_isValid (defines))
9740 e->sets = sRefSet_insert (e->sets, defines);
9745 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
9747 if (sRef_isValid (s) && !sRef_isNothing (s))
9749 uentry ue = sRef_getBaseUentry (s);
9751 if (uentry_isValid (ue))
9753 uentry_setLset (ue);
9756 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9758 voptgenerror (FLG_USEDEF,
9759 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
9763 if (sRef_isMeaningful (s))
9765 sRef_setDefinedComplete (s, exprNode_loc (e));
9768 if (exprNode_isDefined (e))
9770 e->msets = sRefSet_insert (e->msets, s);
9776 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
9778 checkAnyCall (fcn, cstring_undefined, params, args,
9779 FALSE, sRefSet_undefined, FALSE, 0);
9783 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
9784 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
9788 if (uentry_isYield (ucurrent))
9790 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
9791 exprNode_checkSet (current, current->sref);
9795 if (uentry_isSefParam (ucurrent))
9797 sRefSet sets = current->sets;
9798 sRef ref = exprNode_getSref (current);
9800 if (sRef_isMacroParamRef (ref))
9802 uentry ue = sRef_getUentry (ref);
9804 if (!uentry_isSefParam (ue))
9809 ("Parameter %d to %s is declared sef, but "
9810 "the argument is a macro parameter declared "
9812 argno, exprNode_unparse (fcn),
9813 exprNode_unparse (current)),
9814 exprNode_loc (current));
9818 if (!sRefSet_isEmpty (sets))
9820 sRefSet reported = sRefSet_undefined;
9822 sRefSet_realElements (current->sets, el)
9824 if (sRefSet_isSameNameMember (reported, el))
9826 ; /* don't report again */
9830 if (sRef_isUnconstrained (el))
9835 ("Parameter %d to %s is declared sef, but "
9836 "the argument calls unconstrained function %s "
9837 "(no guarantee it will not modify something): %s",
9838 argno, exprNode_unparse (fcn),
9839 sRef_unconstrainedName (el),
9840 exprNode_unparse (current)),
9841 exprNode_loc (current));
9848 ("Parameter %d to %s is declared sef, but "
9849 "the argument may modify %q: %s",
9850 argno, exprNode_unparse (fcn),
9852 exprNode_unparse (current)),
9853 exprNode_loc (current));
9856 } end_sRefSet_realElements;
9860 checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs);
9861 exprNode_mergeUSs (fcn, current);
9866 checkAnyCall (/*@dependent@*/ exprNode fcn,
9867 /*@dependent@*/ cstring fname,
9870 bool hasMods, sRefSet mods,
9875 int nargs = exprNodeList_size (args);
9880 ** concat all args ud's to f, add each arg sref as a use unless
9881 ** it was specified as "out", in which case it is a def.
9884 uentryList_reset (pn);
9889 ** if paramn is only or unique, no other arg may alias argn
9892 exprNodeList_elements (args, current)
9896 if (exprNode_isDefined (current))
9898 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
9900 uentry ucurrent = uentryList_current (pn);
9902 if (specialArgs == 0
9903 || (paramno < specialArgs))
9905 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
9907 if (context_maybeSet (FLG_ALIASUNIQUE))
9909 if (uentry_isOnly (ucurrent)
9910 || uentry_isUnique (ucurrent))
9912 checkUniqueParams (fcn, current, args,
9918 else /* uentry is undefined */
9920 if (specialArgs == 0)
9922 exprNode_checkUseParam (current);
9925 exprNode_mergeUSs (fcn, current);
9928 uentryList_advanceSafe (pn);
9929 } end_exprNodeList_elements;
9935 sRefSet_allElements (mods, s)
9938 sRef rb = sRef_getRootBase (s);
9940 if (sRef_isFileOrGlobalScope (rb))
9942 context_usedGlobal (rb);
9945 fb = sRef_fixBaseParam (s, args);
9947 if (!sRef_isMacroParamRef (fb))
9949 if (sRef_isNothing (fb))
9955 if (sRef_isValid (fb))
9957 uentry ue = sRef_getBaseUentry (s);
9959 if (uentry_isValid (ue))
9961 uentry_setLset (ue);
9965 fcn->sets = sRefSet_insert (fcn->sets, fb);
9968 sRef_clearDerivedComplete (s);
9969 } end_sRefSet_allElements;
9975 if (context_hasMods ())
9977 if (context_maybeSet (FLG_MODUNCON))
9981 message ("Undetected modification possible "
9982 "from call to unconstrained function %s: %s",
9984 exprNode_unparse (fcn)),
9985 exprNode_loc (fcn));
9990 if (context_maybeSet (FLG_MODUNCONNOMODS)
9991 && !(context_inIterDef () || context_inIterEnd ()))
9994 (FLG_MODUNCONNOMODS,
9995 message ("Undetected modification possible "
9996 "from call to unconstrained function %s: %s",
9998 exprNode_unparse (fcn)),
9999 exprNode_loc (fcn));
10003 exprNode_checkSetAny (fcn, fname);
10007 void exprNode_checkUseParam (exprNode current)
10009 if (exprNode_isDefined (current))
10011 exprNode_checkUse (current, current->sref, current->loc);
10016 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10017 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10022 if (!ctype_match (tr1, tr2))
10024 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10025 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10031 (void) gentypeerror
10033 message ("Incompatible types for %s (%s, %s): %s %s %s",
10034 lltok_unparse (op),
10035 ctype_unparse (te1),
10036 ctype_unparse (te2),
10037 exprNode_unparse (e1), lltok_unparse (op),
10038 exprNode_unparse (e2)),
10041 ret = ctype_unknown;
10045 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
10047 ret = ctype_resolveNumerics (tr1, tr2);
10049 else if (!context_msgStrictOps ())
10051 if (ctype_isPointer (tr1))
10053 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10057 else if (ctype_isInt (tr2))
10063 ret = ctype_unknown;
10066 else if (ctype_isPointer (tr2))
10068 if (ctype_isPointer (tr1))
10072 else if (ctype_isInt (tr1))
10078 ret = ctype_unknown;
10083 ret = ctype_resolveNumerics (tr1, tr2);
10088 int opid = lltok_getTok (op);
10089 bool comparop = (opid == EQ_OP || opid == NE_OP
10090 || opid == TLT || opid == TGT
10091 || opid == LE_OP || opid == GE_OP);
10093 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10096 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10097 || (ctype_isBool (tr1) && ctype_isBool (tr2))
10098 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10104 if (ctype_sameName (te1, te2))
10108 message ("Operands of %s are non-numeric (%t): %s %s %s",
10109 lltok_unparse (op), te1,
10110 exprNode_unparse (e1), lltok_unparse (op),
10111 exprNode_unparse (e2)),
10118 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10119 lltok_unparse (op), te1, te2,
10120 exprNode_unparse (e1), lltok_unparse (op),
10121 exprNode_unparse (e2)),
10126 else if (!ctype_isNumeric (tr1))
10130 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10131 lltok_unparse (op), te1,
10132 exprNode_unparse (e1), lltok_unparse (op),
10133 exprNode_unparse (e2)),
10138 if (!ctype_isNumeric (tr2))
10142 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10143 lltok_unparse (op), te2,
10144 exprNode_unparse (e1), lltok_unparse (op),
10145 exprNode_unparse (e2)),
10150 ret = ctype_unknown;
10158 abstractOpError (ctype tr1, ctype tr2, lltok op,
10159 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10160 fileloc loc1, fileloc loc2)
10162 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10164 if (ctype_match (tr1, tr2))
10168 message ("Operands of %s are abstract type (%t): %s %s %s",
10169 lltok_unparse (op), tr1,
10170 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10177 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10178 lltok_unparse (op), tr1, tr2,
10179 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10183 else if (ctype_isRealAbstract (tr1))
10187 message ("Left operand of %s is abstract type (%t): %s %s %s",
10188 lltok_unparse (op), tr1,
10189 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10194 if (ctype_isRealAbstract (tr2))
10198 message ("Right operand of %s is abstract type (%t): %s %s %s",
10199 lltok_unparse (op), tr2,
10200 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10209 ** requies e1 and e2 and not error exprNode's.
10213 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10214 ** the rep of the abstract type is exposed.
10216 ** The order is very important:
10218 ** check rep expose (move into check transfer)
10224 ** This isn't really a sensible procedure, but the indententation
10225 ** was getting too deep.
10229 checkOneRepExpose (sRef ysr, sRef base,
10230 /*@notnull@*/ exprNode e1,
10231 /*@notnull@*/ exprNode e2, ctype ct,
10234 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
10235 || sRef_isOwned (ysr)
10236 || sRef_isExposed (ysr)))
10238 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10239 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10242 if (sRef_isIReference (ysr))
10244 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10249 ("Assignment of mutable component of parameter %q "
10250 "to component of abstract "
10251 "type %s exposes rep: %s = %s",
10252 sRef_unparse (base),
10253 ctype_unparse (ct),
10254 exprNode_unparse (e1), exprNode_unparse (e2)),
10262 ("Assignment of mutable component of parameter %q "
10263 "(through alias %q) to component of abstract "
10264 "type %s exposes rep: %s = %s",
10265 sRef_unparse (base),
10266 sRef_unparse (e2->sref),
10267 ctype_unparse (ct),
10268 exprNode_unparse (e1), exprNode_unparse (e2)),
10274 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10278 message ("Assignment of mutable parameter %q "
10279 "to component of abstract type %s "
10280 "exposes rep: %s = %s",
10281 sRef_unparse (base),
10282 ctype_unparse (ct),
10283 exprNode_unparse (e1),
10284 exprNode_unparse (e2)),
10291 message ("Assignment of mutable parameter %q "
10292 "(through alias %q) to "
10293 "component of abstract type %s exposes "
10295 sRef_unparse (base),
10296 sRef_unparse (e2->sref),
10297 ctype_unparse (ct),
10298 exprNode_unparse (e1),
10299 exprNode_unparse (e2)),
10305 if (sRef_isFileOrGlobalScope (s2b))
10307 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10311 message ("Assignment of global %q "
10313 "abstract type %s exposes rep: %s = %s",
10314 sRef_unparse (base),
10315 ctype_unparse (ct),
10316 exprNode_unparse (e1), exprNode_unparse (e2)),
10323 message ("Assignment of global %q (through alias %q) "
10325 "abstract type %s exposes rep: %s = %s",
10326 sRef_unparse (base),
10327 sRef_unparse (e2->sref),
10328 ctype_unparse (ct),
10329 exprNode_unparse (e1), exprNode_unparse (e2)),
10337 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
10339 if (ctype_isRealFunction (exprNode_getType (e1))
10340 && !ctype_isRealPointer (exprNode_getType (e1)))
10344 message ("Invalid left-hand side of assignment (function type %s): %s",
10345 ctype_unparse (exprNode_getType (e1)),
10346 exprNode_unparse (e1)),
10350 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
10352 ctype t2 = exprNode_getType (e2);
10353 sRef sr = sRef_getRootBase (e1->sref);
10354 ctype ct = sRef_getType (sr);
10356 if (ctype_isAbstract (t2)
10357 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
10359 /* it is immutable, okay to reference */
10360 goto donerepexpose;
10363 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
10365 sRef s2b = sRef_getRootBase (e2->sref);
10366 sRef s1 = e1->sref;
10367 sRef s1b = sRef_getRootBase (s1);
10370 aliases = usymtab_canAlias (e2->sref);
10372 if (!sRef_similar (s2b, s1b)
10373 && !sRef_isExposed (s1)
10374 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
10376 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
10377 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
10378 && !sRef_isExposed (s2b))
10380 if (sRef_isIReference (e2->sref))
10385 ("Assignment of mutable component of parameter %q "
10386 "to component of abstract type %s exposes rep: %s = %s",
10387 sRef_unparse (s2b),
10388 ctype_unparse (ct),
10389 exprNode_unparse (e1), exprNode_unparse (e2)),
10396 message ("Assignment of mutable parameter %q to "
10397 "component of abstract type %s exposes rep: %s = %s",
10398 sRef_unparse (s2b),
10399 ctype_unparse (ct),
10400 exprNode_unparse (e1), exprNode_unparse (e2)),
10405 if (sRef_isFileOrGlobalScope (s2b))
10409 message ("Assignment of global %q to component of "
10410 "abstract type %s exposes rep: %s = %s",
10411 sRef_unparse (s2b),
10412 ctype_unparse (ct),
10413 exprNode_unparse (e1), exprNode_unparse (e2)),
10417 sRefSet_realElements (aliases, ysr)
10419 sRef base = sRef_getRootBase (ysr);
10421 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
10422 || sRef_sameName (base, s1b))
10424 ; /* error already reported or same sref */
10428 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
10430 } end_sRefSet_realElements;
10432 sRefSet_free (aliases);
10439 ** function variables don't really work...
10442 if (!ctype_isFunction (ctype_realType (e2->typ)))
10446 DPRINTF (("Check init: %s / %s",
10447 exprNode_unparse (e1), exprNode_unparse (e2)));
10448 checkInitTransfer (e1, e2);
10452 checkAssignTransfer (e1, e2);
10457 sRef fref = e2->sref;
10459 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
10460 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
10462 /* Need to typecheck the annotation on the parameters */
10464 if (ctype_isRealFunction (e1->typ)) {
10465 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
10466 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
10468 if (!uentryList_isMissingParams (e1p)
10469 && !uentryList_isMissingParams (e2p)
10470 && uentryList_size (e1p) > 0) {
10471 if (uentryList_size (e1p) == uentryList_size (e2p)) {
10474 uentryList_elements (e1p, el1) {
10477 el2 = uentryList_getN (e2p, n);
10479 uentry_checkMatchParam (el1, el2, n, e2);
10480 } end_uentryList_elements;
10486 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
10492 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
10493 updateAliases (e1, e2);
10498 checkMacroParen (exprNode e)
10500 if (exprNode_isError (e) || e->kind == XPR_CAST)
10506 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
10510 message ("Macro parameter used without parentheses: %s",
10511 exprNode_unparse (e)),
10518 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
10522 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
10526 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
10533 ** if e2 is a parameter or global derived location which
10534 ** can be modified (that is, e2 is a mutable abstract type,
10535 ** or a derived pointer), then e1 can alias e2.
10537 ** e1 can alias everything which e2 can alias.
10539 ** Also, if e1 is guarded, remove from guard sets!
10542 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
10544 if (!context_inProtectVars ())
10547 ** depends on types of e1 and e2
10550 sRef s1 = e1->sref;
10551 sRef s2 = e2->sref;
10552 ctype t1 = exprNode_getType (e1);
10554 /* handle pointer sRefs, record fields, arrays, etc... */
10556 if (!ctype_isRealSU (t1))
10558 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
10559 sRef_copyRealDerivedComplete (s1, s2);
10564 ** Fields should alias
10567 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
10570 if (ctype_isMutable (t1) && sRef_isKnown (s1))
10572 usymtab_clearAlias (s1);
10573 usymtab_addMustAlias (s1, s2);
10574 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
10578 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
10581 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
10583 usymtab_unguard (s1);
10588 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
10590 if (exprNode_isDefined (e))
10592 e->loc = fileloc_update (e->loc, loc);
10596 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
10602 static void checkUniqueParams (exprNode fcn,
10603 /*@notnull@*/ exprNode current,
10605 int paramno, uentry ucurrent)
10608 sRef thisref = exprNode_getSref (current);
10611 ** Check if any argument could match this argument.
10614 exprNodeList_elements (args, icurrent)
10618 if (iparamno != paramno)
10620 sRef sr = exprNode_getSref (icurrent);
10622 if (sRef_similarRelaxed (thisref, sr))
10624 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
10629 ("Parameter %d (%s) to function %s is declared %s but "
10630 "is aliased by parameter %d (%s)",
10632 exprNode_unparse (current),
10633 exprNode_unparse (fcn),
10634 alkind_unparse (uentry_getAliasKind (ucurrent)),
10635 iparamno, exprNode_unparse (icurrent)),
10641 sRefSet aliases = usymtab_canAlias (sr);
10643 sRefSet_allElements (aliases, asr)
10645 if (ctype_isUnknown (sRef_getType (thisref)))
10647 sRef_setType (thisref, uentry_getType (ucurrent));
10650 if (sRef_similarRelaxed (thisref, asr))
10652 if (sRef_isExternal (asr))
10654 if (sRef_isLocalState (thisref))
10660 sRef base = sRef_getRootBase (asr);
10662 if (!sRef_similar (sRef_getBase (asr), thisref))
10664 if (sRef_isUnique (base) || sRef_isOnly (base)
10665 || sRef_isKept (base)
10666 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
10667 || (sRef_isAddress (thisref)
10668 && sRef_isLocalVar (sRef_getRootBase (thisref))))
10670 ; /* okay, no error */
10675 (FLG_MAYALIASUNIQUE,
10677 ("Parameter %d (%s) to function %s is declared %s but "
10678 "may be aliased externally by parameter %d (%s)",
10680 exprNode_unparse (current),
10681 exprNode_unparse (fcn),
10682 alkind_unparse (uentry_getAliasKind (ucurrent)),
10683 iparamno, exprNode_unparse (icurrent)),
10694 ("Parameter %d (%s) to function %s is declared %s but "
10695 "is aliased externally by parameter %d (%s) through "
10698 exprNode_unparse (current),
10699 exprNode_unparse (fcn),
10700 alkind_unparse (uentry_getAliasKind (ucurrent)),
10701 iparamno, exprNode_unparse (icurrent),
10702 sRef_unparse (asr)),
10706 } end_sRefSet_allElements;
10707 sRefSet_free (aliases);
10710 } end_exprNodeList_elements;
10713 long exprNode_getLongValue (exprNode e) {
10716 if (exprNode_hasValue (e)
10717 && multiVal_isInt (exprNode_getValue (e)))
10719 value = multiVal_forceInt (exprNode_getValue (e));
10729 /*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
10731 if (exprNode_isDefined (p_e) )
10732 return ( p_e->loc );
10734 return fileloc_undefined;
10737 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
10740 ** Returns the location of the sequence point following e.
10742 ** Only works for statements (for now).
10745 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
10746 lltok t = exprData_getUopTok (e->edata);
10747 return fileloc_copy(lltok_getLoc (t));
10749 //drl possible problem : warning fix
10750 // llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
10751 return fileloc_undefined;
10755 exprNode exprNode_createNew(ctype c)
10759 ret = exprNode_createPlain (c);
10764 bool exprNode_isInitBlock (exprNode e)
10766 return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);