2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
28 # include <ctype.h> /* for isdigit */
29 # include "lclintMacros.nf"
31 # include "cgrammar.h"
32 # include "cgrammar_tokens.h"
34 # include "exprChecks.h"
35 # include "transferChecks.h"
36 # include "exprNodeSList.h"
38 static bool exprNode_isEmptyStatement (exprNode p_e);
39 static /*@exposed@*/ exprNode exprNode_firstStatement (/*@returned@*/ exprNode p_e);
40 static bool exprNode_isFalseConstant (exprNode p_e) /*@*/ ;
41 static bool exprNode_isBlock (exprNode p_e);
42 static void checkGlobUse (uentry p_glob, bool p_isCall, /*@notnull@*/ exprNode p_e);
43 static void exprNode_addUse (exprNode p_e, /*@exposed@*/ sRef p_s);
44 static bool exprNode_matchArgType (ctype p_ct, exprNode p_e);
45 static exprNode exprNode_fakeCopy (exprNode p_e) /*@*/ ;
46 static exprNode exprNode_statementError (/*@only@*/ exprNode p_e, /*@only@*/ lltok p_t);
47 static bool exprNode_matchTypes (exprNode p_e1, exprNode p_e2);
48 static void checkUniqueParams (exprNode p_fcn,
49 /*@notnull@*/ exprNode p_current, exprNodeList p_args,
50 int p_paramno, uentry p_ucurrent);
51 static void updateAliases (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2);
52 static void abstractOpError (ctype p_tr1, ctype p_tr2, lltok p_op,
53 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2,
54 fileloc p_loc1, fileloc p_loc2);
55 static ctype checkNumerics (ctype p_tr1, ctype p_tr2, ctype p_te1, ctype p_te2,
56 /*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, lltok p_op);
57 static void doAssign (/*@notnull@*/ exprNode p_e1, /*@notnull@*/ exprNode p_e2, bool p_isInit);
58 static void checkSafeUse (exprNode p_e, /*@exposed@*/ sRef p_s);
59 static void reflectNullTest (/*@notnull@*/ exprNode p_e, bool p_isnull);
60 static void checkMacroParen (exprNode p_e);
61 static exprNodeSList exprNode_flatten (/*@dependent@*/ exprNode p_e);
62 static void exprNode_checkSetAny (exprNode p_e, /*@dependent@*/ cstring p_name);
63 static void exprNode_checkUse (exprNode p_e, /*@exposed@*/ sRef p_s, fileloc p_loc);
64 static void exprNode_mergeUSs (exprNode p_res, exprNode p_other);
65 static void exprNode_mergeCondUSs (exprNode p_res, exprNode p_other1, exprNode p_other2);
66 static /*@only@*/ /*@notnull@*/ exprNode exprNode_fromIdentifierAux (/*@observer@*/ uentry p_c);
67 static void checkAnyCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn,
68 /*@dependent@*/ cstring p_fname,
69 uentryList p_pn, exprNodeList p_args,
70 bool p_hasMods, sRefSet p_mods, bool p_isSpec,
72 static void checkOneArg (uentry p_ucurrent, /*@notnull@*/ exprNode p_current,
73 /*@dependent@*/ exprNode p_fcn, bool p_isSpec, int p_argno, int p_totargs);
75 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode p_fcn, uentryList p_params, exprNodeList p_args);
77 static /*@only@*/ exprNode exprNode_effect (exprNode p_e)
78 /*@globals internalState@*/ ;
79 static /*@only@*/ cstring exprNode_doUnparse (exprNode p_e);
80 static /*@observer@*/ cstring exprNode_rootVarName (exprNode p_e);
81 static /*@exposed@*/ exprNode
82 exprNode_lastStatement (/*@returned@*/ exprNode p_e);
84 static /*@null@*/ sRef defref = sRef_undefined;
85 static /*@only@*/ exprNode mustExitNode = exprNode_undefined;
87 static int checkArgsReal (uentry p_fcn, /*@dependent@*/ exprNode p_f,
89 exprNodeList p_args, bool p_isIter, exprNode p_ret);
91 static bool inEffect = FALSE;
92 static int nowalloc = 0;
93 static int totalloc = 0;
94 static int maxalloc = 0;
96 static /*@only@*/ uentry regArg;
97 static /*@only@*/ uentry outArg;
98 static /*@only@*/ uentry outStringArg;
99 static /*@exposed@*/ sRef stdinRef;
100 static /*@exposed@*/ sRef stdoutRef;
101 static /*@only@*/ uentry csArg;
102 static /*@only@*/ uentry csOnlyArg;
103 static ctype cstringType;
104 static ctype ctypeType;
105 static ctype filelocType;
106 static bool initMod = FALSE;
108 /*@function void exprNode_swap (sef exprNode, sef exprNode)@*/
110 # define exprNode_swap(e1,e2) do { exprNode m_tmp = (e1); (e1) = (e2); (e2) = m_tmp; } while (FALSE)
113 static void exprNode_defineConstraints(/*@sef@*/ /*@special@*/ /*@notnull@*/ exprNode e)
114 /*@defines e->requiresConstraints, e->ensuresConstraints,
115 e->trueEnsuresConstraints, e->falseEnsuresConstraints @*/
117 e->requiresConstraints = constraintList_makeNew ();
118 e->ensuresConstraints = constraintList_makeNew ();
119 e->trueEnsuresConstraints = constraintList_makeNew ();
120 e->falseEnsuresConstraints = constraintList_makeNew ();
124 ** must occur after library has been read
127 void exprNode_initMod (void)
128 /*@globals undef regArg, undef outArg, undef outStringArg,
129 undef csOnlyArg, undef csArg;
136 cstringType = ctype_unknown;
137 ctypeType = ctype_unknown;
138 filelocType = ctype_unknown;
140 defref = sRef_undefined;
142 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
144 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
147 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
149 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
152 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
154 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
157 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdin")))
159 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdin"));
161 else /* define stdin */
163 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdin"),
165 fileloc_getBuiltin (),
167 uentry_setHasNameError (ue);
168 ue = usymtab_supGlobalEntryReturn (ue);
171 stdinRef = sRef_makePointer (uentry_getSref (ue));
173 if (usymtab_existsGlob (cstring_makeLiteralTemp ("stdout")))
175 ue = usymtab_lookupGlob (cstring_makeLiteralTemp ("stdout"));
179 ue = uentry_makeVariable (cstring_makeLiteralTemp ("stdout"),
181 fileloc_getBuiltin (),
183 uentry_setHasNameError (ue);
184 ue = usymtab_supGlobalEntryReturn (ue);
187 stdoutRef = sRef_makePointer (uentry_getSref (ue));
189 tmp = idDecl_create (cstring_undefined, qtype_create (ctype_unknown));
191 regArg = uentry_makeParam (tmp, PARAMUNKNOWN);
194 qtype_addQual (qtype_create (ctype_makePointer (ctype_unknown)),
197 outArg = uentry_makeParam (tmp, PARAMUNKNOWN);
199 idDecl_setTyp (tmp, qtype_addQual (qtype_create (ctype_string),
202 outStringArg = uentry_makeParam (tmp, PARAMUNKNOWN);
204 idDecl_setTyp (tmp, qtype_addQual (qtype_addQual (qtype_create (cstringType),
206 qual_createNull ()));
208 csOnlyArg = uentry_makeParam (tmp, PARAMUNKNOWN);
210 idDecl_setTyp (tmp, qtype_addQual (qtype_create (cstringType), qual_createNull ()));
211 csArg = uentry_makeParam (tmp, PARAMUNKNOWN);
217 exprNode_destroyMod (void)
218 /*@globals killed regArg, killed outArg, killed outStringArg,
219 killed mustExitNode, initMod @*/
223 uentry_free (regArg);
224 uentry_free (outArg);
225 uentry_free (outStringArg);
227 exprNode_free (mustExitNode);
234 static void exprNode_resetSref (/*@notnull@*/ exprNode e)
239 exprNode exprNode_fakeCopy (exprNode e)
241 /*@-temptrans@*/ /*@-retalias@*/
243 /*@=temptrans@*/ /*@=retalias@*/
246 static bool isFlagKey (char key)
248 return (key == '-' || key == '+' || key == ' ' || key == '#');
251 static void exprNode_combineControl (/*@notnull@*/ exprNode ret,
252 /*@notnull@*/ exprNode ifclause,
253 /*@notnull@*/ exprNode elseclause)
255 ret->canBreak = ifclause->canBreak || elseclause->canBreak;
258 (ifclause->mustBreak || exprNode_mustEscape (ifclause))
259 && (elseclause->mustBreak || exprNode_mustEscape (elseclause));
261 ret->exitCode = exitkind_combine (ifclause->exitCode,
262 elseclause->exitCode);
267 ** For exprNode's returned by exprNode_effect.
270 static bool shallowKind (exprKind kind)
272 return (kind == XPR_STRINGLITERAL
273 || kind == XPR_NUMLIT
276 || kind == XPR_NODE);
280 exprNode_freeIniter (/*@only@*/ exprNode e)
282 if (!exprNode_isError (e))
288 ** Its a fake copy, don't free the field->rec and field->field
293 sfree (e->edata->field);
299 exprNode_free (e->edata->op->b);
300 /*@-compdestroy@*/ sfree (e->edata->op); /*@=compdestroy@*/
304 llbug (message ("other: %s", exprNode_unparse (e)));
307 multiVal_free (e->val);
308 cstring_free (e->etext);
309 fileloc_free (e->loc);
310 sRefSet_free (e->uses);
311 sRefSet_free (e->sets);
312 sRefSet_free (e->msets);
313 guardSet_free (e->guards);
315 constraintList_free(e->requiresConstraints);
316 constraintList_free(e->ensuresConstraints);
317 constraintList_free(e->trueEnsuresConstraints);
318 constraintList_free(e->falseEnsuresConstraints);
320 e->requiresConstraints = NULL;
321 e->ensuresConstraints = NULL;
322 e->trueEnsuresConstraints = NULL;
323 e->falseEnsuresConstraints = NULL;
330 exprNode_freeShallow (/*@only@*/ exprNode e)
332 if (!exprNode_isError (e))
334 if (shallowKind (e->kind))
341 if (e->kind == XPR_EMPTY
342 || e->kind == XPR_BODY
343 || e->kind == XPR_STRINGLITERAL
344 || e->kind == XPR_NUMLIT
345 || e->kind == XPR_NODE
346 || e->kind == XPR_OFFSETOF
347 || e->kind == XPR_ALIGNOFT
348 || e->kind == XPR_ALIGNOF
349 || e->kind == XPR_SIZEOFT
350 || e->kind == XPR_SIZEOF)
352 /* don't free anything */
356 /* multiVal_free (e->val); */
357 cstring_free (e->etext);
358 fileloc_free (e->loc);
359 sRefSet_free (e->uses);
360 sRefSet_free (e->sets);
361 sRefSet_free (e->msets);
362 guardSet_free (e->guards);
363 exprData_freeShallow (e->edata, e->kind);
365 /*@-compdestroy@*/ sfree (e); /*@=compdestroy@*/
374 exprNode_free (exprNode e)
376 if (!exprNode_isError (e))
380 multiVal_free (e->val);
381 cstring_free (e->etext);
382 fileloc_free (e->loc);
383 sRefSet_free (e->uses);
384 sRefSet_free (e->sets);
385 sRefSet_free (e->msets);
386 guardSet_free (e->guards);
387 exprData_free (e->edata, e->kind);
389 constraintList_free(e->requiresConstraints);
390 constraintList_free(e->ensuresConstraints);
391 constraintList_free(e->trueEnsuresConstraints);
392 constraintList_free(e->falseEnsuresConstraints);
394 e->requiresConstraints = NULL;
395 e->ensuresConstraints = NULL;
396 e->trueEnsuresConstraints = NULL;
397 e->falseEnsuresConstraints = NULL;
407 exprNode_makeError ()
409 return exprNode_undefined;
412 static /*@out@*/ /*@only@*/ /*@notnull@*/ exprNode
415 exprNode ret = (exprNode) dmalloc (sizeof (*ret));
416 /* static int lastexpnodes = 0; */
421 if (nowalloc > maxalloc)
429 static /*@notnull@*/ /*@special@*/ exprNode
430 exprNode_createPlain (ctype c)
432 /*@ensures isnull result->edata, result->loc, result->val, result->guards,
433 result->uses, result->sets, result->msets, result->etext @*/
436 exprNode e = exprNode_new ();
440 e->val = multiVal_undefined;
442 e->etext = cstring_undefined;
443 e->loc = fileloc_undefined;
444 e->guards = guardSet_undefined;
445 e->uses = sRefSet_undefined;
446 e->sets = sRefSet_undefined;
447 e->msets = sRefSet_undefined;
448 e->edata = exprData_undefined;
449 e->exitCode = XK_NEVERESCAPE;
451 e->mustBreak = FALSE;
452 e->isJumpPoint = FALSE;
454 exprNode_defineConstraints(e);
459 /*@observer@*/ exprNode exprNode_makeMustExit (void)
461 if (exprNode_isUndefined (mustExitNode))
463 mustExitNode = exprNode_createPlain (ctype_unknown);
464 mustExitNode->exitCode = XK_MUSTEXIT;
471 static /*@notnull@*/ /*@special@*/ exprNode exprNode_create (ctype c)
473 /*@post:isnull result->edata, result->guards, result->val,
474 result->uses, result->sets, result->msets@*/
477 exprNode e = exprNode_createPlain (c);
478 e->loc = fileloc_copy (g_currentloc);
482 static /*@notnull@*/ /*@special@*/ exprNode exprNode_createUnknown (void)
484 /*@post:isnull result->edata, result->guards,
485 result->uses, result->sets, result->msets@*/
488 return (exprNode_create (ctype_unknown));
491 static /*@notnull@*/ /*@special@*/ exprNode
492 exprNode_createLoc (ctype c, /*@keep@*/ fileloc loc)
494 /*@post:isnull result->edata, result->guards, result->val,
495 result->uses, result->sets, result->msets@*/
498 exprNode e = exprNode_createPlain (c);
504 exprNode_copySets (/*@special@*/ /*@notnull@*/ exprNode ret, exprNode e)
505 /*@defines ret->guards, ret->uses, ret->sets, ret->msets@*/
507 if (exprNode_isDefined (e))
509 ret->guards = guardSet_copy (e->guards);
510 ret->uses = sRefSet_newCopy (e->uses);
511 ret->sets = sRefSet_newCopy (e->sets);
512 ret->msets = sRefSet_newCopy (e->msets);
516 ret->guards = guardSet_undefined;
517 ret->uses = sRefSet_undefined;
518 ret->sets = sRefSet_undefined;
519 ret->msets = sRefSet_undefined;
523 static /*@notnull@*/ /*@special@*/ exprNode
524 exprNode_createPartialLocCopy (exprNode e, /*@only@*/ fileloc loc)
526 /*@post:isnull result->edata, result->etext@*/
529 exprNode ret = exprNode_new ();
531 if (exprNode_isError (e))
533 ret->typ = ctype_unknown;
534 ret->val = multiVal_undefined;
536 ret->guards = guardSet_undefined;
537 ret->uses = sRefSet_undefined;
538 ret->sets = sRefSet_undefined;
539 ret->msets = sRefSet_undefined;
544 ret->val = multiVal_copy (e->val);
546 ret->guards = guardSet_copy (e->guards);
547 ret->uses = sRefSet_newCopy (e->uses);
548 ret->sets = sRefSet_newCopy (e->sets);
549 ret->msets = sRefSet_newCopy (e->msets);
552 ret->kind = XPR_EMPTY;
554 ret->etext = cstring_undefined;
555 ret->exitCode = XK_NEVERESCAPE;
556 ret->canBreak = FALSE;
557 ret->mustBreak = FALSE;
558 ret->isJumpPoint = FALSE;
559 ret->edata = exprData_undefined;
561 exprNode_defineConstraints(ret);
567 static /*@notnull@*/ /*@special@*/ exprNode
568 exprNode_createPartialCopy (exprNode e)
570 /*@post:isnull result->edata, result->etext@*/
573 return (exprNode_createPartialLocCopy (e, fileloc_copy (exprNode_loc (e))));
576 static /*@notnull@*/ /*@special@*/ exprNode
577 exprNode_createPartialNVCopy (exprNode e)
579 /*@post:isnull result->edata, result->etext, result->val @*/
582 exprNode ret = exprNode_new ();
584 if (exprNode_isError (e))
586 ret->typ = ctype_unknown;
587 ret->loc = fileloc_undefined;
588 ret->guards = guardSet_undefined;
589 ret->uses = sRefSet_undefined;
590 ret->sets = sRefSet_undefined;
591 ret->msets = sRefSet_undefined;
596 ret->loc = fileloc_copy (e->loc);
597 ret->guards = guardSet_copy (e->guards);
598 ret->uses = sRefSet_newCopy (e->uses);
599 ret->sets = sRefSet_newCopy (e->sets);
600 ret->msets = sRefSet_newCopy (e->msets);
603 ret->val = multiVal_undefined;
604 ret->kind = XPR_EMPTY;
606 ret->etext = cstring_undefined;
607 ret->exitCode = XK_NEVERESCAPE;
608 ret->canBreak = FALSE;
609 ret->mustBreak = FALSE;
610 ret->isJumpPoint = FALSE;
611 ret->edata = exprData_undefined;
613 exprNode_defineConstraints(ret);
618 static /*@notnull@*/ /*@special@*/ exprNode
619 exprNode_createSemiCopy (exprNode e)
621 /*@post:isnull result->edata, result->etext, result->sets,
622 result->msets, result->uses, result->guards@*/
625 if (exprNode_isError (e))
627 return exprNode_createPlain (ctype_unknown);
631 exprNode ret = exprNode_new ();
634 ret->val = multiVal_copy (e->val);
635 ret->loc = fileloc_copy (e->loc);
636 ret->guards = guardSet_undefined;
637 ret->uses = sRefSet_undefined;
638 ret->sets = sRefSet_undefined;
639 ret->msets = sRefSet_undefined;
641 ret->kind = XPR_EMPTY;
643 ret->etext = cstring_undefined;
644 ret->exitCode = XK_NEVERESCAPE;
645 ret->canBreak = FALSE;
646 ret->mustBreak = FALSE;
647 ret->isJumpPoint = FALSE;
648 ret->edata = exprData_undefined;
650 exprNode_defineConstraints(ret);
657 exprNode_isNullValue (exprNode e)
659 if (exprNode_isDefined (e))
661 multiVal m = exprNode_getValue (e);
663 if (multiVal_isInt (m))
665 return (multiVal_forceInt (m) == 0);
673 exprNode_isUnknownConstant (/*@notnull@*/ exprNode e)
675 while (e->kind == XPR_PARENS)
677 e = exprData_getUopNode (e->edata);
678 llassert (exprNode_isDefined (e));
681 if (e->kind == XPR_CONST)
683 multiVal m = exprNode_getValue (e);
685 if (multiVal_isUnknown (m))
695 exprNode_numLiteral (ctype c, /*@temp@*/ cstring t,
696 /*@only@*/ fileloc loc, long val)
698 exprNode e = exprNode_createLoc (c, loc);
700 e->kind = XPR_NUMLIT;
702 llassert (multiVal_isUndefined (e->val));
703 e->val = multiVal_makeInt (val);
704 e->edata = exprData_makeLiteral (cstring_copy (t));
708 e->sref = sRef_makeUnknown ();
709 sRef_setDefNull (e->sref, e->loc);
712 DPRINTF (("Num lit: %s / %s", exprNode_unparse (e), ctype_unparse (exprNode_getType (e))));
717 exprNode_charLiteral (char c, cstring text, /*@only@*/ fileloc loc)
719 exprNode e = exprNode_createLoc (ctype_char, loc);
721 if (context_getFlag (FLG_CHARINTLITERAL))
723 e->typ = ctype_makeConj (ctype_char, ctype_int);
726 e->kind = XPR_NUMLIT;
727 e->val = multiVal_makeChar (c);
729 e->edata = exprData_makeLiteral (cstring_copy (text));
734 exprNode_floatLiteral (double d, ctype ct, cstring text, /*@only@*/ fileloc loc)
736 exprNode e = exprNode_createLoc (ct, loc);
738 e->kind = XPR_NUMLIT;
739 e->val = multiVal_makeDouble (d);
740 e->edata = exprData_makeLiteral (cstring_copy (text));
744 multiVal exprNode_getValue (exprNode e)
746 while (exprNode_isInParens (e)) {
747 if (e->edata != NULL) {
748 e = exprData_getUopNode (e->edata);
754 if (exprNode_isDefined (e)) {
757 return multiVal_undefined;
762 exprNode_combineLiterals (exprNode e, exprNode rest)
766 /* Both must be string literals. */
768 if (exprNode_isUndefined (rest) || exprNode_isUndefined (e))
770 exprNode_free (rest);
774 if (!exprNode_isStringLiteral (e))
778 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e),
779 exprNode_unparse (rest)),
781 exprNode_free (rest);
785 if (!exprNode_isStringLiteral (rest))
789 message ("Constant concatentation is ungrammatical: %s %s", exprNode_unparse (e), exprNode_unparse (rest)),
792 exprNode_free (rest);
796 ns = cstring_concat (multiVal_forceString (exprNode_getValue (e)),
797 multiVal_forceString (exprNode_getValue (rest)));
799 multiVal_free (e->val);
800 exprData_free (e->edata, e->kind);
801 e->edata = exprData_makeLiteral (cstring_copy (ns));
802 e->val = multiVal_makeString (ns);
803 exprNode_free (rest);
808 exprNode_rawStringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
810 exprNode e = exprNode_createLoc (ctype_string, loc);
811 int len = cstring_length (t);
813 if (context_getFlag (FLG_STRINGLITERALLEN))
815 if (len > context_getValue (FLG_STRINGLITERALLEN))
817 voptgenerror (FLG_STRINGLITERALLEN,
819 ("String literal length (%d) exceeds maximum "
820 "length (%d): \"%s\"",
822 context_getValue (FLG_STRINGLITERALLEN),
828 e->kind = XPR_STRINGLITERAL;
829 e->val = multiVal_makeString (cstring_copy (t));
830 e->edata = exprData_makeLiteral (t);
831 e->sref = sRef_makeConst (ctype_string);
833 if (context_getFlag (FLG_READONLYSTRINGS))
835 sRef_setAliasKind (e->sref, AK_STATIC, fileloc_undefined);
836 sRef_setExKind (e->sref, XO_OBSERVER, loc);
840 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
843 return (e); /* s released */
847 exprNode_stringLiteral (/*@only@*/ cstring t, /*@only@*/ fileloc loc)
849 int len = cstring_length (t) - 2;
850 char *ts = cstring_toCharsSafe (t);
851 char *s = cstring_toCharsSafe (cstring_create (len + 1));
853 llassert (*ts == '\"' && *(ts + len + 1) == '\"');
854 strncpy (s, ts+1, size_fromInt (len));
857 return exprNode_rawStringLiteral (cstring_fromCharsO (s), loc);
860 exprNode exprNode_fromUIO (cstring c)
862 fileloc loc = context_getSaveLocation ();
863 exprNode e = exprNode_createPlain (ctype_unknown);
867 if (fileloc_isUndefined (loc))
869 loc = fileloc_copy (g_currentloc);
872 e->loc = loc; /* save loc was mangled */
875 if (usymtab_exists (c))
877 uentry ue = usymtab_lookupEither (c);
879 if (uentry_isDatatype (ue)
880 && uentry_isSpecified (ue))
883 (message ("%q: Specified datatype %s used in code, but not defined. "
884 "(Cannot continue reasonably from this error.)",
885 fileloc_unparse (e->loc), c));
893 llassertprint (!usymtab_exists (c), ("Entry exists: %s", c));
896 ** was supercedeGlobalEntry...is this better?
899 if (!context_inIterEnd ())
901 if (context_inMacro ())
903 if (context_getFlag (FLG_UNRECOG))
907 message ("Unrecognized identifier in macro definition: %s", c), e->loc);
911 flagcode_recordSuppressed (FLG_UNRECOG);
917 (FLG_UNRECOG, message ("Unrecognized identifier: %s", c), e->loc);
921 e->edata = exprData_makeId (uentry_makeUnrecognized (c, fileloc_copy (loc)));
923 /* No alias errors for unrecognized identifiers */
924 sRef_setAliasKind (e->sref, AK_ERROR, loc);
929 exprNode exprNode_createId (/*@observer@*/ uentry c)
931 if (uentry_isValid (c))
933 exprNode e = exprNode_new ();
935 e->typ = uentry_getType (c);
937 if (uentry_isFunction (c)
938 && !sRef_isLocalVar (uentry_getSref (c)))
940 e->sref = sRef_undefined;
944 e->sref = uentry_getSref (c);
947 if (sRef_isStateUnknown (e->sref) && uentry_isNonLocal (c))
949 sRef_setDefined (e->sref, fileloc_undefined);
953 ** yoikes! leaving this out was a heinous bug...that would have been
954 ** caught if i had lclint working first. gag!
957 e->etext = cstring_undefined;
959 if (uentry_isEitherConstant (c))
962 e->val = multiVal_copy (uentry_getConstantValue (c));
967 e->val = multiVal_unknown ();
970 e->edata = exprData_makeId (c);
971 e->loc = context_getSaveLocation ();
973 if (fileloc_isUndefined (e->loc))
975 fileloc_free (e->loc);
976 e->loc = fileloc_copy (g_currentloc);
979 e->guards = guardSet_new ();
980 e->sets = sRefSet_new ();
981 e->msets = sRefSet_new ();
982 e->uses = sRefSet_new ();
984 /*> missing fields, detected by lclint <*/
985 e->exitCode = XK_NEVERESCAPE;
986 e->isJumpPoint = FALSE;
988 e->mustBreak = FALSE;
990 exprNode_defineConstraints(e);
996 return exprNode_createUnknown ();
1000 /*@notnull@*/ exprNode
1001 exprNode_fromIdentifier (/*@observer@*/ uentry c)
1005 if (context_justPopped ()) /* watch out! c could be dead */
1007 uentry ce = usymtab_lookupSafe (LastIdentifier ());
1009 if (uentry_isValid (ce))
1015 llbuglit ("Looks like Aunt Millie forgot to walk to dog again.");
1019 ret = exprNode_fromIdentifierAux (c);
1024 static /*@only@*/ /*@notnull@*/ exprNode
1025 exprNode_fromIdentifierAux (/*@observer@*/ uentry c)
1027 exprNode e = exprNode_createId (c);
1030 uentry_setUsed (c, e->loc);
1032 if (uentry_isVar (c) && sRef_isFileOrGlobalScope (sr))
1034 checkGlobUse (c, FALSE, e);
1041 exprNode_isZero (exprNode e)
1043 if (exprNode_isDefined (e))
1045 multiVal m = exprNode_getValue (e);
1047 if (multiVal_isInt (m))
1049 return (multiVal_forceInt (m) == 0);
1057 exprNode_isNonNegative (exprNode e)
1059 if (exprNode_isDefined (e))
1061 multiVal m = exprNode_getValue (e);
1063 if (multiVal_isInt (m))
1065 return (multiVal_forceInt (m) >= 0);
1073 ** a[x] - uses a but NOT a[]
1074 ** result sref = a[] (set/use in assignment)
1076 ** The syntax x[a] is also legal in C, and has the same
1077 ** semantics. If ind is an array, and arr is an int, flip
1082 exprNode_arrayFetch (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
1085 ** error in arr, error propagates (no new messages)
1086 ** error in ind, assume valid and continue
1089 DPRINTF (("Array fetch: %s / %s",
1090 exprNode_unparse (e1), exprNode_unparse (e2)));
1092 if (exprNode_isError (e1))
1095 return (exprNode_makeError ());
1101 ctype carr = exprNode_getType (e1);
1102 ctype crarr = ctype_realType (carr);
1105 ** this sets up funny aliasing, that leads to spurious
1106 ** lclint errors. Hence, the i2 comments.
1109 /* evans 2001-09-09 added ctype_isKnown so there is no swap when e1 type is unknown */
1110 if (ctype_isKnown (crarr)
1111 && !ctype_isRealArray (crarr)
1112 && ctype_isRealNumeric (crarr)
1113 && !exprNode_isError (e2)
1114 && ctype_isRealAP (exprNode_getType (e2))) /* fetch like 3[a] */
1119 carr = exprNode_getType (arr);
1120 crarr = ctype_realType (carr);
1128 DPRINTF (("arr: %s", exprNode_unparse (arr)));
1130 if (sRef_possiblyNull (arr->sref))
1132 if (!usymtab_isGuarded (arr->sref))
1134 if (optgenerror (FLG_NULLDEREF,
1135 message ("Index of %s pointer %q: %s",
1136 sRef_nullMessage (arr->sref),
1137 sRef_unparse (arr->sref),
1138 exprNode_unparse (arr)),
1141 DPRINTF (("ref: %s", sRef_unparseFull (arr->sref)));
1142 sRef_showNullInfo (arr->sref);
1144 /* suppress future messages */
1145 sRef_setNullError (arr->sref);
1150 if (exprNode_isError (ind))
1152 if ((ctype_isArrayPtr (crarr)
1153 && !ctype_isFunction (crarr))
1154 || ctype_isUnknown (carr))
1156 exprNode ret = exprNode_createPartialCopy (arr);
1158 if (ctype_isKnown (carr))
1160 ret->typ = ctype_baseArrayPtr (crarr);
1164 ret->typ = ctype_unknown;
1167 ret->sref = sRef_makeArrayFetch (arr->sref);
1169 ret->kind = XPR_FETCH;
1172 ** Because of funny aliasing (when arr and ind are
1173 ** flipped) spurious errors would be reported here.
1176 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1177 checkSafeUse (ret, arr->sref);
1182 voptgenerror (FLG_TYPE,
1183 message ("Array fetch from non-array (%t): %s[%s]", carr,
1184 exprNode_unparse (e1), exprNode_unparse (e2)),
1186 exprNode_free (arr);
1187 return (exprNode_makeError ());
1192 if (!ctype_isForceRealInt (&(ind->typ)))
1194 ctype rt = ctype_realType (ind->typ);
1196 if (ctype_isChar (rt))
1200 message ("Array fetch using non-integer, %t: %s[%s]",
1202 exprNode_unparse (e1), exprNode_unparse (e2)),
1205 else if (ctype_isEnum (rt))
1209 message ("Array fetch using non-integer, %t: %s[%s]",
1211 exprNode_unparse (e1), exprNode_unparse (e2)),
1218 message ("Array fetch using non-integer, %t: %s[%s]",
1220 exprNode_unparse (e1), exprNode_unparse (e2)),
1224 multiVal_free (ind->val);
1225 ind->val = multiVal_unknown ();
1228 if (ctype_isArrayPtr (crarr) && !ctype_isFunction (crarr))
1230 exprNode ret = exprNode_createSemiCopy (arr);
1231 multiVal m = exprNode_getValue (ind);
1233 ret->typ = ctype_baseArrayPtr (crarr);
1234 ret->kind = XPR_FETCH;
1236 if (multiVal_isInt (m))
1238 int i = (int) multiVal_forceInt (m);
1240 if (sRef_isValid (arr->sref)) {
1241 ret->sref = sRef_makeArrayFetchKnown (arr->sref, i);
1243 ret->sref = sRef_undefined;
1248 ret->sref = sRef_makeArrayFetch (arr->sref);
1251 ret->sets = sRefSet_realNewUnion (arr->sets, ind->sets);
1252 ret->msets = sRefSet_realNewUnion (arr->msets, ind->msets);
1253 ret->uses = sRefSet_realNewUnion (arr->uses, ind->uses);
1255 /* (see comment on spurious errors above) */
1256 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1258 exprNode_checkUse (ret, ind->sref, ind->loc);
1259 exprNode_checkUse (ret, arr->sref, arr->loc);
1265 if (ctype_isUnknown (carr))
1267 exprNode ret = exprNode_createPartialCopy (arr);
1269 ret->kind = XPR_FETCH;
1270 ret->typ = ctype_unknown;
1271 ret->sets = sRefSet_union (ret->sets, ind->sets);
1272 ret->msets = sRefSet_union (ret->msets, ind->msets);
1273 ret->uses = sRefSet_union (ret->uses, ind->uses);
1275 /* (see comment on spurious errors above) */
1276 /*@i2@*/ ret->edata = exprData_makePair (arr, ind);
1278 exprNode_checkUse (ret, ind->sref, ind->loc);
1279 exprNode_checkUse (ret, arr->sref, arr->loc);
1286 message ("Array fetch from non-array (%t): %s[%s]", carr,
1287 exprNode_unparse (e1), exprNode_unparse (e2)),
1290 exprNode_free (arr);
1291 exprNode_free (ind);
1293 return (exprNode_makeError ());
1303 checkArgs (uentry fcn, /*@dependent@*/ exprNode f, ctype t,
1304 exprNodeList args, exprNode ret)
1306 return (checkArgsReal (fcn, f, ctype_argsFunction (t), args, FALSE, ret));
1310 ** checkPrintfArgs --- checks arguments for printf-like functions
1311 ** Arguments before ... have already been checked.
1312 ** The argument before the ... is a char *.
1313 ** argno is the format string argument.
1317 checkPrintfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1318 exprNodeList args, exprNode ret, int argno)
1321 ** the last argument before the elips is the format string
1326 int nargs = exprNodeList_size (args);
1327 uentryList params = uentry_getParams (fcn);
1331 ** These should be ensured by checkSpecialFunction
1334 llassert (uentryList_size (params) == argno + 1);
1335 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1337 a = exprNodeList_getN (args, argno - 1);
1338 formatloc = fileloc_copy (exprNode_loc (a));
1340 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1341 && exprNode_knownStringValue (a))
1343 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1344 char *code = format;
1347 nargs = exprNodeList_size (args);
1349 while ((code = strchr (code, '%')) != NULL)
1351 char *origcode = code;
1352 cstring codetext = cstring_newEmpty ();
1353 char key = *(++code);
1354 ctype modtype = ctype_int;
1355 bool modified = FALSE;
1357 fileloc_addColumn (formatloc, code - ocode);
1359 codetext = cstring_appendChar (codetext, key);
1362 while (isFlagKey (key))
1365 codetext = cstring_appendChar (codetext, key);
1366 fileloc_incColumn (formatloc);
1369 if (key == 'm') /* skipped in syslog */
1374 /* ignore field width */
1375 while (isdigit ((int) key) != 0)
1378 codetext = cstring_appendChar (codetext, key);
1379 fileloc_incColumn (formatloc);
1382 /* ignore precision */
1386 codetext = cstring_appendChar (codetext, key);
1387 fileloc_incColumn (formatloc);
1390 ** In printf, '*' means: read the next arg as an int for the
1391 ** field width. This seems to be missing from my copy of the
1392 ** standard x3.159-1989. Setion 4.9.6.1 refers to * (described
1393 ** later) but never does.
1398 ; /* don't do anything --- handle later */
1402 while (isdigit ((int) key) != 0)
1405 codetext = cstring_appendChar (codetext, key);
1406 fileloc_incColumn (formatloc);
1413 modtype = ctype_sint; /* short */
1415 codetext = cstring_appendChar (codetext, key);
1416 fileloc_incColumn (formatloc);
1418 else if (key == 'l' || key == 'L')
1420 modtype = ctype_lint; /* long */
1422 codetext = cstring_appendChar (codetext, key);
1423 fileloc_incColumn (formatloc);
1425 if (key == 'l' || key == 'L') {
1426 modtype = ctype_llint; /* long long */
1428 codetext = cstring_appendChar (codetext, key);
1429 fileloc_incColumn (formatloc);
1437 /* now, key = type of conversion to apply */
1439 fileloc_incColumn (formatloc);
1447 message ("No argument corresponding to %q format "
1448 "code %d (%%%s): \"%s\"",
1449 uentry_getName (fcn),
1451 cstring_fromChars (format)),
1454 if (fileloc_isDefined (formatloc)
1455 && context_getFlag (FLG_SHOWCOL))
1457 llgenindentmsg (cstring_makeLiteral ("Corresponding format code"),
1465 a = exprNodeList_getN (args, i);
1468 if (!exprNode_isError (a))
1474 case '*': /* int argument for fieldwidth */
1475 expecttype = ctype_int;
1476 *(--code) = '%'; /* convert it for next code */
1477 fileloc_subColumn (formatloc, 1);
1478 /*@switchbreak@*/ break;
1481 expecttype = ctype_combine (ctype_uint, modtype);
1482 /*@switchbreak@*/ break;
1484 case 'i': /* int argument */
1486 expecttype = ctype_combine (ctype_int, modtype);
1487 /*@switchbreak@*/ break;
1489 case 'x': /* unsigned int */
1491 expecttype = ctype_combine (ctype_uint, modtype);
1493 /*@switchbreak@*/ break;
1499 case 'f': /* double */
1500 expecttype = ctype_combine (ctype_double, modtype);
1501 /*@switchbreak@*/ break;
1503 case 'c': /* int converted to char (check its a char?) */
1504 expecttype = ctype_makeConj (ctype_int,
1505 ctype_makeConj (ctype_char,
1508 /* evans 2001-10-05 - changed to reflect correct ISO spec:
1509 int converted to char */
1511 /* expecttype = ctype_makeConj (ctype_char, ctype_uchar); */
1512 /*@switchbreak@*/ break;
1514 case 's': /* string */
1515 expecttype = ctype_string;
1516 /*@switchbreak@*/ break;
1519 while (((key = *(++code)) != ']')
1522 codetext = cstring_appendChar (codetext, key);
1523 fileloc_incColumn (formatloc);
1529 (message ("Bad character set format: %s",
1530 cstring_fromChars (origcode)));
1533 expecttype = ctype_string;
1534 /*@switchbreak@*/ break;
1536 case 'p': /* pointer */
1537 expecttype = ctype_makePointer (ctype_void);
1538 uentry_setDefState (regArg, SS_RELDEF); /* need not be defined */
1539 sRef_setPosNull (uentry_getSref (regArg), fileloc_undefined); /* could be null */
1540 /*@switchbreak@*/ break;
1542 case 'n': /* pointer to int, modified by call! */
1543 expecttype = ctype_combine (ctype_makePointer (ctype_int), modtype);
1545 uentry_setDefState (regArg, SS_ALLOCATED); /* corresponds to out */
1546 /*@switchbreak@*/ break;
1548 case 'm': /* in a syslog, it doesn't consume an argument */
1549 /* should check we're really doing syslog */
1551 /*@switchbreak@*/ break;
1555 expecttype = ctype_unknown;
1559 message ("Unrecognized format code: %s",
1560 cstring_fromChars (origcode)),
1561 fileloc_isDefined (formatloc)
1562 ? formatloc : g_currentloc);
1564 /*@switchbreak@*/ break;
1567 if (!(exprNode_matchArgType (expecttype, a)))
1569 if (ctype_isVoidPointer (expecttype)
1570 && ctype_isRealAbstract (a->typ)
1571 && (context_getFlag (FLG_ABSTVOIDP)))
1577 if (llgenformattypeerror
1578 (expecttype, exprNode_undefined,
1580 message ("Format argument %d to %q (%%%s) expects "
1583 uentry_getName (fcn),
1586 a->typ, exprNode_unparse (a)),
1589 if (fileloc_isDefined (formatloc)
1590 && context_getFlag (FLG_SHOWCOL))
1593 (cstring_makeLiteral
1594 ("Corresponding format code"),
1601 uentry_setType (regArg, expecttype);
1602 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
1604 if (ctype_equal (expecttype, ctype_string))
1606 exprNode_checkUse (a, sRef_makePointer (a->sref), a->loc);
1609 uentry_setType (regArg, ctype_unknown);
1610 uentry_fixupSref (regArg);
1614 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1625 cstring_free (codetext);
1630 voptgenerror (FLG_TYPE,
1631 message ("Format string for %q has %d arg%&, given %d",
1632 uentry_getName (fcn), i - argno, nargs - argno),
1638 /* no checking possible for compile-time unknown format strings */
1639 if (exprNode_isDefined (a))
1643 message ("Format string parameter to %s is not a compile-time constant: %s",
1644 exprNode_unparse (f),
1645 exprNode_unparse (a)),
1650 fileloc_free (formatloc);
1654 checkScanfArgs (/*@notnull@*/ /*@dependent@*/ exprNode f, uentry fcn,
1655 exprNodeList args, exprNode ret, int argno)
1659 int nargs = exprNodeList_size (args);
1660 uentryList params = uentry_getParams (fcn);
1664 ** These should be ensured by checkSpecialFunction
1667 llassert (uentryList_size (params) == argno + 1);
1668 llassert (uentry_isElipsisMarker (uentryList_getN (params, argno)));
1670 a = exprNodeList_getN (args, argno - 1);
1671 formatloc = fileloc_copy (exprNode_loc (a));
1673 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1674 && exprNode_knownStringValue (a))
1676 char *format = cstring_toCharsSafe (multiVal_forceString (exprNode_getValue (a)));
1677 char *code = format;
1680 nargs = exprNodeList_size (args);
1682 while ((code = strchr (code, '%')) != NULL)
1684 char *origcode = code;
1685 char key = *(++code);
1686 cstring codetext = cstring_newEmpty ();
1687 ctype modtype = ctype_int;
1688 char modifier = '\0';
1689 bool modified = TRUE;
1690 bool ignore = FALSE;
1692 codetext = cstring_appendChar (codetext, key);
1693 fileloc_addColumn (formatloc, code - ocode);
1696 ** this is based on ANSI standard library description of fscanf
1697 ** (from ANSI standard X3.159-1989, 4.9.6.1)
1700 /* '*' suppresses assignment (does not need match argument) */
1705 codetext = cstring_appendChar (codetext, key);
1708 fileloc_incColumn (formatloc);
1711 /* ignore field width */
1712 while (isdigit ((int) key) != 0)
1715 codetext = cstring_appendChar (codetext, key);
1716 fileloc_incColumn (formatloc);
1721 modtype = ctype_sint; /* short */
1723 codetext = cstring_appendChar (codetext, key);
1724 fileloc_incColumn (formatloc);
1726 else if (key == 'l' || key == 'L')
1728 modtype = ctype_lint; /* long */
1732 codetext = cstring_appendChar (codetext, key);
1734 fileloc_incColumn (formatloc);
1736 if (key == 'l' || key == 'L') {
1737 modtype = ctype_llint; /* long long */
1739 codetext = cstring_appendChar (codetext, key);
1740 fileloc_incColumn (formatloc);
1748 /* now, key = type of conversion to apply */
1750 fileloc_incColumn (formatloc);
1764 message ("No argument corresponding to %q format "
1765 "code %d (%%%s): \"%s\"",
1766 uentry_getName (fcn),
1768 cstring_fromChars (format)),
1771 if (fileloc_isDefined (formatloc)
1772 && context_getFlag (FLG_SHOWCOL))
1775 (cstring_makeLiteral ("Corresponding format code"),
1783 a = exprNodeList_getN (args, i);
1786 if (!exprNode_isError (a))
1792 case '*': /* int argument for fieldwidth */
1793 expecttype = ctype_makePointer (ctype_int);
1794 *(--code) = '%'; /* convert it for next code */
1795 fileloc_subColumn (formatloc, 1);
1796 /*@switchbreak@*/ break;
1799 expecttype = ctype_makePointer (ctype_combine (ctype_uint, modtype));
1800 /*@switchbreak@*/ break;
1805 case 'X': /* unsigned int */
1806 expecttype = ctype_makePointer (ctype_combine (ctype_int, modtype));
1807 /*@switchbreak@*/ break;
1814 /* printf is double, scanf is float! */
1816 if (modifier == 'l')
1818 expecttype = ctype_makePointer (ctype_double);
1820 else if (modifier == 'L')
1822 expecttype = ctype_makePointer (ctype_ldouble);
1826 llassert (modifier == '\0');
1827 expecttype = ctype_makePointer (ctype_float);
1829 /*@switchbreak@*/ break;
1831 case 'c': /* int converted to char (check its a char?) */
1832 expecttype = ctype_makePointer (ctype_makeConj (ctype_char, ctype_uchar));
1833 /*@switchbreak@*/ break;
1835 case 's': /* string */
1836 expecttype = ctype_string;
1837 /*@switchbreak@*/ break;
1841 while (((key = *(++code)) != ']')
1844 codetext = cstring_appendChar (codetext, key);
1845 fileloc_incColumn (formatloc);
1851 (message ("Bad character set format: %s",
1852 cstring_fromChars (origcode)));
1855 expecttype = ctype_string;
1856 /*@switchbreak@*/ break;
1859 case 'p': /* pointer */
1862 message ("Format code should not be used in scanf: %s",
1863 cstring_fromChars (origcode)),
1864 fileloc_isDefined (formatloc)
1865 ? formatloc : g_currentloc);
1867 expecttype = ctype_unknown;
1868 /*@switchbreak@*/ break;
1870 case 'n': /* pointer to int, modified by call! */
1871 expecttype = ctype_makePointer (ctype_int);
1872 /*@switchbreak@*/ break;
1875 expecttype = ctype_unknown;
1879 message ("Unrecognized format code: %s",
1880 cstring_fromChars (origcode)),
1881 fileloc_isDefined (formatloc)
1882 ? formatloc : g_currentloc);
1884 /*@switchbreak@*/ break;
1887 if (!(exprNode_matchArgType (expecttype, a)))
1889 if (ctype_isVoidPointer (expecttype)
1890 && ctype_isRealAbstract (a->typ)
1891 && (context_getFlag (FLG_ABSTVOIDP)))
1897 if (llgenformattypeerror
1898 (expecttype, exprNode_undefined,
1900 message ("Format argument %d to %q (%%%s) expects "
1903 uentry_getName (fcn),
1904 codetext, expecttype,
1905 a->typ, exprNode_unparse (a)),
1908 if (fileloc_isDefined (formatloc)
1909 && context_getFlag (FLG_SHOWCOL))
1912 (cstring_makeLiteral
1913 ("Corresponding format code"),
1920 uentry_setType (outArg, expecttype);
1921 checkOneArg (outArg, a, f, FALSE, i+1, nargs);
1922 uentry_setType (outArg, ctype_unknown);
1923 uentry_fixupSref (outArg);
1927 exprNode_checkCallModifyVal (a->sref, args, f, ret);
1932 /* a->sref = defref; */
1939 cstring_free (codetext);
1944 voptgenerror (FLG_TYPE,
1945 message ("Format string for %q has %d arg%&, given %d",
1946 uentry_getName (fcn), i - argno, nargs - argno),
1952 /* no checking possible for compile-time unknown format strings */
1955 fileloc_free (formatloc);
1959 checkMessageArgs (/*@notnull@*/ /*@dependent@*/ exprNode f,
1962 /*@unused@*/ int argno)
1965 ** the last argument before the elips is the format string
1968 int nargs = exprNodeList_size (args);
1973 a = exprNodeList_getN (args, argno - 1);
1974 formatloc = fileloc_copy (exprNode_loc (a));
1976 if (ctype_isUnknown (cstringType)) {
1977 if (usymtab_existsType (cstring_makeLiteralTemp ("cstring")))
1979 cstringType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("cstring"));
1983 if (ctype_isUnknown (ctypeType)) {
1984 if (usymtab_existsType (cstring_makeLiteralTemp ("ctype")))
1986 ctypeType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("ctype"));
1990 if (ctype_isUnknown (filelocType)) {
1991 if (usymtab_existsType (cstring_makeLiteralTemp ("fileloc")))
1993 filelocType = usymtab_lookupAbstractType (cstring_makeLiteralTemp ("fileloc"));
1997 if (exprNode_isDefined (a) && exprNode_isStringLiteral (a)
1998 && exprNode_knownStringValue (a))
2000 cstring format = multiVal_forceString (exprNode_getValue (a));
2001 char *code = cstring_toCharsSafe (format);
2004 nargs = exprNodeList_size (args);
2006 while ((code = strchr (code, '%')) != NULL)
2008 char *origcode = code;
2009 char key = *(++code);
2010 cstring codetext = cstring_newEmpty ();
2011 bool isOnly = FALSE;
2013 codetext = cstring_appendChar (codetext, key);
2015 fileloc_addColumn (formatloc, code - ocode);
2017 while (key >= '0' && key <= '9')
2020 codetext = cstring_appendChar (codetext, key);
2021 fileloc_incColumn (formatloc);
2025 fileloc_incColumn (formatloc);
2029 if (key == '&') /* plural marker */
2038 message ("Message missing format arg %d (%%%s): \"%s\"",
2039 i + 1, codetext, format),
2045 a = exprNodeList_getN (args, i);
2049 if (!exprNode_isError (a))
2053 /*@-loopswitchbreak@*/
2059 expecttype = ctype_char; break;
2061 expecttype = cstringType; break;
2063 expecttype = cstringType; isOnly = TRUE; break;
2065 expecttype = cstringType; isOnly = TRUE; break;
2066 case 'd': expecttype = ctype_int; break;
2067 case 'u': expecttype = ctype_uint; break;
2068 case 'w': expecttype = ctype_ulint; break;
2069 case 'f': expecttype = ctype_float; break;
2070 case 'b': expecttype = ctype_bool; break;
2071 case 't': expecttype = ctypeType; break;
2072 case 'l': expecttype = filelocType; break;
2073 case '&': /* a wee bit of a hack methinks */
2074 expecttype = ctype_int;
2076 case 'r': expecttype = ctype_bool; break;
2078 expecttype = ctype_unknown;
2081 message ("Unrecognized format code: %s",
2082 cstring_fromChars (origcode)),
2083 fileloc_isDefined (formatloc)
2084 ? formatloc : g_currentloc);
2087 /*@=loopswitchbreak@*/
2089 if (!(exprNode_matchArgType (expecttype, a)))
2091 if (ctype_isVoidPointer (expecttype)
2092 && ctype_isRealAbstract (a->typ)
2093 && (context_getFlag (FLG_ABSTVOIDP)))
2099 if (llgenformattypeerror
2100 (expecttype, exprNode_undefined,
2102 message ("Format argument %d to %q (%%%s) expects "
2105 uentry_getName (fcn),
2106 codetext, expecttype,
2107 a->typ, exprNode_unparse (a)),
2110 if (fileloc_isDefined (formatloc)
2111 && context_getFlag (FLG_SHOWCOL))
2114 (cstring_makeLiteral
2115 ("Corresponding format code"),
2122 if (ctype_equal (expecttype, cstringType))
2126 checkOneArg (csOnlyArg, a, f, FALSE, i+1, nargs);
2127 uentry_fixupSref (csOnlyArg);
2131 checkOneArg (csArg, a, f, FALSE, i+1, nargs);
2132 uentry_fixupSref (csArg);
2137 checkOneArg (regArg, a, f, FALSE, i+1, nargs);
2138 uentry_fixupSref (regArg);
2144 cstring_free (codetext);
2149 voptgenerror (FLG_TYPE,
2150 message ("Format string for %q has %d arg%&, given %d",
2151 uentry_getName (fcn), i - argno, nargs -argno),
2157 /* no checking possible for compile-time unknown format strings */
2160 fileloc_free (formatloc);
2164 checkExpressionDefinedAux (/*@notnull@*/ exprNode e1,
2165 /*@notnull@*/ exprNode e2,
2171 bool hadUncon = FALSE;
2173 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e1->sref)) &&
2174 sRefSet_hasUnconstrained (sets2))
2177 (FLG_EVALORDERUNCON,
2179 ("Expression may have undefined behavior (%q used in right operand "
2180 "may set global variable %q used in left operand): %s %s %s",
2181 sRefSet_unparseUnconstrained (sets2),
2182 sRef_unparse (sRef_getRootBase (e1->sref)),
2183 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2187 if (sRef_isFileOrGlobalScope (sRef_getRootBase (e2->sref)) &&
2188 sRefSet_hasUnconstrained (sets1))
2191 (FLG_EVALORDERUNCON,
2193 ("Expression has undefined behavior (%q used in left operand "
2194 "may set global variable %q used in right operand): %s %s %s",
2195 sRefSet_unparseUnconstrained (sets1),
2196 sRef_unparse (e2->sref),
2197 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2201 sRefSet_realElements (e1->uses, sr)
2203 if (sRef_isMeaningful (sr) && sRefSet_member (sets2, sr))
2208 ("Expression has undefined behavior (left operand uses %q, "
2209 "modified by right operand): %s %s %s",
2211 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2214 } end_sRefSet_realElements;
2216 sRefSet_realElements (sets1, sr)
2218 if (sRef_isMeaningful (sr))
2220 if (sRef_same (sr, e2->sref))
2225 ("Expression has undefined behavior (value of right operand "
2226 "modified by left operand): %s %s %s",
2227 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2230 else if (sRefSet_member (e2->uses, sr))
2235 ("Expression has undefined behavior (left operand modifies %q, "
2236 "used by right operand): %s %s %s",
2238 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
2243 if (sRefSet_member (sets2, sr))
2245 if (sRef_isUnconstrained (sr))
2253 hadUncon = optgenerror
2254 (FLG_EVALORDERUNCON,
2256 ("Expression may have undefined behavior. Left operand "
2257 "calls %q; right operand calls %q. The unconstrained "
2258 "functions may modify global state used by "
2259 "the other operand): %s %s %s",
2260 sRefSet_unparseUnconstrained (sets1),
2261 sRefSet_unparseUnconstrained (sets2),
2262 exprNode_unparse (e1), lltok_unparse (op),
2263 exprNode_unparse (e2)),
2272 ("Expression has undefined behavior (both "
2273 "operands modify %q): %s %s %s",
2275 exprNode_unparse (e1),
2276 lltok_unparse (op), exprNode_unparse (e2)),
2282 } end_sRefSet_realElements;
2285 static void checkExpressionDefined (exprNode e1, exprNode e2, lltok op)
2287 bool hasError = FALSE;
2289 if (exprNode_isError (e1) || exprNode_isError (e2))
2294 if (sRefSet_member (e2->sets, e1->sref))
2296 if (e2->kind == XPR_CALL)
2302 hasError = optgenerror
2304 message ("Expression has undefined behavior "
2305 "(value of left operand %s is modified "
2306 "by right operand %s): %s %s %s",
2307 exprNode_unparse (e1),
2308 exprNode_unparse (e2),
2309 exprNode_unparse (e1), lltok_unparse (op),
2310 exprNode_unparse (e2)),
2315 if (context_getFlag (FLG_EVALORDERUNCON))
2317 if (sRefSet_member (e2->msets, e1->sref))
2319 if (e2->kind == XPR_CALL)
2325 hasError = optgenerror
2328 ("Expression has undefined behavior (value of left "
2329 "operand may be modified by right operand): %s %s %s",
2330 exprNode_unparse (e1), lltok_unparse (op),
2331 exprNode_unparse (e2)),
2339 checkExpressionDefinedAux (e1, e2, e1->sets, e2->sets, op, FLG_EVALORDER);
2341 if (context_maybeSet (FLG_EVALORDERUNCON))
2343 checkExpressionDefinedAux (e1, e2, e1->msets,
2344 e2->msets, op, FLG_EVALORDERUNCON);
2349 static void checkSequencing (exprNode p_f, exprNodeList p_args);
2352 checkArgsReal (uentry fcn, /*@dependent@*/ exprNode f, uentryList cl,
2353 exprNodeList args, bool isIter, exprNode ret)
2357 if (!exprNode_isError (f))
2359 if (!uentryList_isMissingParams (cl))
2361 int nargs = exprNodeList_size (args);
2362 int expectargs = uentryList_size (cl);
2366 if (expectargs == 0)
2374 message ("Iter %q invoked with %d args, "
2376 uentry_getName (fcn),
2384 message ("Function %s called with %d args, "
2386 exprNode_unparse (f), nargs),
2393 last = uentry_getType (uentryList_getN (cl, expectargs - 1));
2395 exprNodeList_reset (args);
2397 uentryList_elements (cl, current)
2399 ctype ct = uentry_getType (current);
2402 if (ctype_isElips (ct))
2405 ** do special checking for printf/scanf library functions
2407 ** this is kludgey code, just for handling the special case
2411 if (uentry_isPrintfLike (fcn))
2413 checkPrintfArgs (f, fcn, args, ret, i);
2416 else if (uentry_isScanfLike (fcn))
2418 checkScanfArgs (f, fcn, args, ret, i);
2421 else if (uentry_isMessageLike (fcn))
2423 checkMessageArgs (f, fcn, args, i);
2428 llassert (!uentry_isSpecialFunction (fcn));
2431 nargs = expectargs; /* avoid errors */
2436 if (i >= nargs) break;
2438 a = exprNodeList_current (args);
2439 exprNodeList_advance (args);
2443 if (exprNode_isError (a))
2450 probably necessary? I'm not sure about this one
2451 checkMacroParen (a);
2454 f->guards = guardSet_union (f->guards, a->guards);
2456 DPRINTF (("match arg: %s / %s", ctype_unparse (ct), ctype_unparse (a->typ)));
2458 if (!(exprNode_matchArgType (ct, a)))
2460 DPRINTF (("Args mismatch!"));
2462 if (ctype_isVoidPointer (ct)
2463 && (ctype_isPointer (a->typ)
2464 && (ctype_isRealAbstract (ctype_baseArrayPtr (a->typ)))))
2469 ("Pointer to abstract type (%t) used "
2471 "(arg %d to %q): %s",
2473 uentry_getName (fcn),
2474 exprNode_unparse (a)),
2482 (ct, exprNode_undefined,
2485 ("Iter %q expects arg %d to "
2486 "be %t gets %t: %s",
2487 uentry_getName (fcn),
2488 i, ct, a->typ, exprNode_unparse (a)),
2499 ("Function %q expects arg %d to be %t gets %t: %s",
2500 uentry_getName (fcn),
2501 i, ct, a->typ, exprNode_unparse (a)),
2504 DPRINTF (("Types: %s / %s",
2506 ctype_unparse (a->typ)));
2510 ** Clear null marker for abstract types.
2511 ** (It is not revealed, so suppress future messages.)
2514 if (ctype_isAbstract (a->typ))
2516 sRef_setNullUnknown (exprNode_getSref (a), a->loc);
2523 } end_uentryList_elements ;
2526 if (expectargs != nargs) /* note: not != since we may have ... */
2528 if (ctype_isElips (last))
2532 message ("Function %s called with %d args, expects at least %d",
2533 exprNode_unparse (f),
2534 nargs, expectargs - 1),
2543 message ("Iter %q invoked with %d args, expects %d",
2544 uentry_getName (fcn), nargs, expectargs),
2551 message ("Function %s called with %d args, expects %d",
2552 exprNode_unparse (f),
2565 ** Check for undefined code sequences in function arguments:
2567 ** one parameter sets something used by another parameter
2568 ** one parameter sets something set by another parameter
2572 checkSequencingOne (exprNode f, exprNodeList args,
2573 /*@notnull@*/ exprNode el, int argno)
2576 ** Do second loop, iff +undefunspec
2580 int numloops = context_maybeSet (FLG_EVALORDERUNCON) ? 2 : 1;
2582 for (checkloop = 0; checkloop < numloops; checkloop++)
2588 thissets = el->sets;
2592 llassert (checkloop == 1);
2593 thissets = el->msets;
2596 sRefSet_realElements (thissets, thisset)
2600 /*@access exprNodeList@*/
2601 for (j = 0; j < args->nelements; j++)
2603 exprNode jl = args->elements[j];
2604 int thisargno = j + 1;
2606 if (thisargno != argno && exprNode_isDefined (jl))
2608 sRefSet otheruses = jl->uses;
2610 if (sRef_isFileOrGlobalScope (sRef_getRootBase (jl->sref)) &&
2611 sRefSet_hasUnconstrained (thissets))
2614 (FLG_EVALORDERUNCON,
2617 ("%q used in argument %d may set "
2618 "global variable %q used by argument %d: %s(%q)",
2619 cstring_capitalizeFree (sRefSet_unparseUnconstrained (thissets)),
2622 sRef_unparse (sRef_getRootBase (jl->sref)),
2624 exprNode_unparse (f), exprNodeList_unparse (args)),
2628 if (sRefSet_member (otheruses, thisset))
2630 if (sRef_isUnconstrained (thisset))
2633 (FLG_EVALORDERUNCON,
2635 ("Unconstrained functions used in arguments %d (%q) "
2636 "and %d (%s) may modify "
2637 "or use global state in undefined way: %s(%q)",
2639 sRefSet_unparseUnconstrainedPlain (otheruses),
2641 sRef_unconstrainedName (thisset),
2642 exprNode_unparse (f),
2643 exprNodeList_unparse (args)),
2651 ("Argument %d modifies %q, used by argument %d "
2652 "(order of evaluation of actual parameters is "
2653 "undefined): %s(%q)",
2654 argno, sRef_unparse (thisset), thisargno,
2655 exprNode_unparse (f), exprNodeList_unparse (args)),
2661 sRefSet othersets = jl->sets;
2663 if (sRefSet_member (othersets, thisset))
2665 if (sRef_isUnconstrained (thisset))
2668 (FLG_EVALORDERUNCON,
2670 ("Unconstrained functions used in "
2671 "arguments %d (%q) and %d (%s) may modify "
2672 "or use global state in undefined way: %s(%q)",
2674 sRefSet_unparseUnconstrainedPlain (othersets),
2676 sRef_unconstrainedName (thisset),
2677 exprNode_unparse (f), exprNodeList_unparse (args)),
2685 ("Argument %d modifies %q, set by argument %d (order of"
2686 " evaluation of actual parameters is undefined): %s(%q)",
2687 argno, sRef_unparse (thisset), thisargno,
2688 exprNode_unparse (f), exprNodeList_unparse (args)),
2695 /*@noaccess exprNodeList@*/
2696 } end_sRefSet_realElements;
2701 checkSequencing (exprNode f, exprNodeList args)
2703 if (exprNodeList_size (args) > 1)
2708 /*@access exprNodeList*/
2710 for (i = 0; i < args->nelements; i++)
2712 el = args->elements[i];
2714 if (!exprNode_isError (el))
2716 checkSequencingOne (f, args, el, i + 1);
2719 /*@noaccess exprNodeList*/
2724 ** requires le = exprNode_getUentry (f)
2728 checkGlobMods (/*@notnull@*/ /*@dependent@*/ exprNode f,
2729 uentry le, exprNodeList args,
2730 /*@notnull@*/ exprNode ret, int specialArgs)
2732 bool isSpec = FALSE;
2733 bool hasMods = FALSE;
2735 globSet usesGlobs = globSet_undefined;
2736 sRefSet mods = sRefSet_undefined;
2737 bool freshMods = FALSE;
2738 uentryList params = uentryList_undefined;
2740 DPRINTF (("Check glob mods: %s", exprNode_unparse (ret)));
2743 ** check globals and modifies
2748 if (!uentry_isValid (le))
2750 ctype fr = ctype_realType (f->typ);
2752 if (ctype_isFunction (fr))
2754 params = ctype_argsFunction (fr);
2758 params = uentryList_missingParams;
2761 if (!context_getFlag (FLG_MODNOMODS)
2762 && !context_getFlag (FLG_GLOBUNSPEC))
2764 checkUnspecCall (f, params, args);
2770 fname = uentry_rawName (le);
2774 if (uentry_isFunction (le))
2776 params = uentry_getParams (le);
2777 mods = uentry_getMods (le);
2778 hasMods = uentry_hasMods (le);
2779 usesGlobs = uentry_getGlobs (le);
2780 isSpec = uentry_isSpecified (le);
2782 else /* not a function */
2784 ctype ct = ctype_realType (uentry_getType (le));
2786 llassertprint (uentry_isVar (le) && ctype_isFunction (ct),
2787 ("checkModGlobs: uentry not a function: %s",
2788 uentry_unparse (le)));
2790 params = ctype_argsFunction (ct);
2791 return; /*@32 ! remove this? */
2800 globSet_allElements (usesGlobs, el)
2802 if (sRef_isValid (el))
2804 if (sRef_isInternalState (el) || sRef_isSystemState (el))
2806 context_usedGlobal (el);
2807 exprNode_checkUse (f, el, f->loc);
2809 if (context_checkInternalUse ())
2811 if (!context_globAccess (el))
2813 if (sRef_isSystemState (el)
2814 && !context_getFlag (FLG_MODFILESYSTEM))
2823 ("Called procedure %s may access %q, but "
2824 "globals list does not include globals %s",
2825 exprNode_unparse (f),
2827 cstring_makeLiteralTemp (sRef_isInternalState (el)
2835 else if (sRef_isNothing (el) || sRef_isSpecState (el))
2841 uentry gle = sRef_getUentry (el);
2842 sRef sr = sRef_updateSref (el);
2844 if (sRef_isUndefGlob (el))
2846 sRef_setDefined (sr, f->loc);
2847 exprNode_checkSet (f, sr);
2855 if (sRef_isAllocated (el))
2857 exprNode_checkSet (f, sr);
2861 if (sRef_isStateUndefined (sr))
2866 ("%s %q used by function undefined before call: %s",
2867 sRef_getScopeName (sr),
2869 exprNode_unparse (f)),
2871 sRef_setDefined (sr, f->loc);
2873 exprNode_checkUse (f, sr, f->loc);
2876 checkGlobUse (gle, TRUE, f);
2879 if (sRef_isKilledGlob (el))
2881 sRef_kill (sr, f->loc);
2882 context_usedGlobal (sr);
2886 } end_globSet_allElements;
2892 if (context_hasMods () || context_getFlag (FLG_MODNOMODS))
2894 sRefSet smods = sRefSet_undefined;
2897 ** NEED to check for modifies anything
2901 ** check each sRef that called function modifies (ml), is
2907 sRefSet_allElements (mods, s) /* s is something which may be modified */
2909 DPRINTF (("Check modify: %s", sRef_unparse (s)));
2911 if (sRef_isKindSpecial (s))
2913 if (sRef_isSpecInternalState (s))
2915 if (context_getFlag (FLG_MODINTERNALSTRICT))
2917 exprNode_checkCallModifyVal (s, args, f, ret);
2921 sRefSet mmods = context_modList ();
2923 sRefSet_allElements (mmods, el)
2925 if (sRef_isInternalState (el))
2927 sRef_setModified (el);
2929 } end_sRefSet_allElements ;
2934 exprNode_checkCallModifyVal (s, args, f, ret);
2939 sRef rb = sRef_getRootBase (s);
2941 if (sRef_isFileOrGlobalScope (rb))
2943 context_usedGlobal (rb);
2946 if (sRef_isFileStatic (s)
2947 && !fileId_equal (fileloc_fileId (f->loc),
2948 fileloc_fileId (uentry_whereDefined (le))))
2950 smods = sRefSet_insert (smods, s);
2954 exprNode_checkCallModifyVal (s, args, f, ret);
2957 } end_sRefSet_allElements;
2962 ** Static elements in modifies set can have nasty consequences.
2963 ** (I think...have not been able to reproduce a possible bug.)
2966 if (!sRefSet_isDefined (smods))
2968 mods = sRefSet_newCopy (mods);
2971 sRefSet_allElements (smods, el)
2973 bool res = sRefSet_delete (mods, el);
2976 } end_sRefSet_allElements;
2978 sRefSet_free (smods);
2983 else if (sRefSet_isDefined (mods))
2984 { /* just check observers */
2987 sRefSet_allElements (mods, s) /* s is something which may be modified */
2989 sRef rb = sRef_getRootBase (s);
2993 if (sRef_isParam (rb))
2995 sRef b = sRef_fixBaseParam (s, args);
2997 if (sRef_isObserver (b))
2999 exprNode e = exprNodeList_nth (args, sRef_getParam (rb));
3003 message ("Function call may modify observer%q: %s",
3004 sRef_unparsePreOpt (b), exprNode_unparse (e)),
3007 sRef_showExpInfo (b);
3011 } end_sRefSet_allElements;
3015 if (!hasMods) /* no specified modifications */
3017 if (context_getFlag (FLG_MODOBSERVERUNCON))
3019 exprNodeList_elements (args, e)
3021 if (exprNode_isDefined (e))
3023 sRef s = exprNode_getSref (e);
3025 if (sRef_isObserver (s)
3026 && ctype_isMutable (sRef_getType (s)))
3029 (FLG_MODOBSERVERUNCON,
3031 ("Call to unconstrained function %s may modify observer%q: %s",
3032 exprNode_unparse (f),
3033 sRef_unparsePreOpt (s), exprNode_unparse (e)),
3036 sRef_showExpInfo (s);
3040 } end_exprNodeList_elements;
3045 checkAnyCall (f, fname, params, args, hasMods, mods, isSpec, specialArgs);
3047 ret->uses = sRefSet_union (ret->uses, f->uses);
3048 ret->sets = sRefSet_union (ret->sets, f->sets);
3049 ret->msets = sRefSet_union (ret->msets, f->msets);
3054 ** Spurious errors reported, because lclint can't tell
3055 ** mods must be fresh if freshMods is true.
3058 /*@i@*/ sRefSet_free (mods);
3064 void checkGlobUse (uentry glob, bool isCall, /*@notnull@*/ exprNode e)
3066 if (uentry_isVar (glob))
3068 if (context_inFunctionLike ())
3070 sRef sr = uentry_getSref (glob);
3072 context_usedGlobal (sr);
3074 if (context_checkGlobUse (glob))
3076 if (!context_globAccess (sr))
3082 message ("Called procedure %s may access %s %q",
3083 exprNode_unparse (e),
3084 sRef_unparseScope (sr),
3085 uentry_getName (glob)),
3092 message ("Undocumented use of %s %s",
3093 sRef_unparseScope (sr),
3094 exprNode_unparse (e)),
3103 llbug (message ("Global not variable: %q", uentry_unparse (glob)));
3108 reflectEnsuresClause (exprNode ret, uentry le, exprNode f, exprNodeList args)
3110 DPRINTF (("Reflect ensures clause: %s(%s) / %s / %s",
3111 exprNode_unparse (f), exprNodeList_unparse (args),
3112 uentry_unparseFull (le),
3113 stateClauseList_unparse (uentry_getStateClauseList (le))));
3115 if (uentry_isValid (le) && uentry_isFunction (le))
3117 stateClauseList sclauses = uentry_getStateClauseList (le);
3119 if (stateClauseList_isDefined (sclauses))
3121 DPRINTF (("Reflect ensures: %s / %s / %s",
3122 uentry_unparse (le),
3123 exprNode_unparse (f), exprNodeList_unparse (args)));
3125 stateClauseList_elements (sclauses, cl)
3127 if (stateClause_hasEnsures (cl))
3129 /* Same in usymtab.c:1904 */
3130 if (stateClause_setsMetaState (cl))
3132 qual q = stateClause_getMetaQual (cl);
3133 annotationInfo ainfo = qual_getAnnotationInfo (q);
3134 metaStateInfo minfo = annotationInfo_getState (ainfo);
3135 cstring key = metaStateInfo_getName (minfo);
3136 int mvalue = annotationInfo_getValue (ainfo);
3138 sRefSet osrs = sRefSet_undefined;
3141 if (stateClause_isGlobal (cl))
3143 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3148 srs = stateClause_getRefs (cl);
3151 DPRINTF (("Reflect ensures clause: %s", stateClause_unparse (cl)));
3154 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
3156 sRefSet_elements (srs, sel)
3160 if (sRef_isResult (sRef_getRootBase (sel)))
3162 s = exprNode_getSref (ret);
3166 s = sRef_fixBaseParam (sel, args);
3169 DPRINTF (("Reflecting state clause on: %s / %s",
3170 sRef_unparse (sel), sRef_unparse (s)));
3172 sRef_setMetaStateValueComplete (s, key, mvalue, exprNode_loc (f));
3173 } end_sRefSet_elements;
3175 sRefSet_free (osrs);
3179 sRefSet srs = stateClause_getRefs (cl);
3180 sRefModVal modf = stateClause_getEnsuresFunction (cl);
3181 int eparam = stateClause_getStateParameter (cl);
3183 DPRINTF (("Reflect after clause: %s / %s",
3184 stateClause_unparse (cl),
3185 sRefSet_unparse (srs)));
3187 sRefSet_elements (srs, sel)
3191 DPRINTF (("elements: %s", sRef_unparse (sel)));
3192 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3194 if (sRef_isResult (sRef_getRootBase (sel)))
3196 DPRINTF (("Fix base: %s / %s",
3197 sRef_unparse (sel), sRef_unparse (exprNode_getSref (ret))));
3198 s = sRef_fixBase (sel, exprNode_getSref (ret));
3199 DPRINTF (("==> %s", sRef_unparseFull (s)));
3203 s = sRef_fixBaseParam (sel, args);
3206 DPRINTF (("elements: %s", sRef_unparse (s)));
3207 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3209 DPRINTF (("Reflecting state clause on: %s / %s",
3210 sRef_unparseFull (sel), sRef_unparseFull (s)));
3212 /* evans 2001-08-24 - added aliasSetCompleteParam */
3213 sRef_aliasSetCompleteParam (modf, s, eparam, exprNode_loc (f));
3215 DPRINTF (("After reflecting state clause on: %s / %s",
3216 sRef_unparseFull (sel), sRef_unparseFull (s)));
3217 } end_sRefSet_elements;
3220 } end_stateClauseList_elements ;
3223 DPRINTF (("Here: %s / %s",
3224 uentry_unparseFull (le),
3225 bool_unparse (uentry_hasMetaStateEnsures (le))));
3227 if (uentry_hasMetaStateEnsures (le))
3229 fileloc loc = exprNode_loc (f);
3231 metaStateConstraintList mscl = uentry_getMetaStateEnsures (le);
3233 metaStateConstraintList_elements (mscl, msc)
3235 metaStateSpecifier msspec = metaStateConstraint_getSpecifier (msc);
3236 metaStateInfo msinfo = metaStateSpecifier_getMetaStateInfo (msspec);
3237 metaStateExpression msexpr = metaStateConstraint_getExpression (msc);
3238 cstring key = metaStateInfo_getName (msinfo);
3239 sRef mlsr = metaStateSpecifier_getSref (msspec);
3241 sRef lastref = sRef_undefined;
3242 stateValue sval = stateValue_undefined;
3244 DPRINTF (("Meta state constraint for %s: %s", uentry_unparse (le),
3245 metaStateConstraint_unparse (msc)));
3246 DPRINTF (("Matches left: %s", sRef_unparseDebug (mlsr)));
3248 if (sRef_isResult (sRef_getRootBase (mlsr)))
3250 s = exprNode_getSref (ret);
3254 s = sRef_fixBaseParam (mlsr, args);
3257 DPRINTF (("Setting state: %s", sRef_unparseFull (s)));
3259 while (metaStateExpression_isDefined (msexpr))
3261 metaStateSpecifier ms = metaStateExpression_getSpecifier (msexpr);
3262 metaStateInfo msi = metaStateSpecifier_getMetaStateInfo (ms);
3265 DPRINTF (("Check expression: %s", metaStateExpression_unparse (msexpr)));
3267 if (metaStateExpression_isMerge (msexpr))
3269 msexpr = metaStateExpression_getRest (msexpr);
3273 msexpr = metaStateExpression_undefined;
3276 if (metaStateInfo_isDefined (msi))
3278 /* Must match lhs state */
3279 llassert (metaStateInfo_equal (msinfo, msi));
3282 if (metaStateSpecifier_isElipsis (ms))
3285 ** For elipsis, we need to merge all the relevant elipsis parameters
3289 uentryList params = uentry_getParams (le);
3290 int paramno = uentryList_size (params) - 1;
3292 if (!uentry_isElipsisMarker (uentryList_getN (params, paramno)))
3296 message ("Ensures clauses uses ... for function without ... in parameter list: %q",
3297 uentry_getName (le)),
3298 uentry_whereLast (le));
3299 /*@innerbreak@*/ break;
3302 while (paramno < exprNodeList_size (args))
3304 exprNode arg = exprNodeList_getN (args, paramno);
3305 fs = exprNode_getSref (arg);
3306 DPRINTF (("Merge arg: %s", exprNode_unparse (arg)));
3308 /* cut and pasted... gack*/
3309 if (stateValue_isDefined (sval))
3311 /* Use combination table to merge old state value with new one: */
3312 stateValue tval = sRef_getMetaStateValue (fs, key);
3314 if (stateValue_isDefined (tval))
3316 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3317 cstring msg = cstring_undefined;
3318 int nval = stateCombinationTable_lookup (sctable,
3319 stateValue_getValue (sval),
3320 stateValue_getValue (tval),
3322 DPRINTF (("Combining: %s + %s -> %d",
3323 stateValue_unparseValue (sval, msinfo),
3324 stateValue_unparseValue (tval, msinfo),
3327 if (nval == stateValue_error)
3332 ("Attributes merged in ensures clause in states that "
3333 "cannot be combined (%q is %q, %q is %q)%q",
3334 sRef_unparse (lastref),
3335 stateValue_unparseValue (sval, msinfo),
3337 stateValue_unparseValue (tval, msinfo),
3338 cstring_isDefined (msg) ?
3339 message (": %s", msg) : cstring_undefined),
3342 sRef_showMetaStateInfo (fs, key);
3346 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3347 loc = exprNode_loc (arg);
3351 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3356 sval = sRef_getMetaStateValue (fs, key);
3361 if (stateValue_isError (sval))
3363 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3372 msr = metaStateSpecifier_getSref (ms);
3375 llassert (sRef_isParam (sRef_getRootBase (msr)));
3376 fs = sRef_fixBaseParam (msr, args);
3378 if (stateValue_isDefined (sval))
3380 /* Use combination table to merge old state value with new one: */
3381 stateValue tval = sRef_getMetaStateValue (fs, key);
3383 if (stateValue_isDefined (tval))
3385 stateCombinationTable sctable = metaStateInfo_getMergeTable (msinfo);
3386 cstring msg = cstring_undefined;
3387 int nval = stateCombinationTable_lookup (sctable,
3388 stateValue_getValue (sval),
3389 stateValue_getValue (tval),
3391 DPRINTF (("Combining: %s + %s -> %d",
3392 stateValue_unparseValue (sval, msinfo),
3393 stateValue_unparseValue (tval, msinfo),
3396 if (nval == stateValue_error)
3401 ("Attributes merged in ensures clause in states that "
3402 "cannot be combined (%q is %q, %q is %q)%q",
3403 sRef_unparse (lastref),
3404 stateValue_unparseValue (sval, msinfo),
3406 stateValue_unparseValue (tval, msinfo),
3407 cstring_isDefined (msg)
3408 ? message (": %s", msg) : cstring_undefined),
3411 sRef_showMetaStateInfo (fs, key);
3415 stateValue_updateValueLoc (sval, nval, fileloc_undefined);
3419 DPRINTF (("No value for: %s:%s", sRef_unparse (fs), key));
3424 sval = sRef_getMetaStateValue (fs, key);
3429 if (stateValue_isError (sval))
3431 /*@innerbreak@*/ break; /* Don't merge any more values if here was an error */
3436 DPRINTF (("Setting: %s:%s <- %s", sRef_unparse (s), key, stateValue_unparse (sval)));
3438 if (stateValue_isDefined (sval))
3440 sRef_setMetaStateValueComplete (s, key, stateValue_getValue (sval), loc);
3444 DPRINTF (("Undefined state: %s", cstring_toCharsSafe (sRef_unparse (s))));
3446 } end_metaStateConstraintList_elements ;
3448 metaStateConstraintList_free (mscl);
3454 checkRequiresClause (uentry le, exprNode f, exprNodeList args)
3456 DPRINTF (("Check requires clause: %s(%s) / %s / %s",
3457 exprNode_unparse (f), exprNodeList_unparse (args),
3458 uentry_unparseFull (le),
3459 stateClauseList_unparse (uentry_getStateClauseList (le))));
3461 if (uentry_isValid (le) && uentry_isFunction (le))
3463 stateClauseList sclauses = uentry_getStateClauseList (le);
3465 if (stateClauseList_isDefined (sclauses))
3467 DPRINTF (("Check requires: %s / %s / %s",
3468 uentry_unparse (le),
3469 exprNode_unparse (f), exprNodeList_unparse (args)));
3471 stateClauseList_elements (sclauses, cl)
3473 DPRINTF (("Check clause: %s / %s",
3474 stateClause_unparse (cl),
3475 bool_unparse (stateClause_hasRequires (cl))));
3477 if (stateClause_hasRequires (cl))
3479 sRefSet osrs = sRefSet_undefined;
3482 if (stateClause_isGlobal (cl))
3484 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
3489 srs = stateClause_getRefs (cl);
3492 DPRINTF (("Refs: %s", sRefSet_unparse (srs)));
3494 if (stateClause_setsMetaState (cl))
3496 qual q = stateClause_getMetaQual (cl);
3497 annotationInfo ainfo = qual_getAnnotationInfo (q);
3498 metaStateInfo minfo = annotationInfo_getState (ainfo);
3499 cstring key = metaStateInfo_getName (minfo);
3500 int mvalue = annotationInfo_getValue (ainfo);
3502 DPRINTF (("Requires meta state! %s = %d", key, mvalue));
3504 sRefSet_elements (srs, sel)
3506 sRef s = sRef_fixBaseParam (sel, args);
3508 if (sRef_isResult (sRef_getRootBase (sel)))
3514 DPRINTF (("Checking state clause on: %s / %s / %s = %d",
3515 sRef_unparseFull (sel), sRef_unparseFull (s),
3518 if (!sRef_checkMetaStateValue (s, key, mvalue))
3520 DPRINTF (("HERE: %s", sRef_unparse (s)));
3524 ("Requires clause of called function %q not satisfied%q (state is %q): %q",
3525 uentry_getName (le),
3526 sRef_isGlobalMarker (s)
3528 : message (" by %q", sRef_unparse (s)),
3529 stateValue_unparseValue (sRef_getMetaStateValue (s, key),
3531 stateClause_unparse (cl)),
3534 sRef_showAliasInfo (s);
3538 DPRINTF (("Error supressed!"));
3539 DPRINTF (("Loc: %s", fileloc_unparse (exprNode_loc (f))));
3540 DPRINTF (("Context supress: %s",
3541 bool_unparse (context_suppressFlagMsg (FLG_STATETRANSFER, exprNode_loc (f)))));
3545 } end_sRefSet_elements;
3549 sRefModVal modf = stateClause_getRequiresBodyFunction (cl);
3550 int eparam = stateClause_getStateParameter (cl);
3552 DPRINTF (("Reflect after clause: %s / %s",
3553 stateClause_unparse (cl),
3554 sRefSet_unparse (srs)));
3556 sRefSet_elements (srs, sel)
3560 DPRINTF (("elements: %s", sRef_unparse (sel)));
3561 DPRINTF (("elements: %s", sRef_unparseFull (sel)));
3563 s = sRef_fixBaseParam (sel, args);
3565 DPRINTF (("elements: %s", sRef_unparse (s)));
3566 DPRINTF (("elements: %s", sRef_unparseFull (s)));
3568 if (sRef_isResult (sRef_getRootBase (sel)))
3570 ; /*@i423 what do we do about results */
3574 DPRINTF (("Reflecting state clause on: %s / %s",
3575 sRef_unparse (sel), sRef_unparse (s)));
3577 modf (s, eparam, exprNode_loc (f));
3579 } end_sRefSet_elements;
3582 sRefSet_free (osrs);
3584 } end_stateClauseList_elements ;
3589 static /*@only@*/ exprNode
3590 functionCallSafe (/*@only@*/ /*@notnull@*/ exprNode f,
3591 ctype t, /*@keep@*/ exprNodeList args)
3593 /* requires f is a non-error exprNode, with type function */
3594 cstring fname = exprNode_unparse (f);
3595 uentry le = exprNode_getUentry (f);
3596 exprNode ret = exprNode_createPartialCopy (f);
3601 DPRINTF (("Call: %s %s",exprNode_unparse (f), exprNodeList_unparse (args)));
3603 ret->typ = ctype_getReturnType (t);
3604 ret->kind = XPR_CALL;
3606 ret->edata = exprData_makeCall (f, args);
3609 ** Order of these steps is very important!
3611 ** Must check for argument dependencies before messing up uses and sets.
3614 if (context_getFlag (FLG_EVALORDER))
3616 exprNodeList_elements (args, current)
3618 if (exprNode_isDefined (current))
3620 exprNode_addUse (current, current->sref);
3622 } end_exprNodeList_elements;
3624 if (context_maybeSet (FLG_EVALORDER) || context_maybeSet (FLG_EVALORDERUNCON))
3626 checkSequencing (f, args);
3629 exprNodeList_elements (args, current)
3631 if (exprNode_isDefined (current) && sRef_isMeaningful (current->sref))
3633 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3635 } end_exprNodeList_elements ;
3638 special = checkArgs (le, f, t, args, ret);
3639 checkGlobMods (f, le, args, ret, special);
3640 checkRequiresClause (le, f, args);
3643 if (uentry_isValid (le)
3644 && (uentry_isFunction (le)
3645 || (uentry_isVariable (le)
3646 && ctype_isFunction (uentry_getType (le)))))
3648 exitkind exk = uentry_getExitCode (le);
3650 /* f->typ is already set to the return type */
3652 DPRINTF (("Function: %s", uentry_unparseFull (le)));
3653 ret->sref = uentry_returnedRef (le, args);
3654 DPRINTF (("Returned: %s / %s",
3655 uentry_unparseFull (le),
3656 sRef_unparseFull (ret->sref)));
3658 if (uentry_isFunction (le) && exprNodeList_size (args) >= 1)
3660 qual nullPred = uentry_nullPred (le);
3662 if (qual_isTrueNull (nullPred))
3664 exprNode arg = exprNodeList_head (args);
3666 if (exprNode_isDefined (arg))
3668 ret->guards = guardSet_addFalseGuard (ret->guards, arg->sref);
3671 else if (qual_isFalseNull (nullPred))
3673 exprNode arg = exprNodeList_head (args);
3675 if (exprNode_isDefined (arg))
3677 ret->guards = guardSet_addTrueGuard (ret->guards, arg->sref);
3682 llassert (qual_isUnknown (nullPred));
3686 if (exitkind_isConditionalExit (exk))
3690 ** if (arg0) then { exit! } else { ; }
3692 ** if (arg0) then { ; } else { exit! }
3697 llassert (!exprNodeList_isEmpty (args));
3698 firstArg = exprNodeList_head (args);
3700 if (exprNode_isDefined (firstArg)
3701 && !guardSet_isEmpty (firstArg->guards))
3703 usymtab_trueBranch (guardSet_undefined);
3704 usymtab_altBranch (guardSet_undefined);
3706 if (exitkind_isTrueExit (exk))
3708 usymtab_popBranches (firstArg,
3709 exprNode_makeMustExit (),
3711 TRUE, TRUEEXITCLAUSE);
3715 usymtab_popBranches (firstArg,
3717 exprNode_makeMustExit (),
3718 TRUE, FALSEEXITCLAUSE);
3722 ret->exitCode = XK_MAYEXIT;
3724 else if (exitkind_mustExit (exk))
3726 ret->exitCode = XK_MUSTEXIT;
3728 else if (exitkind_couldExit (exk))
3730 ret->exitCode = XK_MAYEXIT;
3737 if (cstring_equalLit (fname, "exit"))
3739 if (exprNodeList_size (args) == 1)
3741 exprNode arg = exprNodeList_head (args);
3743 if (exprNode_isDefined (arg) && exprNode_knownIntValue (arg))
3745 long int val = multiVal_forceInt (exprNode_getValue (arg));
3752 ("Argument to exit has implementation defined behavior: %s",
3753 exprNode_unparse (arg)),
3754 exprNode_loc (arg));
3763 exprNode_checkSetAny (ret, uentry_rawName (le));
3766 DPRINTF (("Before reflect: %s", sRef_unparseFull (ret->sref)));
3767 DPRINTF (("Reflect: %s", uentry_unparseFull (le)));
3768 reflectEnsuresClause (ret, le, f, args);
3775 ** this is yucky! should keep the uentry as part of exprNode!
3778 uentry exprNode_getUentry (exprNode e)
3780 if (exprNode_isError (e))
3782 return uentry_undefined;
3786 cstring s = exprNode_rootVarName (e);
3787 uentry ue = usymtab_lookupSafe (s);
3794 exprNode_makeInitBlock (lltok brace, /*@only@*/ exprNodeList inits)
3796 exprNode ret = exprNode_createPlain (ctype_unknown);
3798 ret->kind = XPR_INITBLOCK;
3799 ret->edata = exprData_makeCall (exprNode_undefined, inits);
3800 ret->loc = fileloc_update (ret->loc, lltok_getLoc (brace));
3806 exprNode_functionCall (/*@only@*/ exprNode f, /*@only@*/ exprNodeList args)
3812 if (exprNode_isUndefined (f))
3815 exprNodeList_free (args);
3816 return exprNode_undefined;
3819 t = exprNode_getType (f);
3821 if (sRef_isLocalVar (f->sref))
3823 exprNode_checkUse (f, f->sref, f->loc);
3825 if (sRef_possiblyNull (f->sref))
3827 if (!usymtab_isGuarded (f->sref))
3829 if (optgenerror (FLG_NULLDEREF,
3830 message ("Function call using %s pointer %q",
3831 sRef_nullMessage (f->sref),
3832 sRef_unparse (f->sref)),
3835 sRef_showNullInfo (f->sref);
3836 sRef_setNullError (f->sref);
3844 if (ctype_isRealFunction (t))
3846 exprNode ret = functionCallSafe (f, t, args);
3850 else if (ctype_isUnknown (t))
3852 exprNode ret = exprNode_createPartialCopy (f);
3858 exprNodeList_elements (args, current)
3860 if (exprNode_isDefined (current))
3862 exprNode_checkUse (ret, current->sref, ret->loc);
3865 ** also, anything derivable from current->sref may be used
3868 exprNode_addUse (ret, sRef_makeDerived (current->sref));
3869 exprNode_mergeUSs (ret, current);
3871 } end_exprNodeList_elements;
3873 ret->edata = exprData_makeCall (f, args);
3874 ret->kind = XPR_CALL;
3876 tstring = cstring_copy (exprNode_unparse (f));
3878 cstring_markOwned (tstring);
3879 exprNode_checkSetAny (ret, tstring);
3885 voptgenerror (FLG_TYPE,
3886 message ("Call to non-function (type %t): %s", t,
3887 exprNode_unparse (f)),
3890 exprNodeList_free (args);
3892 return (exprNode_makeError ());
3897 exprNode_fieldAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
3898 /*@only@*/ cstring f)
3900 exprNode ret = exprNode_createPartialCopy (s);
3902 ret->kind = XPR_FACCESS;
3904 if (exprNode_isError (s))
3906 ret->edata = exprData_makeField (s, f);
3911 ctype t = exprNode_getType (s);
3912 ctype tr = ctype_realType (t);
3914 checkMacroParen (s);
3916 ret->edata = exprData_makeField (s, f);
3918 if (ctype_isStructorUnion (tr))
3920 uentry tf = uentryList_lookupField (ctype_getFields (tr), f);
3922 if (uentry_isUndefined (tf))
3924 voptgenerror (FLG_TYPE,
3925 message ("Access non-existent field %s of %t: %s", f, t,
3926 exprNode_unparse (ret)),
3928 /*! cstring_free (f); */ /* evans 2001-03-25 self-detect */
3933 uentry_setUsed (tf, exprNode_loc (ret));
3935 ret->typ = uentry_getType (tf);
3936 checkSafeUse (ret, s->sref);
3938 ret->sref = sRef_makeField (s->sref, uentry_rawName (tf));
3939 /*!? exprNode_free (s); */ /* evans 2001-03-25 self-detect */
3943 else /* isStructorUnion */
3945 if (ctype_isRealAbstract (tr))
3949 message ("Access field of abstract type (%t): %s.%s",
3950 t, exprNode_unparse (s), f),
3952 ret->typ = ctype_unknown;
3956 if (ctype_isKnown (tr))
3961 ("Access field of non-struct or union (%t): %s.%s",
3962 t, exprNode_unparse (s), f),
3965 ret->typ = ctype_unknown;
3969 cstring sn = cstring_copy (f);
3971 checkSafeUse (ret, s->sref);
3972 cstring_markOwned (sn);
3973 ret->sref = sRef_makeField (s->sref, sn);
3985 exprNode_fieldAccess (/*@only@*/ exprNode s, /*@only@*/ lltok dot,
3986 /*@only@*/ cstring f)
3988 exprNode res = exprNode_fieldAccessAux (s, lltok_getLoc (dot), f);
3989 lltok_release (dot);
3994 exprNode_addParens (/*@only@*/ lltok lpar, /*@only@*/ exprNode e)
3996 exprNode ret = exprNode_createPartialCopy (e);
3998 ret->loc = fileloc_update (ret->loc, lltok_getLoc (lpar));
3999 ret->kind = XPR_PARENS;
4000 ret->edata = exprData_makeUop (e, lpar);
4002 if (!exprNode_isError (e))
4004 ret->exitCode = e->exitCode;
4005 ret->canBreak = e->canBreak;
4006 ret->mustBreak = e->mustBreak;
4007 ret->isJumpPoint = e->isJumpPoint;
4008 ret->sref = e->sref;
4015 exprNode_arrowAccessAux (/*@only@*/ exprNode s, /*@observer@*/ fileloc loc,
4016 /*@only@*/ cstring f)
4018 exprNode ret = exprNode_createPartialCopy (s);
4020 ret->edata = exprData_makeField (s, f);
4021 ret->kind = XPR_ARROW;
4023 if (exprNode_isError (s))
4029 ctype t = exprNode_getType (s);
4030 ctype tr = ctype_realType (t);
4032 checkMacroParen (s);
4034 (void) ctype_fixArrayPtr (tr); /* REWRITE THIS */
4036 if (ctype_isRealPointer (tr))
4038 ctype b = ctype_realType (ctype_baseArrayPtr (tr));
4040 if (ctype_isStructorUnion (b))
4042 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4044 if (sRef_isKnown (s->sref) && sRef_possiblyNull (s->sref))
4046 if (!usymtab_isGuarded (s->sref) && !context_inProtectVars ())
4050 message ("Arrow access from %s pointer%q: %s",
4051 sRef_nullMessage (s->sref),
4052 sRef_unparsePreOpt (s->sref),
4053 exprNode_unparse (ret)),
4056 sRef_showNullInfo (s->sref);
4057 sRef_setNullError (s->sref);
4062 if (uentry_isUndefined (fentry))
4066 message ("Access non-existent field %s of %t: %s",
4067 f, t, exprNode_unparse (ret)),
4069 ret->typ = ctype_unknown;
4075 ** was safeUse: shouldn't be safe!
4078 ** rec must be defined,
4079 ** *rec must be allocated
4080 ** rec->field need only be defined it if is an rvalue
4083 uentry_setUsed (fentry, exprNode_loc (ret));
4084 ret->typ = uentry_getType (fentry);
4086 exprNode_checkUse (ret, s->sref, s->loc);
4088 /* exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc); */
4089 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4093 else /* Pointer to something that is not a struct or union*/
4095 if (ctype_isRealAbstract (tr))
4097 ctype xrt = ctype_forceRealType (tr);
4101 message ("Arrow access field of abstract type (%t): %s->%s",
4102 t, exprNode_unparse (s), f),
4106 ** Set the state correctly, as if the abstraction is broken.
4109 if (ctype_isRealPointer (xrt) &&
4110 (b = ctype_realType (ctype_baseArrayPtr (xrt)),
4111 ctype_isStructorUnion (b)))
4113 uentry fentry = uentryList_lookupField (ctype_getFields (b), f);
4114 ret->typ = uentry_getType (fentry);
4115 ret->sref = sRef_makeArrow (s->sref, uentry_rawName (fentry));
4119 ret->typ = ctype_unknown;
4120 ret->sref = sRef_undefined;
4123 else /* not a struct, union or abstract */
4125 if (ctype_isUnknown (tr)) {
4126 cstring sn = cstring_copy (f);
4128 DPRINTF (("Here: %s", exprNode_unparse (s)));
4130 exprNode_checkUse (ret, s->sref, s->loc);
4131 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4133 cstring_markOwned (sn);
4134 ret->sref = sRef_makeArrow (s->sref, sn);
4136 ret->kind = XPR_ARROW;
4141 message ("Arrow access field of non-struct or union "
4142 "pointer (%t): %s->%s",
4143 t, exprNode_unparse (s), f),
4146 ret->typ = ctype_unknown;
4147 ret->sref = sRef_undefined;
4152 else /* its not a pointer */
4154 if (!ctype_isUnknown (tr))
4158 message ("Arrow access of non-pointer (%t): %s->%s",
4159 t, exprNode_unparse (s), f),
4162 ret->typ = ctype_unknown;
4163 ret->sref = sRef_undefined;
4167 cstring sn = cstring_copy (f);
4169 DPRINTF (("Here: %s", exprNode_unparse (s)));
4171 exprNode_checkUse (ret, s->sref, s->loc);
4172 exprNode_checkUse (ret, sRef_makePointer (s->sref), s->loc);
4174 cstring_markOwned (sn);
4175 ret->sref = sRef_makeArrow (s->sref, sn);
4177 ret->kind = XPR_ARROW;
4188 exprNode_arrowAccess (/*@only@*/ exprNode s,
4189 /*@only@*/ lltok arrow,
4190 /*@only@*/ cstring f)
4192 exprNode res = exprNode_arrowAccessAux (s, lltok_getLoc (arrow), f);
4193 lltok_release (arrow);
4198 ** only postOp's in C: i++ and i--
4202 exprNode_postOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4204 /* check modification also */
4205 /* cstring opname = lltok_unparse (op);*/
4207 exprNode ret = exprNode_createPartialCopy (e);
4209 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4210 ret->kind = XPR_POSTOP;
4211 ret->edata = exprData_makeUop (e, op);
4213 if (!exprNode_isDefined (e))
4218 checkMacroParen (e);
4220 exprNode_checkUse (ret, e->sref, e->loc);
4221 exprNode_checkSet (ret, e->sref);
4223 t = exprNode_getType (e);
4225 if (sRef_isUnsafe (e->sref))
4227 voptgenerror (FLG_MACROPARAMS,
4228 message ("Operand of %s is macro parameter (non-functional): %s%s",
4229 lltok_unparse (op), exprNode_unparse (e), lltok_unparse (op)),
4231 sRef_makeSafe (e->sref);
4232 sRef_makeSafe (ret->sref);
4235 if (ctype_isForceRealNumeric (&t) || ctype_isRealAP (t))
4241 if (ctype_isRealAbstract (t))
4245 message ("Operand of %s is abstract type (%t): %s",
4246 lltok_unparse (op), t, exprNode_unparse (e)),
4253 message ("Operand of %s is non-numeric (%t): %s",
4254 lltok_unparse (op), t, exprNode_unparse (e)),
4257 ret->typ = ctype_unknown;
4260 /* if (ctype_isZero (t)) e->typ = ctype_int; */
4262 exprNode_checkModify (e, ret);
4264 /* added 7/11/2000 D.L */
4266 /*DRL 6/8/01 I decided to disable all LCLint Warning here since the code
4267 probably needs a rewrite any way */
4272 /* updateEnvironmentForPostOp (e); */
4274 /* start modifications */
4275 /* added by Seejo on 4/16/2000 */
4277 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4279 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4281 ret->sref = sRef_copy (e->sref);
4284 if (lltok_getTok (op) == INC_OP) {
4285 if (sRef_getSize(e->sref) > 0) {
4287 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4289 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4290 /* Assumption: there is only 1 \0 in the buffer */
4291 /* This will not be correct if there are 2 \0's in the buffer */
4292 sRef_setNotNullTerminatedState(ret->sref);
4293 sRef_resetLen(ret->sref);
4295 sRef_setNullTerminatedState(ret->sref);
4296 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4298 if (sRef_isNullTerminated (ret->sref))
4299 printf ("ret->sref is Null Terminated\n");
4300 else if (sRef_isPossiblyNullTerminated (ret->sref))
4301 printf ("ret->sref is Possibly Null Terminated\n");
4302 else if (sRef_isNotNullTerminated (ret->sref))
4303 printf ("ret->sref is Not Null Terminated\n");
4308 if (lltok_getTok (op) == DEC_OP) {
4309 if (sRef_getSize(e->sref) >= 0) {
4310 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4311 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4316 /* end modifications */
4322 exprNode_preOp (/*@only@*/ exprNode e, /*@only@*/ lltok op)
4324 bool checkMod = FALSE;
4326 int opid = lltok_getTok (op);
4327 exprNode ret = exprNode_createSemiCopy (e);
4329 exprNode_copySets (ret, e);
4331 multiVal_free (ret->val);
4332 ret->val = multiVal_undefined;
4333 ret->loc = fileloc_update (ret->loc, lltok_getLoc (op));
4334 ret->kind = XPR_PREOP;
4335 ret->edata = exprData_makeUop (e, op);
4337 if (exprNode_isError (e))
4342 checkMacroParen (e);
4344 te = exprNode_getType (e);
4345 tr = ctype_realType (te);
4347 if (opid != TAMPERSAND)
4349 exprNode_checkUse (ret, e->sref, e->loc);
4351 if (ctype_isRealAbstract (tr)
4352 && (!(ctype_isRealBool (te) && (opid == TEXCL))))
4354 if (optgenerror (FLG_ABSTRACT,
4355 message ("Operand of %s is abstract type (%t): %s",
4356 lltok_unparse (op), tr,
4357 exprNode_unparse (ret)),
4360 tr = te = ctype_unknown;
4361 ret->typ = ctype_unknown;
4362 sRef_setNullError (e->sref);
4370 case DEC_OP: /* should also check modification! */
4371 if (sRef_isMacroParamRef (e->sref))
4375 message ("Operand of %s is macro parameter (non-functional): %s",
4376 lltok_unparse (op), exprNode_unparse (ret)),
4381 exprNode_checkSet (ret, e->sref);
4384 if (ctype_isForceRealNumeric (&tr) || ctype_isRealAP (tr))
4389 if (context_msgStrictOps ())
4393 message ("Operand of %s is non-numeric (%t): %s",
4394 lltok_unparse (op), te, exprNode_unparse (ret)),
4397 ret->typ = ctype_int;
4400 /* start modifications */
4401 /* added by Seejo on 4/16/2000 */
4403 /* Arithmetic operations on pointers wil modify the size/len/null terminated
4405 if ((sRef_isPossiblyNullTerminated (e->sref)) || (sRef_isNullTerminated(e->sref))) {
4407 ret->sref = sRef_copy (e->sref);
4410 if (lltok_getTok (op) == INC_OP) {
4411 if (sRef_getSize(e->sref) > 0) {
4413 sRef_setSize (ret->sref, sRef_getSize(e->sref) - 1);
4415 if (sRef_getLen(e->sref) == 1) { /* i.e. the first character is \0 */
4416 /* Assumption: there is only 1 \0 in the buffer */
4417 /* This will not be correct if there are 2 \0's in the buffer */
4418 sRef_setNotNullTerminatedState(ret->sref);
4419 sRef_resetLen (ret->sref);
4421 sRef_setNullTerminatedState(ret->sref);
4422 sRef_setLen (ret->sref, sRef_getLen(e->sref) - 1);
4428 if (lltok_getTok (op) == DEC_OP) {
4429 if (sRef_getSize(e->sref) >= 0) {
4430 sRef_setSize (ret->sref, sRef_getSize(e->sref) + 1);
4431 sRef_setLen (ret->sref, sRef_getLen(e->sref) + 1);
4436 /* end modifications */
4443 if (ctype_isForceRealNumeric (&tr))
4447 ret->val = multiVal_invert (exprNode_getValue (e));
4451 ret->val = multiVal_copy (exprNode_getValue (e));
4456 if (context_msgStrictOps ())
4460 message ("Operand of %s is non-numeric (%t): %s",
4461 lltok_unparse (op), te, exprNode_unparse (ret)),
4465 ret->typ = ctype_int;
4469 case TEXCL: /* maybe this should be restricted */
4470 guardSet_flip (ret->guards);
4472 if (ctype_isRealBool (te) || ctype_isUnknown (te))
4478 if (ctype_isRealPointer (tr))
4480 if (sRef_isKnown (e->sref))
4482 ret->guards = guardSet_addFalseGuard (ret->guards, e->sref);
4486 (FLG_BOOLOPS, FLG_PTRNEGATE,
4487 message ("Operand of %s is non-boolean (%t): %s",
4488 lltok_unparse (op), te, exprNode_unparse (ret)),
4495 message ("Operand of %s is non-boolean (%t): %s",
4496 lltok_unparse (op), te, exprNode_unparse (ret)),
4500 ret->typ = ctype_bool;
4505 if (ctype_isForceRealInt (&tr))
4510 if (context_msgStrictOps ())
4514 message ("Operand of %s is non-integer (%t): %s",
4515 lltok_unparse (op), te, exprNode_unparse (ret)),
4519 if (ctype_isInt (e->typ))
4525 ret->typ = ctype_int;
4531 ret->typ = ctype_makePointer (e->typ);
4533 if (sRef_isKnown (e->sref))
4535 ret->sref = sRef_makeAddress (e->sref);
4542 if (ctype_isAP (tr))
4544 ret->typ = ctype_baseArrayPtr (e->typ);
4548 if (ctype_isKnown (te))
4550 if (ctype_isFunction (te))
4556 message ("Dereference of function type (%t): %s",
4557 te, exprNode_unparse (ret)),
4562 voptgenerror (FLG_TYPE,
4563 message ("Dereference of non-pointer (%t): %s",
4564 te, exprNode_unparse (ret)),
4566 ret->typ = ctype_unknown;
4571 ret->typ = ctype_unknown;
4576 if (sRef_isKnown (e->sref))
4578 DPRINTF (("Checking possibly null: %s", sRef_unparseFull (e->sref)));
4580 if (sRef_possiblyNull (e->sref))
4582 DPRINTF (("Checking possibly null: %s", sRef_unparse (e->sref)));
4583 if (!usymtab_isGuarded (e->sref) && !context_inProtectVars ())
4587 message ("Dereference of %s pointer %q: %s",
4588 sRef_nullMessage (e->sref),
4589 sRef_unparse (e->sref),
4590 exprNode_unparse (ret)),
4593 sRef_showNullInfo (e->sref);
4594 sRef_setNotNull (e->sref, e->loc); /* suppress future messages */
4599 ret->sref = sRef_makePointer (e->sref);
4604 llbug (message ("exprNode_preOp: unhandled op: %s", lltok_unparse (op)));
4609 exprNode_checkModify (e, ret);
4616 ** any reason to disallow sizeof (abstract type) ?
4620 ** used by both sizeof
4624 ctype sizeof_resultType (void)
4626 static ctype sizet = ctype_unknown;
4628 if (ctype_isUnknown (sizet))
4630 if (usymtab_existsType (cstring_makeLiteralTemp ("size_t")))
4632 sizet = uentry_getAbstractType (usymtab_lookup (cstring_makeLiteralTemp ("size_t")));
4636 sizet = ctype_ulint;
4643 exprNode_sizeofType (/*@only@*/ qtype qt)
4645 exprNode ret = exprNode_create (sizeof_resultType ());
4646 ctype ct = qtype_getType (qt);
4648 ret->kind = XPR_SIZEOFT;
4649 ret->edata = exprData_makeSizeofType (qt);
4651 voptgenerror (FLG_SIZEOFTYPE,
4652 message ("Parameter to sizeof is type %s: %s",
4654 exprNode_unparse (ret)),
4661 exprNode_alignofType (/*@only@*/ qtype qt)
4663 exprNode ret = exprNode_create (sizeof_resultType ());
4664 ctype ct = qtype_getType (qt);
4666 ret->kind = XPR_ALIGNOFT;
4667 ret->edata = exprData_makeSizeofType (qt);
4669 voptgenerror (FLG_SIZEOFTYPE,
4670 message ("Parameter to alignof is type %s: %s",
4672 exprNode_unparse (ret)),
4678 exprNode exprNode_offsetof (qtype qt, cstringList s)
4680 exprNode ret = exprNode_create (sizeof_resultType ());
4681 ctype ct = qtype_getType (qt);
4683 ret->kind = XPR_OFFSETOF;
4684 ret->edata = exprData_makeOffsetof (qt, s);
4686 if (!ctype_isRealSU (ct))
4688 voptgenerror (FLG_TYPE,
4689 message ("First parameter to offsetof is not a "
4690 "struct or union type (type %s): %s",
4692 exprNode_unparse (ret)),
4699 cstringList_elements (s, el) {
4703 if (ctype_isUndefined (lt))
4707 else if (!ctype_isRealSU (lt))
4709 voptgenerror (FLG_TYPE,
4710 message ("Inner offsetof type is not a "
4711 "struct or union type (type %s before field %s): %s",
4712 ctype_unparse (lt), el,
4713 exprNode_unparse (ret)),
4719 fields = ctype_getFields (ctype_realType (lt));
4720 fld = uentryList_lookupField (fields, el);
4721 DPRINTF (("Try: %s / %s", ctype_unparse (lt), el));
4723 if (uentry_isUndefined (fld))
4725 if (ctype_equal (lt, ct)) {
4726 voptgenerror (FLG_TYPE,
4727 message ("Field %s in offsetof is not the "
4728 "name of a field of %s: %s",
4731 exprNode_unparse (ret)),
4734 voptgenerror (FLG_TYPE,
4735 message ("Deep field %s in offsetof is not the "
4736 "name of a field of %s: %s",
4739 exprNode_unparse (ret)),
4745 lt = uentry_getType (fld);
4748 } end_cstringList_elements;
4750 /* Should report error if its a bit field - behavior is undefined! */
4757 exprNode_sizeofExpr (/*@only@*/ exprNode e)
4761 if (exprNode_isUndefined (e))
4763 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4764 ret->edata = exprData_makeSingle (e);
4765 ret->typ = sizeof_resultType ();
4766 ret->kind = XPR_SIZEOF;
4770 uentry u = exprNode_getUentry (e);
4772 ret = exprNode_createPartialCopy (e);
4773 ret->edata = exprData_makeSingle (e);
4775 ret->typ = sizeof_resultType ();
4776 ret->kind = XPR_SIZEOF;
4778 if (uentry_isValid (u)
4779 && uentry_isRefParam (u)
4780 && ctype_isRealArray (uentry_getType (u)))
4783 (FLG_SIZEOFFORMALARRAY,
4784 message ("Parameter to sizeof is an array-type function parameter: %s",
4785 exprNode_unparse (ret)),
4791 ** sizeof (x) doesn't "really" use x
4798 exprNode_alignofExpr (/*@only@*/ exprNode e)
4802 if (exprNode_isUndefined (e))
4804 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
4808 ret = exprNode_createPartialCopy (e);
4811 ret->edata = exprData_makeSingle (e);
4812 ret->typ = sizeof_resultType ();
4813 ret->kind = XPR_ALIGNOF;
4816 ** sizeof (x) doesn't "really" use x
4823 exprNode_cast (/*@only@*/ lltok tok, /*@only@*/ exprNode e, /*@only@*/ qtype q)
4829 if (exprNode_isError (e))
4832 lltok_release (tok);
4833 return exprNode_undefined;
4836 checkMacroParen (e);
4838 c = qtype_getType (q);
4839 t = exprNode_getType (e);
4841 ret = exprNode_createPartialCopy (e);
4843 ret->loc = fileloc_update (ret->loc, lltok_getLoc (tok));
4845 ret->kind = XPR_CAST;
4846 ret->edata = exprData_makeCast (tok, e, q);
4848 if (ctype_isRealSU (ctype_getBaseType (sRef_getType (e->sref))))
4851 ** This is a bit of a hack to avoid a problem
4852 ** when the code does,
4853 ** (some other struct) x
4858 ret->sref = sRef_copy (e->sref);
4859 usymtab_addForceMustAlias (ret->sref, e->sref);
4860 sRef_setTypeFull (ret->sref, c);
4861 DPRINTF (("Cast: %s -> %s", sRef_unparseFull (e->sref),
4862 sRef_unparseFull (ret->sref)));
4866 ret->sref = e->sref;
4867 sRef_setTypeFull (ret->sref, c);
4868 DPRINTF (("Cast 2: -> %s", sRef_unparseFull (ret->sref)));
4875 ** void * <-> abstract * (if FLG_ABSTVOIDP)
4876 ** abstract * <-> void * (if FLG_ABSTVOIDP)
4879 if (ctype_isVoid (c)) /* cast to void is always okay --- discard value */
4883 else if (ctype_isRealAP (c)) /* casting to array or pointer */
4885 ctype bc = ctype_getBaseType (c);
4886 ctype bt = ctype_getBaseType (t);
4887 ctype rt = ctype_realType (t);
4889 if (ctype_isFunction (ctype_baseArrayPtr (ctype_realType (c)))
4890 && (ctype_isArrayPtr (rt)
4891 && !ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4895 message ("Cast from function pointer type (%t) to "
4896 "non-function pointer (%t): %s",
4897 c, t, exprNode_unparse (ret)),
4901 if (!ctype_isFunction (ctype_baseArrayPtr (c))
4902 && (ctype_isArrayPtr (rt)
4903 && ctype_isFunction (ctype_realType (ctype_baseArrayPtr (rt)))))
4907 message ("Cast from non-function pointer type (%t) to "
4908 "function pointer (%t): %s",
4909 c, t, exprNode_unparse (ret)),
4913 if (exprNode_isZero (e) && context_getFlag (FLG_ZEROPTR) &&
4914 !(ctype_isRealAbstract (bc)
4915 && context_hasAccess (ctype_typeId (bc))))
4917 ; /* okay to cast zero */
4921 if (ctype_isRealAbstract (bc)
4922 && !context_hasAccess (ctype_typeId (bc)))
4924 if (ctype_isVoidPointer (t) || ctype_isUnknown (t))
4928 message ("Cast to underlying abstract type %t: %s",
4929 c, exprNode_unparse (ret)),
4936 message ("Cast to underlying abstract type %t: %s",
4937 c, exprNode_unparse (ret)),
4942 if (ctype_isRealAbstract (bt)
4943 && !context_hasAccess (ctype_typeId (bt)))
4945 if (ctype_isUnknown (c) || ctype_isVoidPointer (c))
4949 message ("Cast from underlying abstract type %t: %s",
4950 t, exprNode_unparse (ret)),
4957 message ("Cast from underlying abstract type %t: %s",
4958 t, exprNode_unparse (ret)),
4966 ctype bt = ctype_realType (ctype_getBaseType (t));
4967 ctype bc = ctype_realType (ctype_getBaseType (c));
4969 if (ctype_isAbstract (bt) && !context_hasAccess (ctype_typeId (bt)))
4971 if (ctype_match (c, t))
4973 if (ctype_equal (c, t))
4977 message ("Redundant cast involving abstract type %t: %s",
4978 bt, exprNode_unparse (ret)),
4986 message ("Cast from abstract type %t: %s",
4987 bt, exprNode_unparse (ret)),
4992 if (ctype_isAbstract (bc)
4993 && !context_hasAccess (ctype_typeId (bc)))
4995 if (ctype_match (c, t))
5001 DPRINTF (("No access to: %s / %d",
5002 ctype_unparse (bc), ctype_typeId (bc)));
5003 DPRINTF (("Context %s %s",
5004 bool_unparse (context_inFunctionLike ()),
5005 context_unparse ()));
5008 message ("Cast to abstract type %t: %s", bc,
5009 exprNode_unparse (ret)),
5015 if (ctype_isAbstract (c))
5017 if (sRef_isExposed (e->sref) || sRef_isOnly (e->sref))
5019 /* okay, cast exposed to abstract */
5020 sRef_clearExKindComplete (ret->sref, fileloc_undefined);
5024 if (ctype_isVisiblySharable (t)
5025 && sRef_isExternallyVisible (e->sref)
5026 && !(ctype_isAbstract (t)
5027 && context_hasAccess (ctype_typeId (t))))
5031 message ("Cast to abstract type from externally visible "
5032 "mutable storage exposes rep of %s: %s",
5034 exprNode_unparse (e)),
5044 evaluationOrderUndefined (lltok op)
5046 int opid = lltok_getTok (op);
5048 return (opid != AND_OP && opid != OR_OP);
5051 static bool checkIntegral (/*@notnull@*/ exprNode e1,
5052 /*@notnull@*/ exprNode e2,
5053 /*@notnull@*/ exprNode ret,
5058 ctype te1 = exprNode_getType (e1);
5059 ctype te2 = exprNode_getType (e2);
5061 ctype tr1 = ctype_realishType (te1);
5062 ctype tr2 = ctype_realishType (te2);
5064 if (ctype_isForceRealInt (&tr1) && ctype_isForceRealInt (&tr2))
5070 if (context_msgStrictOps ())
5072 if (!ctype_isInt (tr1) && !ctype_isInt (tr2))
5074 if (ctype_sameName (te1, te2))
5078 message ("Operands of %s are non-integer (%t): %s",
5079 lltok_unparse (op), te1,
5080 exprNode_unparse (ret)),
5087 message ("Operands of %s are non-integers (%t, %t): %s",
5088 lltok_unparse (op), te1, te2,
5089 exprNode_unparse (ret)),
5093 else if (!ctype_isInt (tr1))
5097 message ("Left operand of %s is non-integer (%t): %s",
5098 lltok_unparse (op), te1, exprNode_unparse (ret)),
5102 /* !ctype_isInt (te2) */
5106 message ("Right operand of %s is non-integer (%t): %s",
5107 lltok_unparse (op), te2, exprNode_unparse (ret)),
5117 ** returns exprNode representing e1 op e2
5119 ** uses msg if there are errors
5120 ** can be used for both assignment ops and regular ops
5125 static /*@only@*/ /*@notnull@*/ exprNode
5126 exprNode_makeOp (/*@keep@*/ exprNode e1, /*@keep@*/ exprNode e2,
5127 /*@keep@*/ lltok op)
5129 ctype te1, te2, tr1, tr2, tret;
5130 int opid = lltok_getTok (op);
5131 bool hasError = FALSE;
5134 if (exprNode_isError (e1))
5136 ret = exprNode_createPartialNVCopy (e2);
5140 ret = exprNode_createPartialNVCopy (e1);
5143 ret->val = multiVal_undefined;
5145 ret->edata = exprData_makeOp (e1, e2, op);
5147 if (exprNode_isError (e1) || exprNode_isError (e2))
5149 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5150 || opid == EQ_OP || opid == NE_OP
5151 || opid == AND_OP || opid == OR_OP)
5153 ret->typ = ctype_bool;
5156 if (exprNode_isDefined (e1))
5158 exprNode_checkUse (ret, e1->sref, e1->loc);
5161 if (exprNode_isDefined (e2))
5163 exprNode_mergeUSs (ret, e2);
5164 exprNode_checkUse (ret, e2->sref, e2->loc);
5170 tret = ctype_unknown;
5171 te1 = exprNode_getType (e1);
5172 DPRINTF (("te1 = %s / %s", exprNode_unparse (e1), ctype_unparse (te1)));
5174 te2 = exprNode_getType (e2);
5176 tr1 = ctype_realishType (te1);
5177 tr2 = ctype_realishType (te2);
5181 ret->guards = guardSet_or (ret->guards, e2->guards);
5183 else if (opid == AND_OP)
5185 ret->guards = guardSet_and (ret->guards, e2->guards);
5192 if (opid == EQ_OP || opid == NE_OP)
5194 exprNode temp1 = e1, temp2 = e2;
5196 /* could do NULL == x */
5198 if (exprNode_isNullValue (e1) || exprNode_isUnknownConstant (e1))
5200 temp1 = e2; temp2 = e1;
5203 if (exprNode_isNullValue (temp2) || exprNode_isUnknownConstant (temp2))
5205 reflectNullTest (temp1, (opid == NE_OP));
5206 guardSet_free (ret->guards);
5207 ret->guards = guardSet_copy (temp1->guards);
5211 if (opid == TLT || opid == TGT || opid == LE_OP || opid == GE_OP
5212 || opid == EQ_OP || opid == NE_OP || opid == AND_OP || opid == OR_OP)
5217 if (anyAbstract (tr1, tr2) &&
5218 (!((ctype_isRealBool (te1) || ctype_isRealBool (te2)) &&
5219 (opid == AND_OP || opid == OR_OP
5220 || opid == EQ_OP || opid == NE_OP))))
5222 abstractOpError (tr1, tr2, op, e1, e2, e1->loc, e2->loc);
5224 else if (ctype_isUnknown (te1) || ctype_isUnknown (te2))
5226 /* unknown types, no comparisons possible */
5232 case TMULT: /* multiplication and division: */
5234 case MUL_ASSIGN: /* numeric, numeric -> numeric */
5235 case DIV_ASSIGN: /* */
5237 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5240 case TPLUS: /* addition and subtraction: */
5241 case TMINUS: /* pointer, int -> pointer */
5242 case SUB_ASSIGN: /* int, pointer -> pointer */
5243 case ADD_ASSIGN: /* numeric, numeric -> numeric */
5245 tr1 = ctype_fixArrayPtr (tr1);
5247 if ((ctype_isRealPointer (tr1) && !exprNode_isNullValue (e1))
5248 && (!ctype_isRealPointer (tr2) && ctype_isRealInt (tr2)))
5252 if (context_msgPointerArith ())
5256 message ("Pointer arithmetic (%t, %t): %s",
5257 te1, te2, exprNode_unparse (ret)),
5262 ** Swap terms so e1 is always the pointer
5265 if (ctype_isRealPointer (tr1))
5271 exprNode_swap (e1, e2);
5275 if (sRef_possiblyNull (e1->sref)
5276 && !usymtab_isGuarded (e1->sref))
5279 (FLG_NULLPOINTERARITH,
5280 message ("Pointer arithmetic involving possibly "
5281 "null pointer %s: %s",
5282 exprNode_unparse (e1),
5283 exprNode_unparse (ret)),
5287 ret->sref = sRef_copy (e1->sref);
5289 /* start modifications */
5290 /* added by Seejo on 4/16/2000 */
5292 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5294 if ((sRef_isPossiblyNullTerminated (e1->sref)) || (sRef_isNullTerminated(e1->sref))) {
5297 added ugly fixed to stop
5298 program from crashing on point + int +int
5299 one day I'll fix this or ask Seejo wtf the codes supposed to do. */
5301 if (!multiVal_isInt (e2->val) )
5305 val = (int) multiVal_forceInt (e2->val);
5307 /* Operator : + or += */
5308 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5309 if (sRef_getSize(e1->sref) >= val) {/* Incrementing the pointer by
5310 val should not result in a
5311 size < 0 (size = 0 is ok !) */
5313 sRef_setSize (ret->sref, sRef_getSize(e1->sref) - val);
5315 if (sRef_getLen(e1->sref) == val) { /* i.e. the character at posn val is \0 */
5316 sRef_setNotNullTerminatedState(ret->sref);
5317 sRef_resetLen (ret->sref);
5319 sRef_setNullTerminatedState(ret->sref);
5320 sRef_setLen (ret->sref, sRef_getLen(e1->sref) - val);
5325 /* Operator : - or -= */
5326 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5327 if (sRef_getSize(e1->sref) >= 0) {
5328 sRef_setSize (ret->sref, sRef_getSize(e1->sref) + val);
5329 sRef_setLen (ret->sref, sRef_getLen(e1->sref) + val);
5334 /* end modifications */
5336 sRef_setNullError (ret->sref);
5339 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5340 ** since is points to storage that should not be deallocated
5341 ** through this pointer.
5344 if (sRef_isOnly (ret->sref)
5345 || sRef_isFresh (ret->sref))
5347 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5352 else if ((!ctype_isRealPointer(tr1) && ctype_isRealInt (tr1))
5353 && (ctype_isRealPointer (tr2) && !exprNode_isNullValue (e2)))
5355 if (context_msgPointerArith ())
5359 message ("Pointer arithmetic (%t, %t): %s",
5360 te1, te2, exprNode_unparse (ret)),
5364 if (sRef_possiblyNull (e1->sref)
5365 && !usymtab_isGuarded (e1->sref))
5368 (FLG_NULLPOINTERARITH,
5369 message ("Pointer arithmetic involving possibly "
5370 "null pointer %s: %s",
5371 exprNode_unparse (e2),
5372 exprNode_unparse (ret)),
5376 ret->sref = sRef_copy (e2->sref);
5378 /* start modifications */
5379 /* added by Seejo on 4/16/2000 */
5381 /* Arithmetic operations on pointers wil modify the size/len/null terminated
5384 if ((sRef_isPossiblyNullTerminated (e2->sref)) || (sRef_isNullTerminated(e2->sref))) {
5385 int val = (int) multiVal_forceInt (e1->val);
5387 /* Operator : + or += */
5388 if ((lltok_getTok (op) == TPLUS) || (lltok_getTok(op) == ADD_ASSIGN)) {
5389 if (sRef_getSize(e2->sref) >= val) {/* Incrementing the pointer by
5390 val should not result in a
5391 size < 0 (size = 0 is ok !) */
5393 sRef_setSize (ret->sref, sRef_getSize(e2->sref) - val);
5395 if (sRef_getLen(e2->sref) == val) { /* i.e. the character at posn val is \0 */
5396 sRef_setNotNullTerminatedState(ret->sref);
5397 sRef_resetLen (ret->sref);
5399 sRef_setNullTerminatedState(ret->sref);
5400 sRef_setLen (ret->sref, sRef_getLen(e2->sref) - val);
5405 /* Operator : - or -= */
5406 if ((lltok_getTok (op) == TMINUS) || (lltok_getTok (op) == SUB_ASSIGN)) {
5407 if (sRef_getSize(e2->sref) >= 0) {
5408 sRef_setSize (ret->sref, sRef_getSize(e2->sref) + val);
5409 sRef_setLen (ret->sref, sRef_getLen(e2->sref) + val);
5413 /* end modifications */
5415 sRef_setNullError (ret->sref);
5418 ** Fixed for 2.2c: the alias state of ptr + int is dependent,
5419 ** since is points to storage that should not be deallocated
5420 ** through this pointer.
5423 if (sRef_isOnly (ret->sref)
5424 || sRef_isFresh (ret->sref)) {
5425 sRef_setAliasKind (ret->sref, AK_DEPENDENT, exprNode_loc (ret));
5429 ret->sref = e2->sref;
5433 tret = checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5438 case LEFT_ASSIGN: /* Shifts: should be unsigned values */
5442 case TAMPERSAND: /* bitwise & */
5444 case TCIRC: /* ^ (XOR) */
5449 bool reported = FALSE;
5450 flagcode code = FLG_BITWISEOPS;
5452 if (opid == LEFT_OP || opid == LEFT_ASSIGN
5453 || opid == RIGHT_OP || opid == RIGHT_ASSIGN) {
5454 code = FLG_SHIFTSIGNED;
5457 if (!ctype_isUnsigned (tr1))
5459 if (exprNode_isNonNegative (e1)) {
5462 reported = optgenerror
5464 message ("Left operand of %s is not unsigned value (%t): %s",
5465 lltok_unparse (op), te1,
5466 exprNode_unparse (ret)),
5476 /* right need not be signed for shifts */
5477 if (code != FLG_SHIFTSIGNED
5478 && !ctype_isUnsigned (tr2))
5480 if (!exprNode_isNonNegative (e2)) {
5481 reported = optgenerror
5483 message ("Right operand of %s is not unsigned value (%t): %s",
5484 lltok_unparse (op), te2,
5485 exprNode_unparse (ret)),
5493 if (!checkIntegral (e1, e2, ret, op)) {
5494 te1 = ctype_unknown;
5498 DPRINTF (("Set: %s", ctype_unparse (te1)));
5501 ** tret is the widest type of te1 and te2
5504 tret = ctype_widest (te1, te2);
5509 if (checkIntegral (e1, e2, ret, op)) {
5512 tret = ctype_unknown;
5517 case TLT: /* comparisons */
5518 case TGT: /* numeric, numeric -> bool */
5519 if ((ctype_isReal (tr1) && !ctype_isInt (tr1))
5520 || (ctype_isReal (tr2) && !ctype_isInt (tr2)))
5523 bool fepsilon = FALSE;
5525 if (!ctype_isReal (rtype) || ctype_isInt (rtype))
5530 if (opid == TLT || opid == TGT)
5532 uentry ue1 = exprNode_getUentry (e1);
5533 uentry ue2 = exprNode_getUentry (e2);
5536 ** FLT_EPSILON, etc. really is a variable, not
5540 if (uentry_isVariable (ue1))
5542 cstring uname = uentry_rawName (ue1);
5544 if (cstring_equalLit (uname, "FLT_EPSILON")
5545 || cstring_equalLit (uname, "DBL_EPSILON")
5546 || cstring_equalLit (uname, "LDBL_EPSILON"))
5552 if (uentry_isVariable (ue2))
5554 cstring uname = uentry_rawName (ue2);
5556 if (cstring_equalLit (uname, "FLT_EPSILON")
5557 || cstring_equalLit (uname, "DBL_EPSILON")
5558 || cstring_equalLit (uname, "LDBL_EPSILON"))
5567 ; /* Don't complain. */
5573 message ("Dangerous comparison involving %s types: %s",
5574 ctype_unparse (rtype),
5575 exprNode_unparse (ret)),
5584 ** Types should match.
5587 if (!exprNode_matchTypes (e1, e2))
5589 hasError = gentypeerror
5591 message ("Operands of %s have incompatible types (%t, %t): %s",
5592 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5598 || (ctype_isForceRealNumeric (&tr1)
5599 && ctype_isForceRealNumeric (&tr2)) ||
5600 (ctype_isRealPointer (tr1) && ctype_isRealPointer (tr2)))
5606 if ((ctype_isRealNumeric (tr1) && ctype_isRealPointer (tr2)) ||
5607 (ctype_isRealPointer (tr1) && ctype_isRealNumeric (tr2)))
5611 message ("Comparison of pointer and numeric (%t, %t): %s",
5612 te1, te2, exprNode_unparse (ret)),
5617 (void) checkNumerics (tr1, tr2, te1, te2, e1, e2, op);
5622 /* certain comparisons on unsigned's and zero look suspicious */
5624 if (opid == TLT || opid == LE_OP || opid == GE_OP)
5626 if ((ctype_isUnsigned (tr1) && exprNode_isZero (e2))
5627 || (ctype_isUnsigned (tr2) && exprNode_isZero (e1)))
5630 (FLG_UNSIGNEDCOMPARE,
5631 message ("Comparison of unsigned value involving zero: %s",
5632 exprNode_unparse (ret)),
5637 /* EQ_OP should NOT be used with booleans (unless one is FALSE) */
5639 if ((opid == EQ_OP || opid == NE_OP) &&
5640 ctype_isDirectBool (tr1) && ctype_isDirectBool (tr2))
5643 ** is one a variable?
5646 if (uentry_isVariable (exprNode_getUentry (e1))
5647 || uentry_isVariable (exprNode_getUentry (e2)))
5650 ** comparisons with FALSE are okay
5653 if (exprNode_isFalseConstant (e1)
5654 || exprNode_isFalseConstant (e2))
5663 ("Use of %q with %s variables (risks inconsistency because "
5664 "of multiple true values): %s",
5665 cstring_makeLiteral ((opid == EQ_OP) ? "==" : "!="),
5666 context_printBoolName (), exprNode_unparse (ret)),
5673 case AND_OP: /* bool, bool -> bool */
5676 if (ctype_isForceRealBool (&tr1) && ctype_isForceRealBool (&tr2))
5682 if (context_maybeSet (FLG_BOOLOPS))
5684 if (!ctype_isRealBool (te1) && !ctype_isRealBool (te2))
5686 if (ctype_sameName (te1, te2))
5690 message ("Operands of %s are non-boolean (%t): %s",
5691 lltok_unparse (op), te1,
5692 exprNode_unparse (ret)),
5700 ("Operands of %s are non-booleans (%t, %t): %s",
5701 lltok_unparse (op), te1, te2, exprNode_unparse (ret)),
5705 else if (!ctype_isRealBool (te1))
5709 message ("Left operand of %s is non-boolean (%t): %s",
5710 lltok_unparse (op), te1, exprNode_unparse (ret)),
5713 else if (!ctype_isRealBool (te2))
5717 message ("Right operand of %s is non-boolean (%t): %s",
5718 lltok_unparse (op), te2, exprNode_unparse (ret)),
5731 (cstring_makeLiteral
5732 ("There has been a problem in the parser. This is believed to result "
5733 "from a problem with bison v. 1.25. Please try rebuidling LCLint "
5734 "using the pre-compiled grammar files by commenting out the "
5735 "BISON= line in the top-level Makefile."));
5740 DPRINTF (("Return type: %s", ctype_unparse (tret)));
5743 exprNode_checkUse (ret, e1->sref, e1->loc);
5744 exprNode_mergeUSs (ret, e2);
5745 exprNode_checkUse (ret, e2->sref, e2->loc);
5751 exprNode_op (/*@only@*/ exprNode e1, /*@keep@*/ exprNode e2,
5752 /*@only@*/ lltok op)
5756 checkMacroParen (e1);
5757 checkMacroParen (e2);
5759 if (evaluationOrderUndefined (op) && context_maybeSet (FLG_EVALORDER))
5761 checkExpressionDefined (e1, e2, op);
5764 ret = exprNode_makeOp (e1, e2, op);
5769 void exprNode_checkAssignMod (exprNode e1, exprNode ret)
5772 ** This is somewhat bogus!
5774 ** Assigning to a nested observer in a non-observer datatype
5775 ** should not produce an error.
5778 sRef ref = exprNode_getSref (e1);
5780 DPRINTF (("Check assign mod: %s",
5781 sRef_unparseFull (ref)));
5783 if (sRef_isObserver (ref)
5784 || ((sRef_isFileStatic (ref) || sRef_isFileOrGlobalScope (ref))
5785 && ctype_isArray (ctype_realType (sRef_getType (ref)))))
5787 sRef base = sRef_getBase (ref);
5789 if (sRef_isValid (base) && sRef_isObserver (base))
5791 exprNode_checkModify (e1, ret);
5795 exprNode_checkModifyVal (e1, ret);
5800 exprNode_checkModify (e1, ret);
5805 exprNode_assign (/*@only@*/ exprNode e1,
5806 /*@only@*/ exprNode e2, /*@only@*/ lltok op)
5808 bool isalloc = FALSE;
5809 bool isjustalloc = FALSE;
5810 bool noalias = FALSE;
5813 DPRINTF (("%s [%s] <- %s [%s]",
5814 exprNode_unparse (e1),
5815 ctype_unparse (e1->typ),
5816 exprNode_unparse (e2),
5817 ctype_unparse (e2->typ)));
5819 if (lltok_getTok (op) != TASSIGN)
5821 ret = exprNode_makeOp (e1, e2, op);
5823 DPRINTF (("Here goes: %s %s",
5824 ctype_unparse (e1->typ),
5825 ctype_unparse (e2->typ)));
5827 if (ctype_isNumeric (e2->typ)
5828 || ctype_isNumeric (e1->typ))
5830 /* Its a pointer arithmetic expression like ptr += i */
5836 ret = exprNode_createPartialCopy (e1);
5837 ret->kind = XPR_ASSIGN;
5838 ret->edata = exprData_makeOp (e1, e2, op);
5840 if (!exprNode_isError (e2))
5842 ret->sets = sRefSet_union (ret->sets, e2->sets);
5843 ret->msets = sRefSet_union (ret->msets, e2->msets);
5844 ret->uses = sRefSet_union (ret->uses, e2->uses);
5848 checkExpressionDefined (e1, e2, op);
5850 if (exprNode_isError (e1))
5852 if (!exprNode_isError (e2))
5854 ret->loc = fileloc_update (ret->loc, e2->loc);
5858 ret->loc = fileloc_update (ret->loc, g_currentloc);
5862 if (!exprNode_isError (e2))
5864 checkMacroParen (e2);
5867 if (exprNode_isDefined (e1))
5869 if (sRef_isMacroParamRef (e1->sref))
5871 if (context_inIterDef ())
5873 uentry ue = sRef_getUentry (e1->sref);
5875 if (uentry_isYield (ue))
5881 if (fileloc_isDefined (e1->loc))
5885 message ("Assignment to non-yield iter parameter: %q",
5886 sRef_unparse (e1->sref)),
5893 message ("Assignment to non-yield iter parameter: %q",
5894 sRef_unparse (e1->sref)),
5901 if (fileloc_isDefined (e1->loc))
5905 message ("Assignment to macro parameter: %q",
5906 sRef_unparse (e1->sref)),
5913 message ("Assignment to macro parameter: %q",
5914 sRef_unparse (e1->sref)),
5918 exprNode_checkAssignMod (e1, ret); /* evans 2001-07-22 */
5923 exprNode_checkAssignMod (e1, ret);
5926 if (exprNode_isDefined (e2))
5928 if (lltok_getTok (op) == TASSIGN)
5930 ctype te1 = exprNode_getType (e1);
5931 ctype te2 = exprNode_getType (e2);
5933 if (!ctype_forceMatch (te1, te2))
5935 if (exprNode_matchLiteral (te1, e2))
5943 message ("Assignment of %t to %t: %s %s %s",
5944 te2, te1, exprNode_unparse (e1),
5946 exprNode_unparse (e2)),
5952 exprNode_mergeUSs (ret, e2);
5953 exprNode_checkUse (ret, e2->sref, e2->loc);
5955 DPRINTF (("Do assign! %s %s", exprNode_unparse (e1), exprNode_unparse (e2)));
5962 doAssign (e1, e2, FALSE);
5965 ret->sref = e1->sref;
5969 if (exprNode_isDefined (e2))
5971 exprNode_mergeUSs (ret, e2);
5972 exprNode_checkUse (ret, e2->sref, e2->loc);
5976 if (sRef_isPointer (e1->sref) && !sRef_isMacroParamRef (e1->sref))
5978 exprNode_checkUse (ret, sRef_getBase (e1->sref), e1->loc);
5981 isjustalloc = sRef_isJustAllocated (e1->sref);
5982 isalloc = sRef_isAllocated (e1->sref);
5984 if (sRef_isField (e1->sref))
5986 sRef root = sRef_getRootBase (sRef_getBase (e1->sref));
5988 if (!sRef_isAllocated (root) && !sRef_isMacroParamRef (root))
5990 exprNode_checkUse (ret, root, e1->loc);
5996 ** be careful! this defines e1->sref.
5999 /* evans 2001-07-22: removed if (!sRef_isMacroParamRef (e1->sref)) */
6001 DPRINTF (("Setting: %s -> %s", exprNode_unparse (ret), sRef_unparse (e1->sref)));
6002 exprNode_checkSet (ret, e1->sref);
6006 sRef_setAllocatedComplete (e1->sref, exprNode_isDefined (e2)
6007 ? e2->loc : e1->loc);
6013 sRef_setAllocatedShallowComplete (e1->sref, exprNode_loc (e2));
6022 exprNode_cond (/*@keep@*/ exprNode pred, /*@keep@*/ exprNode ifclause,
6023 /*@keep@*/ exprNode elseclause)
6027 if (!exprNode_isError (pred))
6029 ret = exprNode_createPartialCopy (pred);
6030 checkMacroParen (pred);
6031 exprNode_checkPred (cstring_makeLiteralTemp ("conditional"), pred);
6033 if (!exprNode_isError (ifclause))
6035 checkMacroParen (ifclause); /* update macro counts! */
6037 if (!exprNode_isError (elseclause))
6039 checkMacroParen (elseclause);
6041 if (!exprNode_matchTypes (ifclause, elseclause))
6044 (exprNode_getType (ifclause),
6046 exprNode_getType (elseclause),
6048 message ("Conditional clauses are not of same type: "
6050 exprNode_unparse (ifclause),
6051 exprNode_getType (ifclause),
6052 exprNode_unparse (elseclause),
6053 exprNode_getType (elseclause)),
6056 ret->sref = sRef_undefined;
6057 ret->typ = ctype_unknown;
6062 /* for now...should merge the states */
6063 ret->sref = ifclause->sref;
6064 ret->typ = ifclause->typ;
6066 if (exprNode_isNullValue (ifclause))
6068 ret->typ = elseclause->typ;
6072 exprNode_checkUse (ret, pred->sref, pred->loc);
6073 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6074 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6076 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6081 ret->typ = ifclause->typ;
6083 exprNode_checkUse (pred, pred->sref, pred->loc);
6084 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6086 exprNode_mergeCondUSs (ret, ifclause, exprNode_undefined);
6091 if (!exprNode_isError (elseclause))
6093 ret->typ = elseclause->typ;
6095 exprNode_checkUse (pred, pred->sref, pred->loc);
6096 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6098 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6102 else /* pred is error */
6104 if (!exprNode_isError (ifclause))
6106 ret = exprNode_createSemiCopy (ifclause);
6108 checkMacroParen (ifclause); /* update macro counts! */
6110 if (!exprNode_isError (elseclause))
6112 checkMacroParen (elseclause);
6114 ret->typ = ifclause->typ;
6116 if (!ctype_forceMatch (ifclause->typ, elseclause->typ))
6119 (exprNode_getType (ifclause),
6121 exprNode_getType (elseclause),
6123 message ("Conditional clauses are not of same type: "
6125 exprNode_unparse (ifclause),
6126 exprNode_getType (ifclause),
6127 exprNode_unparse (elseclause),
6128 exprNode_getType (elseclause)),
6131 ret->typ = ctype_unknown;
6135 exprNode_checkUse (ifclause, ifclause->sref, ifclause->loc);
6136 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6138 exprNode_mergeCondUSs (ret, ifclause, elseclause);
6141 else if (!exprNode_isError (elseclause)) /* pred, if errors */
6143 ret = exprNode_createSemiCopy (ifclause);
6145 ret->typ = elseclause->typ;
6146 checkMacroParen (elseclause);
6148 exprNode_checkUse (elseclause, elseclause->sref, elseclause->loc);
6149 exprNode_mergeCondUSs (ret, exprNode_undefined, elseclause);
6151 else /* all errors! */
6153 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6157 ret->kind = XPR_COND;
6158 ret->edata = exprData_makeCond (pred, ifclause, elseclause);
6160 if (exprNode_isDefined (ifclause) && exprNode_isDefined (elseclause))
6162 exprNode_combineControl (ret, ifclause, elseclause);
6169 exprNode_vaArg (/*@only@*/ lltok tok, /*@only@*/ exprNode arg, /*@only@*/ qtype qt)
6171 ctype totype = qtype_getType (qt);
6173 exprNode_createPartialLocCopy (arg, fileloc_copy (lltok_getLoc (tok)));
6177 ** check use of va_arg : <valist>, type -> type
6180 if (exprNode_isError (arg))
6185 targ = exprNode_getType (arg);
6188 ** arg should have be a pointer
6191 if (!ctype_isUA (targ) ||
6192 (!usymId_equal (ctype_typeId (targ),
6193 usymtab_getTypeId (cstring_makeLiteralTemp ("va_list")))))
6197 message ("First argument to va_arg is not a va_list (type %t): %s",
6198 targ, exprNode_unparse (arg)),
6202 exprNode_checkSet (ret, arg->sref);
6206 ** return type is totype
6210 ret->kind = XPR_VAARG;
6211 ret->edata = exprData_makeCast (tok, arg, qt);
6216 exprNode exprNode_labelMarker (/*@only@*/ cstring label)
6218 exprNode ret = exprNode_createPlain (ctype_undefined);
6219 ret->kind = XPR_LABEL;
6220 ret->edata = exprData_makeLiteral (label);
6221 ret->isJumpPoint = TRUE;
6223 return (ret); /* for now, ignore label */
6226 exprNode exprNode_notReached (/*@returned@*/ exprNode stmt)
6228 if (exprNode_isDefined (stmt))
6230 stmt->isJumpPoint = TRUE;
6232 /* This prevent stray no return path errors, etc. */
6233 stmt->exitCode = XK_MUSTEXIT;
6239 bool exprNode_isDefaultMarker (exprNode e)
6241 if (exprNode_isDefined (e))
6243 return (e->kind == XPR_DEFAULT || e->kind == XPR_FTDEFAULT);
6249 bool exprNode_isCaseMarker (exprNode e)
6251 if (exprNode_isDefined (e))
6253 return (e->kind == XPR_FTCASE || e->kind == XPR_CASE);
6259 bool exprNode_isLabelMarker (exprNode e)
6261 if (exprNode_isDefined (e))
6263 return (e->kind == XPR_LABEL);
6269 exprNode exprNode_caseMarker (/*@only@*/ exprNode test, bool fallThrough)
6271 exprNode ret = exprNode_createPartialCopy (test);
6273 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6275 if (exprNode_isError (test)) {
6279 exprNode_checkUse (ret, test->sref, test->loc);
6281 usymtab_setExitCode (ret->exitCode);
6285 usymtab_setMustBreak ();
6288 ret->edata = exprData_makeSingle (test);
6289 ret->isJumpPoint = TRUE;
6295 exprNode exprNode_caseStatement (/*@only@*/ exprNode test, /*@only@*/ exprNode stmt, bool fallThrough)
6297 exprNode ret = exprNode_createPartialCopy (test);
6299 ret->kind = fallThrough ? XPR_FTCASE : XPR_CASE;
6300 ret->edata = exprData_makePair (test, stmt);
6301 ret->isJumpPoint = TRUE;
6303 if (exprNode_isError (test))
6308 exprNode_checkUse (ret, test->sref, test->loc);
6310 if (exprNode_isError (stmt))
6315 exprNode_mergeUSs (ret, stmt);
6317 ret->exitCode = stmt->exitCode;
6318 ret->mustBreak = stmt->mustBreak;
6319 ret->canBreak = stmt->canBreak;
6321 usymtab_setExitCode (ret->exitCode);
6325 usymtab_setMustBreak ();
6332 /*@notnull@*/ /*@only@*/ exprNode
6333 exprNode_defaultMarker (/*@only@*/ lltok def, bool fallThrough)
6335 exprNode ret = exprNode_createTok (def);
6337 ret->isJumpPoint = TRUE;
6338 ret->kind = fallThrough ? XPR_FTDEFAULT : XPR_DEFAULT;
6343 exprNode_mayEscape (exprNode e)
6345 if (exprNode_isDefined (e))
6347 return exitkind_couldEscape (e->exitCode);
6353 exprNode_mustBreak (exprNode e)
6355 if (exprNode_isDefined (e))
6357 return e->mustBreak;
6363 exprNode_mustEscape (exprNode e)
6365 if (exprNode_isDefined (e))
6367 return exitkind_mustEscape (e->exitCode) || exprNode_mustBreak (e);
6374 exprNode_errorEscape (exprNode e)
6376 if (exprNode_isDefined (e))
6378 return exitkind_isError (e->exitCode);
6384 exprNode exprNode_concat (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
6386 exprNode ret = exprNode_createPartialCopy (e1);
6388 DPRINTF (("Concat: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
6390 ret->edata = exprData_makePair (e1, e2);
6391 ret->kind = XPR_STMTLIST;
6393 if (exprNode_isDefined (e1))
6395 ret->isJumpPoint = e1->isJumpPoint;
6396 ret->canBreak = e1->canBreak;
6400 if (exprNode_isDefined (e2))
6402 ret->loc = fileloc_update (ret->loc, e2->loc);
6406 if (exprNode_isDefined (e2))
6408 ret->exitCode = e2->exitCode;
6409 ret->mustBreak = e2->mustBreak;
6410 if (e2->canBreak) ret->canBreak = TRUE;
6414 ** if e1 must return, then e2 is unreachable!
6417 if (exprNode_isDefined (e1) && exprNode_isDefined (e2))
6419 if ((exprNode_mustEscape (e1) || exprNode_mustBreak (e1))
6420 && !(e2->isJumpPoint))
6422 if (context_getFlag (FLG_UNREACHABLE))
6426 if (e2->kind == XPR_STMT)
6428 nr = exprData_getUopNode (e2->edata);
6431 if ((nr->kind == XPR_TOK
6432 && lltok_isSemi (exprData_getTok (nr->edata))))
6434 /* okay to have unreachable ";" */
6435 ret->exitCode = XK_MUSTEXIT;
6436 ret->canBreak = TRUE;
6440 if (optgenerror (FLG_UNREACHABLE,
6441 message ("Unreachable code: %s",
6442 exprNode_unparseFirst (nr)),
6445 ret->isJumpPoint = TRUE;
6446 ret->mustBreak = FALSE;
6447 ret->exitCode = XK_ERROR;
6448 DPRINTF (("Jump point: %s", exprNode_unparse (ret)));
6452 ret->exitCode = XK_MUSTEXIT;
6453 ret->canBreak = TRUE;
6461 if ((e2->kind == XPR_CASE || e2->kind == XPR_DEFAULT))
6464 ** We want a warning anytime we have:
6466 ** yyy; <<<- no break or return
6470 exprNode lastStmt = exprNode_lastStatement (e1);
6472 if (exprNode_isDefined (lastStmt)
6473 && !exprNode_mustEscape (lastStmt)
6474 && !exprNode_mustBreak (lastStmt)
6475 && !exprNode_isCaseMarker (lastStmt)
6476 && !exprNode_isDefaultMarker (lastStmt)
6477 && !exprNode_isLabelMarker (lastStmt))
6479 voptgenerror (FLG_CASEBREAK,
6481 ("Fall through case (no preceding break)"),
6488 exprNode_mergeUSs (ret, e2);
6490 usymtab_setExitCode (ret->exitCode);
6494 usymtab_setMustBreak ();
6500 exprNode exprNode_createTok (/*@only@*/ lltok t)
6502 exprNode ret; /*@i23 if on same line, bad things happen...!@*/
6503 ret = exprNode_create (ctype_unknown);
6504 ret->kind = XPR_TOK;
6505 ret->edata = exprData_makeTok (t);
6509 exprNode exprNode_statement (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6511 if (!exprNode_isError (e))
6513 exprNode_checkStatement(e);
6516 return (exprNode_statementError (e, t));
6519 static exprNode exprNode_statementError (/*@only@*/ exprNode e, /*@only@*/ lltok t)
6521 exprNode ret = exprNode_createPartialCopy (e);
6523 if (!exprNode_isError (e))
6525 if (e->kind != XPR_ASSIGN)
6527 exprNode_checkUse (ret, e->sref, e->loc);
6530 ret->exitCode = e->exitCode;
6531 ret->canBreak = e->canBreak;
6532 ret->mustBreak = e->mustBreak;
6535 ret->edata = exprData_makeUop (e, t);
6536 ret->kind = XPR_STMT;
6541 exprNode exprNode_checkExpr (/*@returned@*/ exprNode e)
6543 if (!exprNode_isError (e))
6545 if (e->kind != XPR_ASSIGN)
6547 exprNode_checkUse (e, e->sref, e->loc);
6554 void exprNode_produceGuards (exprNode pred)
6556 if (!exprNode_isError (pred))
6558 if (ctype_isRealPointer (pred->typ))
6560 pred->guards = guardSet_addTrueGuard (pred->guards, pred->sref);
6563 exprNode_checkUse (pred, pred->sref, pred->loc);
6564 exprNode_resetSref (pred);
6568 exprNode exprNode_makeBlock (/*@only@*/ exprNode e)
6570 exprNode ret = exprNode_createPartialCopy (e);
6572 if (!exprNode_isError (e))
6574 ret->exitCode = e->exitCode;
6575 ret->canBreak = e->canBreak;
6576 ret->mustBreak = e->mustBreak;
6579 ret->edata = exprData_makeSingle (e);
6580 ret->kind = XPR_BLOCK;
6584 bool exprNode_isBlock (exprNode e)
6586 return (exprNode_isDefined (e)
6587 && ((e)->kind == XPR_BLOCK));
6590 bool exprNode_isAssign (exprNode e)
6592 if (exprNode_isDefined (e))
6594 return (e->kind == XPR_ASSIGN);
6600 bool exprNode_isEmptyStatement (exprNode e)
6602 return (exprNode_isDefined (e)
6603 && (e->kind == XPR_TOK)
6604 && (lltok_isSemi (exprData_getTok (e->edata))));
6607 exprNode exprNode_if (/*@only@*/ exprNode pred, /*@only@*/ exprNode tclause)
6610 bool emptyErr = FALSE;
6612 if (context_maybeSet (FLG_IFEMPTY))
6614 if (exprNode_isEmptyStatement (tclause))
6616 emptyErr = optgenerror (FLG_IFEMPTY,
6618 ("Body of if statement is empty"),
6619 exprNode_loc (tclause));
6623 if (!emptyErr && context_maybeSet (FLG_IFBLOCK))
6625 if (exprNode_isDefined (tclause)
6626 && !exprNode_isBlock (tclause))
6628 voptgenerror (FLG_IFBLOCK,
6630 ("Body of if statement is not a block: %s",
6631 exprNode_unparse (tclause)),
6632 exprNode_loc (tclause));
6636 if (exprNode_isError (pred))
6638 if (exprNode_isError (tclause))
6640 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6644 ret = exprNode_createPartialCopy (tclause);
6649 if (exprNode_mustEscape (pred))
6653 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6654 exprNode_loc (pred));
6657 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6658 exprNode_checkUse (pred, pred->sref, pred->loc);
6660 if (!exprNode_isError (tclause))
6662 exprNode_mergeCondUSs (pred, tclause, exprNode_undefined);
6665 ret = exprNode_createPartialCopy (pred);
6669 ret->edata = exprData_makePair (pred, tclause);
6671 ret->exitCode = XK_UNKNOWN;
6673 if (exprNode_isDefined (tclause))
6675 ret->exitCode = exitkind_makeConditional (tclause->exitCode);
6676 ret->canBreak = tclause->canBreak;
6677 ret->sets = sRefSet_union (ret->sets, tclause->sets);
6678 ret->msets = sRefSet_union (ret->msets, tclause->msets);
6679 ret->uses = sRefSet_union (ret->uses, tclause->uses);
6682 ret->mustBreak = FALSE;
6687 exprNode exprNode_ifelse (/*@only@*/ exprNode pred,
6688 /*@only@*/ exprNode tclause,
6689 /*@only@*/ exprNode eclause)
6692 bool tEmptyErr = FALSE;
6693 bool eEmptyErr = FALSE;
6695 if (context_maybeSet (FLG_IFEMPTY))
6697 if (exprNode_isEmptyStatement (tclause))
6699 tEmptyErr = optgenerror
6702 ("Body of if clause of if statement is empty"),
6703 exprNode_loc (tclause));
6706 if (exprNode_isEmptyStatement (eclause))
6708 eEmptyErr = optgenerror
6711 ("Body of else clause of if statement is empty"),
6712 exprNode_loc (eclause));
6716 if (context_maybeSet (FLG_IFBLOCK))
6719 && exprNode_isDefined (tclause)
6720 && !exprNode_isBlock (tclause))
6722 voptgenerror (FLG_IFBLOCK,
6724 ("Body of if clause of if statement is not a block: %s",
6725 exprNode_unparse (tclause)),
6726 exprNode_loc (tclause));
6730 && exprNode_isDefined (eclause)
6731 && !exprNode_isBlock (eclause)
6732 && !(eclause->kind == XPR_IF)
6733 && !(eclause->kind == XPR_IFELSE))
6738 ("Body of else clause of if statement is not a block: %s",
6739 exprNode_unparse (eclause)),
6740 exprNode_loc (eclause));
6744 if (context_maybeSet (FLG_ELSEIFCOMPLETE))
6746 if (exprNode_isDefined (eclause)
6747 && (eclause->kind == XPR_IF))
6749 voptgenerror (FLG_ELSEIFCOMPLETE,
6750 message ("Incomplete else if logic (no final else): %s",
6751 exprNode_unparse (eclause)),
6752 exprNode_loc (eclause));
6756 if (exprNode_isError (pred))
6758 if (exprNode_isError (tclause))
6760 if (exprNode_isError (eclause))
6762 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
6766 ret = exprNode_createPartialCopy (eclause);
6771 ret = exprNode_createPartialCopy (tclause);
6774 else /* pred is okay */
6776 ret = exprNode_createPartialCopy (pred);
6778 if (exprNode_mustEscape (pred))
6782 message ("Predicate always exits: %s", exprNode_unparse (pred)),
6783 exprNode_loc (pred));
6786 exprNode_checkPred (cstring_makeLiteralTemp ("if"), pred);
6787 exprNode_checkUse (ret, pred->sref, pred->loc);
6789 exprNode_mergeCondUSs (ret, tclause, eclause);
6792 ret->kind = XPR_IFELSE;
6793 ret->edata = exprData_makeCond (pred, tclause, eclause);
6795 if (exprNode_isDefined (tclause) && exprNode_isDefined (eclause))
6797 exprNode_combineControl (ret, tclause, eclause);
6798 ret->loc = fileloc_update (ret->loc, eclause->loc);
6805 ** *allpaths <- TRUE iff all executions paths must go through the switch
6809 checkSwitchExpr (exprNode test, /*@dependent@*/ exprNode e, /*@out@*/ bool *allpaths)
6811 exprNodeSList el = exprNode_flatten (e);
6812 bool mustReturn = TRUE; /* find a branch that doesn't */
6813 bool thisReturn = FALSE;
6814 bool hasDefault = FALSE;
6815 bool hasAllMembers = FALSE;
6816 bool inSwitch = FALSE;
6817 bool isEnumSwitch = FALSE;
6818 bool canBreak = FALSE;
6819 bool fallThrough = FALSE;
6820 ctype ct = ctype_unknown;
6821 enumNameSList usedEnums;
6824 if (exprNode_isDefined (test))
6829 ttype = ctype_realType (ct);
6831 if (ctype_isEnum (ttype))
6833 isEnumSwitch = TRUE;
6834 enums = ctype_elist (ttype);
6835 usedEnums = enumNameSList_new ();
6839 exprNodeSList_elements (el, current)
6841 if (exprNode_isDefined (current))
6843 switch (current->kind)
6851 message ("Duplicate default cases in switch"),
6852 exprNode_loc (current));
6857 if (current->kind == XPR_DEFAULT || current->kind == XPR_FTDEFAULT)
6865 exprNode st = exprData_getSingle (current->edata);
6866 uentry ue = exprNode_getUentry (st);
6868 if (uentry_isValid (ue))
6870 cstring cname = uentry_rawName (ue);
6872 if (enumNameList_member (/*@-usedef@*/enums/*@=usedef@*/, cname))
6874 if (enumNameSList_member
6875 (/*@-usedef@*/usedEnums/*@=usedef@*/, cname))
6879 message ("Duplicate case in switch: %s",
6885 enumNameSList_addh (usedEnums, cname);
6892 message ("Case in switch not %s member: %s",
6893 ctype_unparse (ct), cname),
6900 if (inSwitch && !fallThrough)
6902 if (!thisReturn || canBreak)
6912 /*@switchbreak@*/ break;
6914 thisReturn = thisReturn || exprNode_mustEscape (current);
6915 canBreak = canBreak || current->canBreak;
6916 if (canBreak) fallThrough = FALSE;
6919 } end_exprNodeSList_elements;
6921 if (inSwitch) /* check the last one! */
6923 if (!thisReturn || canBreak)
6932 && (enumNameSList_size (/*@-usedef@*/usedEnums/*@=usedef@*/) !=
6933 enumNameList_size (/*@-usedef@*/enums/*@=usedef@*/)))
6935 enumNameSList unused = enumNameSList_subtract (enums, usedEnums);
6937 voptgenerror (FLG_MISSCASE,
6938 message ("Missing case%s in switch: %q",
6939 cstring_makeLiteralTemp
6940 ((enumNameSList_size (unused) > 1) ? "s" : ""),
6941 enumNameSList_unparse (unused)),
6944 enumNameSList_free (unused);
6948 hasAllMembers = TRUE;
6952 enumNameSList_free (usedEnums);
6956 *allpaths = hasDefault;
6959 exprNodeSList_free (el);
6960 return ((hasDefault || hasAllMembers) && mustReturn);
6963 exprNode exprNode_switch (/*@only@*/ exprNode e, /*@only@*/ exprNode s)
6965 exprNode ret = exprNode_createPartialCopy (e);
6968 DPRINTF (("Switch: %s", exprNode_unparse (s)));
6970 ret->kind = XPR_SWITCH;
6971 ret->edata = exprData_makePair (e, s);
6973 if (!exprNode_isError (s))
6975 exprNode fs = exprNode_firstStatement (s);
6976 ret->loc = fileloc_update (ret->loc, s->loc);
6978 if (exprNode_isUndefined (fs)
6979 || exprNode_isCaseMarker (fs) || exprNode_isLabelMarker (fs)
6980 || exprNode_isDefaultMarker (fs)) {
6983 voptgenerror (FLG_FIRSTCASE,
6985 ("Statement after switch is not a case: %s", exprNode_unparse (fs)),
6990 if (!exprNode_isError (e))
6992 if (checkSwitchExpr (e, s, &allpaths))
6994 ret->exitCode = XK_MUSTRETURN;
6998 ret->exitCode = e->exitCode;
7001 ret->canBreak = e->canBreak;
7002 ret->mustBreak = e->mustBreak;
7006 ** exprNode.c:3883,32: Variable allpaths used before definition
7013 DPRINTF (("Context exit switch!"));
7014 context_exitSwitch (ret, allpaths);
7015 DPRINTF (("Context exit switch done!"));
7020 static void checkInfiniteLoop (/*@notnull@*/ exprNode test,
7021 /*@notnull@*/ exprNode body)
7023 sRefSet tuses = test->uses;
7025 if (!sRefSet_isEmpty (test->uses))
7027 sRefSet sets = sRefSet_newCopy (body->sets);
7028 bool hasError = TRUE;
7029 bool innerState = FALSE;
7030 sRefSet tuncon = sRefSet_undefined;
7032 sets = sRefSet_union (sets, test->sets);
7033 sets = sRefSet_union (sets, body->msets);
7034 sets = sRefSet_union (sets, test->msets);
7036 sRefSet_allElements (tuses, el)
7038 if (sRef_isUnconstrained (el))
7040 tuncon = sRefSet_insert (tuncon, el);
7044 if (sRefSet_member (sets, el))
7051 if (sRef_isInternalState (el)
7052 || sRef_isFileStatic (sRef_getRootBase (el)))
7056 } end_sRefSet_allElements ;
7060 sRefSet suncon = sRefSet_undefined;
7061 bool sinner = FALSE;
7063 sRefSet_allElements (sets, el)
7065 if (sRef_isUnconstrained (el))
7067 suncon = sRefSet_insert (suncon, el);
7069 else if (sRef_isInternalState (el))
7077 } end_sRefSet_allElements ;
7079 if (sinner && innerState)
7083 else if (sRefSet_isEmpty (tuncon)
7084 && sRefSet_isEmpty (suncon))
7089 ("Suspected infinite loop. No value used in loop test (%q) "
7090 "is modified by test or loop body.",
7091 sRefSet_unparsePlain (tuses)),
7096 if (sRefSet_isEmpty (tuncon))
7100 message ("Suspected infinite loop. No condition values "
7101 "modified. Modification possible through "
7102 "unconstrained calls: %q",
7103 sRefSet_unparsePlain (suncon)),
7110 message ("Suspected infinite loop. No condition values "
7111 "modified. Possible undetected dependency through "
7112 "unconstrained calls in loop test: %q",
7113 sRefSet_unparsePlain (tuncon)),
7119 sRefSet_free (sets);
7123 exprNode exprNode_while (/*@keep@*/ exprNode t, /*@keep@*/ exprNode b)
7126 bool emptyErr = FALSE;
7128 if (context_maybeSet (FLG_WHILEEMPTY))
7130 if (exprNode_isEmptyStatement (b))
7132 emptyErr = optgenerror
7135 ("Body of while statement is empty"),
7140 if (!emptyErr && context_maybeSet (FLG_WHILEBLOCK))
7142 if (exprNode_isDefined (b)
7143 && !exprNode_isBlock (b))
7145 if (context_inIterDef ()
7146 && (b->kind == XPR_STMTLIST
7147 || b->kind == XPR_TOK))
7153 voptgenerror (FLG_WHILEBLOCK,
7155 ("Body of while statement is not a block: %s",
7156 exprNode_unparse (b)),
7162 if (exprNode_isError (t))
7164 if (exprNode_isError (b))
7166 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7170 ret = exprNode_createPartialCopy (b);
7177 ret = exprNode_createPartialCopy (t);
7179 llassert (t->kind == XPR_WHILEPRED);
7181 test = exprData_getSingle (t->edata);
7183 if (!exprNode_isError (b) && exprNode_isDefined (test))
7185 if (context_maybeSet (FLG_INFLOOPS)
7186 || context_maybeSet (FLG_INFLOOPSUNCON))
7189 ** check that some variable in the predicate is set by the body
7190 ** if the predicate uses any variables
7193 checkInfiniteLoop (test, b);
7196 exprNode_mergeUSs (ret, b);
7198 if (exprNode_isDefined (b))
7200 ret->exitCode = exitkind_makeConditional (b->exitCode);
7205 ret->edata = exprData_makePair (t, b);
7206 ret->kind = XPR_WHILE;
7208 if (exprNode_isDefined (t) && exprNode_mustEscape (t))
7212 message ("Predicate always exits: %s", exprNode_unparse (t)),
7216 ret->exitCode = XK_NEVERESCAPE;
7219 ** If loop is infinite, and there is no break inside,
7220 ** exit code is never reach.
7223 if (exprNode_knownIntValue (t))
7225 if (!exprNode_isZero (t))
7227 if (exprNode_isDefined (b))
7231 /* Really, it means never reached. */
7232 ret->exitCode = XK_MUSTEXIT;
7242 ret->canBreak = FALSE;
7243 ret->mustBreak = FALSE;
7249 ** do { b } while (t);
7251 ** note: body passed as first argument
7254 exprNode exprNode_doWhile (/*@only@*/ exprNode b, /*@only@*/ exprNode t)
7258 if (exprNode_isError (t))
7260 if (exprNode_isError (b))
7262 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7266 ret = exprNode_createPartialCopy (b);
7268 ret->exitCode = exitkind_makeConditional (b->exitCode);
7269 exprNode_checkUse (ret, b->sref, b->loc);
7270 ret->exitCode = b->exitCode;
7271 ret->canBreak = b->canBreak;
7272 ret->mustBreak = b->mustBreak;
7277 ret = exprNode_createPartialCopy (t);
7278 exprNode_checkPred (cstring_makeLiteralTemp ("while"), t);
7280 if (!exprNode_isError (b))
7283 ** forgot the copy's --- why wasn't this detected??
7286 ret->sets = sRefSet_copyInto (ret->sets, b->sets);
7287 ret->msets = sRefSet_copyInto (ret->msets, b->msets);
7288 ret->uses = sRefSet_copyInto (ret->uses, b->uses);
7290 /* left this out --- causes and aliasing bug (infinite loop)
7291 should be detected?? */
7293 exprNode_checkUse (ret, b->sref, b->loc);
7294 exprNode_mergeUSs (ret, t);
7295 exprNode_checkUse (ret, t->sref, t->loc);
7297 ret->exitCode = b->exitCode;
7298 ret->canBreak = b->canBreak;
7299 ret->mustBreak = b->mustBreak;
7303 context_exitDoWhileClause (t);
7305 ret->kind = XPR_DOWHILE;
7306 ret->edata = exprData_makePair (t, b);
7310 exprNode exprNode_for (/*@keep@*/ exprNode inc, /*@keep@*/ exprNode body)
7313 bool emptyErr = FALSE;
7315 if (context_maybeSet (FLG_FOREMPTY))
7317 if (exprNode_isEmptyStatement (body))
7319 emptyErr = optgenerror
7322 ("Body of for statement is empty"),
7323 exprNode_loc (body));
7327 if (!emptyErr && context_maybeSet (FLG_FORBLOCK))
7329 if (exprNode_isDefined (body)
7330 && !exprNode_isBlock (body))
7332 if (context_inIterDef ()
7333 && (body->kind == XPR_STMTLIST
7334 || body->kind == XPR_TOK))
7340 voptgenerror (FLG_FORBLOCK,
7342 ("Body of for statement is not a block: %s",
7343 exprNode_unparse (body)),
7344 exprNode_loc (body));
7350 ** for ud purposes: (alreadly) init -> test -> (now) LOOP: body + inc + test
7353 if (exprNode_isError (body))
7355 ret = exprNode_createPartialCopy (inc);
7359 ret = exprNode_createPartialCopy (body);
7361 ret->exitCode = exitkind_makeConditional (body->exitCode);
7363 exprNode_mergeUSs (inc, body);
7365 if (exprNode_isDefined (inc))
7369 context_setMessageAnnote (cstring_makeLiteral ("in post loop increment"));
7372 tmp = exprNode_effect (exprData_getTripleInc (inc->edata));
7373 exprNode_freeShallow (tmp);
7375 context_clearMessageAnnote ();
7376 context_setMessageAnnote (cstring_makeLiteral ("in post loop test"));
7378 tmp = exprNode_effect (exprData_getTripleTest (inc->edata));
7379 exprNode_freeShallow (tmp);
7381 context_clearMessageAnnote ();
7383 ret->uses = sRefSet_copyInto (ret->uses, inc->uses);
7384 ret->sets = sRefSet_copyInto (ret->sets, inc->sets);
7385 ret->msets = sRefSet_copyInto (ret->msets, inc->msets);
7389 ret->kind = XPR_FOR;
7390 ret->edata = exprData_makePair (inc, body);
7392 if (exprNode_isDefined (inc)) {
7393 exprNode test = exprData_getTripleTest (inc->edata);
7395 if (exprNode_isUndefined (test)) {
7396 if (exprNode_isDefined (body)) {
7397 if (!body->canBreak) {
7398 /* Really, it means never reached. */
7399 ret->exitCode = XK_MUSTEXIT;
7409 ** for (init; test; inc)
7412 ** while (test) { body; inc; }
7414 ** Now: check use of init (may set vars for test)
7415 ** check use of test
7419 /*@observer@*/ guardSet exprNode_getForGuards (exprNode pred)
7423 if (exprNode_isError (pred)) return guardSet_undefined;
7425 llassert (pred->kind == XPR_FORPRED);
7427 test = exprData_getTripleTest (pred->edata);
7429 if (!exprNode_isError (test))
7431 return (test->guards);
7434 return guardSet_undefined;
7437 exprNode exprNode_whilePred (/*@only@*/ exprNode test)
7439 exprNode ret = exprNode_createSemiCopy (test);
7441 if (exprNode_isDefined (test))
7443 exprNode_copySets (ret, test);
7444 exprNode_checkPred (cstring_makeLiteralTemp ("while"), test);
7445 exprNode_checkUse (ret, test->sref, test->loc);
7447 exprNode_produceGuards (test);
7449 ret->guards = guardSet_copy (test->guards);
7452 ret->edata = exprData_makeSingle (test);
7453 ret->kind = XPR_WHILEPRED;
7457 exprNode exprNode_forPred (/*@only@*/ exprNode init, /*@only@*/ exprNode test,
7458 /*@only@*/ exprNode inc)
7463 ** for ud purposes: init -> test -> LOOP: [ body, inc ]
7466 exprNode_checkPred (cstring_makeLiteralTemp ("for"), test);
7468 if (!exprNode_isError (inc))
7470 ret = exprNode_createPartialCopy (inc);
7474 if (!exprNode_isError (init))
7476 ret = exprNode_createPartialCopy (init);
7478 else if (!exprNode_isError (test))
7480 ret = exprNode_createPartialCopy (test);
7484 ret = exprNode_createUnknown ();
7488 exprNode_mergeUSs (ret, init);
7490 if (exprNode_isDefined (init))
7492 exprNode_checkUse (ret, init->sref, init->loc);
7495 exprNode_mergeUSs (ret, test);
7497 if (exprNode_isDefined (test))
7499 exprNode_checkUse (ret, test->sref, test->loc);
7502 ret->kind = XPR_FORPRED;
7503 ret->edata = exprData_makeFor (init, test, inc);
7507 /*@notnull@*/ /*@only@*/ exprNode exprNode_goto (/*@only@*/ cstring label)
7509 exprNode ret = exprNode_createUnknown ();
7511 if (context_inMacro ())
7513 voptgenerror (FLG_MACROSTMT,
7514 message ("Macro %s uses goto (not functional)",
7515 context_inFunctionName ()),
7519 ret->kind = XPR_GOTO;
7520 ret->edata = exprData_makeLiteral (label);
7521 ret->mustBreak = TRUE;
7522 ret->exitCode = XK_GOTO;
7523 ret->canBreak = TRUE;
7527 exprNode exprNode_continue (/*@only@*/ lltok l, int qcontinue)
7529 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7531 ret->kind = XPR_CONTINUE;
7532 ret->edata = exprData_makeTok (l);
7533 ret->canBreak = TRUE;
7534 ret->mustBreak = TRUE;
7536 if (qcontinue == QSAFEBREAK)
7540 else if (qcontinue == QINNERCONTINUE)
7542 if (!context_inDeepLoop ())
7545 (FLG_LOOPLOOPCONTINUE,
7546 cstring_makeLiteral ("Continue statement marked with innercontinue "
7547 "is not inside a nested loop"),
7548 exprNode_loc (ret));
7551 else if (qcontinue == BADTOK)
7553 if (context_inDeepLoop ())
7556 (FLG_LOOPLOOPCONTINUE,
7557 cstring_makeLiteral ("Continue statement in nested loop"),
7558 exprNode_loc (ret));
7563 llbuglit ("exprNode_continue: bad qcontinue");
7569 exprNode exprNode_break (/*@only@*/ lltok l, int bqual)
7571 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (lltok_getLoc (l)));
7572 clause breakClause = context_breakClause ();
7574 ret->kind = XPR_BREAK;
7575 ret->edata = exprData_makeTok (l);
7576 ret->canBreak = TRUE;
7577 ret->mustBreak = TRUE;
7579 if (breakClause == NOCLAUSE)
7583 cstring_makeLiteral ("Break not inside while, for or switch statement"),
7584 exprNode_loc (ret));
7588 if (bqual != BADTOK)
7595 if (breakClause == SWITCHCLAUSE)
7597 if (!context_inDeepSwitch ())
7599 voptgenerror (FLG_SYNTAX,
7601 ("Break preceded by innerbreak is not in a deep switch"),
7602 exprNode_loc (ret));
7607 if (!context_inDeepLoop ())
7609 voptgenerror (FLG_SYNTAX,
7611 ("Break preceded by innerbreak is not in a deep loop"),
7612 exprNode_loc (ret));
7617 if (breakClause == SWITCHCLAUSE)
7619 voptgenerror (FLG_SYNTAX,
7621 ("Break preceded by loopbreak is breaking a switch"),
7622 exprNode_loc (ret));
7626 if (breakClause != SWITCHCLAUSE)
7630 message ("Break preceded by switchbreak is breaking %s",
7631 cstring_makeLiteralTemp
7632 ((breakClause == WHILECLAUSE
7633 || breakClause == DOWHILECLAUSE) ? "a while loop"
7634 : (breakClause == FORCLAUSE) ? "a for loop"
7635 : (breakClause == ITERCLAUSE) ? "an iterator"
7637 exprNode_loc (ret));
7645 if (breakClause == SWITCHCLAUSE)
7647 clause nextBreakClause = context_nextBreakClause ();
7649 switch (nextBreakClause)
7651 case NOCLAUSE: break;
7657 (FLG_LOOPSWITCHBREAK,
7658 cstring_makeLiteral ("Break statement in switch inside loop"),
7659 exprNode_loc (ret));
7663 (FLG_SWITCHSWITCHBREAK,
7664 cstring_makeLiteral ("Break statement in switch inside switch"),
7665 exprNode_loc (ret));
7672 if (context_inDeepLoop ())
7676 cstring_makeLiteral ("Break statement in nested loop"),
7677 exprNode_loc (ret));
7681 if (context_inDeepLoopSwitch ())
7684 (FLG_SWITCHLOOPBREAK,
7685 cstring_makeLiteral ("Break statement in loop inside switch"),
7686 exprNode_loc (ret));
7696 exprNode exprNode_nullReturn (/*@only@*/ lltok t)
7698 fileloc loc = lltok_getLoc (t);
7699 exprNode ret = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
7701 context_returnFunction ();
7702 exprChecks_checkNullReturn (loc);
7704 ret->kind = XPR_NULLRETURN;
7705 ret->edata = exprData_makeTok (t);
7706 ret->exitCode = XK_MUSTRETURN;
7710 exprNode exprNode_return (/*@only@*/ exprNode e)
7714 if (exprNode_isError (e))
7716 ret = exprNode_createUnknown ();
7720 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (e->loc));
7722 exprNode_checkUse (ret, e->sref, e->loc);
7723 exprNode_checkReturn (e);
7726 context_returnFunction ();
7727 ret->kind = XPR_RETURN;
7728 ret->edata = exprData_makeSingle (e);
7729 ret->exitCode = XK_MUSTRETURN;
7734 exprNode exprNode_comma (/*@only@*/ exprNode e1, /*@only@*/ exprNode e2)
7738 if (exprNode_isError (e1))
7740 if (exprNode_isError (e2))
7742 ret = exprNode_createLoc (ctype_unknown, fileloc_copy (g_currentloc));
7746 ret = exprNode_createPartialCopy (e2);
7747 exprNode_checkUse (ret, e2->sref, e2->loc);
7748 ret->sref = e2->sref;
7753 ret = exprNode_createPartialCopy (e1);
7755 exprNode_checkUse (ret, e1->sref, e1->loc);
7757 if (!exprNode_isError (e2))
7759 exprNode_mergeUSs (ret, e2);
7760 exprNode_checkUse (ret, e2->sref, e2->loc);
7761 ret->sref = e2->sref;
7765 ret->kind = XPR_COMMA;
7766 ret->edata = exprData_makePair (e1, e2);
7768 if (exprNode_isDefined (e1))
7770 if (exprNode_isDefined (e2))
7774 if (exprNode_mustEscape (e1) || e1->mustBreak)
7778 message ("Second clause of comma expression is unreachable: %s",
7779 exprNode_unparse (e2)),
7783 ret->exitCode = exitkind_combine (e1->exitCode, e2->exitCode);
7784 ret->mustBreak = e1->mustBreak || e2->mustBreak;
7785 ret->canBreak = e1->canBreak || e2->canBreak;
7789 if (exprNode_mustEscape (e1) || e1->mustBreak)
7793 message ("Second clause of comma expression is unreachable: %s",
7794 exprNode_unparse (e2)),
7798 ret->exitCode = e1->exitCode;
7799 ret->canBreak = e1->canBreak;
7804 if (exprNode_isDefined (e2))
7806 ret->exitCode = e2->exitCode;
7807 ret->mustBreak = e2->mustBreak;
7808 ret->canBreak = e2->canBreak;
7815 static bool exprNode_checkOneInit (/*@notnull@*/ exprNode el, exprNode val)
7817 ctype t1 = exprNode_getType (el);
7818 ctype t2 = exprNode_getType (val);
7819 bool hasError = FALSE;
7821 if (ctype_isUnknown (t1))
7823 voptgenerror (FLG_IMPTYPE,
7824 message ("Variable has unknown (implicitly int) type: %s",
7825 exprNode_unparse (el)),
7829 el->typ = ctype_int;
7832 if (exprNode_isDefined (val) && val->kind == XPR_INITBLOCK)
7834 exprNodeList vals = exprData_getArgs (val->edata);
7836 if (ctype_isRealAP (t1))
7841 /*@i423 check number of entries int a[3] = { 1, 2, 3, 4 } ; */
7843 exprNodeList_elements (vals, oneval)
7845 cstring istring = message ("%d", i);
7848 (exprNode_fakeCopy (el),
7849 exprNode_numLiteral (ctype_int, istring,
7850 fileloc_copy (el->loc), i));
7852 if (exprNode_isDefined (newel))
7854 if (exprNodeList_size (vals) == 1
7855 && ctype_isString (exprNode_getType (oneval))
7856 && ctype_isChar (exprNode_getType (newel)))
7858 exprNode_freeIniter (newel);
7862 if (exprNode_checkOneInit (newel, oneval))
7867 if (nerrors > 3 && exprNodeList_size (vals) > 6)
7870 (message ("Additional initialization errors "
7871 "for %s not reported",
7872 exprNode_unparse (el)),
7874 exprNode_freeIniter (newel);
7879 exprNode_freeIniter (newel);
7884 exprNode_freeIniter (newel);
7889 cstring_free (istring);
7892 } end_exprNodeList_elements;
7895 else if (ctype_isStruct (ctype_realType (t1)))
7897 uentryList fields = ctype_getFields (t1);
7900 if (uentryList_size (fields) != exprNodeList_size (vals))
7902 if (uentryList_size (fields) > exprNodeList_size (vals))
7904 hasError = optgenerror
7906 message ("Initializer block for "
7907 "%s has %d field%&, but %s has %d field%&: %q",
7908 exprNode_unparse (el),
7909 exprNodeList_size (vals),
7911 uentryList_size (fields),
7912 exprNodeList_unparse (vals)),
7917 hasError = optgenerror
7919 message ("Initializer block for "
7920 "%s has %d field%&, but %s has %d field%&: %q",
7921 exprNode_unparse (el),
7922 exprNodeList_size (vals),
7924 uentryList_size (fields),
7925 exprNodeList_unparse (vals)),
7931 exprNodeList_elements (vals, oneval)
7933 uentry thisfield = uentryList_getN (fields, i);
7935 exprNode_fieldAccessAux (exprNode_fakeCopy (el),
7937 uentry_getName (thisfield));
7939 if (exprNode_isDefined (newel))
7941 if (exprNode_checkOneInit (newel, oneval))
7946 exprNode_freeIniter (newel);
7950 } end_exprNodeList_elements;
7955 hasError = optgenerror
7957 message ("Initializer block used for "
7958 "%s where %t is expected: %s",
7959 exprNode_unparse (el), t1, exprNode_unparse (val)),
7965 if (exprNode_isDefined (val))
7967 doAssign (el, val, TRUE);
7969 if (!exprNode_matchType (t1, val))
7971 hasError = gentypeerror
7973 message ("Initial value of %s is type %t, "
7975 exprNode_unparse (el),
7976 t2, t1, exprNode_unparse (val)),
7986 exprNode_makeInitializationAux (/*@temp@*/ idDecl t)
7990 if (usymtab_exists (idDecl_observeId (t)))
7992 uentry ue = usymtab_lookup (idDecl_observeId (t));
7993 ret = exprNode_createId (ue);
7995 /*@i723 don't do this...but why? */
7997 ct = ctype_realishType (ret->typ);
7999 DPRINTF (("Type: %s", ctype_unparse (ret->typ)));
8001 if (ctype_isUnknown (ct))
8003 if (uentry_isAnyTag (ue))
8007 message ("%s used but not previously declared: %s",
8008 uentry_ekindName (ue),
8009 idDecl_getName (t)),
8017 message ("Variable has unknown (implicitly int) type: %s",
8018 idDecl_getName (t)),
8030 DPRINTF (("Unrecognized: %s", idDecl_unparse (t)));
8032 ue = uentry_makeUnrecognized (idDecl_observeId (t), fileloc_copy (g_currentloc));
8033 /*!! fileloc_copy (g_currentloc)); */
8034 /*@i32!!! should get error without this */
8035 ret = exprNode_fromIdentifierAux (ue);
8038 ** No error - this happens in old style declarations:
8042 message ("Unrecognized identifier in intializer: %s", idDecl_observeId (t)),
8049 exprData_free (ret->edata, ret->kind);
8050 ret->edata = exprData_undefined;
8052 ret->exitCode = XK_NEVERESCAPE;
8053 ret->mustBreak = FALSE;
8054 ret->kind = XPR_INIT;
8058 exprNode exprNode_makeEmptyInitialization (/*@only@*/ idDecl t)
8060 exprNode ret = exprNode_makeInitializationAux (t);
8061 llassert (ret->edata == exprData_undefined);
8062 ret->edata = exprData_makeInit (t, exprNode_undefined);
8066 exprNode exprNode_makeInitialization (/*@only@*/ idDecl t,
8067 /*@only@*/ exprNode e)
8069 uentry ue = usymtab_lookup (idDecl_observeId (t));
8070 exprNode ret = exprNode_makeInitializationAux (t);
8071 fileloc loc = exprNode_loc (e);
8073 if (exprNode_isError (e))
8075 e = exprNode_createUnknown ();
8078 /* error: assume initializer is defined */
8079 sRef_setDefined (ret->sref, g_currentloc);
8083 ctype ct = ctype_realishType (ret->typ);
8088 ** was addSafeUse --- what's the problem?
8090 ** int x = 3, y = x ?
8093 exprData_free (ret->edata, ret->kind);
8094 ret->edata = exprData_makeInit (t, e);
8096 exprNode_checkUse (ret, e->sref, e->loc);
8098 if (ctype_isUnknown (e->typ) && uentry_isValid (ue))
8100 exprNode lhs = exprNode_createId (ue);
8103 ** static storage should be undefined before initializing
8106 if (uentry_isStatic (ue))
8108 sRef_setDefState (lhs->sref, SS_PARTIAL, fileloc_undefined);
8111 (void) exprNode_checkOneInit (lhs, e);
8113 if (uentry_isStatic (ue))
8115 sRef_setDefState (lhs->sref, SS_DEFINED, fileloc_undefined);
8118 exprNode_free (lhs);
8122 if (!exprNode_matchType (ct, e))
8124 if (exprNode_isZero (e) && ctype_isArrayPtr (ct))
8131 (exprNode_getType (e), e, exprNode_getType (ret), ret,
8133 ("Variable %q initialized to type %t, expects %t: %s",
8134 uentry_getName (ue), exprNode_getType (e),
8135 exprNode_getType (ret),
8136 exprNode_unparse (e)),
8142 if (uentry_isStatic (ue))
8144 sRef_setDefState (ret->sref, SS_PARTIAL, fileloc_undefined);
8147 doAssign (ret, e, TRUE);
8149 if (uentry_isStatic (ue))
8151 sRef_setDefState (ret->sref, SS_DEFINED, fileloc_undefined);
8155 if (context_inIterDef ())
8157 /* should check if it is yield */
8158 uentry_setUsed (ue, loc);
8165 exprNode_mergeUSs (ret, e);
8169 exprNode exprNode_iter (/*@observer@*/ uentry name,
8170 /*@only@*/ exprNodeList alist,
8171 /*@only@*/ exprNode body,
8172 /*@observer@*/ uentry end)
8177 llassert (uentry_isValid (name));
8179 uentry_setUsed (name, exprNode_loc (body));
8181 ret = exprNode_createPartialCopy (body);
8182 iname = uentry_getName (name);
8184 if (uentry_isInvalid (end))
8187 message ("Iter %s not balanced with end_%s", iname, iname));
8191 cstring ename = uentry_getName (end);
8193 if (!cstring_equalPrefixLit (ename, "end_"))
8195 llerror (FLG_ITER, message ("Iter %s not balanced with end_%s: %s",
8196 iname, iname, ename));
8200 if (!cstring_equal (iname, cstring_suffix (ename, 4)))
8203 message ("Iter %s not balanced with end_%s: %s",
8204 iname, iname, ename));
8208 cstring_free (ename);
8211 context_exitIterClause (body);
8213 ret->kind = XPR_ITER;
8214 ret->edata = exprData_makeIter (name, alist, body, end);
8216 if (uentry_isIter (name))
8218 (void) checkArgsReal (name, body,
8219 uentry_getParams (name), alist, TRUE, ret);
8222 cstring_free (iname);
8228 exprNode_iterNewId (/*@only@*/ cstring s)
8230 exprNode e = exprNode_new ();
8231 uentry ue = uentryList_getN (uentry_getParams (getCurrentIter ()), iterParamNo ());
8233 llassert (processingIterVars ());
8235 e->loc = context_getSaveLocation ();
8237 if (fileloc_isUndefined (e->loc))
8239 fileloc_free (e->loc);
8240 e->loc = fileloc_copy (g_currentloc);
8243 e->uses = sRefSet_new ();
8244 e->sets = sRefSet_new ();
8245 e->msets = sRefSet_new ();
8247 e->val = multiVal_unknown ();
8248 e->guards = guardSet_new ();
8250 e->isJumpPoint = FALSE;
8251 e->exitCode = XK_NEVERESCAPE;
8253 /*> missing fields, detected by lclint <*/
8254 e->canBreak = FALSE;
8255 e->mustBreak = FALSE;
8256 e->etext = cstring_undefined;
8258 if (uentry_isYield (ue))
8260 uentry uue = uentry_makeVariable (s, uentry_getType (ue),
8261 fileloc_copy (e->loc),
8265 uue = usymtab_supEntrySrefReturn (uue);
8267 sr = uentry_getSref (uue);
8268 sRef_mergeStateQuiet (sr, uentry_getSref (ue));
8269 sr = uentry_getSref (uue);
8270 sRef_setDefined (sr, e->loc);
8272 e->typ = uentry_getType (uue);
8274 e->edata = exprData_makeId (uue);
8275 uentry_setUsed (uue, g_currentloc);
8281 sRef_setGlobalScope ();
8282 uue = uentry_makeVariableLoc (s, ctype_unknown);
8284 e->typ = ctype_unknown;
8285 e->edata = exprData_makeId (uue);
8287 uentry_setUsed (uue, e->loc);
8288 uentry_setHasNameError (uue);
8290 if (context_getFlag (FLG_REPEATUNRECOG))
8292 uentry_markOwned (uue);
8296 usymtab_supGlobalEntry (uue);
8299 sRef_clearGlobalScope ();
8301 voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier: %s", s),
8308 exprNode_defineConstraints(e);
8313 exprNode_iterExpr (/*@returned@*/ exprNode e)
8315 if (!processingIterVars ())
8317 llcontbuglit ("checkIterParam: not in iter");
8321 if (uentry_isYield (uentryList_getN (uentry_getParams (getCurrentIter ()),
8324 if (exprNode_isDefined (e))
8326 if (fileloc_isDefined (e->loc))
8330 message ("Yield parameter is not simple identifier: %s",
8331 exprNode_unparse (e)),
8338 message ("Yield parameter is not simple identifier: %s",
8339 exprNode_unparse (e)),
8349 exprNode_iterId (/*@observer@*/ uentry c)
8353 llassert (processingIterVars ());
8355 ue = uentryList_getN (uentry_getParams (getCurrentIter ()),
8358 if (uentry_isYield (ue))
8360 ctype ct = uentry_getType (ue);
8361 exprNode e = exprNode_createPlain (ct);
8362 cstring name = uentry_getName (c);
8363 uentry le = uentry_makeVariable (name, ct, fileloc_undefined, FALSE);
8365 uentry_setUsed (ue, g_currentloc);
8366 uentry_setHasNameError (ue);
8368 cstring_free (name);
8371 e->edata = exprData_makeId (le);
8372 e->loc = context_getSaveLocation ();
8373 e->sref = uentry_getSref (le);
8375 usymtab_supEntrySref (le);
8377 if (!context_inHeader ())
8381 message ("Yield parameter shadows local declaration: %q",
8382 uentry_getName (c)),
8383 fileloc_isDefined (e->loc) ? e->loc : g_currentloc))
8385 uentry_showWhereDeclared (c);
8392 return (exprNode_fromIdentifierAux (c));
8395 exprNode exprNode_iterStart (/*@observer@*/ uentry name, /*@only@*/ exprNodeList alist)
8397 exprNode ret = exprNode_create (ctype_unknown);
8399 ret->kind = XPR_ITERCALL;
8400 ret->edata = exprData_makeIterCall (name, alist);
8402 if (uentry_isIter (name))
8404 uentryList params = uentry_getParams (name);
8406 if (context_inIterDef ()
8407 && uentryList_size (params) == exprNodeList_size (alist))
8411 exprNodeList_elements (alist, arg)
8413 uentry parg = uentryList_getN (params, i);
8415 if (uentry_isYield (parg))
8417 uentry ue = exprNode_getUentry (arg);
8419 if (uentry_isValid (ue))
8426 } end_exprNodeList_elements;
8429 (void) checkArgsReal (name, ret, params, alist, TRUE, ret);
8430 checkUnspecCall (ret, params, alist);
8436 /*@exposed@*/ sRef exprNode_getSref (exprNode e)
8438 if (exprNode_isDefined (e))
8441 if (e->sref == defref) /*@noaccess sRef@*/
8444 e->sref = sRef_makeUnknown ();
8445 sRef_setAliasKind (e->sref, AK_ERROR, fileloc_undefined);
8456 return sRef_undefined;
8460 /*@observer@*/ cstring
8461 exprNode_unparseFirst (exprNode e)
8463 if (exprNode_isDefined (e))
8467 if (e->kind == XPR_STMTLIST
8468 || e->kind == XPR_COMMA || e->kind == XPR_COND)
8470 exprNode first = exprData_getPairA (e->edata);
8472 if (exprNode_isDefined (first))
8474 return (exprNode_unparseFirst (exprData_getPairA (e->edata)));
8478 return (cstring_makeLiteralTemp ("..."));
8482 ret = cstring_elide (exprNode_unparse (e), 20);
8483 cstring_markOwned (ret);
8489 return cstring_makeLiteralTemp ("<error>");
8493 /*@observer@*/ cstring
8494 exprNode_unparse (/*@temp@*/ exprNode e)
8496 if (exprNode_isError (e))
8498 return cstring_makeLiteralTemp ("<error>");
8501 if (cstring_isDefined (e->etext))
8507 cstring ret = exprNode_doUnparse (e);
8509 /*@-modifies@*/ /* benevolent */
8516 /*@observer@*/ fileloc
8517 exprNode_loc (exprNode e)
8519 if (exprNode_isError (e))
8521 return (g_currentloc);
8530 ** executes exprNode e
8531 ** recursively rexecutes as though in original parse using
8532 ** information in e->edata
8535 static /*@only@*/ exprNodeList exprNodeList_effect (exprNodeList e)
8537 exprNodeList ret = exprNodeList_new ();
8539 exprNodeList_elements (e, current)
8541 exprNodeList_addh (ret, exprNode_effect (current));
8542 } end_exprNodeList_elements;
8547 static /*@only@*/ exprNode exprNode_effect (exprNode e)
8548 /*@globals internalState@*/
8550 bool innerEffect = inEffect;
8556 context_clearJustPopped ();
8558 if (exprNode_isError (e))
8560 ret = exprNode_undefined;
8565 ** Turn off expose and dependent transfer checking.
8566 ** Need to pass exposed internal nodes,
8567 ** [ copying would be a waste! ]
8568 ** [ Actually, I think I wasted a lot more time than its worth ]
8569 ** [ trying to do this. ]
8573 /*@-observertrans@*/
8574 /*@-dependenttrans@*/
8581 ret = exprNode_addParens (exprData_getUopTok (data),
8582 exprNode_effect (exprData_getUopNode (data)));
8585 ret = exprNode_assign (exprNode_effect (exprData_getOpA (data)),
8586 exprNode_effect (exprData_getOpB (data)),
8587 exprData_getOpTok (data));
8590 ret = exprNode_undefined;
8593 ret = exprNode_functionCall (exprNode_effect (exprData_getFcn (data)),
8594 exprNodeList_effect (exprData_getArgs (data)));
8607 cstring id = exprData_getId (data);
8608 uentry ue = usymtab_lookupSafe (id);
8610 ret = exprNode_fromIdentifierAux (ue);
8611 ret->loc = fileloc_update (ret->loc, e->loc);
8618 ret = exprNode_arrayFetch (exprNode_effect (exprData_getPairA (data)),
8619 exprNode_effect (exprData_getPairB (data)));
8622 ret = exprNode_op (exprNode_effect (exprData_getOpA (data)),
8623 exprNode_effect (exprData_getOpB (data)),
8624 exprData_getOpTok (data));
8628 ret = exprNode_postOp (exprNode_effect (exprData_getUopNode (data)),
8629 exprData_getUopTok (data));
8632 ret = exprNode_preOp (exprNode_effect (exprData_getUopNode (data)),
8633 exprData_getUopTok (data));
8645 ret = exprNode_vaArg (exprData_getCastTok (data),
8646 exprNode_effect (exprData_getCastNode (data)),
8647 exprData_getCastType (data));
8651 ret = exprNode_cast (exprData_getCastTok (data),
8652 exprNode_effect (exprData_getCastNode (data)),
8653 exprData_getCastType (data));
8656 ret = exprNode_iterStart (exprData_getIterCallIter (data),
8658 (exprData_getIterCallArgs (data)));
8662 ret = exprNode_iter (exprData_getIterSname (data),
8663 exprNodeList_effect (exprData_getIterAlist (data)),
8664 exprNode_effect (exprData_getIterBody (data)),
8665 exprData_getIterEname (data));
8669 ret = exprNode_for (exprNode_effect (exprData_getPairA (data)),
8670 exprNode_effect (exprData_getPairB (data)));
8674 ret = exprNode_forPred (exprNode_effect (exprData_getTripleInit (data)),
8675 exprNode_effect (exprData_getTripleTest (data)),
8676 exprNode_effect (exprData_getTripleInc (data)));
8680 ret = exprNode_createTok (exprData_getTok (data));
8684 ret = exprNode_goto (exprData_getLiteral (data));
8685 ret->loc = fileloc_update (ret->loc, e->loc);
8689 ret = exprNode_continue (exprData_getTok (data), QSAFEBREAK);
8693 ret = exprNode_break (exprData_getTok (data), QSAFEBREAK);
8697 ret = exprNode_return (exprNode_effect (exprData_getSingle (data)));
8700 case XPR_NULLRETURN:
8701 ret = exprNode_nullReturn (exprData_getTok (data));
8705 ret = exprNode_comma (exprNode_effect (exprData_getPairA (data)),
8706 exprNode_effect (exprData_getPairB (data)));
8710 ret = exprNode_cond (exprNode_effect (exprData_getTriplePred (data)),
8711 exprNode_effect (exprData_getTripleTrue (data)),
8712 exprNode_effect (exprData_getTripleFalse (data)));
8715 ret = exprNode_if (exprNode_effect (exprData_getPairA (data)),
8716 exprNode_effect (exprData_getPairB (data)));
8720 ret = exprNode_ifelse (exprNode_effect (exprData_getTriplePred (data)),
8721 exprNode_effect (exprData_getTripleTrue (data)),
8722 exprNode_effect (exprData_getTripleFalse (data)));
8725 ret = exprNode_whilePred (exprData_getSingle (data));
8729 ret = exprNode_while (exprNode_effect (exprData_getPairA (data)),
8730 exprNode_effect (exprData_getPairB (data)));
8734 ret = exprNode_doWhile (exprNode_effect (exprData_getPairA (data)),
8735 exprNode_effect (exprData_getPairB (data)));
8739 ret = exprNode_makeBlock (exprNode_effect (exprData_getSingle (data)));
8743 ret = exprNode_statement (exprNode_effect (exprData_getUopNode (data)),
8744 exprData_getUopTok (data));
8748 ret = exprNode_concat (exprNode_effect (exprData_getPairA (data)),
8749 exprNode_effect (exprData_getPairB (data)));
8754 ret = exprNode_caseMarker
8755 (exprNode_effect (exprData_getSingle (data)),
8761 ret = exprNode_createTok (exprData_getTok (data));
8765 ret = exprNode_switch (exprNode_effect (exprData_getPairA (data)),
8766 exprNode_effect (exprData_getPairB (data)));
8770 ret = exprNode_makeInitialization
8771 (exprData_getInitId (data),
8772 exprNode_effect (exprData_getInitNode (data)));
8776 ret = exprNode_fieldAccessAux
8777 (exprNode_effect (exprData_getFieldNode (data)),
8778 exprNode_loc (exprData_getFieldNode (data)),
8779 cstring_copy (exprData_getFieldName (data)));
8783 ret = exprNode_arrowAccessAux
8784 (exprNode_effect (exprData_getFieldNode (data)),
8785 exprNode_loc (exprData_getFieldNode (data)),
8786 cstring_copy (exprData_getFieldName (data)));
8789 case XPR_STRINGLITERAL:
8803 /*@=observertrans@*/
8805 /*@=dependenttrans@*/
8816 static /*@observer@*/ cstring exprNode_rootVarName (exprNode e)
8821 if (exprNode_isError (e))
8823 return cstring_undefined;
8831 ret = exprNode_rootVarName (exprData_getUopNode (data));
8834 ret = exprNode_rootVarName (exprData_getOpA (data));
8838 ret = exprData_getId (data);
8841 ret = idDecl_getName (exprData_getInitId (data));
8866 case XPR_NULLRETURN:
8888 case XPR_STRINGLITERAL:
8889 ret = cstring_undefined;
8896 static /*@only@*/ cstring exprNode_doUnparse (exprNode e)
8901 if (exprNode_isError (e))
8903 static /*@only@*/ cstring error = cstring_undefined;
8905 if (!cstring_isDefined (error))
8907 error = cstring_makeLiteral ("<error>");
8918 ret = message ("(%s)", exprNode_unparse (exprData_getUopNode (e->edata)));
8921 ret = message ("%s %s %s",
8922 exprNode_unparse (exprData_getOpA (data)),
8923 lltok_unparse (exprData_getOpTok (data)),
8924 exprNode_unparse (exprData_getOpB (data)));
8927 ret = message ("%s(%q)",
8928 exprNode_unparse (exprData_getFcn (data)),
8929 exprNodeList_unparse (exprData_getArgs (data)));
8932 ret = message ("{ %q }", exprNodeList_unparse (exprData_getArgs (data)));
8935 ret = cstring_undefined;
8938 ret = message ("%s:", exprData_getId (data));
8942 ret = cstring_copy (exprData_getId (data));
8945 ret = message ("%s[%s]", exprNode_unparse (exprData_getPairA (data)),
8946 exprNode_unparse (exprData_getPairB (data)));
8949 ret = message ("<body>");
8952 ret = message ("%s %s %s",
8953 exprNode_unparse (exprData_getOpA (data)),
8954 lltok_unparse (exprData_getOpTok (data)),
8955 exprNode_unparse (exprData_getOpB (data)));
8959 ret = message ("%s%s",
8960 lltok_unparse (exprData_getUopTok (data)),
8961 exprNode_unparse (exprData_getUopNode (data)));
8965 ret = message ("%s%s",
8966 exprNode_unparse (exprData_getUopNode (data)),
8967 lltok_unparse (exprData_getUopTok (data)));
8971 ret = message ("offsetof(%s,%q)",
8972 ctype_unparse (qtype_getType (exprData_getOffsetType (data))),
8973 cstringList_unparseSep (exprData_getOffsetName (data), cstring_makeLiteralTemp (".")));
8977 ret = message ("sizeof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8981 ret = message ("sizeof(%s)", exprNode_unparse (exprData_getSingle (data)));
8985 ret = message ("alignof(%s)", ctype_unparse (qtype_getType (exprData_getType (data))));
8989 ret = message ("alignof(%s)", exprNode_unparse (exprData_getSingle (data)));
8993 ret = message ("va_arg(%s, %q)",
8994 exprNode_unparse (exprData_getCastNode (data)),
8995 qtype_unparse (exprData_getCastType (data)));
8999 ret = message ("%q(%q)",
9000 uentry_getName (exprData_getIterCallIter (data)),
9001 exprNodeList_unparse (exprData_getIterCallArgs (data)));
9004 ret = message ("%q(%q) %s %q",
9005 uentry_getName (exprData_getIterSname (data)),
9006 exprNodeList_unparse (exprData_getIterAlist (data)),
9007 exprNode_unparse (exprData_getIterBody (data)),
9008 uentry_getName (exprData_getIterEname (data)));
9011 ret = message ("(%q)%s",
9012 qtype_unparse (exprData_getCastType (data)),
9013 exprNode_unparse (exprData_getCastNode (data)));
9017 ret = message ("%s %s",
9018 exprNode_unparse (exprData_getPairA (data)),
9019 exprNode_unparse (exprData_getPairB (data)));
9023 ret = message ("for (%s; %s; %s)",
9024 exprNode_unparse (exprData_getTripleInit (data)),
9025 exprNode_unparse (exprData_getTripleTest (data)),
9026 exprNode_unparse (exprData_getTripleInc (data)));
9030 ret = message ("goto %s", exprData_getLiteral (data));
9034 ret = cstring_makeLiteral ("continue");
9038 ret = cstring_makeLiteral ("break");
9042 ret = message ("return %s", exprNode_unparse (exprData_getSingle (data)));
9045 case XPR_NULLRETURN:
9046 ret = cstring_makeLiteral ("return");
9050 ret = message ("%s, %s",
9051 exprNode_unparse (exprData_getPairA (data)),
9052 exprNode_unparse (exprData_getPairB (data)));
9056 ret = message ("%s ? %s : %s",
9057 exprNode_unparse (exprData_getTriplePred (data)),
9058 exprNode_unparse (exprData_getTripleTrue (data)),
9059 exprNode_unparse (exprData_getTripleFalse (data)));
9062 ret = message ("if (%s) %s",
9063 exprNode_unparse (exprData_getPairA (data)),
9064 exprNode_unparse (exprData_getPairB (data)));
9068 ret = message ("if (%s) %s else %s",
9069 exprNode_unparse (exprData_getTriplePred (data)),
9070 exprNode_unparse (exprData_getTripleTrue (data)),
9071 exprNode_unparse (exprData_getTripleFalse (data)));
9074 ret = message ("while (%s) %s",
9075 exprNode_unparse (exprData_getPairA (data)),
9076 exprNode_unparse (exprData_getPairB (data)));
9080 ret = cstring_copy (exprNode_unparse (exprData_getSingle (data)));
9084 ret = cstring_copy (lltok_unparse (exprData_getTok (data)));
9088 ret = message ("do { %s } while (%s)",
9089 exprNode_unparse (exprData_getPairB (data)),
9090 exprNode_unparse (exprData_getPairA (data)));
9094 ret = message ("{ %s }", exprNode_unparseFirst (exprData_getSingle (data)));
9098 ret = cstring_copy (exprNode_unparse (exprData_getUopNode (data)));
9102 ret = message ("%s; %s",
9103 exprNode_unparse (exprData_getPairA (data)),
9104 exprNode_unparse (exprData_getPairB (data)));
9109 ret = cstring_makeLiteral ("default:");
9113 ret = message ("switch (%s) %s",
9114 exprNode_unparse (exprData_getPairA (data)),
9115 exprNode_unparse (exprData_getPairB (data)));
9120 ret = message ("case %s:",
9121 exprNode_unparse (exprData_getSingle (data)));
9125 if (exprNode_isError (exprData_getInitNode (data)))
9127 ret = message ("%q", idDecl_unparseC (exprData_getInitId (data)));
9131 ret = message ("%q = %s",
9132 idDecl_unparseC (exprData_getInitId (data)),
9133 exprNode_unparse (exprData_getInitNode (data)));
9138 ret = message ("%s.%s",
9139 exprNode_unparse (exprData_getFieldNode (data)),
9140 exprData_getFieldName (data));
9144 ret = message ("%s->%s",
9145 exprNode_unparse (exprData_getFieldNode (data)),
9146 exprData_getFieldName (data));
9149 case XPR_STRINGLITERAL:
9150 ret = message ("\"%s\"", exprData_getLiteral (data));
9154 ret = cstring_copy (exprData_getLiteral (data));
9158 ret = cstring_makeLiteral ("<node>");
9166 exprNode_isInitializer (exprNode e)
9168 return (exprNode_isDefined (e)
9169 && e->kind == XPR_INIT);
9173 exprNode_isCharLit (exprNode e)
9175 if (exprNode_isDefined (e))
9177 return (multiVal_isChar (exprNode_getValue (e)));
9186 exprNode_isNumLit (exprNode e)
9188 if (exprNode_isDefined (e))
9190 return (multiVal_isInt (exprNode_getValue (e)));
9199 exprNode_isFalseConstant (exprNode e)
9201 if (exprNode_isDefined (e))
9203 cstring s = exprNode_rootVarName (e);
9205 if (cstring_equal (s, context_getFalseName ()))
9215 exprNode_matchLiteral (ctype expected, exprNode e)
9217 if (exprNode_isDefined (e))
9219 multiVal m = exprNode_getValue (e);
9221 if (multiVal_isDefined (m))
9223 if (multiVal_isInt (m))
9225 long int val = multiVal_forceInt (m);
9227 if (ctype_isDirectBool (ctype_realishType (expected)))
9231 return FALSE; /* really?! return TRUE; allow use of 0 for FALSE */
9239 if (ctype_isRealInt (expected))
9242 ** unsigned <- [ constant >= 0 is okay ]
9245 if (ctype_isUnsigned (expected))
9254 ** No checks on sizes of integers...maybe add
9258 DPRINTF (("Here: %s => %s", exprNode_unparse (e), ctype_unparse (expected)));
9259 DPRINTF (("Type: %s / %s", ctype_unparse (exprNode_getType (e)),
9260 bool_unparse (ctype_isInt (exprNode_getType (e)))));
9262 if (context_getFlag (FLG_NUMLITERAL)
9263 && (ctype_isRegularInt (exprNode_getType (e)) || val == 0)) {
9269 return FALSE; /* evs 2000-05-17: previously, always returned TRUE */
9273 else if (ctype_isChar (expected))
9277 else if (ctype_isArrayPtr (expected))
9281 else if (ctype_isAnyFloat (expected))
9283 return (context_getFlag (FLG_NUMLITERAL));
9290 else if (multiVal_isDouble (m))
9292 if (ctype_isAnyFloat (expected))
9297 else if (multiVal_isChar (m))
9299 char val = multiVal_forceChar (m);
9301 if (ctype_isChar (expected))
9303 if (ctype_isUnsigned (expected) && ((int)val) < 0)
9324 exprNode_matchType (ctype expected, exprNode e)
9328 if (!exprNode_isDefined (e)) return TRUE;
9330 actual = ctype_realishType (exprNode_getType (e));
9332 if (ctype_match (ctype_realishType (expected), actual))
9337 llassert (!exprNode_isError (e));
9338 return (exprNode_matchLiteral (expected, e));
9342 exprNode_matchTypes (exprNode e1, exprNode e2)
9347 if (!exprNode_isDefined (e1)) return TRUE;
9348 if (!exprNode_isDefined (e2)) return TRUE;
9351 ** realish type --- keep bools, bools
9354 t1 = ctype_realishType (exprNode_getType (e1));
9355 t2 = ctype_realishType (exprNode_getType (e2));
9357 if (ctype_match (t1, t2))
9362 return (exprNode_matchLiteral (t1, e2) || exprNode_matchLiteral (t2, e1));
9370 exprNode_matchArgType (ctype ct, exprNode e)
9374 if (!exprNode_isDefined (e))
9379 et = ctype_realType (exprNode_getType (e));
9381 if (ctype_matchArg (ct, et)) return TRUE;
9383 llassert (!exprNode_isError (e));
9384 return (exprNode_matchLiteral (ct, e));
9387 static /*@only@*/ exprNodeSList
9388 exprNode_flatten (/*@dependent@*/ exprNode e) /*@*/
9390 if (exprNode_isDefined (e))
9392 if (e->kind == XPR_STMTLIST)
9394 return (exprNodeSList_append
9395 (exprNode_flatten (exprData_getPairA (e->edata)),
9396 exprNode_flatten (exprData_getPairB (e->edata))));
9398 else if (e->kind == XPR_BLOCK)
9400 return (exprNode_flatten (exprData_getSingle (e->edata)));
9404 return (exprNodeSList_singleton (e));
9408 return exprNodeSList_new ();
9411 static /*@exposed@*/ exprNode
9412 exprNode_lastStatement (/*@returned@*/ exprNode e)
9414 if (exprNode_isDefined (e))
9416 if (e->kind == XPR_STMTLIST)
9418 exprNode b = exprData_getPairB (e->edata);
9420 if (exprNode_isDefined (b))
9422 return exprNode_lastStatement (b);
9426 return exprNode_lastStatement (exprData_getPairA (e->edata));
9429 else if (e->kind == XPR_BLOCK)
9431 return (exprNode_lastStatement (exprData_getSingle (e->edata)));
9439 return exprNode_undefined;
9442 static /*@exposed@*/ exprNode
9443 exprNode_firstStatement (/*@returned@*/ exprNode e)
9445 if (exprNode_isDefined (e))
9447 if (e->kind == XPR_STMTLIST)
9449 exprNode b = exprData_getPairA (e->edata);
9451 if (exprNode_isDefined (b))
9453 return exprNode_firstStatement (b);
9457 return exprNode_firstStatement (exprData_getPairB (e->edata));
9460 else if (e->kind == XPR_BLOCK)
9462 return (exprNode_firstStatement (exprData_getSingle (e->edata)));
9470 return exprNode_undefined;
9474 exprNode_mergeUSs (exprNode res, exprNode other)
9476 if (exprNode_isDefined (res) && exprNode_isDefined (other))
9478 res->msets = sRefSet_union (res->msets, other->msets);
9479 res->sets = sRefSet_union (res->sets, other->sets);
9480 res->uses = sRefSet_union (res->uses, other->uses);
9485 exprNode_mergeCondUSs (exprNode res, exprNode other1, exprNode other2)
9487 if (exprNode_isDefined (res))
9489 if (exprNode_isDefined (other1))
9491 res->sets = sRefSet_union (res->sets, other1->sets);
9492 res->msets = sRefSet_union (res->msets, other1->msets);
9493 res->uses = sRefSet_union (res->uses, other1->uses);
9495 if (exprNode_isDefined (other2))
9497 res->sets = sRefSet_union (res->sets, other2->sets);
9498 res->msets = sRefSet_union (res->msets, other2->msets);
9499 res->uses = sRefSet_union (res->uses, other2->uses);
9507 ** Reports errors is s is not defined.
9511 exprNode_addUse (exprNode e, /*@exposed@*/ sRef s)
9513 if (exprNode_isDefined (e))
9515 e->uses = sRefSet_insert (e->uses, s);
9520 exprNode_checkUse (exprNode e, /*@exposed@*/ sRef s, fileloc loc)
9522 if (sRef_isKnown (s) && !sRef_isConst (s))
9525 ** need to check all outer types are useable
9528 DPRINTF (("Check use: %s / %s",
9529 exprNode_unparse (e), sRef_unparse (s)));
9531 exprNode_addUse (e, s);
9533 if (!context_inProtectVars ())
9536 ** only report the deepest error
9539 sRef errorRef = sRef_undefined;
9540 sRef lastRef = sRef_undefined;
9541 bool deadRef = FALSE;
9542 bool unuseable = FALSE;
9543 bool errorMaybe = FALSE;
9545 while (sRef_isValid (s) && sRef_isKnown (s))
9547 ynm readable = sRef_isReadable (s);
9549 DPRINTF (("Readable: %s / %s",
9550 sRef_unparseFull (s), ynm_unparse (readable)));
9552 if (!(ynm_toBoolStrict (readable)))
9554 if (ynm_isMaybe (readable))
9558 DPRINTF (("Setting ERROR: %s", sRef_unparseFull (s)));
9559 deadRef = sRef_isPossiblyDead (errorRef);
9560 unuseable = sRef_isUnuseable (errorRef);
9567 deadRef = sRef_isDead (errorRef);
9568 unuseable = sRef_isUnuseable (errorRef);
9572 if (!sRef_isPartial (s))
9574 DPRINTF (("Defining! %s", sRef_unparseFull (s)));
9575 sRef_setDefined (s, fileloc_undefined);
9579 s = sRef_getBaseSafe (s);
9582 if (sRef_isValid (errorRef))
9584 if (sRef_isValid (lastRef) && sRef_isField (lastRef)
9585 && sRef_isPointer (errorRef))
9592 if (sRef_isThroughArrayFetch (errorRef))
9595 (FLG_STRICTUSERELEASED,
9596 message ("%q %q may be used after being released",
9597 sRef_unparseKindNamePlain (errorRef),
9598 sRef_unparse (errorRef)),
9601 sRef_showRefKilled (errorRef);
9603 if (sRef_isKept (errorRef))
9605 sRef_clearAliasState (errorRef, loc);
9611 DPRINTF (("HERE: %s", sRef_unparse (errorRef)));
9615 message ("%q %q %qused after being released",
9616 sRef_unparseKindNamePlain (errorRef),
9617 sRef_unparse (errorRef),
9618 cstring_makeLiteral (errorMaybe
9622 sRef_showRefKilled (errorRef);
9624 if (sRef_isKept (errorRef))
9626 sRef_clearAliasState (errorRef, loc);
9635 message ("%q %q%qused in inconsistent state",
9636 sRef_unparseKindName (errorRef),
9637 sRef_unparseOpt (errorRef),
9638 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9641 sRef_showStateInconsistent (errorRef);
9646 DPRINTF (("HERE: %s", sRef_unparseFull (errorRef)));
9650 message ("%q %q%qused before definition",
9651 sRef_unparseKindName (errorRef),
9652 sRef_unparseOpt (errorRef),
9653 cstring_makeLiteral (errorMaybe ? "may be " : "")),
9656 DPRINTF (("Error: %s", sRef_unparseFull (errorRef)));
9659 sRef_setDefined (errorRef, loc);
9661 if (sRef_isAddress (errorRef))
9663 sRef_setDefined (sRef_getRootBase (errorRef), loc);
9665 } /* end is error */
9673 checkSafeUse (exprNode e, /*@exposed@*/ sRef s)
9675 if (exprNode_isDefined (e) && sRef_isKnown (s))
9677 e->uses = sRefSet_insert (e->uses, s);
9682 exprNode_checkSetAny (exprNode e, /*@dependent@*/ cstring name)
9684 if (exprNode_isDefined (e))
9686 e->sets = sRefSet_insert (e->sets, sRef_makeUnconstrained (name));
9691 exprNode_checkSet (exprNode e, /*@exposed@*/ sRef s)
9693 sRef defines = sRef_undefined;
9695 if (sRef_isValid (s) && !sRef_isNothing (s))
9697 uentry ue = sRef_getBaseUentry (s);
9699 if (uentry_isValid (ue))
9701 uentry_setLset (ue);
9704 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9706 voptgenerror (FLG_USEDEF,
9707 message ("Attempt to set unuseable storage: %q",
9712 if (sRef_isMeaningful (s))
9714 if (sRef_isDead (s))
9716 sRef base = sRef_getBaseSafe (s);
9718 if (sRef_isValid (base)
9719 && sRef_isDead (base))
9721 sRef_setPartial (s, exprNode_loc (e));
9724 defines = s; /* okay - modifies for only param */
9726 else if (sRef_isPartial (s))
9728 sRef eref = exprNode_getSref (e);
9730 if (!sRef_isPartial (eref))
9733 ** should do something different here???
9736 sRef_setDefinedComplete (eref, exprNode_loc (e));
9740 sRef_setPartialDefinedComplete (eref, exprNode_loc (e));
9743 if (sRef_isMeaningful (eref))
9752 else if (sRef_isAllocated (s))
9754 sRef eref = exprNode_getSref (e);
9757 if (!sRef_isAllocated (eref))
9759 sRef_setDefinedComplete (eref, exprNode_loc (e));
9763 sRef base = sRef_getBaseSafe (eref);
9765 if (sRef_isValid (base))
9767 sRef_setPdefined (base, exprNode_loc (e));
9775 sRef_setDefinedNCComplete (s, exprNode_loc (e));
9780 else /* not meaningful...but still need to insert it */
9786 if (exprNode_isDefined (e) && sRef_isValid (defines))
9788 e->sets = sRefSet_insert (e->sets, defines);
9793 exprNode_checkMSet (exprNode e, /*@exposed@*/ sRef s)
9795 if (sRef_isValid (s) && !sRef_isNothing (s))
9797 uentry ue = sRef_getBaseUentry (s);
9799 if (uentry_isValid (ue))
9801 uentry_setLset (ue);
9804 if (!ynm_toBoolStrict (sRef_isWriteable (s)))
9806 voptgenerror (FLG_USEDEF,
9807 message ("Attempt to set unuseable storage: %q", sRef_unparse (s)),
9811 if (sRef_isMeaningful (s))
9813 sRef_setDefinedComplete (s, exprNode_loc (e));
9816 if (exprNode_isDefined (e))
9818 e->msets = sRefSet_insert (e->msets, s);
9824 checkUnspecCall (/*@notnull@*/ /*@dependent@*/ exprNode fcn, uentryList params, exprNodeList args)
9826 checkAnyCall (fcn, cstring_undefined, params, args,
9827 FALSE, sRefSet_undefined, FALSE, 0);
9831 checkOneArg (uentry ucurrent, /*@notnull@*/ exprNode current,
9832 /*@dependent@*/ exprNode fcn, bool isSpec, int argno, int totargs)
9836 if (uentry_isYield (ucurrent))
9838 sRef_setDefined (exprNode_getSref (current), exprNode_loc (current));
9839 exprNode_checkSet (current, current->sref);
9843 if (uentry_isSefParam (ucurrent))
9845 sRefSet sets = current->sets;
9846 sRef ref = exprNode_getSref (current);
9848 if (sRef_isMacroParamRef (ref))
9850 uentry ue = sRef_getUentry (ref);
9852 if (!uentry_isSefParam (ue))
9857 ("Parameter %d to %s is declared sef, but "
9858 "the argument is a macro parameter declared "
9860 argno, exprNode_unparse (fcn),
9861 exprNode_unparse (current)),
9862 exprNode_loc (current));
9866 if (!sRefSet_isEmpty (sets))
9868 sRefSet reported = sRefSet_undefined;
9870 sRefSet_realElements (current->sets, el)
9872 if (sRefSet_isSameNameMember (reported, el))
9874 ; /* don't report again */
9878 if (sRef_isUnconstrained (el))
9883 ("Parameter %d to %s is declared sef, but "
9884 "the argument calls unconstrained function %s "
9885 "(no guarantee it will not modify something): %s",
9886 argno, exprNode_unparse (fcn),
9887 sRef_unconstrainedName (el),
9888 exprNode_unparse (current)),
9889 exprNode_loc (current));
9896 ("Parameter %d to %s is declared sef, but "
9897 "the argument may modify %q: %s",
9898 argno, exprNode_unparse (fcn),
9900 exprNode_unparse (current)),
9901 exprNode_loc (current));
9904 } end_sRefSet_realElements;
9908 checkPassTransfer (current, ucurrent, isSpec, fcn, argno, totargs);
9909 exprNode_mergeUSs (fcn, current);
9914 checkAnyCall (/*@dependent@*/ exprNode fcn,
9915 /*@dependent@*/ cstring fname,
9918 bool hasMods, sRefSet mods,
9923 int nargs = exprNodeList_size (args);
9928 ** concat all args ud's to f, add each arg sref as a use unless
9929 ** it was specified as "out", in which case it is a def.
9932 uentryList_reset (pn);
9937 ** if paramn is only or unique, no other arg may alias argn
9940 exprNodeList_elements (args, current)
9944 if (exprNode_isDefined (current))
9946 if ((!uentryList_isUndefined (pn) && !uentryList_isFinished (pn)))
9948 uentry ucurrent = uentryList_current (pn);
9950 if (specialArgs == 0
9951 || (paramno < specialArgs))
9953 checkOneArg (ucurrent, current, fcn, isSpec, paramno, nargs);
9955 if (context_maybeSet (FLG_ALIASUNIQUE))
9957 if (uentry_isOnly (ucurrent)
9958 || uentry_isUnique (ucurrent))
9960 checkUniqueParams (fcn, current, args,
9966 else /* uentry is undefined */
9968 if (specialArgs == 0)
9970 exprNode_checkUseParam (current);
9973 exprNode_mergeUSs (fcn, current);
9976 uentryList_advanceSafe (pn);
9977 } end_exprNodeList_elements;
9983 sRefSet_allElements (mods, s)
9986 sRef rb = sRef_getRootBase (s);
9988 if (sRef_isFileOrGlobalScope (rb))
9990 context_usedGlobal (rb);
9993 fb = sRef_fixBaseParam (s, args);
9995 if (!sRef_isMacroParamRef (fb))
9997 if (sRef_isNothing (fb))
10003 if (sRef_isValid (fb))
10005 uentry ue = sRef_getBaseUentry (s);
10007 if (uentry_isValid (ue))
10009 uentry_setLset (ue);
10013 fcn->sets = sRefSet_insert (fcn->sets, fb);
10016 sRef_clearDerivedComplete (s);
10017 } end_sRefSet_allElements;
10023 if (context_hasMods ())
10025 if (context_maybeSet (FLG_MODUNCON))
10029 message ("Undetected modification possible "
10030 "from call to unconstrained function %s: %s",
10032 exprNode_unparse (fcn)),
10033 exprNode_loc (fcn));
10038 if (context_maybeSet (FLG_MODUNCONNOMODS)
10039 && !(context_inIterDef () || context_inIterEnd ()))
10042 (FLG_MODUNCONNOMODS,
10043 message ("Undetected modification possible "
10044 "from call to unconstrained function %s: %s",
10046 exprNode_unparse (fcn)),
10047 exprNode_loc (fcn));
10051 exprNode_checkSetAny (fcn, fname);
10055 void exprNode_checkUseParam (exprNode current)
10057 if (exprNode_isDefined (current))
10059 exprNode_checkUse (current, current->sref, current->loc);
10064 checkNumerics (ctype tr1, ctype tr2, ctype te1, ctype te2,
10065 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10070 if (!ctype_match (tr1, tr2))
10072 if ((ctype_isRealInt (tr1) || ctype_isReal (tr1)) &&
10073 (ctype_isRealInt (tr2) || ctype_isReal (tr2)))
10079 (void) gentypeerror
10081 message ("Incompatible types for %s (%s, %s): %s %s %s",
10082 lltok_unparse (op),
10083 ctype_unparse (te1),
10084 ctype_unparse (te2),
10085 exprNode_unparse (e1), lltok_unparse (op),
10086 exprNode_unparse (e2)),
10089 ret = ctype_unknown;
10093 if (ctype_isForceRealNumeric (&tr1) && ctype_isForceRealNumeric (&tr2))
10095 ret = ctype_resolveNumerics (tr1, tr2);
10097 else if (!context_msgStrictOps ())
10099 if (ctype_isPointer (tr1))
10101 if (ctype_isPointer (tr2) && !exprNode_isNullValue (e2))
10105 else if (ctype_isInt (tr2))
10111 ret = ctype_unknown;
10114 else if (ctype_isPointer (tr2))
10116 if (ctype_isPointer (tr1))
10120 else if (ctype_isInt (tr1))
10126 ret = ctype_unknown;
10131 ret = ctype_resolveNumerics (tr1, tr2);
10136 int opid = lltok_getTok (op);
10137 bool comparop = (opid == EQ_OP || opid == NE_OP
10138 || opid == TLT || opid == TGT
10139 || opid == LE_OP || opid == GE_OP);
10141 if (!ctype_isNumeric (tr1) && !ctype_isNumeric (tr2))
10144 && ((ctype_isEnum (tr1) && ctype_isEnum (tr2))
10145 || (ctype_isBool (tr1) && ctype_isBool (tr2))
10146 || (ctype_isChar (tr1) && ctype_isChar (tr2))))
10152 if (ctype_sameName (te1, te2))
10156 message ("Operands of %s are non-numeric (%t): %s %s %s",
10157 lltok_unparse (op), te1,
10158 exprNode_unparse (e1), lltok_unparse (op),
10159 exprNode_unparse (e2)),
10166 message ("Operands of %s are non-numerics (%t, %t): %s %s %s",
10167 lltok_unparse (op), te1, te2,
10168 exprNode_unparse (e1), lltok_unparse (op),
10169 exprNode_unparse (e2)),
10174 else if (!ctype_isNumeric (tr1))
10178 message ("Right operand of %s is non-numeric (%t): %s %s %s",
10179 lltok_unparse (op), te1,
10180 exprNode_unparse (e1), lltok_unparse (op),
10181 exprNode_unparse (e2)),
10186 if (!ctype_isNumeric (tr2))
10190 message ("Left operand of %s is non-numeric (%t): %s %s %s",
10191 lltok_unparse (op), te2,
10192 exprNode_unparse (e1), lltok_unparse (op),
10193 exprNode_unparse (e2)),
10198 ret = ctype_unknown;
10206 abstractOpError (ctype tr1, ctype tr2, lltok op,
10207 /*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2,
10208 fileloc loc1, fileloc loc2)
10210 if (ctype_isRealAbstract (tr1) && ctype_isRealAbstract (tr2))
10212 if (ctype_match (tr1, tr2))
10216 message ("Operands of %s are abstract type (%t): %s %s %s",
10217 lltok_unparse (op), tr1,
10218 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10225 message ("Operands of %s are abstract types (%t, %t): %s %s %s",
10226 lltok_unparse (op), tr1, tr2,
10227 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10231 else if (ctype_isRealAbstract (tr1))
10235 message ("Left operand of %s is abstract type (%t): %s %s %s",
10236 lltok_unparse (op), tr1,
10237 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10242 if (ctype_isRealAbstract (tr2))
10246 message ("Right operand of %s is abstract type (%t): %s %s %s",
10247 lltok_unparse (op), tr2,
10248 exprNode_unparse (e1), lltok_unparse (op), exprNode_unparse (e2)),
10257 ** requies e1 and e2 and not error exprNode's.
10261 ** If e1 is a component of an abstract type, and e2 is mutable and client-visible,
10262 ** the rep of the abstract type is exposed.
10264 ** The order is very important:
10266 ** check rep expose (move into check transfer)
10272 ** This isn't really a sensible procedure, but the indententation
10273 ** was getting too deep.
10277 checkOneRepExpose (sRef ysr, sRef base,
10278 /*@notnull@*/ exprNode e1,
10279 /*@notnull@*/ exprNode e2, ctype ct,
10282 if (!(sRef_isOnly (ysr) || sRef_isKeep (ysr)
10283 || sRef_isOwned (ysr)
10284 || sRef_isExposed (ysr)))
10286 if (sRef_isAnyParam (base) && !sRef_isExposed (base)
10287 && !sRef_isObserver (base)) /* evans 2001-07-11: added isObserver */
10290 if (sRef_isIReference (ysr))
10292 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10297 ("Assignment of mutable component of parameter %q "
10298 "to component of abstract "
10299 "type %s exposes rep: %s = %s",
10300 sRef_unparse (base),
10301 ctype_unparse (ct),
10302 exprNode_unparse (e1), exprNode_unparse (e2)),
10310 ("Assignment of mutable component of parameter %q "
10311 "(through alias %q) to component of abstract "
10312 "type %s exposes rep: %s = %s",
10313 sRef_unparse (base),
10314 sRef_unparse (e2->sref),
10315 ctype_unparse (ct),
10316 exprNode_unparse (e1), exprNode_unparse (e2)),
10322 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10326 message ("Assignment of mutable parameter %q "
10327 "to component of abstract type %s "
10328 "exposes rep: %s = %s",
10329 sRef_unparse (base),
10330 ctype_unparse (ct),
10331 exprNode_unparse (e1),
10332 exprNode_unparse (e2)),
10339 message ("Assignment of mutable parameter %q "
10340 "(through alias %q) to "
10341 "component of abstract type %s exposes "
10343 sRef_unparse (base),
10344 sRef_unparse (e2->sref),
10345 ctype_unparse (ct),
10346 exprNode_unparse (e1),
10347 exprNode_unparse (e2)),
10353 if (sRef_isFileOrGlobalScope (s2b))
10355 if (sRef_sameName (base, sRef_getRootBase (e2->sref)))
10359 message ("Assignment of global %q "
10361 "abstract type %s exposes rep: %s = %s",
10362 sRef_unparse (base),
10363 ctype_unparse (ct),
10364 exprNode_unparse (e1), exprNode_unparse (e2)),
10371 message ("Assignment of global %q (through alias %q) "
10373 "abstract type %s exposes rep: %s = %s",
10374 sRef_unparse (base),
10375 sRef_unparse (e2->sref),
10376 ctype_unparse (ct),
10377 exprNode_unparse (e1), exprNode_unparse (e2)),
10385 doAssign (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2, bool isInit)
10387 if (ctype_isRealFunction (exprNode_getType (e1))
10388 && !ctype_isRealPointer (exprNode_getType (e1)))
10392 message ("Invalid left-hand side of assignment (function type %s): %s",
10393 ctype_unparse (exprNode_getType (e1)),
10394 exprNode_unparse (e1)),
10398 if (context_getFlag (FLG_ASSIGNEXPOSE) && ctype_isMutable (e2->typ))
10400 ctype t2 = exprNode_getType (e2);
10401 sRef sr = sRef_getRootBase (e1->sref);
10402 ctype ct = sRef_getType (sr);
10404 if (ctype_isAbstract (t2)
10405 && !(uentry_isMutableDatatype (usymtab_getTypeEntry (ctype_typeId (t2)))))
10407 /* it is immutable, okay to reference */
10408 goto donerepexpose;
10411 if (ctype_isAbstract (ct) && sRef_isIReference (e1->sref))
10413 sRef s2b = sRef_getRootBase (e2->sref);
10414 sRef s1 = e1->sref;
10415 sRef s1b = sRef_getRootBase (s1);
10418 aliases = usymtab_canAlias (e2->sref);
10420 if (!sRef_similar (s2b, s1b)
10421 && !sRef_isExposed (s1)
10422 && !(sRef_isOnly (s2b) || sRef_isKeep (s2b) || sRef_isExposed (s2b)))
10424 if (sRef_isAnyParam (s2b) && !sRef_isOnly (s2b)
10425 && !sRef_isOwned (s2b) && !sRef_isKeep (s2b)
10426 && !sRef_isExposed (s2b))
10428 if (sRef_isIReference (e2->sref))
10433 ("Assignment of mutable component of parameter %q "
10434 "to component of abstract type %s exposes rep: %s = %s",
10435 sRef_unparse (s2b),
10436 ctype_unparse (ct),
10437 exprNode_unparse (e1), exprNode_unparse (e2)),
10444 message ("Assignment of mutable parameter %q to "
10445 "component of abstract type %s exposes rep: %s = %s",
10446 sRef_unparse (s2b),
10447 ctype_unparse (ct),
10448 exprNode_unparse (e1), exprNode_unparse (e2)),
10453 if (sRef_isFileOrGlobalScope (s2b))
10457 message ("Assignment of global %q to component of "
10458 "abstract type %s exposes rep: %s = %s",
10459 sRef_unparse (s2b),
10460 ctype_unparse (ct),
10461 exprNode_unparse (e1), exprNode_unparse (e2)),
10465 sRefSet_realElements (aliases, ysr)
10467 sRef base = sRef_getRootBase (ysr);
10469 if (sRef_similar (ysr, s2b) || sRef_similar (s1b, base)
10470 || sRef_sameName (base, s1b))
10472 ; /* error already reported or same sref */
10476 checkOneRepExpose (ysr, base, e1, e2, ct, s2b);
10478 } end_sRefSet_realElements;
10480 sRefSet_free (aliases);
10487 ** function variables don't really work...
10490 if (!ctype_isFunction (ctype_realType (e2->typ)))
10494 DPRINTF (("Check init: %s / %s",
10495 exprNode_unparse (e1), exprNode_unparse (e2)));
10496 checkInitTransfer (e1, e2);
10500 checkAssignTransfer (e1, e2);
10505 sRef fref = e2->sref;
10507 sRef_setDefState (e1->sref, sRef_getDefState (fref), e1->loc);
10508 sRef_setNullState (e1->sref, sRef_getNullState (fref), e1->loc);
10510 /* Need to typecheck the annotation on the parameters */
10512 if (ctype_isRealFunction (e1->typ)) {
10513 uentryList e1p = ctype_argsFunction (ctype_realType (e1->typ));
10514 uentryList e2p = ctype_argsFunction (ctype_realType (e2->typ));
10516 if (!uentryList_isMissingParams (e1p)
10517 && !uentryList_isMissingParams (e2p)
10518 && uentryList_size (e1p) > 0) {
10519 if (uentryList_size (e1p) == uentryList_size (e2p)) {
10522 uentryList_elements (e1p, el1) {
10525 el2 = uentryList_getN (e2p, n);
10527 uentry_checkMatchParam (el1, el2, n, e2);
10528 } end_uentryList_elements;
10534 if (isInit && sRef_isFileOrGlobalScope (e1->sref))
10540 DPRINTF (("Update aliases: %s / %s", exprNode_unparse (e1), exprNode_unparse (e2)));
10541 updateAliases (e1, e2);
10546 checkMacroParen (exprNode e)
10548 if (exprNode_isError (e) || e->kind == XPR_CAST)
10554 if (sRef_isUnsafe (e->sref) && !exprNode_isInParens (e))
10558 message ("Macro parameter used without parentheses: %s",
10559 exprNode_unparse (e)),
10566 reflectNullTest (/*@notnull@*/ exprNode e, bool isnull)
10570 e->guards = guardSet_addTrueGuard (e->guards, e->sref);
10574 e->guards = guardSet_addFalseGuard (e->guards, e->sref);
10581 ** if e2 is a parameter or global derived location which
10582 ** can be modified (that is, e2 is a mutable abstract type,
10583 ** or a derived pointer), then e1 can alias e2.
10585 ** e1 can alias everything which e2 can alias.
10587 ** Also, if e1 is guarded, remove from guard sets!
10590 static void updateAliases (/*@notnull@*/ exprNode e1, /*@notnull@*/ exprNode e2)
10592 if (!context_inProtectVars ())
10595 ** depends on types of e1 and e2
10598 sRef s1 = e1->sref;
10599 sRef s2 = e2->sref;
10600 ctype t1 = exprNode_getType (e1);
10602 /* handle pointer sRefs, record fields, arrays, etc... */
10604 if (!ctype_isRealSU (t1))
10606 DPRINTF (("Copying real! %s", ctype_unparse (t1)));
10607 sRef_copyRealDerivedComplete (s1, s2);
10612 ** Fields should alias
10615 DPRINTF (("Not COPYING!: %s", ctype_unparse (t1)));
10618 if (ctype_isMutable (t1) && sRef_isKnown (s1))
10620 usymtab_clearAlias (s1);
10621 usymtab_addMustAlias (s1, s2);
10622 DPRINTF (("Add must alias: %s / %s", sRef_unparse (s1), sRef_unparse (s2)));
10626 DPRINTF (("Not mutable: %s", ctype_unparse (t1)));
10629 if (sRef_possiblyNull (s1) && usymtab_isGuarded (s1))
10631 usymtab_unguard (s1);
10636 exprNode exprNode_updateLocation (/*@returned@*/ exprNode e, /*@temp@*/ fileloc loc)
10638 if (exprNode_isDefined (e))
10640 e->loc = fileloc_update (e->loc, loc);
10644 e = exprNode_createLoc (ctype_unknown, fileloc_copy (loc));
10650 static void checkUniqueParams (exprNode fcn,
10651 /*@notnull@*/ exprNode current,
10653 int paramno, uentry ucurrent)
10656 sRef thisref = exprNode_getSref (current);
10659 ** Check if any argument could match this argument.
10662 exprNodeList_elements (args, icurrent)
10666 if (iparamno != paramno)
10668 sRef sr = exprNode_getSref (icurrent);
10670 if (sRef_similarRelaxed (thisref, sr))
10672 if (!sRef_isConst (thisref) && !sRef_isConst (sr))
10677 ("Parameter %d (%s) to function %s is declared %s but "
10678 "is aliased by parameter %d (%s)",
10680 exprNode_unparse (current),
10681 exprNode_unparse (fcn),
10682 alkind_unparse (uentry_getAliasKind (ucurrent)),
10683 iparamno, exprNode_unparse (icurrent)),
10689 sRefSet aliases = usymtab_canAlias (sr);
10691 sRefSet_allElements (aliases, asr)
10693 if (ctype_isUnknown (sRef_getType (thisref)))
10695 sRef_setType (thisref, uentry_getType (ucurrent));
10698 if (sRef_similarRelaxed (thisref, asr))
10700 if (sRef_isExternal (asr))
10702 if (sRef_isLocalState (thisref))
10708 sRef base = sRef_getRootBase (asr);
10710 if (!sRef_similar (sRef_getBase (asr), thisref))
10712 if (sRef_isUnique (base) || sRef_isOnly (base)
10713 || sRef_isKept (base)
10714 || (sRef_isAddress (asr) && sRef_isLocalVar (base))
10715 || (sRef_isAddress (thisref)
10716 && sRef_isLocalVar (sRef_getRootBase (thisref))))
10718 ; /* okay, no error */
10723 (FLG_MAYALIASUNIQUE,
10725 ("Parameter %d (%s) to function %s is declared %s but "
10726 "may be aliased externally by parameter %d (%s)",
10728 exprNode_unparse (current),
10729 exprNode_unparse (fcn),
10730 alkind_unparse (uentry_getAliasKind (ucurrent)),
10731 iparamno, exprNode_unparse (icurrent)),
10742 ("Parameter %d (%s) to function %s is declared %s but "
10743 "is aliased externally by parameter %d (%s) through "
10746 exprNode_unparse (current),
10747 exprNode_unparse (fcn),
10748 alkind_unparse (uentry_getAliasKind (ucurrent)),
10749 iparamno, exprNode_unparse (icurrent),
10750 sRef_unparse (asr)),
10754 } end_sRefSet_allElements;
10755 sRefSet_free (aliases);
10758 } end_exprNodeList_elements;
10761 long exprNode_getLongValue (exprNode e) {
10764 if (exprNode_hasValue (e)
10765 && multiVal_isInt (exprNode_getValue (e)))
10767 value = multiVal_forceInt (exprNode_getValue (e));
10777 /*@observer@*/ fileloc exprNode_getfileloc (exprNode p_e)
10779 if (exprNode_isDefined (p_e) )
10780 return ( p_e->loc );
10782 return fileloc_undefined;
10785 /*@only@*/ fileloc exprNode_getNextSequencePoint (exprNode e)
10788 ** Returns the location of the sequence point following e.
10790 ** Only works for statements (for now).
10793 if (exprNode_isDefined (e) && e->kind == XPR_STMT) {
10794 lltok t = exprData_getUopTok (e->edata);
10795 return fileloc_copy(lltok_getLoc (t));
10797 /* drl possible problem : warning fix
10798 llcontbug (message ("Cannot get next sequence point: %s", exprNode_unparse (e)));
10800 return fileloc_undefined;
10804 exprNode exprNode_createNew(ctype c)
10808 ret = exprNode_createPlain (c);
10813 bool exprNode_isInitBlock (exprNode e)
10815 return (exprNode_isDefined(e) && e->kind == XPR_INITBLOCK);