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);
1025 static /*@only@*/ /*@notnull@*/ exprNode
1026 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
1028 exprNode e = exprNode_createId (c);
1031 uentry_setUsed (c, e->loc);
1033 if (uentry_isVar (c) && sRef_isFileOrGlobalScope (sr))
1035 checkGlobUse (c, FALSE, e);
1042 exprNode_isZero (exprNode e)
1044 if (exprNode_isDefined (e))
1046 multiVal m = exprNode_getValue (e);
1048 if (multiVal_isInt (m))
1050 return (multiVal_forceInt (m) == 0);
1058 exprNode_isNonNegative (exprNode e)
1060 if (exprNode_isDefined (e))
1062 multiVal m = exprNode_getValue (e);
1064 if (multiVal_isInt (m))
1066 return (multiVal_forceInt (m) >= 0);
1074 ** a[x] - uses a but NOT a[]
1075 ** result sref = a[] (set/use in assignment)
1077 ** The syntax x[a] is also legal in C, and has the same
1078 ** semantics. If ind is an array, and arr is an int, flip
1083 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
1086 ** error in arr, error propagates (no new messages)
1087 ** error in ind, assume valid and continue
1090 if (exprNode_isError (e1))
1093 return (exprNode_makeError ());
1099 ctype carr = exprNode_getType (e1);
1100 ctype crarr = ctype_realType (carr);
1103 ** this sets up funny aliasing, that leads to spurious
1104 ** lclint errors. Hence, the i2 comments.
1107 if (!ctype_isRealArray (crarr)
1108 && ctype_isRealNumeric (crarr)
1109 && !exprNode_isError (e2)
1110 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1115 carr = exprNode_getType (arr);
1116 crarr = ctype_realType (carr);
1124 if (sRef_possiblyNull (arr->sref))
1126 if (!usymtab_isGuarded (arr->sref))
1128 if (optgenerror (FLG_NULLDEREF,
1129 message ("Index of %s pointer %q: %s",
1130 sRef_nullMessage (arr->sref),
1131 sRef_unparse (arr->sref),
1132 exprNode_unparse (arr)),
1135 sRef_showNullInfo (arr->sref);
1137 /* suppress future messages */
1138 sRef_setNullError (arr->sref);
1143 if (exprNode_isError (ind))
1145 if ((ctype_isArrayPtr (crarr)
1146 && !ctype_isFunction (crarr))
1147 || ctype_isUnknown (carr))
1149 exprNode ret = exprNode_createPartialCopy (arr);
1151 if (ctype_isKnown (carr))
1153 ret->typ = ctype_baseArrayPtr (crarr);
1157 ret->typ = ctype_unknown;
1160 ret->sref = sRef_makeArrayFetch (arr->sref);
1162 ret->kind = XPR_FETCH;
1165 ** Because of funny aliasing (when arr and ind are
1166 ** flipped) spurious errors would be reported here.
1169 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1170 checkSafeUse (ret, arr->sref);
1175 voptgenerror (FLG_TYPE,
1176 message ("Array fetch from non-array (%t): %s[%s]", carr,
1177 exprNode_unparse (e1), exprNode_unparse (e2)),
1179 exprNode_free (arr);
1180 return (exprNode_makeError ());
1185 if (!ctype_isForceRealInt (&(ind->typ)))
1187 ctype rt = ctype_realType (ind->typ);
1189 if (ctype_isChar (rt))
1193 message ("Array fetch using non-integer, %t: %s[%s]",
1195 exprNode_unparse (e1), exprNode_unparse (e2)),
1198 else if (ctype_isEnum (rt))
1202 message ("Array fetch using non-integer, %t: %s[%s]",
1204 exprNode_unparse (e1), exprNode_unparse (e2)),
1211 message ("Array fetch using non-integer, %t: %s[%s]",
1213 exprNode_unparse (e1), exprNode_unparse (e2)),
1217 multiVal_free (ind->val);
1218 ind->val = multiVal_unknown ();
1221 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1223 exprNode ret = exprNode_createSemiCopy (arr);
1224 multiVal m = exprNode_getValue (ind);
1226 ret->typ = ctype_baseArrayPtr (crarr);
1227 ret->kind = XPR_FETCH;
1229 if (multiVal_isInt (m))
1231 int i = (int) multiVal_forceInt (m);
1233 if (sRef_isValid (arr->sref)) {
1234 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1236 ret->sref = sRef_undefined;
1241 ret->sref = sRef_makeArrayFetch (arr->sref);
1244 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1245 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1246 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1248 /* (see comment on spurious errors above) */
1249 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1251 exprNode_checkUse (ret, ind->sref, ind->loc);
1252 exprNode_checkUse (ret, arr->sref, arr->loc);
1258 if (ctype_isUnknown (carr))
1260 exprNode ret = exprNode_createPartialCopy (arr);
1262 ret->kind = XPR_FETCH;
1263 ret->typ = ctype_unknown;
1264 ret->sets = sRefSet_union (ret->sets, ind->sets);
1265 ret->msets = sRefSet_union (ret->msets, ind->msets);
1266 ret->uses = sRefSet_union (ret->uses, ind->uses);
1268 /* (see comment on spurious errors above) */
1269 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1271 exprNode_checkUse (ret, ind->sref, ind->loc);
1272 exprNode_checkUse (ret, arr->sref, arr->loc);
1279 message ("Array fetch from non-array (%t): %s[%s]", carr,
1280 exprNode_unparse (e1), exprNode_unparse (e2)),
1283 exprNode_free (arr);
1284 exprNode_free (ind);
1286 return (exprNode_makeError ());
1296 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1297 exprNodeList args, exprNode ret)
1299 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1303 ** checkPrintfArgs --- checks arguments for printf-like functions
1304 ** Arguments before ... have already been checked.
1305 ** The argument before the ... is a char *.
1306 ** argno is the format string argument.
1310 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1311 exprNodeList args, exprNode ret, int argno)
1314 ** the last argument before the elips is the format string
1319 int nargs = exprNodeList_size (args);
1320 uentryList params = uentry_getParams (fcn);
1324 ** These should be ensured by checkSpecialFunction
1327 llassert (uentryList_size (params) == argno + 1);
1328 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1330 a = exprNodeList_getN (args, argno - 1);
1331 formatloc = fileloc_copy (exprNode_loc (a));
1333 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1334 && exprNode_knownStringValue (a))
1336 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1337 char *code = format;
1340 nargs = exprNodeList_size (args);
1342 while ((code = strchr (code, '%')) != NULL)
1344 char *origcode = code;
1345 cstring codetext = cstring_newEmpty ();
1346 char key = *(++code);
1347 ctype modtype = ctype_int;
1348 bool modified = FALSE;
1350 fileloc_addColumn (formatloc, code - ocode);
1352 codetext = cstring_appendChar (codetext, key);
1355 while (isFlagKey (key))
1358 codetext = cstring_appendChar (codetext, key);
1359 fileloc_incColumn (formatloc);
1362 if (key == 'm') /* skipped in syslog */
1367 /* ignore field width */
1368 while (isdigit ((int) key) != 0)
1371 codetext = cstring_appendChar (codetext, key);
1372 fileloc_incColumn (formatloc);
1375 /* ignore precision */
1379 codetext = cstring_appendChar (codetext, key);
1380 fileloc_incColumn (formatloc);
1383 ** In printf, '*' means: read the next arg as an int for the
1384 ** field width. This seems to be missing from my copy of the
1385 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1386 ** later) but never does.
1391 ; /* don't do anything --- handle later */
1395 while (isdigit ((int) key) != 0)
1398 codetext = cstring_appendChar (codetext, key);
1399 fileloc_incColumn (formatloc);
1406 modtype = ctype_sint; /* short */
1408 codetext = cstring_appendChar (codetext, key);
1409 fileloc_incColumn (formatloc);
1411 else if (key == 'l' || key == 'L')
1413 modtype = ctype_lint; /* long */
1415 codetext = cstring_appendChar (codetext, key);
1416 fileloc_incColumn (formatloc);
1418 if (key == 'l' || key == 'L') {
1419 modtype = ctype_llint; /* long long */
1421 codetext = cstring_appendChar (codetext, key);
1422 fileloc_incColumn (formatloc);
1430 /* now, key = type of conversion to apply */
1432 fileloc_incColumn (formatloc);
1440 message ("No argument corresponding to %q format "
1441 "code %d (%%%s): \"%s\"",
1442 uentry_getName (fcn),
1444 cstring_fromChars (format)),
1447 if (fileloc_isDefined (formatloc)
1448 && context_getFlag (FLG_SHOWCOL))
1450 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1458 a = exprNodeList_getN (args, i);
1461 if (!exprNode_isError (a))
1467 case '*': /* int argument for fieldwidth */
1468 expecttype = ctype_int;
1469 *(--code) = '%'; /* convert it for next code */
1470 fileloc_subColumn (formatloc, 1);
1471 /*@switchbreak@*/ break;
1474 expecttype = ctype_combine (ctype_uint, modtype);
1475 /*@switchbreak@*/ break;
1477 case 'i': /* int argument */
1479 expecttype = ctype_combine (ctype_int, modtype);
1480 /*@switchbreak@*/ break;
1482 case 'x': /* unsigned int */
1484 expecttype = ctype_combine (ctype_uint, modtype);
1486 /*@switchbreak@*/ break;
1492 case 'f': /* double */
1493 expecttype = ctype_combine (ctype_double, modtype);
1494 /*@switchbreak@*/ break;
1496 case 'c': /* int converted to char (check its a char?) */
1497 expecttype = ctype_makeConj (ctype_char, ctype_uchar);
1498 /*@switchbreak@*/ break;
1500 case 's': /* string */
1501 expecttype = ctype_string;
1502 /*@switchbreak@*/ break;
1505 while (((key = *(++code)) != ']')
1508 codetext = cstring_appendChar (codetext, key);
1509 fileloc_incColumn (formatloc);
1515 (message ("Bad character set format: %s",
1516 cstring_fromChars (origcode)));
1519 expecttype = ctype_string;
1520 /*@switchbreak@*/ break;
1522 case 'p': /* pointer */
1523 expecttype = ctype_makePointer (ctype_void);
1524 uentry_setDefState (regArg, SS_RELDEF); /* need not be defined */
1525 sRef_setPosNull (uentry_getSref (regArg), fileloc_undefined); /* could be null */
1526 /*@switchbreak@*/ break;
1528 case 'n': /* pointer to int, modified by call! */
1529 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1531 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1532 /*@switchbreak@*/ break;
1534 case 'm': /* in a syslog, it doesn't consume an argument */
1535 /* should check we're really doing syslog */
1537 /*@switchbreak@*/ break;
1541 expecttype = ctype_unknown;
1545 message ("Unrecognized format code: %s",
1546 cstring_fromChars (origcode)),
1547 fileloc_isDefined (formatloc)
1548 ? formatloc : g_currentloc);
1550 /*@switchbreak@*/ break;
1553 if (!(exprNode_matchArgType (expecttype, a)))
1555 if (ctype_isVoidPointer (expecttype)
1556 && ctype_isRealAbstract (a->typ)
1557 && (context_getFlag (FLG_ABSTVOIDP)))
1563 if (llgenformattypeerror
1564 (expecttype, exprNode_undefined,
1566 message ("Format argument %d to %q (%%%s) expects "
1569 uentry_getName (fcn),
1572 a->typ, exprNode_unparse (a)),
1575 if (fileloc_isDefined (formatloc)
1576 && context_getFlag (FLG_SHOWCOL))
1579 (cstring_makeLiteral
1580 ("Corresponding format code"),
1587 uentry_setType (regArg, expecttype);
1588 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1590 if (ctype_equal (expecttype, ctype_string))
1592 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1595 uentry_setType (regArg, ctype_unknown);
1596 uentry_fixupSref (regArg);
1600 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1611 cstring_free (codetext);
1616 voptgenerror (FLG_TYPE,
1617 message ("Format string for %q has %d arg%&, given %d",
1618 uentry_getName (fcn), i - argno, nargs - argno),
1624 /* no checking possible for compile-time unknown format strings */
1625 if (exprNode_isDefined (a))
1629 message ("Format string parameter to %s is not a compile-time constant: %s",
1630 exprNode_unparse (f),
1631 exprNode_unparse (a)),
1636 fileloc_free (formatloc);
1640 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1641 exprNodeList args, exprNode ret, int argno)
1645 int nargs = exprNodeList_size (args);
1646 uentryList params = uentry_getParams (fcn);
1650 ** These should be ensured by checkSpecialFunction
1653 llassert (uentryList_size (params) == argno + 1);
1654 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1656 a = exprNodeList_getN (args, argno - 1);
1657 formatloc = fileloc_copy (exprNode_loc (a));
1659 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1660 && exprNode_knownStringValue (a))
1662 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1663 char *code = format;
1666 nargs = exprNodeList_size (args);
1668 while ((code = strchr (code, '%')) != NULL)
1670 char *origcode = code;
1671 char key = *(++code);
1672 cstring codetext = cstring_newEmpty ();
1673 ctype modtype = ctype_int;
1674 char modifier = '\0';
1675 bool modified = TRUE;
1676 bool ignore = FALSE;
1678 codetext = cstring_appendChar (codetext, key);
1679 fileloc_addColumn (formatloc, code - ocode);
1682 ** this is based on ANSI standard library description of fscanf
1683 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1686 /* '*' suppresses assignment (does not need match argument) */
1691 codetext = cstring_appendChar (codetext, key);
1694 fileloc_incColumn (formatloc);
1697 /* ignore field width */
1698 while (isdigit ((int) key) != 0)
1701 codetext = cstring_appendChar (codetext, key);
1702 fileloc_incColumn (formatloc);
1707 modtype = ctype_sint; /* short */
1709 codetext = cstring_appendChar (codetext, key);
1710 fileloc_incColumn (formatloc);
1712 else if (key == 'l' || key == 'L')
1714 modtype = ctype_lint; /* long */
1718 codetext = cstring_appendChar (codetext, key);
1720 fileloc_incColumn (formatloc);
1722 if (key == 'l' || key == 'L') {
1723 modtype = ctype_llint; /* long long */
1725 codetext = cstring_appendChar (codetext, key);
1726 fileloc_incColumn (formatloc);
1734 /* now, key = type of conversion to apply */
1736 fileloc_incColumn (formatloc);
1750 message ("No argument corresponding to %q format "
1751 "code %d (%%%s): \"%s\"",
1752 uentry_getName (fcn),
1754 cstring_fromChars (format)),
1757 if (fileloc_isDefined (formatloc)
1758 && context_getFlag (FLG_SHOWCOL))
1761 (cstring_makeLiteral ("Corresponding format code"),
1769 a = exprNodeList_getN (args, i);
1772 if (!exprNode_isError (a))
1778 case '*': /* int argument for fieldwidth */
1779 expecttype = ctype_makePointer (ctype_int);
1780 *(--code) = '%'; /* convert it for next code */
1781 fileloc_subColumn (formatloc, 1);
1782 /*@switchbreak@*/ break;
1785 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1786 /*@switchbreak@*/ break;
1791 case 'X': /* unsigned int */
1792 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1793 /*@switchbreak@*/ break;
1800 /* printf is double, scanf is float! */
1802 if (modifier == 'l')
1804 expecttype = ctype_makePointer (ctype_double);
1806 else if (modifier == 'L')
1808 expecttype = ctype_makePointer (ctype_ldouble);
1812 llassert (modifier == '\0');
1813 expecttype = ctype_makePointer (ctype_float);
1815 /*@switchbreak@*/ break;
1817 case 'c': /* int converted to char (check its a char?) */
1818 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1819 /*@switchbreak@*/ break;
1821 case 's': /* string */
1822 expecttype = ctype_string;
1823 /*@switchbreak@*/ break;
1827 while (((key = *(++code)) != ']')
1830 codetext = cstring_appendChar (codetext, key);
1831 fileloc_incColumn (formatloc);
1837 (message ("Bad character set format: %s",
1838 cstring_fromChars (origcode)));
1841 expecttype = ctype_string;
1842 /*@switchbreak@*/ break;
1845 case 'p': /* pointer */
1848 message ("Format code should not be used in scanf: %s",
1849 cstring_fromChars (origcode)),
1850 fileloc_isDefined (formatloc)
1851 ? formatloc : g_currentloc);
1853 expecttype = ctype_unknown;
1854 /*@switchbreak@*/ break;
1856 case 'n': /* pointer to int, modified by call! */
1857 expecttype = ctype_makePointer (ctype_int);
1858 /*@switchbreak@*/ break;
1861 expecttype = ctype_unknown;
1865 message ("Unrecognized format code: %s",
1866 cstring_fromChars (origcode)),
1867 fileloc_isDefined (formatloc)
1868 ? formatloc : g_currentloc);
1870 /*@switchbreak@*/ break;
1873 if (!(exprNode_matchArgType (expecttype, a)))
1875 if (ctype_isVoidPointer (expecttype)
1876 && ctype_isRealAbstract (a->typ)
1877 && (context_getFlag (FLG_ABSTVOIDP)))
1883 if (llgenformattypeerror
1884 (expecttype, exprNode_undefined,
1886 message ("Format argument %d to %q (%%%s) expects "
1889 uentry_getName (fcn),
1890 codetext, expecttype,
1891 a->typ, exprNode_unparse (a)),
1894 if (fileloc_isDefined (formatloc)
1895 && context_getFlag (FLG_SHOWCOL))
1898 (cstring_makeLiteral
1899 ("Corresponding format code"),
1906 uentry_setType (outArg, expecttype);
1907 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
1908 uentry_setType (outArg, ctype_unknown);
1909 uentry_fixupSref (outArg);
1913 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1918 /* a->sref = defref; */
1925 cstring_free (codetext);
1930 voptgenerror (FLG_TYPE,
1931 message ("Format string for %q has %d arg%&, given %d",
1932 uentry_getName (fcn), i - argno, nargs - argno),
1938 /* no checking possible for compile-time unknown format strings */
1941 fileloc_free (formatloc);
1945 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
1948 /*@unused@*/ int argno)
1951 ** the last argument before the elips is the format string
1954 int nargs = exprNodeList_size (args);
1959 a = exprNodeList_getN (args, argno - 1);
1960 formatloc = fileloc_copy (exprNode_loc (a));
1962 if (ctype_isUnknown (cstringType)) {
1963 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
1965 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
1969 if (ctype_isUnknown (ctypeType)) {
1970 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
1972 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
1976 if (ctype_isUnknown (filelocType)) {
1977 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
1979 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
1983 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1984 && exprNode_knownStringValue (a))
1986 cstring format = multiVal_forceString (exprNode_getValue (a));
1987 char *code = cstring_toCharsSafe (format);
1990 nargs = exprNodeList_size (args);
1992 while ((code = strchr (code, '%')) != NULL)
1994 char *origcode = code;
1995 char key = *(++code);
1996 cstring codetext = cstring_newEmpty ();
1997 bool isOnly = FALSE;
1999 codetext = cstring_appendChar (codetext, key);
2001 fileloc_addColumn (formatloc, code - ocode);
2003 while (key >= '0' && key <= '9')
2006 codetext = cstring_appendChar (codetext, key);
2007 fileloc_incColumn (formatloc);
2011 fileloc_incColumn (formatloc);
2015 if (key == '&') /* plural marker */
2024 message ("Message missing format arg %d (%%%s): \"%s\"",
2025 i + 1, codetext, format),
2031 a = exprNodeList_getN (args, i);
2035 if (!exprNode_isError (a))
2039 /*@-loopswitchbreak@*/
2045 expecttype = ctype_char; break;
2047 expecttype = cstringType; break;
2049 expecttype = cstringType; isOnly = TRUE; break;
2051 expecttype = cstringType; isOnly = TRUE; break;
2052 case 'd': expecttype = ctype_int; break;
2053 case 'u': expecttype = ctype_uint; break;
2054 case 'w': expecttype = ctype_ulint; break;
2055 case 'f': expecttype = ctype_float; break;
2056 case 'b': expecttype = ctype_bool; break;
2057 case 't': expecttype = ctypeType; break;
2058 case 'l': expecttype = filelocType; break;
2059 case '&': /* a wee bit of a hack methinks */
2060 expecttype = ctype_int;
2062 case 'r': expecttype = ctype_bool; break;
2064 expecttype = ctype_unknown;
2067 message ("Unrecognized format code: %s",
2068 cstring_fromChars (origcode)),
2069 fileloc_isDefined (formatloc)
2070 ? formatloc : g_currentloc);
2073 /*@=loopswitchbreak@*/
2075 if (!(exprNode_matchArgType (expecttype, a)))
2077 if (ctype_isVoidPointer (expecttype)
2078 && ctype_isRealAbstract (a->typ)
2079 && (context_getFlag (FLG_ABSTVOIDP)))
2085 if (llgenformattypeerror
2086 (expecttype, exprNode_undefined,
2088 message ("Format argument %d to %q (%%%s) expects "
2091 uentry_getName (fcn),
2092 codetext, expecttype,
2093 a->typ, exprNode_unparse (a)),
2096 if (fileloc_isDefined (formatloc)
2097 && context_getFlag (FLG_SHOWCOL))
2100 (cstring_makeLiteral
2101 ("Corresponding format code"),
2108 if (ctype_equal (expecttype, cstringType))
2112 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2113 uentry_fixupSref (csOnlyArg);
2117 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2118 uentry_fixupSref (csArg);
2123 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2124 uentry_fixupSref (regArg);
2130 cstring_free (codetext);
2135 voptgenerror (FLG_TYPE,
2136 message ("Format string for %q has %d arg%&, given %d",
2137 uentry_getName (fcn), i - argno, nargs -argno),
2143 /* no checking possible for compile-time unknown format strings */
2146 fileloc_free (formatloc);
2150 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2151 /*@notnull@*/ exprNode e2,
2157 bool hadUncon = FALSE;
2159 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
2160 sRefSet_hasUnconstrained (sets2))
2163 (FLG_EVALORDERUNCON,
2165 ("Expression may have undefined behavior (%q used in right operand "
2166 "may set global variable %q used in left operand): %s %s %s",
2167 sRefSet_unparseUnconstrained (sets2),
2168 sRef_unparse (sRef_getRootBase (e1->sref)),
2169 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2173 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
2174 sRefSet_hasUnconstrained (sets1))
2177 (FLG_EVALORDERUNCON,
2179 ("Expression has undefined behavior (%q used in left operand "
2180 "may set global variable %q used in right operand): %s %s %s",
2181 sRefSet_unparseUnconstrained (sets1),
2182 sRef_unparse (e2->sref),
2183 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2187 sRefSet_realElements (e1->uses, sr)
2189 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2194 ("Expression has undefined behavior (left operand uses %q, "
2195 "modified by right operand): %s %s %s",
2197 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2200 } end_sRefSet_realElements;
2202 sRefSet_realElements (sets1, sr)
2204 if (sRef_isMeaningful (sr))
2206 if (sRef_same (sr, e2->sref))
2211 ("Expression has undefined behavior (value of right operand "
2212 "modified by left operand): %s %s %s",
2213 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2216 else if (sRefSet_member (e2->uses, sr))
2221 ("Expression has undefined behavior (left operand modifies %q, "
2222 "used by right operand): %s %s %s",
2224 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2229 if (sRefSet_member (sets2, sr))
2231 if (sRef_isUnconstrained (sr))
2239 hadUncon = optgenerror
2240 (FLG_EVALORDERUNCON,
2242 ("Expression may have undefined behavior. Left operand "
2243 "calls %q; right operand calls %q. The unconstrained "
2244 "functions may modify global state used by "
2245 "the other operand): %s %s %s",
2246 sRefSet_unparseUnconstrained (sets1),
2247 sRefSet_unparseUnconstrained (sets2),
2248 exprNode_unparse (e1), lltok_unparse (op),
2249 exprNode_unparse (e2)),
2258 ("Expression has undefined behavior (both "
2259 "operands modify %q): %s %s %s",
2261 exprNode_unparse (e1),
2262 lltok_unparse (op), exprNode_unparse (e2)),
2268 } end_sRefSet_realElements;
2271 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2273 bool hasError = FALSE;
2275 if (exprNode_isError (e1) || exprNode_isError (e2))
2280 if (sRefSet_member (e2->sets, e1->sref))
2282 if (e2->kind == XPR_CALL)
2288 hasError = optgenerror
2290 message ("Expression has undefined behavior "
2291 "(value of left operand %s is modified "
2292 "by right operand %s): %s %s %s",
2293 exprNode_unparse (e1),
2294 exprNode_unparse (e2),
2295 exprNode_unparse (e1), lltok_unparse (op),
2296 exprNode_unparse (e2)),
2301 if (context_getFlag (FLG_EVALORDERUNCON))
2303 if (sRefSet_member (e2->msets, e1->sref))
2305 if (e2->kind == XPR_CALL)
2311 hasError = optgenerror
2314 ("Expression has undefined behavior (value of left "
2315 "operand may be modified by right operand): %s %s %s",
2316 exprNode_unparse (e1), lltok_unparse (op),
2317 exprNode_unparse (e2)),
2325 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2327 if (context_maybeSet (FLG_EVALORDERUNCON))
2329 checkExpressionDefinedAux (e1, e2, e1->msets,
2330 e2->msets, op, FLG_EVALORDERUNCON);
2335 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2338 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2339 exprNodeList args, bool isIter, exprNode ret)
2343 if (!exprNode_isError (f))
2345 if (!uentryList_isMissingParams (cl))
2347 int nargs = exprNodeList_size (args);
2348 int expectargs = uentryList_size (cl);
2352 if (expectargs == 0)
2360 message ("Iter %q invoked with %d args, "
2362 uentry_getName (fcn),
2370 message ("Function %s called with %d args, "
2372 exprNode_unparse (f), nargs),
2379 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2381 exprNodeList_reset (args);
2383 uentryList_elements (cl, current)
2385 ctype ct = uentry_getType (current);
2388 if (ctype_isElips (ct))
2391 ** do special checking for printf/scanf library functions
2393 ** this is kludgey code, just for handling the special case
2397 if (uentry_isPrintfLike (fcn))
2399 checkPrintfArgs (f, fcn, args, ret, i);
2402 else if (uentry_isScanfLike (fcn))
2404 checkScanfArgs (f, fcn, args, ret, i);
2407 else if (uentry_isMessageLike (fcn))
2409 checkMessageArgs (f, fcn, args, i);
2414 llassert (!uentry_isSpecialFunction (fcn));
2417 nargs = expectargs; /* avoid errors */
2422 if (i >= nargs) break;
2424 a = exprNodeList_current (args);
2425 exprNodeList_advance (args);
2429 if (exprNode_isError (a))
2436 probably necessary? I'm not sure about this one
2437 checkMacroParen (a);
2440 f->guards = guardSet_union (f->guards, a->guards);
2442 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2444 if (!(exprNode_matchArgType (ct, a)))
2446 DPRINTF (("Args mismatch!"));
2448 if (ctype_isVoidPointer (ct)
2449 && (ctype_isPointer (a->typ)
2450 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2455 ("Pointer to abstract type (%t) used "
2457 "(arg %d to %q): %s",
2459 uentry_getName (fcn),
2460 exprNode_unparse (a)),
2468 (ct, exprNode_undefined,
2471 ("Iter %q expects arg %d to "
2472 "be %t gets %t: %s",
2473 uentry_getName (fcn),
2474 i, ct, a->typ, exprNode_unparse (a)),
2485 ("Function %q expects arg %d to be %t gets %t: %s",
2486 uentry_getName (fcn),
2487 i, ct, a->typ, exprNode_unparse (a)),
2490 DPRINTF (("Types: %s / %s",
2492 ctype_unparse (a->typ)));
2496 ** Clear null marker for abstract types.
2497 ** (It is not revealed, so suppress future messages.)
2500 if (ctype_isAbstract (a->typ))
2502 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2509 } end_uentryList_elements ;
2512 if (expectargs != nargs) /* note: not != since we may have ... */
2514 if (ctype_isElips (last))
2518 message ("Function %s called with %d args, expects at least %d",
2519 exprNode_unparse (f),
2520 nargs, expectargs - 1),
2529 message ("Iter %q invoked with %d args, expects %d",
2530 uentry_getName (fcn), nargs, expectargs),
2537 message ("Function %s called with %d args, expects %d",
2538 exprNode_unparse (f),
2551 ** Check for undefined code sequences in function arguments:
2553 ** one parameter sets something used by another parameter
2554 ** one parameter sets something set by another parameter
2558 checkSequencingOne (exprNode f, exprNodeList args,
2559 /*@notnull@*/ exprNode el, int argno)
2562 ** Do second loop, iff +undefunspec
2566 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2568 for (checkloop = 0; checkloop < numloops; checkloop++)
2574 thissets = el->sets;
2578 llassert (checkloop == 1);
2579 thissets = el->msets;
2582 sRefSet_realElements (thissets, thisset)
2586 /*@access exprNodeList@*/
2587 for (j = 0; j < args->nelements; j++)
2589 exprNode jl = args->elements[j];
2590 int thisargno = j + 1;
2592 if (thisargno != argno && exprNode_isDefined (jl))
2594 sRefSet otheruses = jl->uses;
2596 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
2597 sRefSet_hasUnconstrained (thissets))
2600 (FLG_EVALORDERUNCON,
2603 ("%q used in argument %d may set "
2604 "global variable %q used by argument %d: %s(%q)",
2605 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2608 sRef_unparse (sRef_getRootBase (jl->sref)),
2610 exprNode_unparse (f), exprNodeList_unparse (args)),
2614 if (sRefSet_member (otheruses, thisset))
2616 if (sRef_isUnconstrained (thisset))
2619 (FLG_EVALORDERUNCON,
2621 ("Unconstrained functions used in arguments %d (%q) "
2622 "and %d (%s) may modify "
2623 "or use global state in undefined way: %s(%q)",
2625 sRefSet_unparseUnconstrainedPlain (otheruses),
2627 sRef_unconstrainedName (thisset),
2628 exprNode_unparse (f),
2629 exprNodeList_unparse (args)),
2637 ("Argument %d modifies %q, used by argument %d "
2638 "(order of evaluation of actual parameters is "
2639 "undefined): %s(%q)",
2640 argno, sRef_unparse (thisset), thisargno,
2641 exprNode_unparse (f), exprNodeList_unparse (args)),
2647 sRefSet othersets = jl->sets;
2649 if (sRefSet_member (othersets, thisset))
2651 if (sRef_isUnconstrained (thisset))
2654 (FLG_EVALORDERUNCON,
2656 ("Unconstrained functions used in "
2657 "arguments %d (%q) and %d (%s) may modify "
2658 "or use global state in undefined way: %s(%q)",
2660 sRefSet_unparseUnconstrainedPlain (othersets),
2662 sRef_unconstrainedName (thisset),
2663 exprNode_unparse (f), exprNodeList_unparse (args)),
2671 ("Argument %d modifies %q, set by argument %d (order of"
2672 " evaluation of actual parameters is undefined): %s(%q)",
2673 argno, sRef_unparse (thisset), thisargno,
2674 exprNode_unparse (f), exprNodeList_unparse (args)),
2681 /*@noaccess exprNodeList@*/
2682 } end_sRefSet_realElements;
2687 checkSequencing (exprNode f, exprNodeList args)
2689 if (exprNodeList_size (args) > 1)
2694 /*@access exprNodeList*/
2696 for (i = 0; i < args->nelements; i++)
2698 el = args->elements[i];
2700 if (!exprNode_isError (el))
2702 checkSequencingOne (f, args, el, i + 1);
2705 /*@noaccess exprNodeList*/
2710 ** requires le = exprNode_getUentry (f)
2714 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2715 uentry le, exprNodeList args,
2716 /*@notnull@*/ exprNode ret, int specialArgs)
2718 bool isSpec = FALSE;
2719 bool hasMods = FALSE;
2721 globSet usesGlobs = globSet_undefined;
2722 sRefSet mods = sRefSet_undefined;
2723 bool freshMods = FALSE;
2724 uentryList params = uentryList_undefined;
2726 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2729 ** check globals and modifies
2734 if (!uentry_isValid (le))
2736 ctype fr = ctype_realType (f->typ);
2738 if (ctype_isFunction (fr))
2740 params = ctype_argsFunction (fr);
2744 params = uentryList_missingParams;
2747 if (!context_getFlag (FLG_MODNOMODS)
2748 && !context_getFlag (FLG_GLOBUNSPEC))
2750 checkUnspecCall (f, params, args);
2756 fname = uentry_rawName (le);
2760 if (uentry_isFunction (le))
2762 params = uentry_getParams (le);
2763 mods = uentry_getMods (le);
2764 hasMods = uentry_hasMods (le);
2765 usesGlobs = uentry_getGlobs (le);
2766 isSpec = uentry_isSpecified (le);
2768 else /* not a function */
2770 ctype ct = ctype_realType (uentry_getType (le));
2772 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2773 ("checkModGlobs: uentry not a function: %s",
2774 uentry_unparse (le)));
2776 params = ctype_argsFunction (ct);
2777 return; /*@32 ! remove this? */
2786 globSet_allElements (usesGlobs, el)
2788 if (sRef_isValid (el))
2790 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2792 context_usedGlobal (el);
2793 exprNode_checkUse (f, el, f->loc);
2795 if (context_checkInternalUse ())
2797 if (!context_globAccess (el))
2799 if (sRef_isSystemState (el)
2800 && !context_getFlag (FLG_MODFILESYSTEM))
2809 ("Called procedure %s may access %q, but "
2810 "globals list does not include globals %s",
2811 exprNode_unparse (f),
2813 cstring_makeLiteralTemp (sRef_isInternalState (el)
2821 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2827 uentry gle = sRef_getUentry (el);
2828 sRef sr = sRef_updateSref (el);
2830 if (sRef_isUndefGlob (el))
2832 sRef_setDefined (sr, f->loc);
2833 exprNode_checkSet (f, sr);
2841 if (sRef_isAllocated (el))
2843 exprNode_checkSet (f, sr);
2847 if (sRef_isStateUndefined (sr))
2852 ("%s %q used by function undefined before call: %s",
2853 sRef_getScopeName (sr),
2855 exprNode_unparse (f)),
2857 sRef_setDefined (sr, f->loc);
2859 exprNode_checkUse (f, sr, f->loc);
2862 checkGlobUse (gle, TRUE, f);
2865 if (sRef_isKilledGlob (el))
2867 sRef_kill (sr, f->loc);
2868 context_usedGlobal (sr);
2872 } end_globSet_allElements;
2878 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
2880 sRefSet smods = sRefSet_undefined;
2883 ** NEED to check for modifies anything
2887 ** check each sRef that called function modifies (ml), is
2893 sRefSet_allElements (mods, s) /* s is something which may be modified */
2895 DPRINTF (("Check modify: %s", sRef_unparse (s)));
2897 if (sRef_isKindSpecial (s))
2899 if (sRef_isSpecInternalState (s))
2901 if (context_getFlag (FLG_MODINTERNALSTRICT))
2903 exprNode_checkCallModifyVal (s, args, f, ret);
2907 sRefSet mmods = context_modList ();
2909 sRefSet_allElements (mmods, el)
2911 if (sRef_isInternalState (el))
2913 sRef_setModified (el);
2915 } end_sRefSet_allElements ;
2920 exprNode_checkCallModifyVal (s, args, f, ret);
2925 sRef rb = sRef_getRootBase (s);
2927 if (sRef_isFileOrGlobalScope (rb))
2929 context_usedGlobal (rb);
2932 if (sRef_isFileStatic (s)
2933 && !fileId_equal (fileloc_fileId (f->loc),
2934 fileloc_fileId (uentry_whereDefined (le))))
2936 smods = sRefSet_insert (smods, s);
2940 exprNode_checkCallModifyVal (s, args, f, ret);
2943 } end_sRefSet_allElements;
2948 ** Static elements in modifies set can have nasty consequences.
2949 ** (I think...have not been able to reproduce a possible bug.)
2952 if (!sRefSet_isDefined (smods))
2954 mods = sRefSet_newCopy (mods);
2957 sRefSet_allElements (smods, el)
2959 bool res = sRefSet_delete (mods, el);
2962 } end_sRefSet_allElements;
2964 sRefSet_free (smods);
2969 else if (sRefSet_isDefined (mods))
2970 { /* just check observers */
2973 sRefSet_allElements (mods, s) /* s is something which may be modified */
2975 sRef rb = sRef_getRootBase (s);
2979 if (sRef_isParam (rb))
2981 sRef b = sRef_fixBaseParam (s, args);
2983 if (sRef_isObserver (b))
2985 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
2989 message ("Function call may modify observer%q: %s",
2990 sRef_unparsePreOpt (b), exprNode_unparse (e)),
2993 sRef_showExpInfo (b);
2997 } end_sRefSet_allElements;
3001 if (!hasMods) /* no specified modifications */
3003 if (context_getFlag (FLG_MODOBSERVERUNCON))
3005 exprNodeList_elements (args, e)
3007 if (exprNode_isDefined (e))
3009 sRef s = exprNode_getSref (e);
3011 if (sRef_isObserver (s)
3012 && ctype_isMutable (sRef_getType (s)))
3015 (FLG_MODOBSERVERUNCON,
3017 ("Call to unconstrained function %s may modify observer%q: %s",
3018 exprNode_unparse (f),
3019 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3022 sRef_showExpInfo (s);
3026 } end_exprNodeList_elements;
3031 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3033 ret->uses = sRefSet_union (ret->uses, f->uses);
3034 ret->sets = sRefSet_union (ret->sets, f->sets);
3035 ret->msets = sRefSet_union (ret->msets, f->msets);
3040 ** Spurious errors reported, because lclint can't tell
3041 ** mods must be fresh if freshMods is true.
3044 /*@i@*/ sRefSet_free (mods);
3050 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3052 if (uentry_isVar (glob))
3054 if (context_inFunctionLike ())
3056 sRef sr = uentry_getSref (glob);
3058 context_usedGlobal (sr);
3060 if (context_checkGlobUse (glob))
3062 if (!context_globAccess (sr))
3068 message ("Called procedure %s may access %s %q",
3069 exprNode_unparse (e),
3070 sRef_unparseScope (sr),
3071 uentry_getName (glob)),
3078 message ("Undocumented use of %s %s",
3079 sRef_unparseScope (sr),
3080 exprNode_unparse (e)),
3089 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3094 reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
3096 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3097 exprNode_unparse (f), exprNodeList_unparse (args),
3098 uentry_unparseFull (le),
3099 stateClauseList_unparse (uentry_getStateClauseList (le))));
3101 if (uentry_isValid (le) && uentry_isFunction (le))
3103 stateClauseList sclauses = uentry_getStateClauseList (le);
3105 if (stateClauseList_isDefined (sclauses))
3107 DPRINTF (("Reflect ensures: %s / %s / %s",
3108 uentry_unparse (le),
3109 exprNode_unparse (f), exprNodeList_unparse (args)));
3111 stateClauseList_elements (sclauses, cl)
3113 if (stateClause_hasEnsures (cl))
3115 /* Same in usymtab.c:1904 */
3116 if (stateClause_setsMetaState (cl))
3118 qual q = stateClause_getMetaQual (cl);
3119 annotationInfo ainfo = qual_getAnnotationInfo (q);
3120 metaStateInfo minfo = annotationInfo_getState (ainfo);
3121 cstring key = metaStateInfo_getName (minfo);
3122 int mvalue = annotationInfo_getValue (ainfo);
3124 sRefSet osrs = sRefSet_undefined;
3127 if (stateClause_isGlobal (cl))
3129 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3134 srs = stateClause_getRefs (cl);
3137 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3140 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3142 sRefSet_elements (srs, sel)
3146 if (sRef_isResult (sRef_getRootBase (sel)))
3148 s = exprNode_getSref (ret);
3152 s = sRef_fixBaseParam (sel, args);
3155 DPRINTF (("Reflecting state clause on: %s / %s",
3156 sRef_unparse (sel), sRef_unparse (s)));
3158 sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3159 } end_sRefSet_elements;
3161 sRefSet_free (osrs);
3165 sRefSet srs = stateClause_getRefs (cl);
3166 sRefModVal modf = stateClause_getEnsuresFunction (cl);
3167 int eparam = stateClause_getStateParameter (cl);
3169 DPRINTF (("Reflect after clause: %s / %s",
3170 stateClause_unparse (cl),
3171 sRefSet_unparse (srs)));
3173 sRefSet_elements (srs, sel)
3177 DPRINTF (("elements: %s", sRef_unparse (sel)));
3178 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3180 if (sRef_isResult (sRef_getRootBase (sel)))
3182 DPRINTF (("Fix base: %s / %s",
3183 sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
3184 s = sRef_fixBase (sel, exprNode_getSref (ret));
3185 DPRINTF (("==> %s", sRef_unparseFull (s)));
3189 s = sRef_fixBaseParam (sel, args);
3192 DPRINTF (("elements: %s", sRef_unparse (s)));
3193 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3195 DPRINTF (("Reflecting state clause on: %s / %s",
3196 sRef_unparse (sel), sRef_unparse (s)));
3198 modf (s, eparam, exprNode_loc (f));
3199 } end_sRefSet_elements;
3202 } end_stateClauseList_elements ;
3205 DPRINTF (("Here: %s / %s",
3206 uentry_unparseFull (le),
3207 bool_unparse (uentry_hasMetaStateEnsures (le))));
3209 if (uentry_hasMetaStateEnsures (le))
3211 fileloc loc = exprNode_loc (f);
3213 metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3215 metaStateConstraintList_elements (mscl, msc)
3217 metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3218 metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3219 metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
3220 cstring key = metaStateInfo_getName (msinfo);
3221 sRef mlsr = metaStateSpecifier_getSref (msspec);
3223 sRef lastref = sRef_undefined;
3224 stateValue sval = stateValue_undefined;
3226 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3227 metaStateConstraint_unparse (msc)));
3228 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3230 if (sRef_isResult (sRef_getRootBase (mlsr)))
3232 s = exprNode_getSref (ret);
3236 s = sRef_fixBaseParam (mlsr, args);
3239 DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3241 while (metaStateExpression_isDefined (msexpr))
3243 metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
3244 metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
3247 DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3249 if (metaStateExpression_isMerge (msexpr))
3251 msexpr = metaStateExpression_getRest (msexpr);
3255 msexpr = metaStateExpression_undefined;
3258 if (metaStateInfo_isDefined (msi))
3260 /* Must match lhs state */
3261 llassert (metaStateInfo_equal (msinfo, msi));
3264 if (metaStateSpecifier_isElipsis (ms))
3267 ** For elipsis, we need to merge all the relevant elipsis parameters
3271 uentryList params = uentry_getParams (le);
3272 int paramno = uentryList_size (params) - 1;
3274 if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
3278 message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3279 uentry_getName (le)),
3280 uentry_whereLast (le));
3281 /*@innerbreak@*/ break;
3284 while (paramno < exprNodeList_size (args))
3286 exprNode arg = exprNodeList_getN (args, paramno);
3287 fs = exprNode_getSref (arg);
3288 DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3290 /* cut and pasted... gack*/
3291 if (stateValue_isDefined (sval))
3293 /* Use combination table to merge old state value with new one: */
3294 stateValue tval = sRef_getMetaStateValue (fs, key);
3296 if (stateValue_isDefined (tval))
3298 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3299 cstring msg = cstring_undefined;
3300 int nval = stateCombinationTable_lookup (sctable,
3301 stateValue_getValue (sval),
3302 stateValue_getValue (tval),
3304 DPRINTF (("Combining: %s + %s -> %d",
3305 stateValue_unparseValue (sval, msinfo),
3306 stateValue_unparseValue (tval, msinfo),
3309 if (nval == stateValue_error)
3311 llassert (cstring_isDefined (msg));
3316 ("Attributes merged in ensures clause in states that "
3317 "cannot be combined (%q is %q, %q is %q): %s",
3318 sRef_unparse (lastref),
3319 stateValue_unparseValue (sval, msinfo),
3321 stateValue_unparseValue (tval, msinfo),
3325 sRef_showMetaStateInfo (fs, key);
3329 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3330 loc = exprNode_loc (arg);
3334 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3339 sval = sRef_getMetaStateValue (fs, key);
3344 if (stateValue_isError (sval))
3346 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3355 msr = metaStateSpecifier_getSref (ms);
3358 llassert (sRef_isParam (sRef_getRootBase (msr)));
3359 fs = sRef_fixBaseParam (msr, args);
3361 if (stateValue_isDefined (sval))
3363 /* Use combination table to merge old state value with new one: */
3364 stateValue tval = sRef_getMetaStateValue (fs, key);
3366 if (stateValue_isDefined (tval))
3368 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3369 cstring msg = cstring_undefined;
3370 int nval = stateCombinationTable_lookup (sctable,
3371 stateValue_getValue (sval),
3372 stateValue_getValue (tval),
3374 DPRINTF (("Combining: %s + %s -> %d",
3375 stateValue_unparseValue (sval, msinfo),
3376 stateValue_unparseValue (tval, msinfo),
3379 if (nval == stateValue_error)
3381 llassert (cstring_isDefined (msg));
3386 ("Attributes merged in ensures clause in states that "
3387 "cannot be combined (%q is %q, %q is %q): %s",
3388 sRef_unparse (lastref),
3389 stateValue_unparseValue (sval, msinfo),
3391 stateValue_unparseValue (tval, msinfo),
3395 sRef_showMetaStateInfo (fs, key);
3399 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3403 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3408 sval = sRef_getMetaStateValue (fs, key);
3413 if (stateValue_isError (sval))
3415 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3420 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3422 if (stateValue_isDefined (sval))
3424 sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
3428 DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
3430 } end_metaStateConstraintList_elements ;
3432 metaStateConstraintList_free (mscl);
3438 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3440 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3441 exprNode_unparse (f), exprNodeList_unparse (args),
3442 uentry_unparseFull (le),
3443 stateClauseList_unparse (uentry_getStateClauseList (le))));
3445 if (uentry_isValid (le) && uentry_isFunction (le))
3447 stateClauseList sclauses = uentry_getStateClauseList (le);
3449 if (stateClauseList_isDefined (sclauses))
3451 DPRINTF (("Check requires: %s / %s / %s",
3452 uentry_unparse (le),
3453 exprNode_unparse (f), exprNodeList_unparse (args)));
3455 stateClauseList_elements (sclauses, cl)
3457 DPRINTF (("Check clause: %s / %s",
3458 stateClause_unparse (cl),
3459 bool_unparse (stateClause_hasRequires (cl))));
3461 if (stateClause_hasRequires (cl))
3463 sRefSet osrs = sRefSet_undefined;
3466 if (stateClause_isGlobal (cl))
3468 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3473 srs = stateClause_getRefs (cl);
3476 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3478 if (stateClause_setsMetaState (cl))
3480 qual q = stateClause_getMetaQual (cl);
3481 annotationInfo ainfo = qual_getAnnotationInfo (q);
3482 metaStateInfo minfo = annotationInfo_getState (ainfo);
3483 cstring key = metaStateInfo_getName (minfo);
3484 int mvalue = annotationInfo_getValue (ainfo);
3486 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3488 sRefSet_elements (srs, sel)
3490 sRef s = sRef_fixBaseParam (sel, args);
3492 if (sRef_isResult (sRef_getRootBase (sel)))
3498 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3499 sRef_unparseFull (sel), sRef_unparseFull (s),
3502 if (!sRef_checkMetaStateValue (s, key, mvalue))
3504 DPRINTF (("HERE: %s", sRef_unparse (s)));
3508 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3509 uentry_getName (le),
3510 sRef_isGlobalMarker (s)
3512 : message (" by %q", sRef_unparse (s)),
3513 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3515 stateClause_unparse (cl)),
3518 sRef_showAliasInfo (s);
3522 DPRINTF (("Error supressed!"));
3523 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3524 DPRINTF (("Context supress: %s",
3525 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3529 } end_sRefSet_elements;
3533 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3534 int eparam = stateClause_getStateParameter (cl);
3536 DPRINTF (("Reflect after clause: %s / %s",
3537 stateClause_unparse (cl),
3538 sRefSet_unparse (srs)));
3540 sRefSet_elements (srs, sel)
3544 DPRINTF (("elements: %s", sRef_unparse (sel)));
3545 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3547 s = sRef_fixBaseParam (sel, args);
3549 DPRINTF (("elements: %s", sRef_unparse (s)));
3550 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3552 if (sRef_isResult (sRef_getRootBase (sel)))
3554 ; /*@i423 what do we do about results */
3558 DPRINTF (("Reflecting state clause on: %s / %s",
3559 sRef_unparse (sel), sRef_unparse (s)));
3561 modf (s, eparam, exprNode_loc (f));
3563 } end_sRefSet_elements;
3566 sRefSet_free (osrs);
3568 } end_stateClauseList_elements ;
3573 static /*@only@*/ exprNode
3574 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3575 ctype t, /*@keep@*/ exprNodeList args)
3577 /* requires f is a non-error exprNode, with type function */
3578 cstring fname = exprNode_unparse (f);
3579 uentry le = exprNode_getUentry (f);
3580 exprNode ret = exprNode_createPartialCopy (f);
3585 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3587 ret->typ = ctype_getReturnType (t);
3588 ret->kind = XPR_CALL;
3590 ret->edata = exprData_makeCall (f, args);
3593 ** Order of these steps is very important!
3595 ** Must check for argument dependencies before messing up uses and sets.
3598 if (context_getFlag (FLG_EVALORDER))
3600 exprNodeList_elements (args, current)
3602 if (exprNode_isDefined (current))
3604 exprNode_addUse (current, current->sref);
3606 } end_exprNodeList_elements;
3608 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3610 checkSequencing (f, args);
3613 exprNodeList_elements (args, current)
3615 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3617 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3619 } end_exprNodeList_elements ;
3622 special = checkArgs (le, f, t, args, ret);
3623 checkGlobMods (f, le, args, ret, special);
3624 checkRequiresClause (le, f, args);
3627 if (uentry_isValid (le)
3628 && (uentry_isFunction (le)
3629 || (uentry_isVariable (le)
3630 && ctype_isFunction (uentry_getType (le)))))
3632 exitkind exk = uentry_getExitCode (le);
3634 /* f->typ is already set to the return type */
3636 DPRINTF (("Function: %s", uentry_unparseFull (le)));
3637 ret->sref = uentry_returnedRef (le, args);
3638 DPRINTF (("Returned: %s / %s",
3639 uentry_unparseFull (le),
3640 sRef_unparseFull (ret->sref)));
3642 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3644 qual nullPred = uentry_nullPred (le);
3646 if (qual_isTrueNull (nullPred))
3648 exprNode arg = exprNodeList_head (args);
3650 if (exprNode_isDefined (arg))
3652 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3655 else if (qual_isFalseNull (nullPred))
3657 exprNode arg = exprNodeList_head (args);
3659 if (exprNode_isDefined (arg))
3661 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3666 llassert (qual_isUnknown (nullPred));
3670 if (exitkind_isConditionalExit (exk))
3674 ** if (arg0) then { exit! } else { ; }
3676 ** if (arg0) then { ; } else { exit! }
3681 llassert (!exprNodeList_isEmpty (args));
3682 firstArg = exprNodeList_head (args);
3684 if (exprNode_isDefined (firstArg)
3685 && !guardSet_isEmpty (firstArg->guards))
3687 usymtab_trueBranch (guardSet_undefined);
3688 usymtab_altBranch (guardSet_undefined);
3690 if (exitkind_isTrueExit (exk))
3692 usymtab_popBranches (firstArg,
3693 exprNode_makeMustExit (),
3695 TRUE, TRUEEXITCLAUSE);
3699 usymtab_popBranches (firstArg,
3701 exprNode_makeMustExit (),
3702 TRUE, FALSEEXITCLAUSE);
3706 ret->exitCode = XK_MAYEXIT;
3708 else if (exitkind_mustExit (exk))
3710 ret->exitCode = XK_MUSTEXIT;
3712 else if (exitkind_couldExit (exk))
3714 ret->exitCode = XK_MAYEXIT;
3721 if (cstring_equalLit (fname, "exit"))
3723 if (exprNodeList_size (args) == 1)
3725 exprNode arg = exprNodeList_head (args);
3727 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3729 long int val = multiVal_forceInt (exprNode_getValue (arg));
3736 ("Argument to exit has implementation defined behavior: %s",
3737 exprNode_unparse (arg)),
3738 exprNode_loc (arg));
3747 exprNode_checkSetAny (ret, uentry_rawName (le));
3750 DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3751 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3752 reflectEnsuresClause (ret, le, f, args);
3759 ** this is yucky! should keep the uentry as part of exprNode!
3762 /*@observer@*/ uentry
3763 exprNode_getUentry (exprNode e)
3765 if (exprNode_isError (e))
3767 return uentry_undefined;
3771 cstring s = exprNode_rootVarName (e);
3772 uentry ue = usymtab_lookupSafe (s);
3779 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3781 exprNode ret = exprNode_createPlain (ctype_unknown);
3783 ret->kind = XPR_INITBLOCK;
3784 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3785 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3791 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3797 if (exprNode_isUndefined (f))
3800 exprNodeList_free (args);
3801 return exprNode_undefined;
3804 t = exprNode_getType (f);
3806 if (sRef_isLocalVar (f->sref))
3808 exprNode_checkUse (f, f->sref, f->loc);
3810 if (sRef_possiblyNull (f->sref))
3812 if (!usymtab_isGuarded (f->sref))
3814 if (optgenerror (FLG_NULLDEREF,
3815 message ("Function call using %s pointer %q",
3816 sRef_nullMessage (f->sref),
3817 sRef_unparse (f->sref)),
3820 sRef_showNullInfo (f->sref);
3821 sRef_setNullError (f->sref);
3829 if (ctype_isRealFunction (t))
3831 exprNode ret = functionCallSafe (f, t, args);
3835 else if (ctype_isUnknown (t))
3837 exprNode ret = exprNode_createPartialCopy (f);
3843 exprNodeList_elements (args, current)
3845 if (exprNode_isDefined (current))
3847 exprNode_checkUse (ret, current->sref, ret->loc);
3850 ** also, anything derivable from current->sref may be used
3853 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3854 exprNode_mergeUSs (ret, current);
3856 } end_exprNodeList_elements;
3858 ret->edata = exprData_makeCall (f, args);
3859 ret->kind = XPR_CALL;
3861 tstring = cstring_copy (exprNode_unparse (f));
3863 cstring_markOwned (tstring);
3864 exprNode_checkSetAny (ret, tstring);
3870 voptgenerror (FLG_TYPE,
3871 message ("Call to non-function (type %t): %s", t,
3872 exprNode_unparse (f)),
3875 exprNodeList_free (args);
3877 return (exprNode_makeError ());
3882 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
3883 /*@only@*/ cstring f)
3885 exprNode ret = exprNode_createPartialCopy (s);
3887 ret->kind = XPR_FACCESS;
3889 if (exprNode_isError (s))
3891 ret->edata = exprData_makeField (s, f);
3896 ctype t = exprNode_getType (s);
3897 ctype tr = ctype_realType (t);
3899 checkMacroParen (s);
3901 ret->edata = exprData_makeField (s, f);
3903 if (ctype_isStructorUnion (tr))
3905 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
3907 if (uentry_isUndefined (tf))
3909 voptgenerror (FLG_TYPE,
3910 message ("Access non-existent field %s of %t: %s", f, t,
3911 exprNode_unparse (ret)),
3913 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
3918 uentry_setUsed (tf, exprNode_loc (ret));
3920 ret->typ = uentry_getType (tf);
3921 checkSafeUse (ret, s->sref);
3923 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
3924 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
3928 else /* isStructorUnion */
3930 if (ctype_isRealAbstract (tr))
3934 message ("Access field of abstract type (%t): %s.%s",
3935 t, exprNode_unparse (s), f),
3937 ret->typ = ctype_unknown;
3941 if (ctype_isKnown (tr))
3946 ("Access field of non-struct or union (%t): %s.%s",
3947 t, exprNode_unparse (s), f),
3950 ret->typ = ctype_unknown;
3954 cstring sn = cstring_copy (f);
3956 checkSafeUse (ret, s->sref);
3957 cstring_markOwned (sn);
3958 ret->sref = sRef_makeField (s->sref, sn);
3970 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
3971 /*@only@*/ cstring f)
3973 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
3974 lltok_release (dot);
3979 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
3981 exprNode ret = exprNode_createPartialCopy (e);
3983 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
3984 ret->kind = XPR_PARENS;
3985 ret->edata = exprData_makeUop (e, lpar);
3987 if (!exprNode_isError (e))
3989 ret->exitCode = e->exitCode;
3990 ret->canBreak = e->canBreak;
3991 ret->mustBreak = e->mustBreak;
3992 ret->isJumpPoint = e->isJumpPoint;
3993 ret->sref = e->sref;
4000 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4001 /*@only@*/ cstring f)
4003 exprNode ret = exprNode_createPartialCopy (s);
4005 ret->edata = exprData_makeField (s, f);
4006 ret->kind = XPR_ARROW;
4008 if (exprNode_isError (s))
4014 ctype t = exprNode_getType (s);
4015 ctype tr = ctype_realType (t);
4017 checkMacroParen (s);
4019 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4021 if (ctype_isRealPointer (tr))
4023 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4025 if (ctype_isStructorUnion (b))
4027 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4029 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4031 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4035 message ("Arrow access from %s pointer%q: %s",
4036 sRef_nullMessage (s->sref),
4037 sRef_unparsePreOpt (s->sref),
4038 exprNode_unparse (ret)),
4041 sRef_showNullInfo (s->sref);
4042 sRef_setNullError (s->sref);
4047 if (uentry_isUndefined (fentry))
4051 message ("Access non-existent field %s of %t: %s",
4052 f, t, exprNode_unparse (ret)),
4054 ret->typ = ctype_unknown;
4060 ** was safeUse: shouldn't be safe!
4063 ** rec must be defined,
4064 ** *rec must be allocated
4065 ** rec->field need only be defined it if is an rvalue
4068 uentry_setUsed (fentry, exprNode_loc (ret));
4069 ret->typ = uentry_getType (fentry);
4071 exprNode_checkUse (ret, s->sref, s->loc);
4073 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4074 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4078 else /* Pointer to something that is not a struct or union*/
4080 if (ctype_isRealAbstract (tr))
4082 ctype xrt = ctype_forceRealType (tr);
4086 message ("Arrow access field of abstract type (%t): %s->%s",
4087 t, exprNode_unparse (s), f),
4091 ** Set the state correctly, as if the abstraction is broken.
4094 if (ctype_isRealPointer (xrt) &&
4095 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4096 ctype_isStructorUnion (b)))
4098 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4099 ret->typ = uentry_getType (fentry);
4100 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4104 ret->typ = ctype_unknown;
4105 ret->sref = sRef_undefined;
4108 else /* not a struct, union or abstract */
4110 if (ctype_isUnknown (tr)) {
4111 cstring sn = cstring_copy (f);
4113 DPRINTF (("Here: %s", exprNode_unparse (s)));
4115 exprNode_checkUse (ret, s->sref, s->loc);
4116 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4118 cstring_markOwned (sn);
4119 ret->sref = sRef_makeArrow (s->sref, sn);
4121 ret->kind = XPR_ARROW;
4126 message ("Arrow access field of non-struct or union "
4127 "pointer (%t): %s->%s",
4128 t, exprNode_unparse (s), f),
4131 ret->typ = ctype_unknown;
4132 ret->sref = sRef_undefined;
4137 else /* its not a pointer */
4139 if (!ctype_isUnknown (tr))
4143 message ("Arrow access of non-pointer (%t): %s->%s",
4144 t, exprNode_unparse (s), f),
4147 ret->typ = ctype_unknown;
4148 ret->sref = sRef_undefined;
4152 cstring sn = cstring_copy (f);
4154 DPRINTF (("Here: %s", exprNode_unparse (s)));
4156 exprNode_checkUse (ret, s->sref, s->loc);
4157 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4159 cstring_markOwned (sn);
4160 ret->sref = sRef_makeArrow (s->sref, sn);
4162 ret->kind = XPR_ARROW;
4173 exprNode_arrowAccess (/*@only@*/ exprNode s,
4174 /*@only@*/ lltok arrow,
4175 /*@only@*/ cstring f)
4177 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4178 lltok_release (arrow);
4183 ** only postOp's in C: i++ and i--
4187 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4189 /* check modification also */
4190 /* cstring opname = lltok_unparse (op);*/
4192 exprNode ret = exprNode_createPartialCopy (e);
4194 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4195 ret->kind = XPR_POSTOP;
4196 ret->edata = exprData_makeUop (e, op);
4198 if (!exprNode_isDefined (e))
4203 checkMacroParen (e);
4205 exprNode_checkUse (ret, e->sref, e->loc);
4206 exprNode_checkSet (ret, e->sref);
4208 t = exprNode_getType (e);
4210 if (sRef_isUnsafe (e->sref))
4212 voptgenerror (FLG_MACROPARAMS,
4213 message ("Operand of %s is macro parameter (non-functional): %s%s",
4214 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4216 sRef_makeSafe (e->sref);
4217 sRef_makeSafe (ret->sref);
4220 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4226 if (ctype_isRealAbstract (t))
4230 message ("Operand of %s is abstract type (%t): %s",
4231 lltok_unparse (op), t, exprNode_unparse (e)),
4238 message ("Operand of %s is non-numeric (%t): %s",
4239 lltok_unparse (op), t, exprNode_unparse (e)),
4242 ret->typ = ctype_unknown;
4245 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4247 exprNode_checkModify (e, ret);
4249 /* added 7/11/2000 D.L */
4251 /*DRL 6/8/01 I decided to disable all LCLint Warning here since the code
4252 probably needs a rewrite any way */
4256 // updateEnvironmentForPostOp (e);
4258 /* start modifications */
4259 /* added by Seejo on 4/16/2000 */
4261 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4263 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4265 ret->sref = sRef_copy (e->sref);
4268 if (lltok_getTok (op) == INC_OP) {
4269 if (sRef_getSize(e->sref) > 0) {
4271 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4273 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4274 /* Assumption: there is only 1 \0 in the buffer */
4275 /* This will not be correct if there are 2 \0's in the buffer */
4276 sRef_setNotNullTerminatedState(ret->sref);
4277 sRef_resetLen(ret->sref);
4279 sRef_setNullTerminatedState(ret->sref);
4280 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4282 if (sRef_isNullTerminated (ret->sref))
4283 printf ("ret->sref is Null Terminated\n");
4284 else if (sRef_isPossiblyNullTerminated (ret->sref))
4285 printf ("ret->sref is Possibly Null Terminated\n");
4286 else if (sRef_isNotNullTerminated (ret->sref))
4287 printf ("ret->sref is Not Null Terminated\n");
4292 if (lltok_getTok (op) == DEC_OP) {
4293 if (sRef_getSize(e->sref) >= 0) {
4294 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4295 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4300 /* end modifications */
4306 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4308 bool checkMod = FALSE;
4310 int opid = lltok_getTok (op);
4311 exprNode ret = exprNode_createSemiCopy (e);
4313 exprNode_copySets (ret, e);
4315 multiVal_free (ret->val);
4316 ret->val = multiVal_undefined;
4317 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4318 ret->kind = XPR_PREOP;
4319 ret->edata = exprData_makeUop (e, op);
4321 if (exprNode_isError (e))
4326 checkMacroParen (e);
4328 te = exprNode_getType (e);
4329 tr = ctype_realType (te);
4331 if (opid != TAMPERSAND)
4333 exprNode_checkUse (ret, e->sref, e->loc);
4335 if (ctype_isRealAbstract (tr)
4336 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4338 if (optgenerror (FLG_ABSTRACT,
4339 message ("Operand of %s is abstract type (%t): %s",
4340 lltok_unparse (op), tr,
4341 exprNode_unparse (ret)),
4344 tr = te = ctype_unknown;
4345 ret->typ = ctype_unknown;
4346 sRef_setNullError (e->sref);
4354 case DEC_OP: /* should also check modification! */
4355 if (sRef_isMacroParamRef (e->sref))
4359 message ("Operand of %s is macro parameter (non-functional): %s",
4360 lltok_unparse (op), exprNode_unparse (ret)),
4365 exprNode_checkSet (ret, e->sref);
4368 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4373 if (context_msgStrictOps ())
4377 message ("Operand of %s is non-numeric (%t): %s",
4378 lltok_unparse (op), te, exprNode_unparse (ret)),
4381 ret->typ = ctype_int;
4384 /* start modifications */
4385 /* added by Seejo on 4/16/2000 */
4387 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4389 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4391 ret->sref = sRef_copy (e->sref);
4394 if (lltok_getTok (op) == INC_OP) {
4395 if (sRef_getSize(e->sref) > 0) {
4397 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4399 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4400 /* Assumption: there is only 1 \0 in the buffer */
4401 /* This will not be correct if there are 2 \0's in the buffer */
4402 sRef_setNotNullTerminatedState(ret->sref);
4403 sRef_resetLen (ret->sref);
4405 sRef_setNullTerminatedState(ret->sref);
4406 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4412 if (lltok_getTok (op) == DEC_OP) {
4413 if (sRef_getSize(e->sref) >= 0) {
4414 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4415 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4420 /* end modifications */
4427 if (ctype_isForceRealNumeric (&tr))
4431 ret->val = multiVal_invert (exprNode_getValue (e));
4435 ret->val = multiVal_copy (exprNode_getValue (e));
4440 if (context_msgStrictOps ())
4444 message ("Operand of %s is non-numeric (%t): %s",
4445 lltok_unparse (op), te, exprNode_unparse (ret)),
4449 ret->typ = ctype_int;
4453 case TEXCL: /* maybe this should be restricted */
4454 guardSet_flip (ret->guards);
4456 if (ctype_isRealBool (te) || ctype_isUnknown (te))
4462 if (ctype_isRealPointer (tr))
4464 if (sRef_isKnown (e->sref))
4466 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4470 (FLG_BOOLOPS, FLG_PTRNEGATE,
4471 message ("Operand of %s is non-boolean (%t): %s",
4472 lltok_unparse (op), te, exprNode_unparse (ret)),
4479 message ("Operand of %s is non-boolean (%t): %s",
4480 lltok_unparse (op), te, exprNode_unparse (ret)),
4484 ret->typ = ctype_bool;
4489 if (ctype_isForceRealInt (&tr))
4494 if (context_msgStrictOps ())
4498 message ("Operand of %s is non-integer (%t): %s",
4499 lltok_unparse (op), te, exprNode_unparse (ret)),
4503 if (ctype_isInt (e->typ))
4509 ret->typ = ctype_int;
4515 ret->typ = ctype_makePointer (e->typ);
4517 if (sRef_isKnown (e->sref))
4519 ret->sref = sRef_makeAddress (e->sref);
4526 if (ctype_isAP (tr))
4528 ret->typ = ctype_baseArrayPtr (e->typ);
4532 if (ctype_isKnown (te))
4534 if (ctype_isFunction (te))
4540 message ("Dereference of function type (%t): %s",
4541 te, exprNode_unparse (ret)),
4546 voptgenerror (FLG_TYPE,
4547 message ("Dereference of non-pointer (%t): %s",
4548 te, exprNode_unparse (ret)),
4550 ret->typ = ctype_unknown;
4555 ret->typ = ctype_unknown;
4560 if (sRef_isKnown (e->sref))
4562 if (sRef_possiblyNull (e->sref))
4564 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4568 message ("Dereference of %s pointer %q: %s",
4569 sRef_nullMessage (e->sref),
4570 sRef_unparse (e->sref),
4571 exprNode_unparse (ret)),
4574 sRef_showNullInfo (e->sref);
4575 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4580 ret->sref = sRef_makePointer (e->sref);
4585 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4590 exprNode_checkModify (e, ret);
4597 ** any reason to disallow sizeof (abstract type) ?
4601 ** used by both sizeof
4605 ctype sizeof_resultType (void)
4607 static ctype sizet = ctype_unknown;
4609 if (ctype_isUnknown (sizet))
4611 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4613 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4617 sizet = ctype_ulint;
4624 exprNode_sizeofType (/*@only@*/ qtype qt)
4626 exprNode ret = exprNode_create (sizeof_resultType ());
4627 ctype ct = qtype_getType (qt);
4629 ret->kind = XPR_SIZEOFT;
4630 ret->edata = exprData_makeSizeofType (qt);
4632 voptgenerror (FLG_SIZEOFTYPE,
4633 message ("Parameter to sizeof is type %s: %s",
4635 exprNode_unparse (ret)),
4642 exprNode_alignofType (/*@only@*/ qtype qt)
4644 exprNode ret = exprNode_create (sizeof_resultType ());
4645 ctype ct = qtype_getType (qt);
4647 ret->kind = XPR_ALIGNOFT;
4648 ret->edata = exprData_makeSizeofType (qt);
4650 voptgenerror (FLG_SIZEOFTYPE,
4651 message ("Parameter to alignof is type %s: %s",
4653 exprNode_unparse (ret)),
4659 exprNode exprNode_offsetof (qtype qt, cstringList s)
4661 exprNode ret = exprNode_create (sizeof_resultType ());
4662 ctype ct = qtype_getType (qt);
4664 ret->kind = XPR_OFFSETOF;
4665 ret->edata = exprData_makeOffsetof (qt, s);
4667 if (!ctype_isRealSU (ct))
4669 voptgenerror (FLG_TYPE,
4670 message ("First parameter to offsetof is not a "
4671 "struct or union type (type %s): %s",
4673 exprNode_unparse (ret)),
4680 cstringList_elements (s, el) {
4684 if (ctype_isUndefined (lt))
4688 else if (!ctype_isRealSU (lt))
4690 voptgenerror (FLG_TYPE,
4691 message ("Inner offsetof type is not a "
4692 "struct or union type (type %s before field %s): %s",
4693 ctype_unparse (lt), el,
4694 exprNode_unparse (ret)),
4700 fields = ctype_getFields (ctype_realType (lt));
4701 fld = uentryList_lookupField (fields, el);
4702 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4704 if (uentry_isUndefined (fld))
4706 if (ctype_equal (lt, ct)) {
4707 voptgenerror (FLG_TYPE,
4708 message ("Field %s in offsetof is not the "
4709 "name of a field of %s: %s",
4712 exprNode_unparse (ret)),
4715 voptgenerror (FLG_TYPE,
4716 message ("Deep field %s in offsetof is not the "
4717 "name of a field of %s: %s",
4720 exprNode_unparse (ret)),
4726 lt = uentry_getType (fld);
4729 } end_cstringList_elements;
4731 /* Should report error if its a bit field - behavior is undefined! */
4738 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4742 if (exprNode_isUndefined (e))
4744 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4745 ret->edata = exprData_makeSingle (e);
4746 ret->typ = sizeof_resultType ();
4747 ret->kind = XPR_SIZEOF;
4751 uentry u = exprNode_getUentry (e);
4753 ret = exprNode_createPartialCopy (e);
4754 ret->edata = exprData_makeSingle (e);
4756 ret->typ = sizeof_resultType ();
4757 ret->kind = XPR_SIZEOF;
4759 if (uentry_isValid (u)
4760 && uentry_isRefParam (u)
4761 && ctype_isRealArray (uentry_getType (u)))
4764 (FLG_SIZEOFFORMALARRAY,
4765 message ("Parameter to sizeof is an array-type function parameter: %s",
4766 exprNode_unparse (ret)),
4772 ** sizeof (x) doesn't "really" use x
4779 exprNode_alignofExpr (/*@only@*/ exprNode e)
4783 if (exprNode_isUndefined (e))
4785 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4789 ret = exprNode_createPartialCopy (e);
4792 ret->edata = exprData_makeSingle (e);
4793 ret->typ = sizeof_resultType ();
4794 ret->kind = XPR_ALIGNOF;
4797 ** sizeof (x) doesn't "really" use x
4804 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4810 if (exprNode_isError (e))
4813 lltok_release (tok);
4814 return exprNode_undefined;
4817 checkMacroParen (e);
4819 c = qtype_getType (q);
4820 t = exprNode_getType (e);
4822 ret = exprNode_createPartialCopy (e);
4824 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4826 ret->kind = XPR_CAST;
4827 ret->edata = exprData_makeCast (tok, e, q);
4829 if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
4832 ** This is a bit of a hack to avoid a problem
4833 ** when the code does,
4834 ** (some other struct) x
4839 ret->sref = sRef_copy (e->sref);
4840 usymtab_addForceMustAlias (ret->sref, e->sref);
4841 sRef_setTypeFull (ret->sref, c);
4842 DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
4843 sRef_unparseFull (ret->sref)));
4847 ret->sref = e->sref;
4848 sRef_setTypeFull (ret->sref, c);
4849 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
4856 ** void * <-> abstract * (if FLG_ABSTVOIDP)
4857 ** abstract * <-> void * (if FLG_ABSTVOIDP)
4860 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
4864 else if (ctype_isRealAP (c)) /* casting to array or pointer */
4866 ctype bc = ctype_getBaseType (c);
4867 ctype bt = ctype_getBaseType (t);
4868 ctype rt = ctype_realType (t);
4870 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
4871 && (ctype_isArrayPtr (rt)
4872 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4876 message ("Cast from function pointer type (%t) to "
4877 "non-function pointer (%t): %s",
4878 c, t, exprNode_unparse (ret)),
4882 if (!ctype_isFunction (ctype_baseArrayPtr (c))
4883 && (ctype_isArrayPtr (rt)
4884 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4888 message ("Cast from non-function pointer type (%t) to "
4889 "function pointer (%t): %s",
4890 c, t, exprNode_unparse (ret)),
4894 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
4895 !(ctype_isRealAbstract (bc)
4896 && context_hasAccess (ctype_typeId (bc))))
4898 ; /* okay to cast zero */
4902 if (ctype_isRealAbstract (bc)
4903 && !context_hasAccess (ctype_typeId (bc)))
4905 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
4909 message ("Cast to underlying abstract type %t: %s",
4910 c, exprNode_unparse (ret)),
4917 message ("Cast to underlying abstract type %t: %s",
4918 c, exprNode_unparse (ret)),
4923 if (ctype_isRealAbstract (bt)
4924 && !context_hasAccess (ctype_typeId (bt)))
4926 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
4930 message ("Cast from underlying abstract type %t: %s",
4931 t, exprNode_unparse (ret)),
4938 message ("Cast from underlying abstract type %t: %s",
4939 t, exprNode_unparse (ret)),
4947 ctype bt = ctype_realType (ctype_getBaseType (t));
4948 ctype bc = ctype_realType (ctype_getBaseType (c));
4950 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
4952 if (ctype_match (c, t))
4954 if (ctype_equal (c, t))
4958 message ("Redundant cast involving abstract type %t: %s",
4959 bt, exprNode_unparse (ret)),
4967 message ("Cast from abstract type %t: %s",
4968 bt, exprNode_unparse (ret)),
4973 if (ctype_isAbstract (bc)
4974 && !context_hasAccess (ctype_typeId (bc)))
4976 if (ctype_match (c, t))
4982 DPRINTF (("No access to: %s / %d",
4983 ctype_unparse (bc), ctype_typeId (bc)));
4984 DPRINTF (("Context %s %s",
4985 bool_unparse (context_inFunctionLike ()),
4986 context_unparse ()));
4989 message ("Cast to abstract type %t: %s", bc,
4990 exprNode_unparse (ret)),
4996 if (ctype_isAbstract (c))
4998 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
5000 /* okay, cast exposed to abstract */
5001 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
5005 if (ctype_isVisiblySharable (t)
5006 && sRef_isExternallyVisible (e->sref)
5007 && !(ctype_isAbstract (t)
5008 && context_hasAccess (ctype_typeId (t))))
5012 message ("Cast to abstract type from externally visible "
5013 "mutable storage exposes rep of %s: %s",
5015 exprNode_unparse (e)),
5025 evaluationOrderUndefined (lltok op)
5027 int opid = lltok_getTok (op);
5029 return (opid != AND_OP && opid != OR_OP);
5032 static bool checkIntegral (/*@notnull@*/ exprNode e1,
5033 /*@notnull@*/ exprNode e2,
5034 /*@notnull@*/ exprNode ret,
5039 ctype te1 = exprNode_getType (e1);
5040 ctype te2 = exprNode_getType (e2);
5042 ctype tr1 = ctype_realishType (te1);
5043 ctype tr2 = ctype_realishType (te2);
5045 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5051 if (context_msgStrictOps ())
5053 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5055 if (ctype_sameName (te1, te2))
5059 message ("Operands of %s are non-integer (%t): %s",
5060 lltok_unparse (op), te1,
5061 exprNode_unparse (ret)),
5068 message ("Operands of %s are non-integers (%t, %t): %s",
5069 lltok_unparse (op), te1, te2,
5070 exprNode_unparse (ret)),
5074 else if (!ctype_isInt (tr1))
5078 message ("Left operand of %s is non-integer (%t): %s",
5079 lltok_unparse (op), te1, exprNode_unparse (ret)),
5083 /* !ctype_isInt (te2) */
5087 message ("Right operand of %s is non-integer (%t): %s",
5088 lltok_unparse (op), te2, exprNode_unparse (ret)),
5098 ** returns exprNode representing e1 op e2
5100 ** uses msg if there are errors
5101 ** can be used for both assignment ops and regular ops
5106 static /*@only@*/ /*@notnull@*/ exprNode
5107 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
5108 /*@keep@*/ lltok op)
5110 ctype te1, te2, tr1, tr2, tret;
5111 int opid = lltok_getTok (op);
5112 bool hasError = FALSE;
5115 if (exprNode_isError (e1))
5117 ret = exprNode_createPartialNVCopy (e2);
5121 ret = exprNode_createPartialNVCopy (e1);
5124 ret->val = multiVal_undefined;
5126 ret->edata = exprData_makeOp (e1, e2, op);
5128 if (exprNode_isError (e1) || exprNode_isError (e2))
5130 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5131 || opid == EQ_OP || opid == NE_OP
5132 || opid == AND_OP || opid == OR_OP)
5134 ret->typ = ctype_bool;
5137 if (exprNode_isDefined (e1))
5139 exprNode_checkUse (ret, e1->sref, e1->loc);
5142 if (exprNode_isDefined (e2))
5144 exprNode_mergeUSs (ret, e2);
5145 exprNode_checkUse (ret, e2->sref, e2->loc);
5151 tret = ctype_unknown;
5152 te1 = exprNode_getType (e1);
5153 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5155 te2 = exprNode_getType (e2);
5157 tr1 = ctype_realishType (te1);
5158 tr2 = ctype_realishType (te2);
5162 ret->guards = guardSet_or (ret->guards, e2->guards);
5164 else if (opid == AND_OP)
5166 ret->guards = guardSet_and (ret->guards, e2->guards);
5173 if (opid == EQ_OP || opid == NE_OP)
5175 exprNode temp1 = e1, temp2 = e2;
5177 /* could do NULL == x */
5179 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5181 temp1 = e2; temp2 = e1;
5184 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5186 reflectNullTest (temp1, (opid == NE_OP));
5187 guardSet_free (ret->guards);
5188 ret->guards = guardSet_copy (temp1->guards);
5192 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5193 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5198 if (anyAbstract (tr1, tr2) &&
5199 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
5200 (opid == AND_OP || opid == OR_OP
5201 || opid == EQ_OP || opid == NE_OP))))
5203 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
5205 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5207 /* unknown types, no comparisons possible */
5213 case TMULT: /* multiplication and division: */
5215 case MUL_ASSIGN: /* numeric, numeric -> numeric */
5216 case DIV_ASSIGN: /* */
5218 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5221 case TPLUS: /* addition and subtraction: */
5222 case TMINUS: /* pointer, int -> pointer */
5223 case SUB_ASSIGN: /* int, pointer -> pointer */
5224 case ADD_ASSIGN: /* numeric, numeric -> numeric */
5226 tr1 = ctype_fixArrayPtr (tr1);
5228 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5229 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5233 if (context_msgPointerArith ())
5237 message ("Pointer arithmetic (%t, %t): %s",
5238 te1, te2, exprNode_unparse (ret)),
5243 ** Swap terms so e1 is always the pointer
5246 if (ctype_isRealPointer (tr1))
5252 exprNode_swap (e1, e2);
5256 if (sRef_possiblyNull (e1->sref)
5257 && !usymtab_isGuarded (e1->sref))
5260 (FLG_NULLPOINTERARITH,
5261 message ("Pointer arithmetic involving possibly "
5262 "null pointer %s: %s",
5263 exprNode_unparse (e1),
5264 exprNode_unparse (ret)),
5268 ret->sref = sRef_copy (e1->sref);
5270 /* start modifications */
5271 /* added by Seejo on 4/16/2000 */
5273 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5275 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5276 //if (sRef_isKnown (e->sref)) {
5277 //ret->sref = sRef_makeAddress (e->sref);
5282 added ugly fixed to stop
5283 program from crashing on point + int +int
5284 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5286 if (!multiVal_isInt (e2->val) )
5290 val = (int) multiVal_forceInt (e2->val);
5292 /* Operator : + or += */
5293 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5294 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5295 val should not result in a
5296 size < 0 (size = 0 is ok !) */
5298 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5300 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5301 sRef_setNotNullTerminatedState(ret->sref);
5302 sRef_resetLen (ret->sref);
5304 sRef_setNullTerminatedState(ret->sref);
5305 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5310 /* Operator : - or -= */
5311 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5312 if (sRef_getSize(e1->sref) >= 0) {
5313 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5314 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5319 /* end modifications */
5321 sRef_setNullError (ret->sref);
5324 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5325 ** since is points to storage that should not be deallocated
5326 ** through this pointer.
5329 if (sRef_isOnly (ret->sref)
5330 || sRef_isFresh (ret->sref))
5332 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5337 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5338 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5340 if (context_msgPointerArith ())
5344 message ("Pointer arithmetic (%t, %t): %s",
5345 te1, te2, exprNode_unparse (ret)),
5349 if (sRef_possiblyNull (e1->sref)
5350 && !usymtab_isGuarded (e1->sref))
5353 (FLG_NULLPOINTERARITH,
5354 message ("Pointer arithmetic involving possibly "
5355 "null pointer %s: %s",
5356 exprNode_unparse (e2),
5357 exprNode_unparse (ret)),
5361 ret->sref = sRef_copy (e2->sref);
5363 /* start modifications */
5364 /* added by Seejo on 4/16/2000 */
5366 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5369 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5370 //if (sRef_isKnown (e->sref)) {
5371 //ret->sref = sRef_makeAddress (e->sref);
5374 int val = (int) multiVal_forceInt (e1->val);
5376 /* Operator : + or += */
5377 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5378 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5379 val should not result in a
5380 size < 0 (size = 0 is ok !) */
5382 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5384 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5385 sRef_setNotNullTerminatedState(ret->sref);
5386 sRef_resetLen (ret->sref);
5388 sRef_setNullTerminatedState(ret->sref);
5389 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5394 /* Operator : - or -= */
5395 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5396 if (sRef_getSize(e2->sref) >= 0) {
5397 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5398 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5403 /* end modifications */
5405 sRef_setNullError (ret->sref);
5408 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5409 ** since is points to storage that should not be deallocated
5410 ** through this pointer.
5413 if (sRef_isOnly (ret->sref)
5414 || sRef_isFresh (ret->sref)) {
5415 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5419 ret->sref = e2->sref;
5423 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5428 case LEFT_ASSIGN: /* Shifts: should be unsigned values */
5432 case TAMPERSAND: /* bitwise & */
5434 case TCIRC: /* ^ (XOR) */
5439 bool reported = FALSE;
5440 flagcode code = FLG_BITWISEOPS;
5442 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5443 || opid == RIGHT_OP || opid == RIGHT_ASSIGN) {
5444 code = FLG_SHIFTSIGNED;
5447 if (!ctype_isUnsigned (tr1))
5449 if (exprNode_isNonNegative (e1)) {
5452 reported = optgenerror
5454 message ("Left operand of %s is not unsigned value (%t): %s",
5455 lltok_unparse (op), te1,
5456 exprNode_unparse (ret)),
5466 /* right need not be signed for shifts */
5467 if (code != FLG_SHIFTSIGNED
5468 && !ctype_isUnsigned (tr2))
5470 if (!exprNode_isNonNegative (e2)) {
5471 reported = optgenerror
5473 message ("Right operand of %s is not unsigned value (%t): %s",
5474 lltok_unparse (op), te2,
5475 exprNode_unparse (ret)),
5483 if (!checkIntegral (e1, e2, ret, op)) {
5484 te1 = ctype_unknown;
5488 DPRINTF (("Set: %s", ctype_unparse (te1)));
5491 ** tret is the widest type of te1 and te2
5494 tret = ctype_widest (te1, te2);
5499 if (checkIntegral (e1, e2, ret, op)) {
5502 tret = ctype_unknown;
5507 case TLT: /* comparisons */
5508 case TGT: /* numeric, numeric -> bool */
5509 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5510 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5513 bool fepsilon = FALSE;
5515 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5520 if (opid == TLT || opid == TGT)
5522 uentry ue1 = exprNode_getUentry (e1);
5523 uentry ue2 = exprNode_getUentry (e2);
5526 ** FLT_EPSILON, etc. really is a variable, not
5530 if (uentry_isVariable (ue1))
5532 cstring uname = uentry_rawName (ue1);
5534 if (cstring_equalLit (uname, "FLT_EPSILON")
5535 || cstring_equalLit (uname, "DBL_EPSILON")
5536 || cstring_equalLit (uname, "LDBL_EPSILON"))
5542 if (uentry_isVariable (ue2))
5544 cstring uname = uentry_rawName (ue2);
5546 if (cstring_equalLit (uname, "FLT_EPSILON")
5547 || cstring_equalLit (uname, "DBL_EPSILON")
5548 || cstring_equalLit (uname, "LDBL_EPSILON"))
5557 ; /* Don't complain. */
5563 message ("Dangerous comparison involving %s types: %s",
5564 ctype_unparse (rtype),
5565 exprNode_unparse (ret)),
5574 ** Types should match.
5577 if (!exprNode_matchTypes (e1, e2))
5579 hasError = gentypeerror
5581 message ("Operands of %s have incompatible types (%t, %t): %s",
5582 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5588 || (ctype_isForceRealNumeric (&tr1)
5589 && ctype_isForceRealNumeric (&tr2)) ||
5590 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5596 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5597 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5601 message ("Comparison of pointer and numeric (%t, %t): %s",
5602 te1, te2, exprNode_unparse (ret)),
5607 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5612 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5614 if ((opid == EQ_OP || opid == NE_OP) &&
5615 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5618 ** is one a variable?
5621 if (uentry_isVariable (exprNode_getUentry (e1))
5622 || uentry_isVariable (exprNode_getUentry (e2)))
5625 ** comparisons with FALSE are okay
5628 if (exprNode_isFalseConstant (e1)
5629 || exprNode_isFalseConstant (e2))
5638 ("Use of %q with %s variables (risks inconsistency because "
5639 "of multiple true values): %s",
5640 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5641 context_printBoolName (), exprNode_unparse (ret)),
5648 case AND_OP: /* bool, bool -> bool */
5651 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5657 if (context_maybeSet (FLG_BOOLOPS))
5659 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5661 if (ctype_sameName (te1, te2))
5665 message ("Operands of %s are non-boolean (%t): %s",
5666 lltok_unparse (op), te1,
5667 exprNode_unparse (ret)),
5675 ("Operands of %s are non-booleans (%t, %t): %s",
5676 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5680 else if (!ctype_isRealBool (te1))
5684 message ("Left operand of %s is non-boolean (%t): %s",
5685 lltok_unparse (op), te1, exprNode_unparse (ret)),
5688 else if (!ctype_isRealBool (te2))
5692 message ("Right operand of %s is non-boolean (%t): %s",
5693 lltok_unparse (op), te2, exprNode_unparse (ret)),
5706 (cstring_makeLiteral
5707 ("There has been a problem in the parser. This is believed to result "
5708 "from a problem with bison v. 1.25. Please try rebuidling LCLint "
5709 "using the pre-compiled grammar files by commenting out the "
5710 "BISON= line in the top-level Makefile."));
5715 DPRINTF (("Return type: %s", ctype_unparse (tret)));
5718 exprNode_checkUse (ret, e1->sref, e1->loc);
5719 exprNode_mergeUSs (ret, e2);
5720 exprNode_checkUse (ret, e2->sref, e2->loc);
5726 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5727 /*@only@*/ lltok op)
5731 checkMacroParen (e1);
5732 checkMacroParen (e2);
5734 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5736 checkExpressionDefined (e1, e2, op);
5739 ret = exprNode_makeOp (e1, e2, op);
5744 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5747 ** This is somewhat bogus!
5749 ** Assigning to a nested observer in a non-observer datatype
5750 ** should not produce an error.
5753 sRef ref = exprNode_getSref (e1);
5755 DPRINTF (("Check assign mod: %s",
5756 sRef_unparseFull (ref)));
5758 if (sRef_isObserver (ref)
5759 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
5760 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5762 sRef base = sRef_getBase (ref);
5764 if (sRef_isValid (base) && sRef_isObserver (base))
5766 exprNode_checkModify (e1, ret);
5770 exprNode_checkModifyVal (e1, ret);
5775 exprNode_checkModify (e1, ret);
5780 exprNode_assign (/*@only@*/ exprNode e1,
5781 /*@only@*/ exprNode e2, /*@only@*/ lltok op)
5783 bool isalloc = FALSE;
5784 bool isjustalloc = FALSE;
5787 DPRINTF (("%s [%s] <- %s [%s]",
5788 exprNode_unparse (e1),
5789 ctype_unparse (e1->typ),
5790 exprNode_unparse (e2),
5791 ctype_unparse (e2->typ)));
5793 if (lltok_getTok (op) != TASSIGN)
5795 ret = exprNode_makeOp (e1, e2, op);
5799 ret = exprNode_createPartialCopy (e1);
5800 ret->kind = XPR_ASSIGN;
5801 ret->edata = exprData_makeOp (e1, e2, op);
5803 if (!exprNode_isError (e2))
5805 ret->sets = sRefSet_union (ret->sets, e2->sets);
5806 ret->msets = sRefSet_union (ret->msets, e2->msets);
5807 ret->uses = sRefSet_union (ret->uses, e2->uses);
5811 checkExpressionDefined (e1, e2, op);
5813 if (exprNode_isError (e1))
5815 if (!exprNode_isError (e2))
5817 ret->loc = fileloc_update (ret->loc, e2->loc);
5821 ret->loc = fileloc_update (ret->loc, g_currentloc);
5825 if (!exprNode_isError (e2))
5827 checkMacroParen (e2);
5830 if (exprNode_isDefined (e1))
5832 if (sRef_isMacroParamRef (e1->sref))
5834 if (context_inIterDef ())
5836 uentry ue = sRef_getUentry (e1->sref);
5838 if (uentry_isYield (ue))
5844 if (fileloc_isDefined (e1->loc))
5848 message ("Assignment to non-yield iter parameter: %q",
5849 sRef_unparse (e1->sref)),
5856 message ("Assignment to non-yield iter parameter: %q",
5857 sRef_unparse (e1->sref)),
5864 if (fileloc_isDefined (e1->loc))
5868 message ("Assignment to macro parameter: %q",
5869 sRef_unparse (e1->sref)),
5876 message ("Assignment to macro parameter: %q",
5877 sRef_unparse (e1->sref)),
5881 exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
5886 exprNode_checkAssignMod (e1, ret);
5889 if (exprNode_isDefined (e2))
5891 if (lltok_getTok (op) == TASSIGN)
5893 ctype te1 = exprNode_getType (e1);
5894 ctype te2 = exprNode_getType (e2);
5896 if (!ctype_forceMatch (te1, te2))
5898 if (exprNode_matchLiteral (te1, e2))
5906 message ("Assignment of %t to %t: %s %s %s",
5907 te2, te1, exprNode_unparse (e1),
5909 exprNode_unparse (e2)),
5915 exprNode_mergeUSs (ret, e2);
5916 exprNode_checkUse (ret, e2->sref, e2->loc);
5918 doAssign (e1, e2, FALSE);
5919 ret->sref = e1->sref;
5923 if (exprNode_isDefined (e2))
5925 exprNode_mergeUSs (ret, e2);
5926 exprNode_checkUse (ret, e2->sref, e2->loc);
5930 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
5932 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
5935 isjustalloc = sRef_isJustAllocated (e1->sref);
5936 isalloc = sRef_isAllocated (e1->sref);
5938 if (sRef_isField (e1->sref))
5940 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
5942 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
5944 exprNode_checkUse (ret, root, e1->loc);
5950 ** be careful! this defines e1->sref.
5953 /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
5955 exprNode_checkSet (ret, e1->sref);
5959 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
5960 ? e2->loc : e1->loc);
5966 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
5975 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
5976 /*@keep@*/ exprNode elseclause)
5980 if (!exprNode_isError (pred))
5982 ret = exprNode_createPartialCopy (pred);
5983 checkMacroParen (pred);
5984 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
5986 if (!exprNode_isError (ifclause))
5988 checkMacroParen (ifclause); /* update macro counts! */
5990 if (!exprNode_isError (elseclause))
5992 checkMacroParen (elseclause);
5994 if (!exprNode_matchTypes (ifclause, elseclause))
5997 (exprNode_getType (ifclause),
5999 exprNode_getType (elseclause),
6001 message ("Conditional clauses are not of same type: "
6003 exprNode_unparse (ifclause),
6004 exprNode_getType (ifclause),
6005 exprNode_unparse (elseclause),
6006 exprNode_getType (elseclause)),
6009 ret->sref = sRef_undefined;
6010 ret->typ = ctype_unknown;
6015 /* for now...should merge the states */
6016 ret->sref = ifclause->sref;
6017 ret->typ = ifclause->typ;
6019 if (exprNode_isNullValue (ifclause))
6021 ret->typ = elseclause->typ;
6025 exprNode_checkUse (ret, pred->sref, pred->loc);
6026 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6027 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6029 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6034 ret->typ = ifclause->typ;
6036 exprNode_checkUse (pred, pred->sref, pred->loc);
6037 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6039 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6044 if (!exprNode_isError (elseclause))
6046 ret->typ = elseclause->typ;
6048 exprNode_checkUse (pred, pred->sref, pred->loc);
6049 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6051 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6055 else /* pred is error */
6057 if (!exprNode_isError (ifclause))
6059 ret = exprNode_createSemiCopy (ifclause);
6061 checkMacroParen (ifclause); /* update macro counts! */
6063 if (!exprNode_isError (elseclause))
6065 checkMacroParen (elseclause);
6067 ret->typ = ifclause->typ;
6069 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6072 (exprNode_getType (ifclause),
6074 exprNode_getType (elseclause),
6076 message ("Conditional clauses are not of same type: "
6078 exprNode_unparse (ifclause),
6079 exprNode_getType (ifclause),
6080 exprNode_unparse (elseclause),
6081 exprNode_getType (elseclause)),
6084 ret->typ = ctype_unknown;
6088 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6089 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6091 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6094 else if (!exprNode_isError (elseclause)) /* pred, if errors */
6096 ret = exprNode_createSemiCopy (ifclause);
6098 ret->typ = elseclause->typ;
6099 checkMacroParen (elseclause);
6101 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6102 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6104 else /* all errors! */
6106 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6110 ret->kind = XPR_COND;
6111 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
6113 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6115 exprNode_combineControl (ret, ifclause, elseclause);
6122 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6124 ctype totype = qtype_getType (qt);
6126 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6130 ** check use of va_arg : <valist>, type -> type
6133 if (exprNode_isError (arg))
6138 targ = exprNode_getType (arg);
6141 ** arg should have be a pointer
6144 if (!ctype_isUA (targ) ||
6145 (!usymId_equal (ctype_typeId (targ),
6146 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6150 message ("First argument to va_arg is not a va_list (type %t): %s",
6151 targ, exprNode_unparse (arg)),
6155 exprNode_checkSet (ret, arg->sref);
6159 ** return type is totype
6163 ret->kind = XPR_VAARG;
6164 ret->edata = exprData_makeCast (tok, arg, qt);
6169 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6171 exprNode ret = exprNode_createPlain (ctype_undefined);
6172 ret->kind = XPR_LABEL;
6173 ret->edata = exprData_makeLiteral (label);
6174 ret->isJumpPoint = TRUE;
6176 return (ret); /* for now, ignore label */
6179 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6181 if (exprNode_isDefined (stmt))
6183 stmt->isJumpPoint = TRUE;
6185 /* This prevent stray no return path errors, etc. */
6186 stmt->exitCode = XK_MUSTEXIT;
6192 bool exprNode_isDefaultMarker (exprNode e)
6194 if (exprNode_isDefined (e))
6196 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6202 bool exprNode_isCaseMarker (exprNode e)
6204 if (exprNode_isDefined (e))
6206 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6212 bool exprNode_isLabelMarker (exprNode e)
6214 if (exprNode_isDefined (e))
6216 return (e->kind == XPR_LABEL);
6222 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6224 exprNode ret = exprNode_createPartialCopy (test);
6226 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6228 if (exprNode_isError (test)) {
6232 exprNode_checkUse (ret, test->sref, test->loc);
6234 usymtab_setExitCode (ret->exitCode);
6238 usymtab_setMustBreak ();
6241 ret->edata = exprData_makeSingle (test);
6242 ret->isJumpPoint = TRUE;
6248 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6250 exprNode ret = exprNode_createPartialCopy (test);
6252 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6253 ret->edata = exprData_makePair (test, stmt);
6254 ret->isJumpPoint = TRUE;
6256 if (exprNode_isError (test))
6261 exprNode_checkUse (ret, test->sref, test->loc);
6263 if (exprNode_isError (stmt))
6268 exprNode_mergeUSs (ret, stmt);
6270 ret->exitCode = stmt->exitCode;
6271 ret->mustBreak = stmt->mustBreak;
6272 ret->canBreak = stmt->canBreak;
6274 usymtab_setExitCode (ret->exitCode);
6278 usymtab_setMustBreak ();
6285 /*@notnull@*/ /*@only@*/ exprNode
6286 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6288 exprNode ret = exprNode_createTok (def);
6290 ret->isJumpPoint = TRUE;
6291 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6296 exprNode_mayEscape (exprNode e)
6298 if (exprNode_isDefined (e))
6300 return exitkind_couldEscape (e->exitCode);
6306 exprNode_mustBreak (exprNode e)
6308 if (exprNode_isDefined (e))
6310 return e->mustBreak;
6316 exprNode_mustEscape (exprNode e)
6318 if (exprNode_isDefined (e))
6320 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6327 exprNode_errorEscape (exprNode e)
6329 if (exprNode_isDefined (e))
6331 return exitkind_isError (e->exitCode);
6337 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6339 exprNode ret = exprNode_createPartialCopy (e1);
6341 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6343 ret->edata = exprData_makePair (e1, e2);
6344 ret->kind = XPR_STMTLIST;
6346 if (exprNode_isDefined (e1))
6348 ret->isJumpPoint = e1->isJumpPoint;
6349 ret->canBreak = e1->canBreak;
6353 if (exprNode_isDefined (e2))
6355 ret->loc = fileloc_update (ret->loc, e2->loc);
6359 if (exprNode_isDefined (e2))
6361 ret->exitCode = e2->exitCode;
6362 ret->mustBreak = e2->mustBreak;
6363 if (e2->canBreak) ret->canBreak = TRUE;
6367 ** if e1 must return, then e2 is unreachable!
6370 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6372 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6373 && !(e2->isJumpPoint))
6375 if (context_getFlag (FLG_UNREACHABLE))
6379 if (e2->kind == XPR_STMT)
6381 nr = exprData_getUopNode (e2->edata);
6384 if ((nr->kind == XPR_TOK
6385 && lltok_isSemi (exprData_getTok (nr->edata))))
6387 /* okay to have unreachable ";" */
6388 ret->exitCode = XK_MUSTEXIT;
6389 ret->canBreak = TRUE;
6393 if (optgenerror (FLG_UNREACHABLE,
6394 message ("Unreachable code: %s",
6395 exprNode_unparseFirst (nr)),
6398 ret->isJumpPoint = TRUE;
6399 ret->mustBreak = FALSE;
6400 ret->exitCode = XK_ERROR;
6401 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6405 ret->exitCode = XK_MUSTEXIT;
6406 ret->canBreak = TRUE;
6414 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6417 ** We want a warning anytime we have:
6419 ** yyy; <<<- no break or return
6423 exprNode lastStmt = exprNode_lastStatement (e1);
6425 if (exprNode_isDefined (lastStmt)
6426 && !exprNode_mustEscape (lastStmt)
6427 && !exprNode_mustBreak (lastStmt)
6428 && !exprNode_isCaseMarker (lastStmt)
6429 && !exprNode_isDefaultMarker (lastStmt)
6430 && !exprNode_isLabelMarker (lastStmt))
6432 voptgenerror (FLG_CASEBREAK,
6434 ("Fall through case (no preceeding break)"),
6441 exprNode_mergeUSs (ret, e2);
6443 usymtab_setExitCode (ret->exitCode);
6447 usymtab_setMustBreak ();
6453 exprNode exprNode_createTok (/*@only@*/ lltok t)
6455 exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6456 ret = exprNode_create (ctype_unknown);
6457 ret->kind = XPR_TOK;
6458 ret->edata = exprData_makeTok (t);
6462 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6464 if (!exprNode_isError (e))
6466 exprNode_checkStatement(e);
6469 return (exprNode_statementError (e, t));
6472 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6474 exprNode ret = exprNode_createPartialCopy (e);
6476 if (!exprNode_isError (e))
6478 if (e->kind != XPR_ASSIGN)
6480 exprNode_checkUse (ret, e->sref, e->loc);
6483 ret->exitCode = e->exitCode;
6484 ret->canBreak = e->canBreak;
6485 ret->mustBreak = e->mustBreak;
6488 ret->edata = exprData_makeUop (e, t);
6489 ret->kind = XPR_STMT;
6494 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6496 if (!exprNode_isError (e))
6498 if (e->kind != XPR_ASSIGN)
6500 exprNode_checkUse (e, e->sref, e->loc);
6507 void exprNode_produceGuards (exprNode pred)
6509 if (!exprNode_isError (pred))
6511 if (ctype_isRealPointer (pred->typ))
6513 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6516 exprNode_checkUse (pred, pred->sref, pred->loc);
6517 exprNode_resetSref (pred);
6521 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6523 exprNode ret = exprNode_createPartialCopy (e);
6525 if (!exprNode_isError (e))
6527 ret->exitCode = e->exitCode;
6528 ret->canBreak = e->canBreak;
6529 ret->mustBreak = e->mustBreak;
6532 ret->edata = exprData_makeSingle (e);
6533 ret->kind = XPR_BLOCK;
6537 bool exprNode_isBlock (exprNode e)
6539 return (exprNode_isDefined (e)
6540 && ((e)->kind == XPR_BLOCK));
6543 bool exprNode_isAssign (exprNode e)
6545 if (exprNode_isDefined (e))
6547 return (e->kind == XPR_ASSIGN);
6553 bool exprNode_isEmptyStatement (exprNode e)
6555 return (exprNode_isDefined (e)
6556 && (e->kind == XPR_TOK)
6557 && (lltok_isSemi (exprData_getTok (e->edata))));
6560 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6563 bool emptyErr = FALSE;
6565 if (context_maybeSet (FLG_IFEMPTY))
6567 if (exprNode_isEmptyStatement (tclause))
6569 emptyErr = optgenerror (FLG_IFEMPTY,
6571 ("Body of if statement is empty"),
6572 exprNode_loc (tclause));
6576 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6578 if (exprNode_isDefined (tclause)
6579 && !exprNode_isBlock (tclause))
6581 voptgenerror (FLG_IFBLOCK,
6583 ("Body of if statement is not a block: %s",
6584 exprNode_unparse (tclause)),
6585 exprNode_loc (tclause));
6589 if (exprNode_isError (pred))
6591 if (exprNode_isError (tclause))
6593 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6597 ret = exprNode_createPartialCopy (tclause);
6602 if (exprNode_mustEscape (pred))
6606 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6607 exprNode_loc (pred));
6610 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6611 exprNode_checkUse (pred, pred->sref, pred->loc);
6613 if (!exprNode_isError (tclause))
6615 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
6618 ret = exprNode_createPartialCopy (pred);
6622 ret->edata = exprData_makePair (pred, tclause);
6624 ret->exitCode = XK_UNKNOWN;
6626 if (exprNode_isDefined (tclause))
6628 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
6629 ret->canBreak = tclause->canBreak;
6630 ret->sets = sRefSet_union (ret->sets, tclause->sets);
6631 ret->msets = sRefSet_union (ret->msets, tclause->msets);
6632 ret->uses = sRefSet_union (ret->uses, tclause->uses);
6635 ret->mustBreak = FALSE;
6640 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
6641 /*@only@*/ exprNode tclause,
6642 /*@only@*/ exprNode eclause)
6645 bool tEmptyErr = FALSE;
6646 bool eEmptyErr = FALSE;
6648 if (context_maybeSet (FLG_IFEMPTY))
6650 if (exprNode_isEmptyStatement (tclause))
6652 tEmptyErr = optgenerror
6655 ("Body of if clause of if statement is empty"),
6656 exprNode_loc (tclause));
6659 if (exprNode_isEmptyStatement (eclause))
6661 eEmptyErr = optgenerror
6664 ("Body of else clause of if statement is empty"),
6665 exprNode_loc (eclause));
6669 if (context_maybeSet (FLG_IFBLOCK))
6672 && exprNode_isDefined (tclause)
6673 && !exprNode_isBlock (tclause))
6675 voptgenerror (FLG_IFBLOCK,
6677 ("Body of if clause of if statement is not a block: %s",
6678 exprNode_unparse (tclause)),
6679 exprNode_loc (tclause));
6683 && exprNode_isDefined (eclause)
6684 && !exprNode_isBlock (eclause)
6685 && !(eclause->kind == XPR_IF)
6686 && !(eclause->kind == XPR_IFELSE))
6691 ("Body of else clause of if statement is not a block: %s",
6692 exprNode_unparse (eclause)),
6693 exprNode_loc (eclause));
6697 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
6699 if (exprNode_isDefined (eclause)
6700 && (eclause->kind == XPR_IF))
6702 voptgenerror (FLG_ELSEIFCOMPLETE,
6703 message ("Incomplete else if logic (no final else): %s",
6704 exprNode_unparse (eclause)),
6705 exprNode_loc (eclause));
6709 if (exprNode_isError (pred))
6711 if (exprNode_isError (tclause))
6713 if (exprNode_isError (eclause))
6715 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6719 ret = exprNode_createPartialCopy (eclause);
6724 ret = exprNode_createPartialCopy (tclause);
6727 else /* pred is okay */
6729 ret = exprNode_createPartialCopy (pred);
6731 if (exprNode_mustEscape (pred))
6735 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6736 exprNode_loc (pred));
6739 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6740 exprNode_checkUse (ret, pred->sref, pred->loc);
6742 exprNode_mergeCondUSs (ret, tclause, eclause);
6745 ret->kind = XPR_IFELSE;
6746 ret->edata = exprData_makeCond (pred, tclause, eclause);
6748 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
6750 exprNode_combineControl (ret, tclause, eclause);
6751 ret->loc = fileloc_update (ret->loc, eclause->loc);
6758 ** *allpaths <- TRUE iff all executions paths must go through the switch
6762 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
6764 exprNodeSList el = exprNode_flatten (e);
6765 bool mustReturn = TRUE; /* find a branch that doesn't */
6766 bool thisReturn = FALSE;
6767 bool hasDefault = FALSE;
6768 bool hasAllMembers = FALSE;
6769 bool inSwitch = FALSE;
6770 bool isEnumSwitch = FALSE;
6771 bool canBreak = FALSE;
6772 bool fallThrough = FALSE;
6773 ctype ct = ctype_unknown;
6774 enumNameSList usedEnums;
6777 if (exprNode_isDefined (test))
6782 ttype = ctype_realType (ct);
6784 if (ctype_isEnum (ttype))
6786 isEnumSwitch = TRUE;
6787 enums = ctype_elist (ttype);
6788 usedEnums = enumNameSList_new ();
6792 exprNodeSList_elements (el, current)
6794 if (exprNode_isDefined (current))
6796 switch (current->kind)
6804 message ("Duplicate default cases in switch"),
6805 exprNode_loc (current));
6810 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
6818 exprNode st = exprData_getSingle (current->edata);
6819 uentry ue = exprNode_getUentry (st);
6821 if (uentry_isValid (ue))
6823 cstring cname = uentry_rawName (ue);
6825 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
6827 if (enumNameSList_member
6828 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
6832 message ("Duplicate case in switch: %s",
6838 enumNameSList_addh (usedEnums, cname);
6845 message ("Case in switch not %s member: %s",
6846 ctype_unparse (ct), cname),
6853 if (inSwitch && !fallThrough)
6855 if (!thisReturn || canBreak)
6865 /*@switchbreak@*/ break;
6867 thisReturn = thisReturn || exprNode_mustEscape (current);
6868 canBreak = canBreak || current->canBreak;
6869 if (canBreak) fallThrough = FALSE;
6872 } end_exprNodeSList_elements;
6874 if (inSwitch) /* check the last one! */
6876 if (!thisReturn || canBreak)
6885 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
6886 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
6888 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
6890 voptgenerror (FLG_MISSCASE,
6891 message ("Missing case%s in switch: %q",
6892 cstring_makeLiteralTemp
6893 ((enumNameSList_size (unused) > 1) ? "s" : ""),
6894 enumNameSList_unparse (unused)),
6897 enumNameSList_free (unused);
6901 hasAllMembers = TRUE;
6905 enumNameSList_free (usedEnums);
6909 *allpaths = hasDefault;
6912 exprNodeSList_free (el);
6913 return ((hasDefault || hasAllMembers) && mustReturn);
6916 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
6918 exprNode ret = exprNode_createPartialCopy (e);
6921 DPRINTF (("Switch: %s", exprNode_unparse (s)));
6923 ret->kind = XPR_SWITCH;
6924 ret->edata = exprData_makePair (e, s);
6926 if (!exprNode_isError (s))
6928 exprNode fs = exprNode_firstStatement (s);
6929 ret->loc = fileloc_update (ret->loc, s->loc);
6931 if (exprNode_isUndefined (fs)
6932 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
6933 || exprNode_isDefaultMarker (fs)) {
6936 voptgenerror (FLG_FIRSTCASE,
6938 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
6943 if (!exprNode_isError (e))
6945 if (checkSwitchExpr (e, s, &allpaths))
6947 ret->exitCode = XK_MUSTRETURN;
6951 ret->exitCode = e->exitCode;
6954 ret->canBreak = e->canBreak;
6955 ret->mustBreak = e->mustBreak;
6959 ** exprNode.c:3883,32: Variable allpaths used before definition
6966 DPRINTF (("Context exit switch!"));
6967 context_exitSwitch (ret, allpaths);
6968 DPRINTF (("Context exit switch done!"));
6973 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
6974 /*@notnull@*/ exprNode body)
6976 sRefSet tuses = test->uses;
6978 if (!sRefSet_isEmpty (test->uses))
6980 sRefSet sets = sRefSet_newCopy (body->sets);
6981 bool hasError = TRUE;
6982 bool innerState = FALSE;
6983 sRefSet tuncon = sRefSet_undefined;
6985 sets = sRefSet_union (sets, test->sets);
6986 sets = sRefSet_union (sets, body->msets);
6987 sets = sRefSet_union (sets, test->msets);
6989 sRefSet_allElements (tuses, el)
6991 if (sRef_isUnconstrained (el))
6993 tuncon = sRefSet_insert (tuncon, el);
6997 if (sRefSet_member (sets, el))
7004 if (sRef_isInternalState (el)
7005 || sRef_isFileStatic (sRef_getRootBase (el)))
7009 } end_sRefSet_allElements ;
7013 sRefSet suncon = sRefSet_undefined;
7014 bool sinner = FALSE;
7016 sRefSet_allElements (sets, el)
7018 if (sRef_isUnconstrained (el))
7020 suncon = sRefSet_insert (suncon, el);
7022 else if (sRef_isInternalState (el))
7030 } end_sRefSet_allElements ;
7032 if (sinner && innerState)
7036 else if (sRefSet_isEmpty (tuncon)
7037 && sRefSet_isEmpty (suncon))
7042 ("Suspected infinite loop. No value used in loop test (%q) "
7043 "is modified by test or loop body.",
7044 sRefSet_unparsePlain (tuses)),
7049 if (sRefSet_isEmpty (tuncon))
7053 message ("Suspected infinite loop. No condition values "
7054 "modified. Modification possible through "
7055 "unconstrained calls: %q",
7056 sRefSet_unparsePlain (suncon)),
7063 message ("Suspected infinite loop. No condition values "
7064 "modified. Possible undetected dependency through "
7065 "unconstrained calls in loop test: %q",
7066 sRefSet_unparsePlain (tuncon)),
7072 sRefSet_free (sets);
7076 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7079 bool emptyErr = FALSE;
7081 if (context_maybeSet (FLG_WHILEEMPTY))
7083 if (exprNode_isEmptyStatement (b))
7085 emptyErr = optgenerror
7088 ("Body of while statement is empty"),
7093 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7095 if (exprNode_isDefined (b)
7096 && !exprNode_isBlock (b))
7098 if (context_inIterDef ()
7099 && (b->kind == XPR_STMTLIST
7100 || b->kind == XPR_TOK))
7106 voptgenerror (FLG_WHILEBLOCK,
7108 ("Body of while statement is not a block: %s",
7109 exprNode_unparse (b)),
7115 if (exprNode_isError (t))
7117 if (exprNode_isError (b))
7119 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7123 ret = exprNode_createPartialCopy (b);
7130 ret = exprNode_createPartialCopy (t);
7132 llassert (t->kind == XPR_WHILEPRED);
7134 test = exprData_getSingle (t->edata);
7136 if (!exprNode_isError (b) && exprNode_isDefined (test))
7138 if (context_maybeSet (FLG_INFLOOPS)
7139 || context_maybeSet (FLG_INFLOOPSUNCON))
7142 ** check that some variable in the predicate is set by the body
7143 ** if the predicate uses any variables
7146 checkInfiniteLoop (test, b);
7149 exprNode_mergeUSs (ret, b);
7151 if (exprNode_isDefined (b))
7153 ret->exitCode = exitkind_makeConditional (b->exitCode);
7158 ret->edata = exprData_makePair (t, b);
7159 ret->kind = XPR_WHILE;
7161 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7165 message ("Predicate always exits: %s", exprNode_unparse (t)),
7169 ret->exitCode = XK_NEVERESCAPE;
7172 ** If loop is infinite, and there is no break inside,
7173 ** exit code is never reach.
7176 if (exprNode_knownIntValue (t))
7178 if (!exprNode_isZero (t))
7180 if (exprNode_isDefined (b))
7184 /* Really, it means never reached. */
7185 ret->exitCode = XK_MUSTEXIT;
7195 ret->canBreak = FALSE;
7196 ret->mustBreak = FALSE;
7202 ** do { b } while (t);
7204 ** note: body passed as first argument
7207 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7211 if (exprNode_isError (t))
7213 if (exprNode_isError (b))
7215 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7219 ret = exprNode_createPartialCopy (b);
7221 ret->exitCode = exitkind_makeConditional (b->exitCode);
7222 exprNode_checkUse (ret, b->sref, b->loc);
7223 ret->exitCode = b->exitCode;
7224 ret->canBreak = b->canBreak;
7225 ret->mustBreak = b->mustBreak;
7230 ret = exprNode_createPartialCopy (t);
7231 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7233 if (!exprNode_isError (b))
7236 ** forgot the copy's --- why wasn't this detected??
7239 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7240 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7241 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
7243 /* left this out --- causes and aliasing bug (infinite loop)
7244 should be detected?? */
7246 exprNode_checkUse (ret, b->sref, b->loc);
7247 exprNode_mergeUSs (ret, t);
7248 exprNode_checkUse (ret, t->sref, t->loc);
7250 ret->exitCode = b->exitCode;
7251 ret->canBreak = b->canBreak;
7252 ret->mustBreak = b->mustBreak;
7256 context_exitDoWhileClause (t);
7258 ret->kind = XPR_DOWHILE;
7259 ret->edata = exprData_makePair (t, b);
7263 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7266 bool emptyErr = FALSE;
7268 if (context_maybeSet (FLG_FOREMPTY))
7270 if (exprNode_isEmptyStatement (body))
7272 emptyErr = optgenerror
7275 ("Body of for statement is empty"),
7276 exprNode_loc (body));
7280 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7282 if (exprNode_isDefined (body)
7283 && !exprNode_isBlock (body))
7285 if (context_inIterDef ()
7286 && (body->kind == XPR_STMTLIST
7287 || body->kind == XPR_TOK))
7293 voptgenerror (FLG_FORBLOCK,
7295 ("Body of for statement is not a block: %s",
7296 exprNode_unparse (body)),
7297 exprNode_loc (body));
7303 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7306 if (exprNode_isError (body))
7308 ret = exprNode_createPartialCopy (inc);
7312 ret = exprNode_createPartialCopy (body);
7314 ret->exitCode = exitkind_makeConditional (body->exitCode);
7316 exprNode_mergeUSs (inc, body);
7318 if (exprNode_isDefined (inc))
7322 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7325 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7326 exprNode_freeShallow (tmp);
7328 context_clearMessageAnnote ();
7329 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7331 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7332 exprNode_freeShallow (tmp);
7334 context_clearMessageAnnote ();
7336 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7337 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7338 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7342 ret->kind = XPR_FOR;
7343 ret->edata = exprData_makePair (inc, body);
7345 if (exprNode_isDefined (inc)) {
7346 exprNode test = exprData_getTripleTest (inc->edata);
7348 if (exprNode_isUndefined (test)) {
7349 if (exprNode_isDefined (body)) {
7350 if (!body->canBreak) {
7351 /* Really, it means never reached. */
7352 ret->exitCode = XK_MUSTEXIT;
7362 ** for (init; test; inc)
7365 ** while (test) { body; inc; }
7367 ** Now: check use of init (may set vars for test)
7368 ** check use of test
7372 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7376 if (exprNode_isError (pred)) return guardSet_undefined;
7378 llassert (pred->kind == XPR_FORPRED);
7380 test = exprData_getTripleTest (pred->edata);
7382 if (!exprNode_isError (test))
7384 return (test->guards);
7387 return guardSet_undefined;
7390 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7392 exprNode ret = exprNode_createSemiCopy (test);
7394 if (exprNode_isDefined (test))
7396 exprNode_copySets (ret, test);
7397 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7398 exprNode_checkUse (ret, test->sref, test->loc);
7400 exprNode_produceGuards (test);
7402 ret->guards = guardSet_copy (test->guards);
7405 ret->edata = exprData_makeSingle (test);
7406 ret->kind = XPR_WHILEPRED;
7410 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7411 /*@only@*/ exprNode inc)
7416 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7419 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7421 if (!exprNode_isError (inc))
7423 ret = exprNode_createPartialCopy (inc);
7427 if (!exprNode_isError (init))
7429 ret = exprNode_createPartialCopy (init);
7431 else if (!exprNode_isError (test))
7433 ret = exprNode_createPartialCopy (test);
7437 ret = exprNode_createUnknown ();
7441 exprNode_mergeUSs (ret, init);
7443 if (exprNode_isDefined (init))
7445 exprNode_checkUse (ret, init->sref, init->loc);
7448 exprNode_mergeUSs (ret, test);
7450 if (exprNode_isDefined (test))
7452 exprNode_checkUse (ret, test->sref, test->loc);
7455 ret->kind = XPR_FORPRED;
7456 ret->edata = exprData_makeFor (init, test, inc);
7460 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7462 exprNode ret = exprNode_createUnknown ();
7464 if (context_inMacro ())
7466 voptgenerror (FLG_MACROSTMT,
7467 message ("Macro %s uses goto (not functional)",
7468 context_inFunctionName ()),
7472 ret->kind = XPR_GOTO;
7473 ret->edata = exprData_makeLiteral (label);
7474 ret->mustBreak = TRUE;
7475 ret->exitCode = XK_GOTO;
7476 ret->canBreak = TRUE;
7480 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7482 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7484 ret->kind = XPR_CONTINUE;
7485 ret->edata = exprData_makeTok (l);
7486 ret->canBreak = TRUE;
7487 ret->mustBreak = TRUE;
7489 if (qcontinue == QSAFEBREAK)
7493 else if (qcontinue == QINNERCONTINUE)
7495 if (!context_inDeepLoop ())
7498 (FLG_LOOPLOOPCONTINUE,
7499 cstring_makeLiteral ("Continue statement marked with innercontinue "
7500 "is not inside a nested loop"),
7501 exprNode_loc (ret));
7504 else if (qcontinue == BADTOK)
7506 if (context_inDeepLoop ())
7509 (FLG_LOOPLOOPCONTINUE,
7510 cstring_makeLiteral ("Continue statement in nested loop"),
7511 exprNode_loc (ret));
7516 llbuglit ("exprNode_continue: bad qcontinue");
7522 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
7524 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7525 clause breakClause = context_breakClause ();
7527 ret->kind = XPR_BREAK;
7528 ret->edata = exprData_makeTok (l);
7529 ret->canBreak = TRUE;
7530 ret->mustBreak = TRUE;
7532 if (breakClause == NOCLAUSE)
7536 cstring_makeLiteral ("Break not inside while, for or switch statement"),
7537 exprNode_loc (ret));
7541 if (bqual != BADTOK)
7548 if (breakClause == SWITCHCLAUSE)
7550 if (!context_inDeepSwitch ())
7552 voptgenerror (FLG_SYNTAX,
7554 ("Break preceded by innerbreak is not in a deep switch"),
7555 exprNode_loc (ret));
7560 if (!context_inDeepLoop ())
7562 voptgenerror (FLG_SYNTAX,
7564 ("Break preceded by innerbreak is not in a deep loop"),
7565 exprNode_loc (ret));
7570 if (breakClause == SWITCHCLAUSE)
7572 voptgenerror (FLG_SYNTAX,
7574 ("Break preceded by loopbreak is breaking a switch"),
7575 exprNode_loc (ret));
7579 if (breakClause != SWITCHCLAUSE)
7583 message ("Break preceded by switchbreak is breaking %s",
7584 cstring_makeLiteralTemp
7585 ((breakClause == WHILECLAUSE
7586 || breakClause == DOWHILECLAUSE) ? "a while loop"
7587 : (breakClause == FORCLAUSE) ? "a for loop"
7588 : (breakClause == ITERCLAUSE) ? "an iterator"
7590 exprNode_loc (ret));
7598 if (breakClause == SWITCHCLAUSE)
7600 clause nextBreakClause = context_nextBreakClause ();
7602 switch (nextBreakClause)
7604 case NOCLAUSE: break;
7610 (FLG_LOOPSWITCHBREAK,
7611 cstring_makeLiteral ("Break statement in switch inside loop"),
7612 exprNode_loc (ret));
7616 (FLG_SWITCHSWITCHBREAK,
7617 cstring_makeLiteral ("Break statement in switch inside switch"),
7618 exprNode_loc (ret));
7625 if (context_inDeepLoop ())
7629 cstring_makeLiteral ("Break statement in nested loop"),
7630 exprNode_loc (ret));
7634 if (context_inDeepLoopSwitch ())
7637 (FLG_SWITCHLOOPBREAK,
7638 cstring_makeLiteral ("Break statement in loop inside switch"),
7639 exprNode_loc (ret));
7649 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
7651 fileloc loc = lltok_getLoc (t);
7652 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
7654 context_returnFunction ();
7655 exprChecks_checkNullReturn (loc);
7657 ret->kind = XPR_NULLRETURN;
7658 ret->edata = exprData_makeTok (t);
7659 ret->exitCode = XK_MUSTRETURN;
7663 exprNode exprNode_return (/*@only@*/ exprNode e)
7667 if (exprNode_isError (e))
7669 ret = exprNode_createUnknown ();
7673 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
7675 exprNode_checkUse (ret, e->sref, e->loc);
7676 exprNode_checkReturn (e);
7679 context_returnFunction ();
7680 ret->kind = XPR_RETURN;
7681 ret->edata = exprData_makeSingle (e);
7682 ret->exitCode = XK_MUSTRETURN;
7687 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
7691 if (exprNode_isError (e1))
7693 if (exprNode_isError (e2))
7695 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7699 ret = exprNode_createPartialCopy (e2);
7700 exprNode_checkUse (ret, e2->sref, e2->loc);
7701 ret->sref = e2->sref;
7706 ret = exprNode_createPartialCopy (e1);
7708 exprNode_checkUse (ret, e1->sref, e1->loc);
7710 if (!exprNode_isError (e2))
7712 exprNode_mergeUSs (ret, e2);
7713 exprNode_checkUse (ret, e2->sref, e2->loc);
7714 ret->sref = e2->sref;
7718 ret->kind = XPR_COMMA;
7719 ret->edata = exprData_makePair (e1, e2);
7721 if (exprNode_isDefined (e1))
7723 if (exprNode_isDefined (e2))
7727 if (exprNode_mustEscape (e1) || e1->mustBreak)
7731 message ("Second clause of comma expression is unreachable: %s",
7732 exprNode_unparse (e2)),
7736 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
7737 ret->mustBreak = e1->mustBreak || e2->mustBreak;
7738 ret->canBreak = e1->canBreak || e2->canBreak;
7742 if (exprNode_mustEscape (e1) || e1->mustBreak)
7746 message ("Second clause of comma expression is unreachable: %s",
7747 exprNode_unparse (e2)),
7751 ret->exitCode = e1->exitCode;
7752 ret->canBreak = e1->canBreak;
7757 if (exprNode_isDefined (e2))
7759 ret->exitCode = e2->exitCode;
7760 ret->mustBreak = e2->mustBreak;
7761 ret->canBreak = e2->canBreak;
7768 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
7770 ctype t1 = exprNode_getType (el);
7771 ctype t2 = exprNode_getType (val);
7772 bool hasError = FALSE;
7774 if (ctype_isUnknown (t1))
7776 voptgenerror (FLG_IMPTYPE,
7777 message ("Variable has unknown (implicitly int) type: %s",
7778 exprNode_unparse (el)),
7782 el->typ = ctype_int;
7785 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
7787 exprNodeList vals = exprData_getArgs (val->edata);
7789 if (ctype_isRealAP (t1))
7794 /*@i423 check number of entries int a[3] = { 1, 2, 3, 4 } ; */
7796 exprNodeList_elements (vals, oneval)
7798 cstring istring = message ("%d", i);
7801 (exprNode_fakeCopy (el),
7802 exprNode_numLiteral (ctype_int, istring,
7803 fileloc_copy (el->loc), i));
7805 if (exprNode_isDefined (newel))
7807 if (exprNodeList_size (vals) == 1
7808 && ctype_isString (exprNode_getType (oneval))
7809 && ctype_isChar (exprNode_getType (newel)))
7811 exprNode_freeIniter (newel);
7815 if (exprNode_checkOneInit (newel, oneval))
7820 if (nerrors > 3 && exprNodeList_size (vals) > 6)
7823 (message ("Additional initialization errors "
7824 "for %s not reported",
7825 exprNode_unparse (el)),
7827 exprNode_freeIniter (newel);
7832 exprNode_freeIniter (newel);
7837 exprNode_freeIniter (newel);
7842 cstring_free (istring);
7845 } end_exprNodeList_elements;
7848 else if (ctype_isStruct (ctype_realType (t1)))
7850 uentryList fields = ctype_getFields (t1);
7853 if (uentryList_size (fields) != exprNodeList_size (vals))
7855 if (uentryList_size (fields) > exprNodeList_size (vals))
7857 hasError = optgenerror
7859 message ("Initializer block for "
7860 "%s has %d field%&, but %s has %d field%&: %q",
7861 exprNode_unparse (el),
7862 exprNodeList_size (vals),
7864 uentryList_size (fields),
7865 exprNodeList_unparse (vals)),
7870 hasError = optgenerror
7872 message ("Initializer block for "
7873 "%s has %d field%&, but %s has %d field%&: %q",
7874 exprNode_unparse (el),
7875 exprNodeList_size (vals),
7877 uentryList_size (fields),
7878 exprNodeList_unparse (vals)),
7884 exprNodeList_elements (vals, oneval)
7886 uentry thisfield = uentryList_getN (fields, i);
7888 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
7890 uentry_getName (thisfield));
7892 if (exprNode_isDefined (newel))
7894 if (exprNode_checkOneInit (newel, oneval))
7899 exprNode_freeIniter (newel);
7903 } end_exprNodeList_elements;
7908 hasError = optgenerror
7910 message ("Initializer block used for "
7911 "%s where %t is expected: %s",
7912 exprNode_unparse (el), t1, exprNode_unparse (val)),
7918 if (exprNode_isDefined (val))
7920 doAssign (el, val, TRUE);
7922 if (!exprNode_matchType (t1, val))
7924 hasError = gentypeerror
7926 message ("Initial value of %s is type %t, "
7928 exprNode_unparse (el),
7929 t2, t1, exprNode_unparse (val)),
7939 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
7943 if (usymtab_exists (idDecl_observeId (t)))
7945 uentry ue = usymtab_lookup (idDecl_observeId (t));
7946 ret = exprNode_createId (ue);
7948 /*@i723 don't do this...but why? */
7950 ct = ctype_realishType (ret->typ);
7952 DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
7954 if (ctype_isUnknown (ct))
7956 if (uentry_isAnyTag (ue))
7960 message ("%s used but not previously declared: %s",
7961 uentry_ekindName (ue),
7962 idDecl_getName (t)),
7970 message ("Variable has unknown (implicitly int) type: %s",
7971 idDecl_getName (t)),
7983 DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
7985 ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
7986 /*!! fileloc_copy (g_currentloc)); */
7987 /*@i32!!! should get error without this */
7988 ret = exprNode_fromIdentifierAux (ue);
7991 ** No error - this happens in old style declarations:
7995 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8002 exprData_free (ret->edata, ret->kind);
8003 ret->edata = exprData_undefined;
8004 ret->exitCode = XK_NEVERESCAPE;
8005 ret->mustBreak = FALSE;
8006 ret->kind = XPR_INIT;
8010 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8012 exprNode ret = exprNode_makeInitializationAux (t);
8013 llassert (ret->edata == exprData_undefined);
8014 ret->edata = exprData_makeInit (t, exprNode_undefined);
8018 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8019 /*@only@*/ exprNode e)
8021 uentry ue = usymtab_lookup (idDecl_observeId (t));
8022 exprNode ret = exprNode_makeInitializationAux (t);
8023 fileloc loc = exprNode_loc (e);
8025 if (exprNode_isError (e))
8027 e = exprNode_createUnknown ();
8030 /* error: assume initializer is defined */
8031 sRef_setDefined (ret->sref, g_currentloc);
8035 ctype ct = ctype_realishType (ret->typ);
8040 ** was addSafeUse --- what's the problem?
8042 ** int x = 3, y = x ?
8045 exprData_free (ret->edata, ret->kind);
8046 ret->edata = exprData_makeInit (t, e);
8048 exprNode_checkUse (ret, e->sref, e->loc);
8050 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8052 exprNode lhs = exprNode_createId (ue);
8055 ** static storage should be undefined before initializing
8058 if (uentry_isStatic (ue))
8060 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8063 (void) exprNode_checkOneInit (lhs, e);
8065 if (uentry_isStatic (ue))
8067 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8070 exprNode_free (lhs);
8074 if (!exprNode_matchType (ct, e))
8076 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
8083 (exprNode_getType (e), e, exprNode_getType (ret), ret,
8085 ("Variable %q initialized to type %t, expects %t: %s",
8086 uentry_getName (ue), exprNode_getType (e),
8087 exprNode_getType (ret),
8088 exprNode_unparse (e)),
8094 if (uentry_isStatic (ue))
8096 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8099 doAssign (ret, e, TRUE);
8101 if (uentry_isStatic (ue))
8103 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8107 if (context_inIterDef ())
8109 /* should check if it is yield */
8110 uentry_setUsed (ue, loc);
8117 exprNode_mergeUSs (ret, e);
8121 exprNode exprNode_iter (/*@observer@*/ uentry name,
8122 /*@only@*/ exprNodeList alist,
8123 /*@only@*/ exprNode body,
8124 /*@observer@*/ uentry end)
8129 llassert (uentry_isValid (name));
8131 uentry_setUsed (name, exprNode_loc (body));
8133 ret = exprNode_createPartialCopy (body);
8134 iname = uentry_getName (name);
8136 if (uentry_isInvalid (end))
8139 message ("Iter %s not balanced with end_%s", iname, iname));
8143 cstring ename = uentry_getName (end);
8145 if (!cstring_equalPrefix (ename, "end_"))
8147 llerror (FLG_ITER, message ("Iter %s not balanced with end_%s: %s",
8148 iname, iname, ename));
8152 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8155 message ("Iter %s not balanced with end_%s: %s",
8156 iname, iname, ename));
8160 cstring_free (ename);
8163 context_exitIterClause (body);
8165 ret->kind = XPR_ITER;
8166 ret->edata = exprData_makeIter (name, alist, body, end);
8168 if (uentry_isIter (name))
8170 (void) checkArgsReal (name, body,
8171 uentry_getParams (name), alist, TRUE, ret);
8174 cstring_free (iname);
8180 exprNode_iterNewId (/*@only@*/ cstring s)
8182 exprNode e = exprNode_new ();
8183 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8185 llassert (processingIterVars ());
8187 e->loc = context_getSaveLocation ();
8189 if (fileloc_isUndefined (e->loc))
8191 fileloc_free (e->loc);
8192 e->loc = fileloc_copy (g_currentloc);
8195 e->uses = sRefSet_new ();
8196 e->sets = sRefSet_new ();
8197 e->msets = sRefSet_new ();
8199 e->val = multiVal_unknown ();
8200 e->guards = guardSet_new ();
8202 e->isJumpPoint = FALSE;
8203 e->exitCode = XK_NEVERESCAPE;
8205 /*> missing fields, detected by lclint <*/
8206 e->canBreak = FALSE;
8207 e->mustBreak = FALSE;
8208 e->etext = cstring_undefined;
8210 if (uentry_isYield (ue))
8212 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8213 fileloc_copy (e->loc),
8217 uue = usymtab_supEntrySrefReturn (uue);
8219 sr = uentry_getSref (uue);
8220 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8221 sr = uentry_getSref (uue);
8222 sRef_setDefined (sr, e->loc);
8224 e->typ = uentry_getType (uue);
8226 e->edata = exprData_makeId (uue);
8227 uentry_setUsed (uue, g_currentloc);
8233 sRef_setGlobalScope ();
8234 uue = uentry_makeVariableLoc (s, ctype_unknown);
8236 e->typ = ctype_unknown;
8237 e->edata = exprData_makeId (uue);
8239 uentry_setUsed (uue, e->loc);
8240 uentry_setHasNameError (uue);
8242 if (context_getFlag (FLG_REPEATUNRECOG))
8244 uentry_markOwned (uue);
8248 usymtab_supGlobalEntry (uue);
8251 sRef_clearGlobalScope ();
8253 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8260 exprNode_defineConstraints(e);
8265 exprNode_iterExpr (/*@returned@*/ exprNode e)
8267 if (!processingIterVars ())
8269 llcontbuglit ("checkIterParam: not in iter");
8273 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8276 if (exprNode_isDefined (e))
8278 if (fileloc_isDefined (e->loc))
8282 message ("Yield parameter is not simple identifier: %s",
8283 exprNode_unparse (e)),
8290 message ("Yield parameter is not simple identifier: %s",
8291 exprNode_unparse (e)),
8301 exprNode_iterId (/*@observer@*/ uentry c)
8305 llassert (processingIterVars ());
8307 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8310 if (uentry_isYield (ue))
8312 ctype ct = uentry_getType (ue);
8313 exprNode e = exprNode_createPlain (ct);
8314 cstring name = uentry_getName (c);
8315 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8317 uentry_setUsed (ue, g_currentloc);
8318 uentry_setHasNameError (ue);
8320 cstring_free (name);
8323 e->edata = exprData_makeId (le);
8324 e->loc = context_getSaveLocation ();
8325 e->sref = uentry_getSref (le);
8327 usymtab_supEntrySref (le);
8329 if (!context_inHeader ())
8333 message ("Yield parameter shadows local declaration: %q",
8334 uentry_getName (c)),
8335 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8337 uentry_showWhereDeclared (c);
8344 return (exprNode_fromIdentifierAux (c));
8347 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8349 exprNode ret = exprNode_create (ctype_unknown);
8351 ret->kind = XPR_ITERCALL;
8352 ret->edata = exprData_makeIterCall (name, alist);
8354 if (uentry_isIter (name))
8356 uentryList params = uentry_getParams (name);
8358 if (context_inIterDef ()
8359 && uentryList_size (params) == exprNodeList_size (alist))
8363 exprNodeList_elements (alist, arg)
8365 uentry parg = uentryList_getN (params, i);
8367 if (uentry_isYield (parg))
8369 uentry ue = exprNode_getUentry (arg);
8371 if (uentry_isValid (ue))
8378 } end_exprNodeList_elements;
8381 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8382 checkUnspecCall (ret, params, alist);
8388 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8390 if (exprNode_isDefined (e))
8393 if (e->sref == defref) /*@noaccess sRef@*/
8396 e->sref = sRef_makeUnknown ();
8397 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8408 return sRef_undefined;
8412 /*@observer@*/ cstring
8413 exprNode_unparseFirst (exprNode e)
8415 if (exprNode_isDefined (e))
8419 if (e->kind == XPR_STMTLIST
8420 || e->kind == XPR_COMMA || e->kind == XPR_COND)
8422 exprNode first = exprData_getPairA (e->edata);
8424 if (exprNode_isDefined (first))
8426 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8430 return (cstring_makeLiteralTemp ("..."));
8434 ret = cstring_elide (exprNode_unparse (e), 20);
8435 cstring_markOwned (ret);
8441 return cstring_makeLiteralTemp ("<error>");
8445 /*@observer@*/ cstring
8446 exprNode_unparse (/*@temp@*/ exprNode e)
8448 if (exprNode_isError (e))
8450 return cstring_makeLiteralTemp ("<error>");
8453 if (cstring_isDefined (e->etext))
8459 cstring ret = exprNode_doUnparse (e);
8461 /*@-modifies@*/ /* benevolent */
8468 /*@observer@*/ fileloc
8469 exprNode_loc (exprNode e)
8471 if (exprNode_isError (e))
8473 return (g_currentloc);
8482 ** executes exprNode e
8483 ** recursively rexecutes as though in original parse using
8484 ** information in e->edata
8487 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
8489 exprNodeList ret = exprNodeList_new ();
8491 exprNodeList_elements (e, current)
8493 exprNodeList_addh (ret, exprNode_effect (current));
8494 } end_exprNodeList_elements;
8499 static /*@only@*/ exprNode exprNode_effect (exprNode e)
8500 /*@globals internalState@*/
8502 bool innerEffect = inEffect;
8508 context_clearJustPopped ();
8510 if (exprNode_isError (e))
8512 ret = exprNode_undefined;
8517 ** Turn off expose and dependent transfer checking.
8518 ** Need to pass exposed internal nodes,
8519 ** [ copying would be a waste! ]
8520 ** [ Actually, I think I wasted a lot more time than its worth ]
8521 ** [ trying to do this. ]
8525 /*@-observertrans@*/
8526 /*@-dependenttrans@*/
8533 ret = exprNode_addParens (exprData_getUopTok (data),
8534 exprNode_effect (exprData_getUopNode (data)));
8537 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
8538 exprNode_effect (exprData_getOpB (data)),
8539 exprData_getOpTok (data));
8542 ret = exprNode_undefined;
8545 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
8546 exprNodeList_effect (exprData_getArgs (data)));
8559 cstring id = exprData_getId (data);
8560 uentry ue = usymtab_lookupSafe (id);
8562 ret = exprNode_fromIdentifierAux (ue);
8563 ret->loc = fileloc_update (ret->loc, e->loc);
8570 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
8571 exprNode_effect (exprData_getPairB (data)));
8574 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
8575 exprNode_effect (exprData_getOpB (data)),
8576 exprData_getOpTok (data));
8580 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
8581 exprData_getUopTok (data));
8584 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
8585 exprData_getUopTok (data));
8597 ret = exprNode_vaArg (exprData_getCastTok (data),
8598 exprNode_effect (exprData_getCastNode (data)),
8599 exprData_getCastType (data));
8603 ret = exprNode_cast (exprData_getCastTok (data),
8604 exprNode_effect (exprData_getCastNode (data)),
8605 exprData_getCastType (data));
8608 ret = exprNode_iterStart (exprData_getIterCallIter (data),
8610 (exprData_getIterCallArgs (data)));
8614 ret = exprNode_iter (exprData_getIterSname (data),
8615 exprNodeList_effect (exprData_getIterAlist (data)),
8616 exprNode_effect (exprData_getIterBody (data)),
8617 exprData_getIterEname (data));
8621 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
8622 exprNode_effect (exprData_getPairB (data)));
8626 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
8627 exprNode_effect (exprData_getTripleTest (data)),
8628 exprNode_effect (exprData_getTripleInc (data)));
8632 ret = exprNode_createTok (exprData_getTok (data));
8636 ret = exprNode_goto (exprData_getLiteral (data));
8637 ret->loc = fileloc_update (ret->loc, e->loc);
8641 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
8645 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
8649 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
8652 case XPR_NULLRETURN:
8653 ret = exprNode_nullReturn (exprData_getTok (data));
8657 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
8658 exprNode_effect (exprData_getPairB (data)));
8662 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
8663 exprNode_effect (exprData_getTripleTrue (data)),
8664 exprNode_effect (exprData_getTripleFalse (data)));
8667 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
8668 exprNode_effect (exprData_getPairB (data)));
8672 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
8673 exprNode_effect (exprData_getTripleTrue (data)),
8674 exprNode_effect (exprData_getTripleFalse (data)));
8677 ret = exprNode_whilePred (exprData_getSingle (data));
8681 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
8682 exprNode_effect (exprData_getPairB (data)));
8686 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
8687 exprNode_effect (exprData_getPairB (data)));
8691 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
8695 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
8696 exprData_getUopTok (data));
8700 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
8701 exprNode_effect (exprData_getPairB (data)));
8706 ret = exprNode_caseMarker
8707 (exprNode_effect (exprData_getSingle (data)),
8713 ret = exprNode_createTok (exprData_getTok (data));
8717 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
8718 exprNode_effect (exprData_getPairB (data)));
8722 ret = exprNode_makeInitialization
8723 (exprData_getInitId (data),
8724 exprNode_effect (exprData_getInitNode (data)));
8728 ret = exprNode_fieldAccessAux
8729 (exprNode_effect (exprData_getFieldNode (data)),
8730 exprNode_loc (exprData_getFieldNode (data)),
8731 cstring_copy (exprData_getFieldName (data)));
8735 ret = exprNode_arrowAccessAux
8736 (exprNode_effect (exprData_getFieldNode (data)),
8737 exprNode_loc (exprData_getFieldNode (data)),
8738 cstring_copy (exprData_getFieldName (data)));
8741 case XPR_STRINGLITERAL:
8755 /*@=observertrans@*/
8757 /*@=dependenttrans@*/
8768 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
8773 if (exprNode_isError (e))
8775 return cstring_undefined;
8783 ret = exprNode_rootVarName (exprData_getUopNode (data));
8786 ret = exprNode_rootVarName (exprData_getOpA (data));
8790 ret = exprData_getId (data);
8815 case XPR_NULLRETURN:
8838 case XPR_STRINGLITERAL:
8839 ret = cstring_undefined;
8846 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
8851 if (exprNode_isError (e))
8853 static /*@only@*/ cstring error = cstring_undefined;
8855 if (!cstring_isDefined (error))
8857 error = cstring_makeLiteral ("<error>");
8868 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
8871 ret = message ("%s %s %s",
8872 exprNode_unparse (exprData_getOpA (data)),
8873 lltok_unparse (exprData_getOpTok (data)),
8874 exprNode_unparse (exprData_getOpB (data)));
8877 ret = message ("%s(%q)",
8878 exprNode_unparse (exprData_getFcn (data)),
8879 exprNodeList_unparse (exprData_getArgs (data)));
8882 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
8885 ret = cstring_undefined;
8888 ret = message ("%s:", exprData_getId (data));
8892 ret = cstring_copy (exprData_getId (data));
8895 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
8896 exprNode_unparse (exprData_getPairB (data)));
8899 ret = message ("<body>");
8902 ret = message ("%s %s %s",
8903 exprNode_unparse (exprData_getOpA (data)),
8904 lltok_unparse (exprData_getOpTok (data)),
8905 exprNode_unparse (exprData_getOpB (data)));
8909 ret = message ("%s%s",
8910 lltok_unparse (exprData_getUopTok (data)),
8911 exprNode_unparse (exprData_getUopNode (data)));
8915 ret = message ("%s%s",
8916 exprNode_unparse (exprData_getUopNode (data)),
8917 lltok_unparse (exprData_getUopTok (data)));
8921 ret = message ("offsetof(%s,%q)",
8922 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
8923 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
8927 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8931 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
8935 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8939 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
8943 ret = message ("va_arg(%s, %q)",
8944 exprNode_unparse (exprData_getCastNode (data)),
8945 qtype_unparse (exprData_getCastType (data)));
8949 ret = message ("%q(%q)",
8950 uentry_getName (exprData_getIterCallIter (data)),
8951 exprNodeList_unparse (exprData_getIterCallArgs (data)));
8954 ret = message ("%q(%q) %s %q",
8955 uentry_getName (exprData_getIterSname (data)),
8956 exprNodeList_unparse (exprData_getIterAlist (data)),
8957 exprNode_unparse (exprData_getIterBody (data)),
8958 uentry_getName (exprData_getIterEname (data)));
8961 ret = message ("(%q)%s",
8962 qtype_unparse (exprData_getCastType (data)),
8963 exprNode_unparse (exprData_getCastNode (data)));
8967 ret = message ("%s %s",
8968 exprNode_unparse (exprData_getPairA (data)),
8969 exprNode_unparse (exprData_getPairB (data)));
8973 ret = message ("for (%s; %s; %s)",
8974 exprNode_unparse (exprData_getTripleInit (data)),
8975 exprNode_unparse (exprData_getTripleTest (data)),
8976 exprNode_unparse (exprData_getTripleInc (data)));
8980 ret = message ("goto %s", exprData_getLiteral (data));
8984 ret = cstring_makeLiteral ("continue");
8988 ret = cstring_makeLiteral ("break");
8992 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
8995 case XPR_NULLRETURN:
8996 ret = cstring_makeLiteral ("return");
9000 ret = message ("%s, %s",
9001 exprNode_unparse (exprData_getPairA (data)),
9002 exprNode_unparse (exprData_getPairB (data)));
9006 ret = message ("%s ? %s : %s",
9007 exprNode_unparse (exprData_getTriplePred (data)),
9008 exprNode_unparse (exprData_getTripleTrue (data)),
9009 exprNode_unparse (exprData_getTripleFalse (data)));
9012 ret = message ("if (%s) %s",
9013 exprNode_unparse (exprData_getPairA (data)),
9014 exprNode_unparse (exprData_getPairB (data)));
9018 ret = message ("if (%s) %s else %s",
9019 exprNode_unparse (exprData_getTriplePred (data)),
9020 exprNode_unparse (exprData_getTripleTrue (data)),
9021 exprNode_unparse (exprData_getTripleFalse (data)));
9024 ret = message ("while (%s) %s",
9025 exprNode_unparse (exprData_getPairA (data)),
9026 exprNode_unparse (exprData_getPairB (data)));
9030 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9034 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9038 ret = message ("do { %s } while (%s)",
9039 exprNode_unparse (exprData_getPairB (data)),
9040 exprNode_unparse (exprData_getPairA (data)));
9044 ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
9048 ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
9052 ret = message ("%s; %s",
9053 exprNode_unparse (exprData_getPairA (data)),
9054 exprNode_unparse (exprData_getPairB (data)));
9059 ret = cstring_makeLiteral ("default:");
9063 ret = message ("switch (%s) %s",
9064 exprNode_unparse (exprData_getPairA (data)),
9065 exprNode_unparse (exprData_getPairB (data)));
9070 ret = message ("case %s:",
9071 exprNode_unparse (exprData_getSingle (data)));
9075 if (exprNode_isError (exprData_getInitNode (data)))
9077 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9081 ret = message ("%q = %s",
9082 idDecl_unparseC (exprData_getInitId (data)),
9083 exprNode_unparse (exprData_getInitNode (data)));
9088 ret = message ("%s.%s",
9089 exprNode_unparse (exprData_getFieldNode (data)),
9090 exprData_getFieldName (data));
9094 ret = message ("%s->%s",
9095 exprNode_unparse (exprData_getFieldNode (data)),
9096 exprData_getFieldName (data));
9099 case XPR_STRINGLITERAL:
9100 ret = message ("\"%s\"", exprData_getLiteral (data));
9104 ret = cstring_copy (exprData_getLiteral (data));
9108 ret = cstring_makeLiteral ("<node>");
9116 exprNode_isInitializer (exprNode e)
9118 return (exprNode_isDefined (e)
9119 && e->kind == XPR_INIT);
9123 exprNode_isCharLit (exprNode e)
9125 if (exprNode_isDefined (e))
9127 return (multiVal_isChar (exprNode_getValue (e)));
9136 exprNode_isNumLit (exprNode e)
9138 if (exprNode_isDefined (e))
9140 return (multiVal_isInt (exprNode_getValue (e)));
9149 exprNode_isFalseConstant (exprNode e)
9151 if (exprNode_isDefined (e))
9153 cstring s = exprNode_rootVarName (e);
9155 if (cstring_equal (s, context_getFalseName ()))
9165 exprNode_matchLiteral (ctype expected, exprNode e)
9167 if (exprNode_isDefined (e))
9169 multiVal m = exprNode_getValue (e);
9171 if (multiVal_isDefined (m))
9173 if (multiVal_isInt (m))
9175 long int val = multiVal_forceInt (m);
9177 if (ctype_isDirectBool (ctype_realishType (expected)))
9181 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9189 if (ctype_isRealInt (expected))
9192 ** unsigned <- [ constant >= 0 is okay ]
9195 if (ctype_isUnsigned (expected))
9204 ** No checks on sizes of integers...maybe add
9208 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9209 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9210 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9212 if (context_getFlag (FLG_NUMLITERAL)
9213 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9219 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9223 else if (ctype_isChar (expected))
9227 else if (ctype_isArrayPtr (expected))
9231 else if (ctype_isAnyFloat (expected))
9233 return (context_getFlag (FLG_NUMLITERAL));
9240 else if (multiVal_isDouble (m))
9242 if (ctype_isAnyFloat (expected))
9247 else if (multiVal_isChar (m))
9249 char val = multiVal_forceChar (m);
9251 if (ctype_isChar (expected))
9253 if (ctype_isUnsigned (expected) && ((int)val) < 0)
9274 exprNode_matchType (ctype expected, exprNode e)
9278 if (!exprNode_isDefined (e)) return TRUE;
9280 actual = ctype_realishType (exprNode_getType (e));
9282 if (ctype_match (ctype_realishType (expected), actual))
9287 llassert (!exprNode_isError (e));
9288 return (exprNode_matchLiteral (expected, e));
9292 exprNode_matchTypes (exprNode e1, exprNode e2)
9297 if (!exprNode_isDefined (e1)) return TRUE;
9298 if (!exprNode_isDefined (e2)) return TRUE;
9301 ** realish type --- keep bools, bools
9304 t1 = ctype_realishType (exprNode_getType (e1));
9305 t2 = ctype_realishType (exprNode_getType (e2));
9307 if (ctype_match (t1, t2))
9312 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9320 exprNode_matchArgType (ctype ct, exprNode e)
9324 if (!exprNode_isDefined (e))
9329 et = ctype_realType (exprNode_getType (e));
9331 if (ctype_matchArg (ct, et)) return TRUE;
9333 llassert (!exprNode_isError (e));
9334 return (exprNode_matchLiteral (ct, e));
9337 static /*@only@*/ exprNodeSList
9338 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9340 if (exprNode_isDefined (e))
9342 if (e->kind == XPR_STMTLIST)
9344 return (exprNodeSList_append
9345 (exprNode_flatten (exprData_getPairA (e->edata)),
9346 exprNode_flatten (exprData_getPairB (e->edata))));
9348 else if (e->kind == XPR_BLOCK)
9350 return (exprNode_flatten (exprData_getSingle (e->edata)));
9354 return (exprNodeSList_singleton (e));
9358 return exprNodeSList_new ();
9361 static /*@exposed@*/ exprNode
9362 exprNode_lastStatement (/*@returned@*/ exprNode e)
9364 if (exprNode_isDefined (e))
9366 if (e->kind == XPR_STMTLIST)
9368 exprNode b = exprData_getPairB (e->edata);
9370 if (exprNode_isDefined (b))
9372 return exprNode_lastStatement (b);
9376 return exprNode_lastStatement (exprData_getPairA (e->edata));
9379 else if (e->kind == XPR_BLOCK)
9381 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
9389 return exprNode_undefined;
9392 static /*@exposed@*/ exprNode
9393 exprNode_firstStatement (/*@returned@*/ exprNode e)
9395 if (exprNode_isDefined (e))
9397 if (e->kind == XPR_STMTLIST)
9399 exprNode b = exprData_getPairA (e->edata);
9401 if (exprNode_isDefined (b))
9403 return exprNode_firstStatement (b);
9407 return exprNode_firstStatement (exprData_getPairB (e->edata));
9410 else if (e->kind == XPR_BLOCK)
9412 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
9420 return exprNode_undefined;
9424 exprNode_mergeUSs (exprNode res, exprNode other)
9426 if (exprNode_isDefined (res) && exprNode_isDefined (other))
9428 res->msets = sRefSet_union (res->msets, other->msets);
9429 res->sets = sRefSet_union (res->sets, other->sets);
9430 res->uses = sRefSet_union (res->uses, other->uses);
9435 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
9437 if (exprNode_isDefined (res))
9439 if (exprNode_isDefined (other1))
9441 res->sets = sRefSet_union (res->sets, other1->sets);
9442 res->msets = sRefSet_union (res->msets, other1->msets);
9443 res->uses = sRefSet_union (res->uses, other1->uses);
9445 if (exprNode_isDefined (other2))
9447 res->sets = sRefSet_union (res->sets, other2->sets);
9448 res->msets = sRefSet_union (res->msets, other2->msets);
9449 res->uses = sRefSet_union (res->uses, other2->uses);
9457 ** Reports errors is s is not defined.
9461 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
9463 if (exprNode_isDefined (e))
9465 e->uses = sRefSet_insert (e->uses, s);
9470 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
9472 if (sRef_isKnown (s) && !sRef_isConst (s))
9475 ** need to check all outer types are useable
9478 DPRINTF (("Check use: %s / %s",
9479 exprNode_unparse (e), sRef_unparse (s)));
9481 exprNode_addUse (e, s);
9483 if (!context_inProtectVars ())
9486 ** only report the deepest error
9489 sRef errorRef = sRef_undefined;
9490 sRef lastRef = sRef_undefined;
9491 bool deadRef = FALSE;
9492 bool unuseable = FALSE;
9493 bool errorMaybe = FALSE;
9495 while (sRef_isValid (s) && sRef_isKnown (s))
9497 ynm readable = sRef_isReadable (s);
9499 DPRINTF (("Readable: %s / %s",
9500 sRef_unparseFull (s), ynm_unparse (readable)));
9502 if (!(ynm_toBoolStrict (readable)))
9504 if (ynm_isMaybe (readable))
9508 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
9509 deadRef = sRef_isPossiblyDead (errorRef);
9510 unuseable = sRef_isUnuseable (errorRef);
9517 deadRef = sRef_isDead (errorRef);
9518 unuseable = sRef_isUnuseable (errorRef);
9522 if (!sRef_isPartial (s))
9524 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
9525 sRef_setDefined (s, fileloc_undefined);
9529 s = sRef_getBaseSafe (s);
9532 if (sRef_isValid (errorRef))
9534 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
9535 && sRef_isPointer (errorRef))
9542 if (sRef_isThroughArrayFetch (errorRef))
9545 (FLG_STRICTUSERELEASED,
9546 message ("%q %q may be used after being released",
9547 sRef_unparseKindNamePlain (errorRef),
9548 sRef_unparse (errorRef)),
9551 sRef_showRefKilled (errorRef);
9553 if (sRef_isKept (errorRef))
9555 sRef_clearAliasState (errorRef, loc);
9561 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
9565 message ("%q %q %qused after being released",
9566 sRef_unparseKindNamePlain (errorRef),
9567 sRef_unparse (errorRef),
9568 cstring_makeLiteral (errorMaybe
9572 sRef_showRefKilled (errorRef);
9574 if (sRef_isKept (errorRef))
9576 sRef_clearAliasState (errorRef, loc);
9585 message ("%q %q%qused in inconsistent state",
9586 sRef_unparseKindName (errorRef),
9587 sRef_unparseOpt (errorRef),
9588 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9591 sRef_showStateInconsistent (errorRef);
9596 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
9600 message ("%q %q%qused before definition",
9601 sRef_unparseKindName (errorRef),
9602 sRef_unparseOpt (errorRef),
9603 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9606 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
9609 sRef_setDefined (errorRef, loc);
9611 if (sRef_isAddress (errorRef))
9613 sRef_setDefined (sRef_getRootBase (errorRef), loc);
9615 } /* end is error */
9623 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
9625 if (exprNode_isDefined (e) && sRef_isKnown (s))
9627 e->uses = sRefSet_insert (e->uses, s);
9632 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
9634 if (exprNode_isDefined (e))
9636 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
9641 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
9643 sRef defines = sRef_undefined;
9645 if (sRef_isValid (s) && !sRef_isNothing (s))
9647 uentry ue = sRef_getBaseUentry (s);
9649 if (uentry_isValid (ue))
9651 uentry_setLset (ue);
9654 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9656 voptgenerror (FLG_USEDEF,
9657 message ("Attempt to set unuseable storage: %q",
9662 if (sRef_isMeaningful (s))
9665 if (sRef_isDead (s))
9667 sRef base = sRef_getBaseSafe (s);
9669 if (sRef_isValid (base)
9670 && sRef_isDead (base))
9672 sRef_setPartial (s, exprNode_loc (e));
9675 defines = s; /* okay - modifies for only param */
9677 else if (sRef_isPartial (s))
9679 sRef eref = exprNode_getSref (e);
9681 if (!sRef_isPartial (eref))
9684 ** should do something different here???
9687 sRef_setDefinedComplete (eref, exprNode_loc (e));
9691 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
9694 if (sRef_isMeaningful (eref))
9703 else if (sRef_isAllocated (s))
9705 sRef eref = exprNode_getSref (e);
9708 if (!sRef_isAllocated (eref))
9710 sRef_setDefinedComplete (eref, exprNode_loc (e));
9714 sRef base = sRef_getBaseSafe (eref);
9716 if (sRef_isValid (base))
9718 sRef_setPdefined (base, exprNode_loc (e));
9726 sRef_setDefinedNCComplete (s, exprNode_loc (e));
9731 else /* not meaningful...but still need to insert it */
9737 if (exprNode_isDefined (e) && sRef_isValid (defines))
9739 e->sets = sRefSet_insert (e->sets, defines);
9744 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
9746 if (sRef_isValid (s) && !sRef_isNothing (s))
9748 uentry ue = sRef_getBaseUentry (s);
9750 if (uentry_isValid (ue))
9752 uentry_setLset (ue);
9755 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9757 voptgenerror (FLG_USEDEF,
9758 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
9762 if (sRef_isMeaningful (s))
9764 sRef_setDefinedComplete (s, exprNode_loc (e));
9767 if (exprNode_isDefined (e))
9769 e->msets = sRefSet_insert (e->msets, s);
9775 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
9777 checkAnyCall (fcn, cstring_undefined, params, args,
9778 FALSE, sRefSet_undefined, FALSE, 0);
9782 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
9783 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
9787 if (uentry_isYield (ucurrent))
9789 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
9790 exprNode_checkSet (current, current->sref);
9794 if (uentry_isSefParam (ucurrent))
9796 sRefSet sets = current->sets;
9797 sRef ref = exprNode_getSref (current);
9799 if (sRef_isMacroParamRef (ref))
9801 uentry ue = sRef_getUentry (ref);
9803 if (!uentry_isSefParam (ue))
9808 ("Parameter %d to %s is declared sef, but "
9809 "the argument is a macro parameter declared "
9811 argno, exprNode_unparse (fcn),
9812 exprNode_unparse (current)),
9813 exprNode_loc (current));
9817 if (!sRefSet_isEmpty (sets))
9819 sRefSet reported = sRefSet_undefined;
9821 sRefSet_realElements (current->sets, el)
9823 if (sRefSet_isSameNameMember (reported, el))
9825 ; /* don't report again */
9829 if (sRef_isUnconstrained (el))
9834 ("Parameter %d to %s is declared sef, but "
9835 "the argument calls unconstrained function %s "
9836 "(no guarantee it will not modify something): %s",
9837 argno, exprNode_unparse (fcn),
9838 sRef_unconstrainedName (el),
9839 exprNode_unparse (current)),
9840 exprNode_loc (current));
9847 ("Parameter %d to %s is declared sef, but "
9848 "the argument may modify %q: %s",
9849 argno, exprNode_unparse (fcn),
9851 exprNode_unparse (current)),
9852 exprNode_loc (current));
9855 } end_sRefSet_realElements;
9859 checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs);
9860 exprNode_mergeUSs (fcn, current);
9865 checkAnyCall (/*@dependent@*/ exprNode fcn,
9866 /*@dependent@*/ cstring fname,
9869 bool hasMods, sRefSet mods,
9874 int nargs = exprNodeList_size (args);
9879 ** concat all args ud's to f, add each arg sref as a use unless
9880 ** it was specified as "out", in which case it is a def.
9883 uentryList_reset (pn);
9888 ** if paramn is only or unique, no other arg may alias argn
9891 exprNodeList_elements (args, current)
9895 if (exprNode_isDefined (current))
9897 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
9899 uentry ucurrent = uentryList_current (pn);
9901 if (specialArgs == 0
9902 || (paramno < specialArgs))
9904 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
9906 if (context_maybeSet (FLG_ALIASUNIQUE))
9908 if (uentry_isOnly (ucurrent)
9909 || uentry_isUnique (ucurrent))
9911 checkUniqueParams (fcn, current, args,
9917 else /* uentry is undefined */
9919 if (specialArgs == 0)
9921 exprNode_checkUseParam (current);
9924 exprNode_mergeUSs (fcn, current);
9927 uentryList_advanceSafe (pn);
9928 } end_exprNodeList_elements;
9934 sRefSet_allElements (mods, s)
9937 sRef rb = sRef_getRootBase (s);
9939 if (sRef_isFileOrGlobalScope (rb))
9941 context_usedGlobal (rb);
9944 fb = sRef_fixBaseParam (s, args);
9946 if (!sRef_isMacroParamRef (fb))
9948 if (sRef_isNothing (fb))
9954 if (sRef_isValid (fb))
9956 uentry ue = sRef_getBaseUentry (s);
9958 if (uentry_isValid (ue))
9960 uentry_setLset (ue);
9964 fcn->sets = sRefSet_insert (fcn->sets, fb);
9967 sRef_clearDerivedComplete (s);
9968 } end_sRefSet_allElements;
9974 if (context_hasMods ())
9976 if (context_maybeSet (FLG_MODUNCON))
9980 message ("Undetected modification possible "
9981 "from call to unconstrained function %s: %s",
9983 exprNode_unparse (fcn)),
9984 exprNode_loc (fcn));
9989 if (context_maybeSet (FLG_MODUNCONNOMODS)
9990 && !(context_inIterDef () || context_inIterEnd ()))
9993 (FLG_MODUNCONNOMODS,
9994 message ("Undetected modification possible "
9995 "from call to unconstrained function %s: %s",
9997 exprNode_unparse (fcn)),
9998 exprNode_loc (fcn));
10002 exprNode_checkSetAny (fcn, fname);
10006 void exprNode_checkUseParam (exprNode current)
10008 if (exprNode_isDefined (current))
10010 exprNode_checkUse (current, current->sref, current->loc);
10015 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10016 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10021 if (!ctype_match (tr1, tr2))
10023 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10024 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10030 (void) gentypeerror
10032 message ("Incompatible types for %s (%s, %s): %s %s %s",
10033 lltok_unparse (op),
10034 ctype_unparse (te1),
10035 ctype_unparse (te2),
10036 exprNode_unparse (e1), lltok_unparse (op),
10037 exprNode_unparse (e2)),
10040 ret = ctype_unknown;
10044 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
10046 ret = ctype_resolveNumerics (tr1, tr2);
10048 else if (!context_msgStrictOps ())
10050 if (ctype_isPointer (tr1))
10052 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10056 else if (ctype_isInt (tr2))
10062 ret = ctype_unknown;
10065 else if (ctype_isPointer (tr2))
10067 if (ctype_isPointer (tr1))
10071 else if (ctype_isInt (tr1))
10077 ret = ctype_unknown;
10082 ret = ctype_resolveNumerics (tr1, tr2);
10087 int opid = lltok_getTok (op);
10088 bool comparop = (opid == EQ_OP || opid == NE_OP
10089 || opid == TLT || opid == TGT
10090 || opid == LE_OP || opid == GE_OP);
10092 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10095 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10096 || (ctype_isBool (tr1) && ctype_isBool (tr2))
10097 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10103 if (ctype_sameName (te1, te2))
10107 message ("Operands of %s are non-numeric (%t): %s %s %s",
10108 lltok_unparse (op), te1,
10109 exprNode_unparse (e1), lltok_unparse (op),
10110 exprNode_unparse (e2)),
10117 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10118 lltok_unparse (op), te1, te2,
10119 exprNode_unparse (e1), lltok_unparse (op),
10120 exprNode_unparse (e2)),
10125 else if (!ctype_isNumeric (tr1))
10129 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10130 lltok_unparse (op), te1,
10131 exprNode_unparse (e1), lltok_unparse (op),
10132 exprNode_unparse (e2)),
10137 if (!ctype_isNumeric (tr2))
10141 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10142 lltok_unparse (op), te2,
10143 exprNode_unparse (e1), lltok_unparse (op),
10144 exprNode_unparse (e2)),
10149 ret = ctype_unknown;
10157 abstractOpError (ctype tr1, ctype tr2, lltok op,
10158 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10159 fileloc loc1, fileloc loc2)
10161 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10163 if (ctype_match (tr1, tr2))
10167 message ("Operands of %s are abstract type (%t): %s %s %s",
10168 lltok_unparse (op), tr1,
10169 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10176 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10177 lltok_unparse (op), tr1, tr2,
10178 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10182 else if (ctype_isRealAbstract (tr1))
10186 message ("Left operand of %s is abstract type (%t): %s %s %s",
10187 lltok_unparse (op), tr1,
10188 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10193 if (ctype_isRealAbstract (tr2))
10197 message ("Right operand of %s is abstract type (%t): %s %s %s",
10198 lltok_unparse (op), tr2,
10199 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10208 ** requies e1 and e2 and not error exprNode's.
10212 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10213 ** the rep of the abstract type is exposed.
10215 ** The order is very important:
10217 ** check rep expose (move into check transfer)
10223 ** This isn't really a sensible procedure, but the indententation
10224 ** was getting too deep.
10228 checkOneRepExpose (sRef ysr, sRef base,
10229 /*@notnull@*/ exprNode e1,
10230 /*@notnull@*/ exprNode e2, ctype ct,
10233 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
10234 || sRef_isOwned (ysr)
10235 || sRef_isExposed (ysr)))
10237 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10238 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10241 if (sRef_isIReference (ysr))
10243 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10248 ("Assignment of mutable component of parameter %q "
10249 "to component of abstract "
10250 "type %s exposes rep: %s = %s",
10251 sRef_unparse (base),
10252 ctype_unparse (ct),
10253 exprNode_unparse (e1), exprNode_unparse (e2)),
10261 ("Assignment of mutable component of parameter %q "
10262 "(through alias %q) to component of abstract "
10263 "type %s exposes rep: %s = %s",
10264 sRef_unparse (base),
10265 sRef_unparse (e2->sref),
10266 ctype_unparse (ct),
10267 exprNode_unparse (e1), exprNode_unparse (e2)),
10273 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10277 message ("Assignment of mutable parameter %q "
10278 "to component of abstract type %s "
10279 "exposes rep: %s = %s",
10280 sRef_unparse (base),
10281 ctype_unparse (ct),
10282 exprNode_unparse (e1),
10283 exprNode_unparse (e2)),
10290 message ("Assignment of mutable parameter %q "
10291 "(through alias %q) to "
10292 "component of abstract type %s exposes "
10294 sRef_unparse (base),
10295 sRef_unparse (e2->sref),
10296 ctype_unparse (ct),
10297 exprNode_unparse (e1),
10298 exprNode_unparse (e2)),
10304 if (sRef_isFileOrGlobalScope (s2b))
10306 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10310 message ("Assignment of global %q "
10312 "abstract type %s exposes rep: %s = %s",
10313 sRef_unparse (base),
10314 ctype_unparse (ct),
10315 exprNode_unparse (e1), exprNode_unparse (e2)),
10322 message ("Assignment of global %q (through alias %q) "
10324 "abstract type %s exposes rep: %s = %s",
10325 sRef_unparse (base),
10326 sRef_unparse (e2->sref),
10327 ctype_unparse (ct),
10328 exprNode_unparse (e1), exprNode_unparse (e2)),
10336 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
10338 if (ctype_isRealFunction (exprNode_getType (e1))
10339 && !ctype_isRealPointer (exprNode_getType (e1)))
10343 message ("Invalid left-hand side of assignment (function type %s): %s",
10344 ctype_unparse (exprNode_getType (e1)),
10345 exprNode_unparse (e1)),
10349 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
10351 ctype t2 = exprNode_getType (e2);
10352 sRef sr = sRef_getRootBase (e1->sref);
10353 ctype ct = sRef_getType (sr);
10355 if (ctype_isAbstract (t2)
10356 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
10358 /* it is immutable, okay to reference */
10359 goto donerepexpose;
10362 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
10364 sRef s2b = sRef_getRootBase (e2->sref);
10365 sRef s1 = e1->sref;
10366 sRef s1b = sRef_getRootBase (s1);
10369 aliases = usymtab_canAlias (e2->sref);
10371 if (!sRef_similar (s2b, s1b)
10372 && !sRef_isExposed (s1)
10373 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
10375 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
10376 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
10377 && !sRef_isExposed (s2b))
10379 if (sRef_isIReference (e2->sref))
10384 ("Assignment of mutable component of parameter %q "
10385 "to component of abstract type %s exposes rep: %s = %s",
10386 sRef_unparse (s2b),
10387 ctype_unparse (ct),
10388 exprNode_unparse (e1), exprNode_unparse (e2)),
10395 message ("Assignment of mutable parameter %q to "
10396 "component of abstract type %s exposes rep: %s = %s",
10397 sRef_unparse (s2b),
10398 ctype_unparse (ct),
10399 exprNode_unparse (e1), exprNode_unparse (e2)),
10404 if (sRef_isFileOrGlobalScope (s2b))
10408 message ("Assignment of global %q to component of "
10409 "abstract type %s exposes rep: %s = %s",
10410 sRef_unparse (s2b),
10411 ctype_unparse (ct),
10412 exprNode_unparse (e1), exprNode_unparse (e2)),
10416 sRefSet_realElements (aliases, ysr)
10418 sRef base = sRef_getRootBase (ysr);
10420 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
10421 || sRef_sameName (base, s1b))
10423 ; /* error already reported or same sref */
10427 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
10429 } end_sRefSet_realElements;
10431 sRefSet_free (aliases);
10438 ** function variables don't really work...
10441 if (!ctype_isFunction (ctype_realType (e2->typ)))
10445 DPRINTF (("Check init: %s / %s",
10446 exprNode_unparse (e1), exprNode_unparse (e2)));
10447 checkInitTransfer (e1, e2);
10451 checkAssignTransfer (e1, e2);
10456 sRef fref = e2->sref;
10458 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
10459 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
10461 /* Need to typecheck the annotation on the parameters */
10463 if (ctype_isRealFunction (e1->typ)) {
10464 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
10465 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
10467 if (!uentryList_isMissingParams (e1p)
10468 && !uentryList_isMissingParams (e2p)
10469 && uentryList_size (e1p) > 0) {
10470 if (uentryList_size (e1p) == uentryList_size (e2p)) {
10473 uentryList_elements (e1p, el1) {
10476 el2 = uentryList_getN (e2p, n);
10478 uentry_checkMatchParam (el1, el2, n, e2);
10479 } end_uentryList_elements;
10485 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
10491 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
10492 updateAliases (e1, e2);
10497 checkMacroParen (exprNode e)
10499 if (exprNode_isError (e) || e->kind == XPR_CAST)
10505 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
10509 message ("Macro parameter used without parentheses: %s",
10510 exprNode_unparse (e)),
10517 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
10521 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
10525 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
10532 ** if e2 is a parameter or global derived location which
10533 ** can be modified (that is, e2 is a mutable abstract type,
10534 ** or a derived pointer), then e1 can alias e2.
10536 ** e1 can alias everything which e2 can alias.
10538 ** Also, if e1 is guarded, remove from guard sets!
10541 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
10543 if (!context_inProtectVars ())
10546 ** depends on types of e1 and e2
10549 sRef s1 = e1->sref;
10550 sRef s2 = e2->sref;
10551 ctype t1 = exprNode_getType (e1);
10553 /* handle pointer sRefs, record fields, arrays, etc... */
10555 if (!ctype_isRealSU (t1))
10557 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
10558 sRef_copyRealDerivedComplete (s1, s2);
10563 ** Fields should alias
10566 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
10569 if (ctype_isMutable (t1) && sRef_isKnown (s1))
10571 usymtab_clearAlias (s1);
10572 usymtab_addMustAlias (s1, s2);
10573 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
10577 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
10580 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
10582 usymtab_unguard (s1);
10587 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
10589 if (exprNode_isDefined (e))
10591 e->loc = fileloc_update (e->loc, loc);
10595 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
10601 static void checkUniqueParams (exprNode fcn,
10602 /*@notnull@*/ exprNode current,
10604 int paramno, uentry ucurrent)
10607 sRef thisref = exprNode_getSref (current);
10610 ** Check if any argument could match this argument.
10613 exprNodeList_elements (args, icurrent)
10617 if (iparamno != paramno)
10619 sRef sr = exprNode_getSref (icurrent);
10621 if (sRef_similarRelaxed (thisref, sr))
10623 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
10628 ("Parameter %d (%s) to function %s is declared %s but "
10629 "is aliased by parameter %d (%s)",
10631 exprNode_unparse (current),
10632 exprNode_unparse (fcn),
10633 alkind_unparse (uentry_getAliasKind (ucurrent)),
10634 iparamno, exprNode_unparse (icurrent)),
10640 sRefSet aliases = usymtab_canAlias (sr);
10642 sRefSet_allElements (aliases, asr)
10644 if (ctype_isUnknown (sRef_getType (thisref)))
10646 sRef_setType (thisref, uentry_getType (ucurrent));
10649 if (sRef_similarRelaxed (thisref, asr))
10651 if (sRef_isExternal (asr))
10653 if (sRef_isLocalState (thisref))
10659 sRef base = sRef_getRootBase (asr);
10661 if (!sRef_similar (sRef_getBase (asr), thisref))
10663 if (sRef_isUnique (base) || sRef_isOnly (base)
10664 || sRef_isKept (base)
10665 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
10666 || (sRef_isAddress (thisref)
10667 && sRef_isLocalVar (sRef_getRootBase (thisref))))
10669 ; /* okay, no error */
10674 (FLG_MAYALIASUNIQUE,
10676 ("Parameter %d (%s) to function %s is declared %s but "
10677 "may be aliased externally by parameter %d (%s)",
10679 exprNode_unparse (current),
10680 exprNode_unparse (fcn),
10681 alkind_unparse (uentry_getAliasKind (ucurrent)),
10682 iparamno, exprNode_unparse (icurrent)),
10693 ("Parameter %d (%s) to function %s is declared %s but "
10694 "is aliased externally by parameter %d (%s) through "
10697 exprNode_unparse (current),
10698 exprNode_unparse (fcn),
10699 alkind_unparse (uentry_getAliasKind (ucurrent)),
10700 iparamno, exprNode_unparse (icurrent),
10701 sRef_unparse (asr)),
10705 } end_sRefSet_allElements;
10706 sRefSet_free (aliases);
10709 } end_exprNodeList_elements;
10712 long exprNode_getLongValue (exprNode e) {
10715 if (exprNode_hasValue (e)
10716 && multiVal_isInt (exprNode_getValue (e)))
10718 value = multiVal_forceInt (exprNode_getValue (e));
10728 /*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
10730 if (exprNode_isDefined (p_e) )
10731 return ( p_e->loc );
10733 return fileloc_undefined;
10736 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
10739 ** Returns the location of the sequence point following e.
10741 ** Only works for statements (for now).
10744 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
10745 lltok t = exprData_getUopTok (e->edata);
10746 return fileloc_copy(lltok_getLoc (t));
10748 //drl possible problem : warning fix
10749 // llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
10750 return fileloc_undefined;
10754 exprNode exprNode_createNew(ctype c)
10758 ret = exprNode_createPlain (c);
10763 bool exprNode_isInitBlock (exprNode e)
10765 return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);